|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v7 1/5] xen/vpci: Move ecam access functions to common code
On Fri, Oct 15, 2021 at 02:59:18PM +0100, Bertrand Marquis wrote:
> PCI standard is using ECAM and not MCFG which is coming from ACPI[1].
> Use ECAM/ecam instead of MCFG in common code and in new functions added
> in common vpci code by this patch.
>
> Move vpci_access_allowed from arch/x86/hvm/io.c to drivers/vpci/vpci.c.
>
> Create vpci_ecam_{read,write} in drivers/vpci/vpci.c that
> contains the common code to perform these operations, changed
> vpci_mmcfg_{read,write} accordingly to make use of these functions.
>
> The vpci_ecam_{read,write} functions are returning false on error and
> true on success. As the x86 code was previously always returning
> X86EMUL_OKAY the return code is ignored. A comment has been added in
> the code to show that this is intentional.
I still wonder how you plan to propagate those errors back to the
guest in a proper way, so I'm dubious whether returning a boolean is
really warranted here, as I don't think raising a CPU fault/abort or
similar on vpci errors in correct. We will see I guess, and the
current behavior for x86 is not changed anyway.
>
> Those functions will be used in a following patch inside by arm vpci
> implementation.
>
> Rename MMCFG_BDF to VPCI_ECAM_BDF and move it to vpci.h.
> This macro is only used by functions calling vpci_ecam helpers.
>
> No functional change intended with this patch.
>
> [1] https://wiki.osdev.org/PCI_Express
>
> Suggested-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
> Signed-off-by: Bertrand Marquis <bertrand.marquis@xxxxxxx>
Acked-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
> ---
> Changes in v7:
> - Rename vpci_ecam_access_allowed to vpci_access_allowed
> - Rename vpci_ecam_mmio_{read/write} to vpci_ecam_{read/write}
> - Replace comment in x86/hvm/io.c with one suggested by Roger
> - Remove 32bit comments and fixes from this patch and move it to the next
> one to keep only the moving+renaming in this patch
> - Change return type of vpci_ecam_{read/write} to bool
> - rename ECAM_BDF to VPCI_ECAM_BDF and move it to vpci.h
> Changes in v6: Patch added
> ---
> xen/arch/x86/hvm/io.c | 46 ++++-----------------------------
> xen/drivers/vpci/vpci.c | 54 +++++++++++++++++++++++++++++++++++++++
> xen/include/asm-x86/pci.h | 2 --
> xen/include/xen/vpci.h | 12 +++++++++
> 4 files changed, 71 insertions(+), 43 deletions(-)
>
> diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c
> index 046a8eb4ed..eb3c80743e 100644
> --- a/xen/arch/x86/hvm/io.c
> +++ b/xen/arch/x86/hvm/io.c
> @@ -260,20 +260,6 @@ unsigned int hvm_pci_decode_addr(unsigned int cf8,
> unsigned int addr,
> return CF8_ADDR_LO(cf8) | (addr & 3);
> }
>
> -/* Do some sanity checks. */
> -static bool vpci_access_allowed(unsigned int reg, unsigned int len)
> -{
> - /* Check access size. */
> - if ( len != 1 && len != 2 && len != 4 && len != 8 )
> - return false;
> -
> - /* Check that access is size aligned. */
> - if ( (reg & (len - 1)) )
> - return false;
> -
> - return true;
> -}
> -
> /* vPCI config space IO ports handlers (0xcf8/0xcfc). */
> static bool vpci_portio_accept(const struct hvm_io_handler *handler,
> const ioreq_t *p)
> @@ -394,7 +380,7 @@ static unsigned int vpci_mmcfg_decode_addr(const struct
> hvm_mmcfg *mmcfg,
> paddr_t addr, pci_sbdf_t *sbdf)
> {
> addr -= mmcfg->addr;
> - sbdf->bdf = MMCFG_BDF(addr);
> + sbdf->bdf = VCPI_ECAM_BDF(addr);
> sbdf->bus += mmcfg->start_bus;
> sbdf->seg = mmcfg->segment;
>
> @@ -434,25 +420,8 @@ static int vpci_mmcfg_read(struct vcpu *v, unsigned long
> addr,
> reg = vpci_mmcfg_decode_addr(mmcfg, addr, &sbdf);
> read_unlock(&d->arch.hvm.mmcfg_lock);
>
> - if ( !vpci_access_allowed(reg, len) ||
> - (reg + len) > PCI_CFG_SPACE_EXP_SIZE )
> - return X86EMUL_OKAY;
> -
> - /*
> - * According to the PCIe 3.1A specification:
> - * - Configuration Reads and Writes must usually be DWORD or smaller
> - * in size.
> - * - Because Root Complex implementations are not required to support
> - * accesses to a RCRB that cross DW boundaries [...] software
> - * should take care not to cause the generation of such accesses
> - * when accessing a RCRB unless the Root Complex will support the
> - * access.
> - * Xen however supports 8byte accesses by splitting them into two
> - * 4byte accesses.
> - */
> - *data = vpci_read(sbdf, reg, min(4u, len));
> - if ( len == 8 )
> - *data |= (uint64_t)vpci_read(sbdf, reg + 4, 4) << 32;
> + /* Failed reads are not propagated to the caller */
> + vpci_ecam_read(sbdf, reg, len, data);
>
> return X86EMUL_OKAY;
> }
> @@ -476,13 +445,8 @@ static int vpci_mmcfg_write(struct vcpu *v, unsigned
> long addr,
> reg = vpci_mmcfg_decode_addr(mmcfg, addr, &sbdf);
> read_unlock(&d->arch.hvm.mmcfg_lock);
>
> - if ( !vpci_access_allowed(reg, len) ||
> - (reg + len) > PCI_CFG_SPACE_EXP_SIZE )
> - return X86EMUL_OKAY;
> -
> - vpci_write(sbdf, reg, min(4u, len), data);
> - if ( len == 8 )
> - vpci_write(sbdf, reg + 4, 4, data >> 32);
> + /* Failed writes are not propagated to the caller */
> + vpci_ecam_write(sbdf, reg, len, data);
>
> return X86EMUL_OKAY;
> }
> diff --git a/xen/drivers/vpci/vpci.c b/xen/drivers/vpci/vpci.c
> index cbd1bac7fc..ef690f15a9 100644
> --- a/xen/drivers/vpci/vpci.c
> +++ b/xen/drivers/vpci/vpci.c
> @@ -478,6 +478,60 @@ void vpci_write(pci_sbdf_t sbdf, unsigned int reg,
> unsigned int size,
> spin_unlock(&pdev->vpci->lock);
> }
>
> +/* Helper function to check an access size and alignment on vpci space. */
> +bool vpci_access_allowed(unsigned int reg, unsigned int len)
> +{
> + /* Check access size. */
> + if ( len != 1 && len != 2 && len != 4 && len != 8 )
> + return false;
> +
> + /* Check that access is size aligned. */
> + if ( (reg & (len - 1)) )
> + return false;
> +
> + return true;
> +}
> +
> +bool vpci_ecam_write(pci_sbdf_t sbdf, unsigned int reg, unsigned int len,
> + unsigned long data)
> +{
> + if ( !vpci_access_allowed(reg, len) ||
> + (reg + len) > PCI_CFG_SPACE_EXP_SIZE )
> + return false;
> +
> + vpci_write(sbdf, reg, min(4u, len), data);
> + if ( len == 8 )
> + vpci_write(sbdf, reg + 4, 4, data >> 32);
> +
> + return true;
> +}
> +
> +bool vpci_ecam_read(pci_sbdf_t sbdf, unsigned int reg, unsigned int len,
> + unsigned long *data)
> +{
> + if ( !vpci_access_allowed(reg, len) ||
> + (reg + len) > PCI_CFG_SPACE_EXP_SIZE )
> + return false;
> +
> + /*
> + * According to the PCIe 3.1A specification:
> + * - Configuration Reads and Writes must usually be DWORD or smaller
> + * in size.
> + * - Because Root Complex implementations are not required to support
> + * accesses to a RCRB that cross DW boundaries [...] software
> + * should take care not to cause the generation of such accesses
> + * when accessing a RCRB unless the Root Complex will support the
> + * access.
> + * Xen however supports 8byte accesses by splitting them into two
> + * 4byte accesses.
> + */
> + *data = vpci_read(sbdf, reg, min(4u, len));
> + if ( len == 8 )
> + *data |= (uint64_t)vpci_read(sbdf, reg + 4, 4) << 32;
> +
> + return true;
> +}
> +
> /*
> * Local variables:
> * mode: C
> diff --git a/xen/include/asm-x86/pci.h b/xen/include/asm-x86/pci.h
> index edd7c3e71a..443f25347d 100644
> --- a/xen/include/asm-x86/pci.h
> +++ b/xen/include/asm-x86/pci.h
> @@ -6,8 +6,6 @@
> #define CF8_ADDR_HI(cf8) ( ((cf8) & 0x0f000000) >> 16)
> #define CF8_ENABLED(cf8) (!!((cf8) & 0x80000000))
>
> -#define MMCFG_BDF(addr) ( ((addr) & 0x0ffff000) >> 12)
> -
> #define IS_SNB_GFX(id) (id == 0x01068086 || id == 0x01168086 \
> || id == 0x01268086 || id == 0x01028086 \
> || id == 0x01128086 || id == 0x01228086 \
> diff --git a/xen/include/xen/vpci.h b/xen/include/xen/vpci.h
> index 9f5b5d52e1..d6cf0baf14 100644
> --- a/xen/include/xen/vpci.h
> +++ b/xen/include/xen/vpci.h
> @@ -19,6 +19,8 @@ typedef int vpci_register_init_t(struct pci_dev *dev);
> #define VPCI_PRIORITY_MIDDLE "5"
> #define VPCI_PRIORITY_LOW "9"
>
> +#define VPCI_ECAM_BDF(addr) (((addr) & 0x0ffff000) >> 12)
> +
> #define REGISTER_VPCI_INIT(x, p) \
> static vpci_register_init_t *const x##_entry \
> __used_section(".data.vpci." p) = x
> @@ -208,6 +210,16 @@ static inline unsigned int vmsix_entry_nr(const struct
> vpci_msix *msix,
> {
> return entry - msix->entries;
> }
> +
> +/* ECAM mmio read/write helpers */
Nit: comment should likely be below vpci_access_allowed.
> +bool vpci_access_allowed(unsigned int reg, unsigned int len);
> +
> +bool vpci_ecam_write(pci_sbdf_t sbdf, unsigned int reg, unsigned int len,
> + unsigned long data);
> +
> +bool vpci_ecam_read(pci_sbdf_t sbdf, unsigned int reg, unsigned int len,
> + unsigned long *data);
Nit: the lines containing the overflow parameter are not properly
aligned.
Thanks, Roger.
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |