[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v1 06/23] xen/pt: XenHostPCIDevice: provide functions for PCI Cap
From: |
Joel Upham |
Subject: |
[PATCH v1 06/23] xen/pt: XenHostPCIDevice: provide functions for PCI Capabilities and PCIe Extended Capabilities enumeration |
Date: |
Tue, 20 Jun 2023 13:24:40 -0400 |
This patch introduces 2 new functions,
- xen_host_pci_find_next_ext_cap (actually a reworked
xen_host_pci_find_ext_cap_offset function which is unused)
- xen_host_pci_find_next_cap
These functions allow to search for PCI/PCIe capabilities in a uniform
way. Both functions allow to search either a specific capability or any
encountered next (by specifying CAP_ID_ANY as a capability ID) -- this may
be useful when we merely need to traverse the capability list one-by-one.
In both functions the 'pos' argument allows to continue searching from
last position (0 means to start from beginning).
In order not to probe PCIe Extended Capabilities existence every time,
xen_host_pci_find_next_ext_cap makes use of the new 'has_pcie_ext_caps'
field in XenHostPCIDevice structure which is filled only once (in
xen_host_pci_device_get).
Signed-off-by: Alexey Gerasimenko <x1917x@xxxxxxxxx>
Signed-off-by: Joel Upham <jupham125@gmail.com>
---
hw/xen/xen-host-pci-device.c | 91 ++++++++++++++++++++++++++++++++----
hw/xen/xen-host-pci-device.h | 5 +-
2 files changed, 85 insertions(+), 11 deletions(-)
diff --git a/hw/xen/xen-host-pci-device.c b/hw/xen/xen-host-pci-device.c
index 8c6e9a1716..a7021a5d56 100644
--- a/hw/xen/xen-host-pci-device.c
+++ b/hw/xen/xen-host-pci-device.c
@@ -32,6 +32,7 @@
#define IORESOURCE_PREFETCH 0x00001000 /* No side effects */
#define IORESOURCE_MEM_64 0x00100000
+#define XEN_HOST_PCI_CAP_MAX 48
static void xen_host_pci_sysfs_path(const XenHostPCIDevice *d,
const char *name, char *buf, ssize_t size)
@@ -198,6 +199,19 @@ static bool xen_host_pci_dev_is_virtfn(XenHostPCIDevice *d)
return !stat(path, &buf);
}
+static bool xen_host_pci_dev_has_pcie_ext_caps(XenHostPCIDevice *d)
+{
+ uint32_t header;
+
+ if (xen_host_pci_get_long(d, PCI_CONFIG_SPACE_SIZE, &header))
+ return false;
+
+ if (header == 0 || header == ~0U)
+ return false;
+
+ return true;
+}
+
static void xen_host_pci_config_open(XenHostPCIDevice *d, Error **errp)
{
char path[PATH_MAX];
@@ -296,37 +310,93 @@ int xen_host_pci_set_block(XenHostPCIDevice *d, int pos,
uint8_t *buf, int len)
return xen_host_pci_config_write(d, pos, buf, len);
}
-int xen_host_pci_find_ext_cap_offset(XenHostPCIDevice *d, uint32_t cap)
+int xen_host_pci_find_next_ext_cap(XenHostPCIDevice *d, int pos, uint32_t cap)
{
uint32_t header = 0;
int max_cap = XEN_HOST_PCI_MAX_EXT_CAP;
- int pos = PCI_CONFIG_SPACE_SIZE;
+
+ if (!d->has_pcie_ext_caps)
+ return 0;
+
+ if (!pos) {
+ pos = PCI_CONFIG_SPACE_SIZE;
+ } else {
+ if (xen_host_pci_get_long(d, pos, &header))
+ return 0;
+
+ pos = PCI_EXT_CAP_NEXT(header);
+ }
do {
+ if (!pos || pos < PCI_CONFIG_SPACE_SIZE) {
+ break;
+ }
+
if (xen_host_pci_get_long(d, pos, &header)) {
break;
}
/*
* If we have no capabilities, this is indicated by cap ID,
* cap version and next pointer all being 0.
+ * Also check for all F's returned (which means PCIe ext conf space
+ * is unreadable for some reason)
*/
- if (header == 0) {
+ if (header == 0 || header == ~0U) {
break;
}
- if (PCI_EXT_CAP_ID(header) == cap) {
+ if (cap == CAP_ID_ANY) {
+ return pos;
+ } else if (PCI_EXT_CAP_ID(header) == cap) {
return pos;
}
pos = PCI_EXT_CAP_NEXT(header);
- if (pos < PCI_CONFIG_SPACE_SIZE) {
+ } while (--max_cap);
+
+ return 0;
+}
+
+int xen_host_pci_find_next_cap(XenHostPCIDevice *d, int pos, uint32_t cap)
+{
+ uint8_t id;
+ unsigned max_cap = XEN_HOST_PCI_CAP_MAX;
+ uint8_t status = 0;
+ uint8_t curpos;
+
+ if (xen_host_pci_get_byte(d, PCI_STATUS, &status))
+ return 0;
+
+ if ((status & PCI_STATUS_CAP_LIST) == 0)
+ return 0;
+
+ if (pos < PCI_CAPABILITY_LIST) {
+ curpos = PCI_CAPABILITY_LIST;
+ } else {
+ curpos = (uint8_t) pos;
+ }
+
+ while (max_cap--) {
+ if (xen_host_pci_get_byte(d, curpos, &curpos))
+ break;
+ if (!curpos)
+ break;
+
+ if (cap == CAP_ID_ANY)
+ return curpos;
+
+ if (xen_host_pci_get_byte(d, curpos + PCI_CAP_LIST_ID, &id))
break;
- }
- max_cap--;
- } while (max_cap > 0);
+ if (id == 0xff)
+ break;
+ else if (id == cap)
+ return curpos;
+
+ curpos += PCI_CAP_LIST_NEXT;
+ }
- return -1;
+ return 0;
}
void xen_host_pci_device_get(XenHostPCIDevice *d, uint16_t domain,
@@ -376,7 +446,8 @@ void xen_host_pci_device_get(XenHostPCIDevice *d, uint16_t
domain,
}
d->class_code = v;
- d->is_virtfn = xen_host_pci_dev_is_virtfn(d);
+ d->is_virtfn = xen_host_pci_dev_is_virtfn(d);
+ d->has_pcie_ext_caps = xen_host_pci_dev_has_pcie_ext_caps(d);
return;
diff --git a/hw/xen/xen-host-pci-device.h b/hw/xen/xen-host-pci-device.h
index 4d8d34ecb0..37c5614a24 100644
--- a/hw/xen/xen-host-pci-device.h
+++ b/hw/xen/xen-host-pci-device.h
@@ -32,6 +32,7 @@ typedef struct XenHostPCIDevice {
XenHostPCIIORegion rom;
bool is_virtfn;
+ bool has_pcie_ext_caps;
int config_fd;
} XenHostPCIDevice;
@@ -53,6 +54,8 @@ int xen_host_pci_set_long(XenHostPCIDevice *d, int pos,
uint32_t data);
int xen_host_pci_set_block(XenHostPCIDevice *d, int pos, uint8_t *buf,
int len);
-int xen_host_pci_find_ext_cap_offset(XenHostPCIDevice *s, uint32_t cap);
+#define CAP_ID_ANY (~0U)
+int xen_host_pci_find_next_cap(XenHostPCIDevice *s, int pos, uint32_t cap);
+int xen_host_pci_find_next_ext_cap(XenHostPCIDevice *d, int pos, uint32_t cap);
#endif /* XEN_HOST_PCI_DEVICE_H */
--
2.34.1
- [PATCH v1 14/23] xen/pt: add fixed-size PCIe Extended Capabilities descriptors, (continued)
- [PATCH v1 14/23] xen/pt: add fixed-size PCIe Extended Capabilities descriptors, Joel Upham, 2023/06/20
- [PATCH v1 16/23] xen/pt: add descriptors and size calculation for RCLD/ACS/PMUX/DPA/MCAST/TPH/DPC PCIe Extended Capabilities, Joel Upham, 2023/06/20
- [PATCH v1 19/23] xen/pt: Fake capability id, Joel Upham, 2023/06/20
- [PATCH v1 22/23] qdev-monitor/pt: bypass root device check, Joel Upham, 2023/06/20
- [PATCH v1 09/23] xen/pt: Xen PCIe passthrough support for Q35: bypass PCIe topology check, Joel Upham, 2023/06/20
- [PATCH v1 08/23] xen/pt: determine the legacy/PCIe mode for a passed through device, Joel Upham, 2023/06/20
- [PATCH v1 21/23] pc/q35: setup q35 for xen, Joel Upham, 2023/06/20
- [PATCH v1 23/23] s3 support: enabling s3 with q35, Joel Upham, 2023/06/20
- [PATCH v1 06/23] xen/pt: XenHostPCIDevice: provide functions for PCI Capabilities and PCIe Extended Capabilities enumeration,
Joel Upham <=
- [PATCH v1 13/23] xen/pt: add Vendor-specific PCIe Extended Capability descriptor and sizing, Joel Upham, 2023/06/20
- Re: [PATCH v1 00/23] Q35 support for Xen, Bernhard Beschow, 2023/06/22