* [Qemu-devel] [PATCH v7 1/3] pci: refactor pci_find_capapibilty to get bdf as the first argument instead of the whole pci_device
2017-08-17 23:12 [Qemu-devel] [PATCH v7 0/3] Red Hat PCI bridge resource reserve capability Aleksandr Bezzubikov
@ 2017-08-17 23:12 ` Aleksandr Bezzubikov
2017-08-17 23:12 ` [Qemu-devel] [PATCH v7 2/3] pci: add QEMU-specific PCI capability structure Aleksandr Bezzubikov
2017-08-17 23:12 ` [Qemu-devel] [PATCH v7 3/3] pci: enable RedHat PCI bridges to reserve additional resources on PCI init Aleksandr Bezzubikov
2 siblings, 0 replies; 4+ messages in thread
From: Aleksandr Bezzubikov @ 2017-08-17 23:12 UTC (permalink / raw)
To: seabios
Cc: marcel, mst, kraxel, kevin, lersek, qemu-devel,
Aleksandr Bezzubikov
Refactor pci_find_capability function to get bdf instead of
a whole pci_device* as the only necessary field for this function
is still bdf.
Signed-off-by: Aleksandr Bezzubikov <zuban32s@gmail.com>
Reviewed-by: Marcel Apfelbaum <marcel@redhat.com>
---
src/fw/pciinit.c | 4 ++--
src/hw/pci.c | 25 +++++++++++++++++++++++++
src/hw/pci.h | 1 +
src/hw/pcidevice.c | 24 ------------------------
src/hw/pcidevice.h | 1 -
src/hw/virtio-pci.c | 6 +++---
6 files changed, 31 insertions(+), 30 deletions(-)
diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c
index 08221e6..864954f 100644
--- a/src/fw/pciinit.c
+++ b/src/fw/pciinit.c
@@ -762,7 +762,7 @@ static int pci_bus_hotplug_support(struct pci_bus *bus, u8 pcie_cap)
return downstream_port && slot_implemented;
}
- shpc_cap = pci_find_capability(bus->bus_dev, PCI_CAP_ID_SHPC, 0);
+ shpc_cap = pci_find_capability(bus->bus_dev->bdf, PCI_CAP_ID_SHPC, 0);
return !!shpc_cap;
}
@@ -844,7 +844,7 @@ static int pci_bios_check_devices(struct pci_bus *busses)
*/
parent = &busses[0];
int type;
- u8 pcie_cap = pci_find_capability(s->bus_dev, PCI_CAP_ID_EXP, 0);
+ u8 pcie_cap = pci_find_capability(s->bus_dev->bdf, PCI_CAP_ID_EXP, 0);
int hotplug_support = pci_bus_hotplug_support(s, pcie_cap);
for (type = 0; type < PCI_REGION_TYPE_COUNT; type++) {
u64 align = (type == PCI_REGION_TYPE_IO) ?
diff --git a/src/hw/pci.c b/src/hw/pci.c
index 8e3d617..50d9d2d 100644
--- a/src/hw/pci.c
+++ b/src/hw/pci.c
@@ -58,6 +58,30 @@ pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on)
pci_config_writew(bdf, addr, val);
}
+u8 pci_find_capability(u16 bdf, u8 cap_id, u8 cap)
+{
+ int i;
+ u16 status = pci_config_readw(bdf, PCI_STATUS);
+
+ if (!(status & PCI_STATUS_CAP_LIST))
+ return 0;
+
+ if (cap == 0) {
+ /* find first */
+ cap = pci_config_readb(bdf, PCI_CAPABILITY_LIST);
+ } else {
+ /* find next */
+ cap = pci_config_readb(bdf, cap + PCI_CAP_LIST_NEXT);
+ }
+ for (i = 0; cap && i <= 0xff; i++) {
+ if (pci_config_readb(bdf, cap + PCI_CAP_LIST_ID) == cap_id)
+ return cap;
+ cap = pci_config_readb(bdf, cap + PCI_CAP_LIST_NEXT);
+ }
+
+ return 0;
+}
+
// Helper function for foreachbdf() macro - return next device
int
pci_next(int bdf, int bus)
@@ -107,3 +131,4 @@ pci_reboot(void)
outb(v|6, PORT_PCI_REBOOT); /* Actually do the reset */
udelay(50);
}
+
diff --git a/src/hw/pci.h b/src/hw/pci.h
index ee6e196..2e30e28 100644
--- a/src/hw/pci.h
+++ b/src/hw/pci.h
@@ -39,6 +39,7 @@ u32 pci_config_readl(u16 bdf, u32 addr);
u16 pci_config_readw(u16 bdf, u32 addr);
u8 pci_config_readb(u16 bdf, u32 addr);
void pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on);
+u8 pci_find_capability(u16 bdf, u8 cap_id, u8 cap);
int pci_next(int bdf, int bus);
int pci_probe_host(void);
void pci_reboot(void);
diff --git a/src/hw/pcidevice.c b/src/hw/pcidevice.c
index cfebf66..8853cf7 100644
--- a/src/hw/pcidevice.c
+++ b/src/hw/pcidevice.c
@@ -134,30 +134,6 @@ pci_find_init_device(const struct pci_device_id *ids, void *arg)
return NULL;
}
-u8 pci_find_capability(struct pci_device *pci, u8 cap_id, u8 cap)
-{
- int i;
- u16 status = pci_config_readw(pci->bdf, PCI_STATUS);
-
- if (!(status & PCI_STATUS_CAP_LIST))
- return 0;
-
- if (cap == 0) {
- /* find first */
- cap = pci_config_readb(pci->bdf, PCI_CAPABILITY_LIST);
- } else {
- /* find next */
- cap = pci_config_readb(pci->bdf, cap + PCI_CAP_LIST_NEXT);
- }
- for (i = 0; cap && i <= 0xff; i++) {
- if (pci_config_readb(pci->bdf, cap + PCI_CAP_LIST_ID) == cap_id)
- return cap;
- cap = pci_config_readb(pci->bdf, cap + PCI_CAP_LIST_NEXT);
- }
-
- return 0;
-}
-
// Enable PCI bus-mastering (ie, DMA) support on a pci device
void
pci_enable_busmaster(struct pci_device *pci)
diff --git a/src/hw/pcidevice.h b/src/hw/pcidevice.h
index 354b549..225d545 100644
--- a/src/hw/pcidevice.h
+++ b/src/hw/pcidevice.h
@@ -69,7 +69,6 @@ int pci_init_device(const struct pci_device_id *ids
, struct pci_device *pci, void *arg);
struct pci_device *pci_find_init_device(const struct pci_device_id *ids
, void *arg);
-u8 pci_find_capability(struct pci_device *pci, u8 cap_id, u8 cap);
void pci_enable_busmaster(struct pci_device *pci);
u16 pci_enable_iobar(struct pci_device *pci, u32 addr);
void *pci_enable_membar(struct pci_device *pci, u32 addr);
diff --git a/src/hw/virtio-pci.c b/src/hw/virtio-pci.c
index e5c2c33..96f9c6b 100644
--- a/src/hw/virtio-pci.c
+++ b/src/hw/virtio-pci.c
@@ -19,7 +19,7 @@
#include "malloc.h" // free
#include "output.h" // dprintf
#include "pci.h" // pci_config_readl
-#include "pcidevice.h" // pci_find_capability
+#include "pcidevice.h" // struct pci_device
#include "pci_regs.h" // PCI_BASE_ADDRESS_0
#include "string.h" // memset
#include "virtio-pci.h"
@@ -381,7 +381,7 @@ fail:
void vp_init_simple(struct vp_device *vp, struct pci_device *pci)
{
- u8 cap = pci_find_capability(pci, PCI_CAP_ID_VNDR, 0);
+ u8 cap = pci_find_capability(pci->bdf, PCI_CAP_ID_VNDR, 0);
struct vp_cap *vp_cap;
const char *mode;
u32 offset, base, mul;
@@ -479,7 +479,7 @@ void vp_init_simple(struct vp_device *vp, struct pci_device *pci)
vp_cap->cap, type, vp_cap->bar, addr, offset, mode);
}
- cap = pci_find_capability(pci, PCI_CAP_ID_VNDR, cap);
+ cap = pci_find_capability(pci->bdf, PCI_CAP_ID_VNDR, cap);
}
if (vp->common.cap && vp->notify.cap && vp->isr.cap && vp->device.cap) {
--
2.7.4
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [Qemu-devel] [PATCH v7 3/3] pci: enable RedHat PCI bridges to reserve additional resources on PCI init
2017-08-17 23:12 [Qemu-devel] [PATCH v7 0/3] Red Hat PCI bridge resource reserve capability Aleksandr Bezzubikov
2017-08-17 23:12 ` [Qemu-devel] [PATCH v7 1/3] pci: refactor pci_find_capapibilty to get bdf as the first argument instead of the whole pci_device Aleksandr Bezzubikov
2017-08-17 23:12 ` [Qemu-devel] [PATCH v7 2/3] pci: add QEMU-specific PCI capability structure Aleksandr Bezzubikov
@ 2017-08-17 23:12 ` Aleksandr Bezzubikov
2 siblings, 0 replies; 4+ messages in thread
From: Aleksandr Bezzubikov @ 2017-08-17 23:12 UTC (permalink / raw)
To: seabios
Cc: marcel, mst, kraxel, kevin, lersek, qemu-devel,
Aleksandr Bezzubikov
In case of Red Hat Generic PCIE Root Port reserve additional buses
and/or IO/MEM/PREF space, which values are provided in a vendor-specific capability.
Signed-off-by: Aleksandr Bezzubikov <zuban32s@gmail.com>
Reviewed-by: Marcel Apfelbaum <marcel@redhat.com>
---
src/fw/pciinit.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
src/hw/pci_ids.h | 3 ++
2 files changed, 105 insertions(+), 4 deletions(-)
diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c
index 864954f..22a12f8 100644
--- a/src/fw/pciinit.c
+++ b/src/fw/pciinit.c
@@ -15,6 +15,7 @@
#include "hw/pcidevice.h" // pci_probe_devices
#include "hw/pci_ids.h" // PCI_VENDOR_ID_INTEL
#include "hw/pci_regs.h" // PCI_COMMAND
+#include "fw/dev-pci.h" // REDHAT_CAP_RESOURCE_RESERVE
#include "list.h" // struct hlist_node
#include "malloc.h" // free
#include "output.h" // dprintf
@@ -522,6 +523,32 @@ static void pci_bios_init_platform(void)
}
}
+static u8 pci_find_resource_reserve_capability(u16 bdf)
+{
+ if (pci_config_readw(bdf, PCI_VENDOR_ID) == PCI_VENDOR_ID_REDHAT &&
+ pci_config_readw(bdf, PCI_DEVICE_ID) ==
+ PCI_DEVICE_ID_REDHAT_ROOT_PORT) {
+ u8 cap = 0;
+ do {
+ cap = pci_find_capability(bdf, PCI_CAP_ID_VNDR, cap);
+ } while (cap &&
+ pci_config_readb(bdf, cap + PCI_CAP_REDHAT_TYPE_OFFSET) !=
+ REDHAT_CAP_RESOURCE_RESERVE);
+ if (cap) {
+ u8 cap_len = pci_config_readb(bdf, cap + PCI_CAP_FLAGS);
+ if (cap_len < RES_RESERVE_CAP_SIZE) {
+ dprintf(1, "PCI: QEMU resource reserve cap length %d is invalid\n",
+ cap_len);
+ }
+ } else {
+ dprintf(1, "PCI: invalid QEMU resource reserve cap offset\n");
+ }
+ return cap;
+ } else {
+ dprintf(1, "PCI: QEMU resource reserve cap not found\n");
+ return 0;
+ }
+}
/****************************************************************
* Bus initialization
@@ -578,9 +605,33 @@ pci_bios_init_bus_rec(int bus, u8 *pci_bus)
pci_bios_init_bus_rec(secbus, pci_bus);
if (subbus != *pci_bus) {
+ u8 res_bus = 0;
+ u8 cap = pci_find_resource_reserve_capability(bdf);
+
+ if (cap) {
+ u32 tmp_res_bus = pci_config_readl(bdf,
+ cap + RES_RESERVE_BUS_RES);
+ if (tmp_res_bus != (u32)-1) {
+ res_bus = tmp_res_bus & 0xFF;
+ if ((u8)(res_bus + secbus) < secbus ||
+ (u8)(res_bus + secbus) < res_bus) {
+ dprintf(1, "PCI: bus_reserve value %d is invalid\n",
+ res_bus);
+ res_bus = 0;
+ }
+ }
+ if (secbus + res_bus > *pci_bus) {
+ dprintf(1, "PCI: QEMU resource reserve cap: bus = %u\n",
+ res_bus);
+ res_bus = secbus + res_bus;
+ } else {
+ res_bus = *pci_bus;
+ }
+ }
dprintf(1, "PCI: subordinate bus = 0x%x -> 0x%x\n",
- subbus, *pci_bus);
- subbus = *pci_bus;
+ subbus, res_bus);
+ subbus = res_bus;
+ *pci_bus = res_bus;
} else {
dprintf(1, "PCI: subordinate bus = 0x%x\n", subbus);
}
@@ -844,20 +895,67 @@ static int pci_bios_check_devices(struct pci_bus *busses)
*/
parent = &busses[0];
int type;
- u8 pcie_cap = pci_find_capability(s->bus_dev->bdf, PCI_CAP_ID_EXP, 0);
+ u16 bdf = s->bus_dev->bdf;
+ u8 pcie_cap = pci_find_capability(bdf, PCI_CAP_ID_EXP, 0);
+ u8 qemu_cap = pci_find_resource_reserve_capability(bdf);
+
int hotplug_support = pci_bus_hotplug_support(s, pcie_cap);
for (type = 0; type < PCI_REGION_TYPE_COUNT; type++) {
u64 align = (type == PCI_REGION_TYPE_IO) ?
PCI_BRIDGE_IO_MIN : PCI_BRIDGE_MEM_MIN;
if (!pci_bridge_has_region(s->bus_dev, type))
continue;
+ u64 size = 0;
+ if (qemu_cap) {
+ u32 tmp_size;
+ u64 tmp_size_64;
+ switch(type) {
+ case PCI_REGION_TYPE_IO:
+ tmp_size_64 = (pci_config_readl(bdf, qemu_cap + RES_RESERVE_IO) |
+ (u64)pci_config_readl(bdf, qemu_cap + RES_RESERVE_IO + 4) << 32);
+ if (tmp_size_64 != (u64)-1) {
+ size = tmp_size_64;
+ }
+ break;
+ case PCI_REGION_TYPE_MEM:
+ tmp_size = pci_config_readl(bdf, qemu_cap + RES_RESERVE_MEM);
+ if (tmp_size != (u32)-1) {
+ size = tmp_size;
+ }
+ break;
+ case PCI_REGION_TYPE_PREFMEM:
+ tmp_size = pci_config_readl(bdf, qemu_cap + RES_RESERVE_PREF_MEM_32);
+ tmp_size_64 = (pci_config_readl(bdf, qemu_cap + RES_RESERVE_PREF_MEM_64) |
+ (u64)pci_config_readl(bdf, qemu_cap + RES_RESERVE_PREF_MEM_64 + 4) << 32);
+ if (tmp_size != (u32)-1 && tmp_size_64 == (u64)-1) {
+ size = tmp_size;
+ } else if (tmp_size == (u32)-1 && tmp_size_64 != (u64)-1) {
+ size = tmp_size_64;
+ } else if (tmp_size != (u32)-1 && tmp_size_64 != (u64)-1) {
+ dprintf(1, "PCI: resource reserve cap PREF32 and PREF64"
+ " conflict\n");
+ }
+ break;
+ default:
+ break;
+ }
+ }
if (pci_region_align(&s->r[type]) > align)
align = pci_region_align(&s->r[type]);
u64 sum = pci_region_sum(&s->r[type]);
int resource_optional = pcie_cap && (type == PCI_REGION_TYPE_IO);
if (!sum && hotplug_support && !resource_optional)
sum = align; /* reserve min size for hot-plug */
- u64 size = ALIGN(sum, align);
+ if (size > sum) {
+ dprintf(1, "PCI: QEMU resource reserve cap: "
+ "size %08llx type %s\n",
+ size, region_type_name[type]);
+ if (type != PCI_REGION_TYPE_IO) {
+ size = ALIGN(size, align);
+ }
+ } else {
+ size = ALIGN(sum, align);
+ }
int is64 = pci_bios_bridge_region_is64(&s->r[type],
s->bus_dev, type);
// entry->bar is -1 if the entry represents a bridge region
diff --git a/src/hw/pci_ids.h b/src/hw/pci_ids.h
index 4ac73b4..38fa2ca 100644
--- a/src/hw/pci_ids.h
+++ b/src/hw/pci_ids.h
@@ -2263,6 +2263,9 @@
#define PCI_DEVICE_ID_KORENIX_JETCARDF0 0x1600
#define PCI_DEVICE_ID_KORENIX_JETCARDF1 0x16ff
+#define PCI_VENDOR_ID_REDHAT 0x1b36
+#define PCI_DEVICE_ID_REDHAT_ROOT_PORT 0x000C
+
#define PCI_VENDOR_ID_TEKRAM 0x1de1
#define PCI_DEVICE_ID_TEKRAM_DC290 0xdc29
--
2.7.4
^ permalink raw reply related [flat|nested] 4+ messages in thread