|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v6 1/3] xen/vpci: Move ecam access functions to common code
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.
Rename vpci_access_allowed to vpci_ecam_access_allowed and move it
from arch/x86/hvm/io.c to drivers/vpci/vpci.c.
Create vpci_ecam_mmio_{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_mmio_{read,write} functions are returning 0 on error and 1
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.
Those functions will be used in a following patch inside by arm vpci
implementation.
Rename MMCFG_SBDF to ECAM_SBDF.
Not 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>
---
Changes in v6: Patch added
---
xen/arch/x86/hvm/io.c | 50 +++++---------------------------
xen/drivers/vpci/vpci.c | 60 +++++++++++++++++++++++++++++++++++++++
xen/include/asm-x86/pci.h | 2 +-
xen/include/xen/vpci.h | 10 +++++++
4 files changed, 78 insertions(+), 44 deletions(-)
diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c
index 046a8eb4ed..340b8c8b0e 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)
@@ -305,7 +291,7 @@ static int vpci_portio_read(const struct hvm_io_handler
*handler,
reg = hvm_pci_decode_addr(cf8, addr, &sbdf);
- if ( !vpci_access_allowed(reg, size) )
+ if ( !vpci_ecam_access_allowed(reg, size) )
return X86EMUL_OKAY;
*data = vpci_read(sbdf, reg, size);
@@ -335,7 +321,7 @@ static int vpci_portio_write(const struct hvm_io_handler
*handler,
reg = hvm_pci_decode_addr(cf8, addr, &sbdf);
- if ( !vpci_access_allowed(reg, size) )
+ if ( !vpci_ecam_access_allowed(reg, size) )
return X86EMUL_OKAY;
vpci_write(sbdf, reg, size, data);
@@ -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 = 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;
+ /* Ignore return code */
+ vpci_ecam_mmio_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);
+ /* Ignore return code */
+ vpci_ecam_mmio_write(sbdf, reg, len, data);
return X86EMUL_OKAY;
}
diff --git a/xen/drivers/vpci/vpci.c b/xen/drivers/vpci/vpci.c
index cbd1bac7fc..c0853176d7 100644
--- a/xen/drivers/vpci/vpci.c
+++ b/xen/drivers/vpci/vpci.c
@@ -478,6 +478,66 @@ 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_ecam_access_allowed(unsigned int reg, unsigned int len)
+{
+ /*
+ * Check access size.
+ *
+ * On arm32 or for 32bit guests on arm, 64bit accesses should be forbidden
+ * but as for those platform ISV register, which gives the access size,
+ * cannot have a value 3, checking this would just harden the code.
+ */
+ 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;
+}
+
+int vpci_ecam_mmio_write(pci_sbdf_t sbdf, unsigned int reg, unsigned int len,
+ unsigned long data)
+{
+ if ( !vpci_ecam_access_allowed(reg, len) ||
+ (reg + len) > PCI_CFG_SPACE_EXP_SIZE )
+ return 0;
+
+ vpci_write(sbdf, reg, min(4u, len), data);
+ if ( len == 8 )
+ vpci_write(sbdf, reg + 4, 4, data >> 32);
+
+ return 1;
+}
+
+int vpci_ecam_mmio_read(pci_sbdf_t sbdf, unsigned int reg, unsigned int len,
+ unsigned long *data)
+{
+ if ( !vpci_ecam_access_allowed(reg, len) ||
+ (reg + len) > PCI_CFG_SPACE_EXP_SIZE )
+ return 0;
+
+ /*
+ * 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 1;
+}
+
/*
* Local variables:
* mode: C
diff --git a/xen/include/asm-x86/pci.h b/xen/include/asm-x86/pci.h
index edd7c3e71a..a0df5c1279 100644
--- a/xen/include/asm-x86/pci.h
+++ b/xen/include/asm-x86/pci.h
@@ -6,7 +6,7 @@
#define CF8_ADDR_HI(cf8) ( ((cf8) & 0x0f000000) >> 16)
#define CF8_ENABLED(cf8) (!!((cf8) & 0x80000000))
-#define MMCFG_BDF(addr) ( ((addr) & 0x0ffff000) >> 12)
+#define ECAM_BDF(addr) ( ((addr) & 0x0ffff000) >> 12)
#define IS_SNB_GFX(id) (id == 0x01068086 || id == 0x01168086 \
|| id == 0x01268086 || id == 0x01028086 \
diff --git a/xen/include/xen/vpci.h b/xen/include/xen/vpci.h
index 9f5b5d52e1..4a0c3d77c9 100644
--- a/xen/include/xen/vpci.h
+++ b/xen/include/xen/vpci.h
@@ -208,6 +208,16 @@ static inline unsigned int vmsix_entry_nr(const struct
vpci_msix *msix,
{
return entry - msix->entries;
}
+
+/* ECAM mmio read/write helpers */
+bool vpci_ecam_access_allowed(unsigned int reg, unsigned int len);
+
+int vpci_ecam_mmio_write(pci_sbdf_t sbdf, unsigned int reg, unsigned int len,
+ unsigned long data);
+
+int vpci_ecam_mmio_read(pci_sbdf_t sbdf, unsigned int reg, unsigned int len,
+ unsigned long *data);
+
#endif /* __XEN__ */
#else /* !CONFIG_HAS_VPCI */
--
2.25.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |