aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorAlexandru Elisei <alexandru.elisei@arm.com>2021-07-13 18:06:30 +0100
committerWill Deacon <will@kernel.org>2021-07-16 16:02:34 +0100
commite69b7663b06e8af9cc2dae16e6ec906a64c3c63d (patch)
tree1017880cbee16369c9012559b420b3b146f41408 /include
parent6b74f68fcf06a3de6f5ac49f39e60a42bd3e78dc (diff)
downloadkvmtool-e69b7663b06e8af9cc2dae16e6ec906a64c3c63d.tar.gz
arm/arm64: Add PCI Express 1.1 support
PCI Express comes with an extended addressing scheme, which directly translated into a bigger device configuration space (256->4096 bytes) and bigger PCI configuration space (16->256 MB), as well as mandatory capabilities (power management [1] and PCI Express capability [2]). However, our virtio PCI implementation implements version 0.9 of the protocol and it still uses transitional PCI device ID's, so we have opted to omit the mandatory PCI Express capabilities. For VFIO, the power management and PCI Express capability are left for a subsequent patch. [1] PCI Express Base Specification Revision 1.1, section 7.6 [2] PCI Express Base Specification Revision 1.1, section 7.8 Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com> Reviewed-by: Andre Przywara <andre.przywara@arm.com> Link: https://lore.kernel.org/r/20210713170631.155595-4-alexandru.elisei@arm.com Signed-off-by: Will Deacon <will@kernel.org>
Diffstat (limited to 'include')
-rw-r--r--include/kvm/pci.h51
1 files changed, 46 insertions, 5 deletions
diff --git a/include/kvm/pci.h b/include/kvm/pci.h
index bf81323d..42d9e1c5 100644
--- a/include/kvm/pci.h
+++ b/include/kvm/pci.h
@@ -10,6 +10,7 @@
#include "kvm/devices.h"
#include "kvm/msi.h"
#include "kvm/fdt.h"
+#include "kvm/kvm-arch.h"
#define pci_dev_err(pci_hdr, fmt, ...) \
pr_err("[%04x:%04x] " fmt, pci_hdr->vendor_id, pci_hdr->device_id, ##__VA_ARGS__)
@@ -32,10 +33,49 @@
#define PCI_CONFIG_BUS_FORWARD 0xcfa
#define PCI_IO_SIZE 0x100
#define PCI_IOPORT_START 0x6200
-#define PCI_CFG_SIZE (1ULL << 24)
struct kvm;
+/*
+ * On some distributions, pci_regs.h doesn't define PCI_CFG_SPACE_SIZE and
+ * PCI_CFG_SPACE_EXP_SIZE, so we define our own.
+ */
+#define PCI_CFG_SIZE_LEGACY (1ULL << 24)
+#define PCI_DEV_CFG_SIZE_LEGACY 256
+#define PCI_CFG_SIZE_EXTENDED (1ULL << 28)
+#define PCI_DEV_CFG_SIZE_EXTENDED 4096
+
+#ifdef ARCH_HAS_PCI_EXP
+#define PCI_CFG_SIZE PCI_CFG_SIZE_EXTENDED
+#define PCI_DEV_CFG_SIZE PCI_DEV_CFG_SIZE_EXTENDED
+
+union pci_config_address {
+ struct {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned reg_offset : 2; /* 1 .. 0 */
+ unsigned register_number : 10; /* 11 .. 2 */
+ unsigned function_number : 3; /* 14 .. 12 */
+ unsigned device_number : 5; /* 19 .. 15 */
+ unsigned bus_number : 8; /* 27 .. 20 */
+ unsigned reserved : 3; /* 30 .. 28 */
+ unsigned enable_bit : 1; /* 31 */
+#else
+ unsigned enable_bit : 1; /* 31 */
+ unsigned reserved : 3; /* 30 .. 28 */
+ unsigned bus_number : 8; /* 27 .. 20 */
+ unsigned device_number : 5; /* 19 .. 15 */
+ unsigned function_number : 3; /* 14 .. 12 */
+ unsigned register_number : 10; /* 11 .. 2 */
+ unsigned reg_offset : 2; /* 1 .. 0 */
+#endif
+ };
+ u32 w;
+};
+
+#else
+#define PCI_CFG_SIZE PCI_CFG_SIZE_LEGACY
+#define PCI_DEV_CFG_SIZE PCI_DEV_CFG_SIZE_LEGACY
+
union pci_config_address {
struct {
#if __BYTE_ORDER == __LITTLE_ENDIAN
@@ -58,6 +98,9 @@ union pci_config_address {
};
u32 w;
};
+#endif /* ARCH_HAS_PCI_EXP */
+
+#define PCI_DEV_CFG_MASK (PCI_DEV_CFG_SIZE - 1)
struct msix_table {
struct msi_msg msg;
@@ -110,14 +153,12 @@ typedef int (*bar_deactivate_fn_t)(struct kvm *kvm,
int bar_num, void *data);
#define PCI_BAR_OFFSET(b) (offsetof(struct pci_device_header, bar[b]))
-#define PCI_DEV_CFG_SIZE 256
-#define PCI_DEV_CFG_MASK (PCI_DEV_CFG_SIZE - 1)
struct pci_config_operations {
void (*write)(struct kvm *kvm, struct pci_device_header *pci_hdr,
- u8 offset, void *data, int sz);
+ u16 offset, void *data, int sz);
void (*read)(struct kvm *kvm, struct pci_device_header *pci_hdr,
- u8 offset, void *data, int sz);
+ u16 offset, void *data, int sz);
};
struct pci_device_header {