Re: [PATCH 3/3] vfio/pci: Expose setup ROM at ROM bar when needed

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, 12 Dec 2024 15:50:50 -0500
Yunxiang Li <Yunxiang.Li@xxxxxxx> wrote:

> If ROM bar is missing for any reason, we can fallback to using pdev->rom
> to expose the ROM content to the guest. This fixes some passthrough use
> cases where the upstream bridge does not have enough address window.
> 
> Signed-off-by: Yunxiang Li <Yunxiang.Li@xxxxxxx>
> ---
>  drivers/vfio/pci/vfio_pci_config.c |  4 ++++
>  drivers/vfio/pci/vfio_pci_core.c   | 35 +++++++++++++++---------------
>  drivers/vfio/pci/vfio_pci_rdwr.c   | 14 ++++++++++--
>  3 files changed, 34 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c
> index e41c3a965663e..4c673d842fb35 100644
> --- a/drivers/vfio/pci/vfio_pci_config.c
> +++ b/drivers/vfio/pci/vfio_pci_config.c
> @@ -511,6 +511,10 @@ static void vfio_bar_fixup(struct vfio_pci_core_device *vdev)
>  		mask = ~(pci_resource_len(pdev, PCI_ROM_RESOURCE) - 1);
>  		mask |= PCI_ROM_ADDRESS_ENABLE;
>  		*vbar &= cpu_to_le32((u32)mask);
> +	} else if (pdev->rom && pdev->romlen) {
> +		mask = ~(roundup_pow_of_two(pdev->romlen) - 1);
> +		mask |= PCI_ROM_ADDRESS_ENABLE;
> +		*vbar &= cpu_to_le32((u32)mask);
>  	} else {
>  		*vbar = 0;
>  	}
> diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
> index b49dd9cdc072a..3120c1e9f22cb 100644
> --- a/drivers/vfio/pci/vfio_pci_core.c
> +++ b/drivers/vfio/pci/vfio_pci_core.c
> @@ -1049,30 +1049,31 @@ static int vfio_pci_ioctl_get_region_info(struct vfio_pci_core_device *vdev,
>  		break;
>  	case VFIO_PCI_ROM_REGION_INDEX: {
>  		void __iomem *io;
> -		size_t size;
> +		size_t dont_care;

It still receives the size even if we don't consume it.

>  		u16 cmd;
>  
>  		info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index);
>  		info.flags = 0;
> +		info.size = 0;
>  
> -		/* Report the BAR size, not the ROM size */
> -		info.size = pci_resource_len(pdev, info.index);
> -		if (!info.size)
> -			break;
> -
> -		/*
> -		 * Is it really there?  Enable memory decode for implicit access
> -		 * in pci_map_rom().
> -		 */
> -		cmd = vfio_pci_memory_lock_and_enable(vdev);
> -		io = pci_map_rom(pdev, &size);
> -		if (io) {
> +		if (pci_resource_start(pdev, PCI_ROM_RESOURCE)) {
> +			/* Check ROM content is valid. Need to enable memory

Incorrect comment style.

> +			 * decode for ROM access in pci_map_rom().
> +			 */
> +			cmd = vfio_pci_memory_lock_and_enable(vdev);
> +			io = pci_map_rom(pdev, &dont_care);
> +			if (io) {
> +				info.flags = VFIO_REGION_INFO_FLAG_READ;
> +				/* Report the BAR size, not the ROM size. */
> +				info.size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
> +				pci_unmap_rom(pdev, io);
> +			}
> +			vfio_pci_memory_unlock_and_restore(vdev, cmd);
> +		} else if (pdev->rom && pdev->romlen) {
>  			info.flags = VFIO_REGION_INFO_FLAG_READ;
> -			pci_unmap_rom(pdev, io);
> -		} else {
> -			info.size = 0;
> +			/* Report BAR size as power of two. */
> +			info.size = roundup_pow_of_two(pdev->romlen);
>  		}
> -		vfio_pci_memory_unlock_and_restore(vdev, cmd);
>  
>  		break;
>  	}
> diff --git a/drivers/vfio/pci/vfio_pci_rdwr.c b/drivers/vfio/pci/vfio_pci_rdwr.c
> index 4bed9fd5af50f..4ea983cf499d9 100644
> --- a/drivers/vfio/pci/vfio_pci_rdwr.c
> +++ b/drivers/vfio/pci/vfio_pci_rdwr.c
> @@ -243,6 +243,8 @@ ssize_t vfio_pci_bar_rw(struct vfio_pci_core_device *vdev, char __user *buf,
>  
>  	if (pci_resource_start(pdev, bar))
>  		end = pci_resource_len(pdev, bar);
> +	else if (bar == PCI_ROM_RESOURCE && pdev->rom && pdev->romlen)
> +		end = roundup_pow_of_two(pdev->romlen);
>  	else
>  		return -EINVAL;
>  
> @@ -259,7 +261,12 @@ ssize_t vfio_pci_bar_rw(struct vfio_pci_core_device *vdev, char __user *buf,
>  		 * excluded range at the end of the actual ROM.  This makes
>  		 * filling large ROM BARs much faster.
>  		 */
> -		io = pci_map_rom(pdev, &x_start);
> +		if (pci_resource_start(pdev, bar)) {
> +			io = pci_map_rom(pdev, &x_start);
> +		} else {
> +			io = ioremap(pdev->rom, pdev->romlen);
> +			x_start = pdev->romlen;
> +		}
>  		if (!io)
>  			return -ENOMEM;
>  		x_end = end;
> @@ -267,7 +274,10 @@ ssize_t vfio_pci_bar_rw(struct vfio_pci_core_device *vdev, char __user *buf,
>  		done = vfio_pci_core_do_io_rw(vdev, 1, io, buf, pos,
>  					      count, x_start, x_end, 0);
>  
> -		pci_unmap_rom(pdev, io);
> +		if (pci_resource_start(pdev, bar))
> +			pci_unmap_rom(pdev, io);
> +		else
> +			iounmap(io);
>  	} else {
>  		done = vfio_pci_core_setup_barmap(vdev, bar);
>  		if (done)

It's not clear why the refactoring of the previous patch was really
necessary simply to have an alternate map and unmap path.  Thanks,

Alex





[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux