mirror of
https://github.com/qemu/qemu.git
synced 2024-11-29 23:03:41 +08:00
hw/pci: introduce bridge-only vendor-specific capability to provide some hints to firmware
On PCI init PCI bridges may need some extra info about bus number, IO, memory and prefetchable memory to reserve. QEMU can provide this with a special vendor-specific PCI capability. Signed-off-by: Aleksandr Bezzubikov <zuban32s@gmail.com> Reviewed-by: Marcel Apfelbaum <marcel@redhat.com> Tested-by: Marcel Apfelbaum <marcel@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
a35fe22655
commit
70e1ee59bb
@ -408,6 +408,52 @@ void pci_bridge_map_irq(PCIBridge *br, const char* bus_name,
|
||||
br->bus_name = bus_name;
|
||||
}
|
||||
|
||||
|
||||
int pci_bridge_qemu_reserve_cap_init(PCIDevice *dev, int cap_offset,
|
||||
uint32_t bus_reserve, uint64_t io_reserve,
|
||||
uint32_t mem_non_pref_reserve,
|
||||
uint32_t mem_pref_32_reserve,
|
||||
uint64_t mem_pref_64_reserve,
|
||||
Error **errp)
|
||||
{
|
||||
if (mem_pref_32_reserve != (uint32_t)-1 &&
|
||||
mem_pref_64_reserve != (uint64_t)-1) {
|
||||
error_setg(errp,
|
||||
"PCI resource reserve cap: PREF32 and PREF64 conflict");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (bus_reserve == (uint32_t)-1 &&
|
||||
io_reserve == (uint64_t)-1 &&
|
||||
mem_non_pref_reserve == (uint32_t)-1 &&
|
||||
mem_pref_32_reserve == (uint32_t)-1 &&
|
||||
mem_pref_64_reserve == (uint64_t)-1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t cap_len = sizeof(PCIBridgeQemuCap);
|
||||
PCIBridgeQemuCap cap = {
|
||||
.len = cap_len,
|
||||
.type = REDHAT_PCI_CAP_RESOURCE_RESERVE,
|
||||
.bus_res = bus_reserve,
|
||||
.io = io_reserve,
|
||||
.mem = mem_non_pref_reserve,
|
||||
.mem_pref_32 = mem_pref_32_reserve,
|
||||
.mem_pref_64 = mem_pref_64_reserve
|
||||
};
|
||||
|
||||
int offset = pci_add_capability(dev, PCI_CAP_ID_VNDR,
|
||||
cap_offset, cap_len, errp);
|
||||
if (offset < 0) {
|
||||
return offset;
|
||||
}
|
||||
|
||||
memcpy(dev->config + offset + PCI_CAP_FLAGS,
|
||||
(char *)&cap + PCI_CAP_FLAGS,
|
||||
cap_len - PCI_CAP_FLAGS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const TypeInfo pci_bridge_type_info = {
|
||||
.name = TYPE_PCI_BRIDGE,
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
|
@ -67,4 +67,29 @@ void pci_bridge_map_irq(PCIBridge *br, const char* bus_name,
|
||||
#define PCI_BRIDGE_CTL_DISCARD_STATUS 0x400 /* Discard timer status */
|
||||
#define PCI_BRIDGE_CTL_DISCARD_SERR 0x800 /* Discard timer SERR# enable */
|
||||
|
||||
typedef struct PCIBridgeQemuCap {
|
||||
uint8_t id; /* Standard PCI capability header field */
|
||||
uint8_t next; /* Standard PCI capability header field */
|
||||
uint8_t len; /* Standard PCI vendor-specific capability header field */
|
||||
uint8_t type; /* Red Hat vendor-specific capability type.
|
||||
Types are defined with REDHAT_PCI_CAP_ prefix */
|
||||
|
||||
uint32_t bus_res; /* Minimum number of buses to reserve */
|
||||
uint64_t io; /* IO space to reserve */
|
||||
uint32_t mem; /* Non-prefetchable memory to reserve */
|
||||
/* At most one of the following two fields may be set to a value
|
||||
* different from -1 */
|
||||
uint32_t mem_pref_32; /* Prefetchable memory to reserve (32-bit MMIO) */
|
||||
uint64_t mem_pref_64; /* Prefetchable memory to reserve (64-bit MMIO) */
|
||||
} PCIBridgeQemuCap;
|
||||
|
||||
#define REDHAT_PCI_CAP_RESOURCE_RESERVE 1
|
||||
|
||||
int pci_bridge_qemu_reserve_cap_init(PCIDevice *dev, int cap_offset,
|
||||
uint32_t bus_reserve, uint64_t io_reserve,
|
||||
uint32_t mem_non_pref_reserve,
|
||||
uint32_t mem_pref_32_reserve,
|
||||
uint64_t mem_pref_64_reserve,
|
||||
Error **errp);
|
||||
|
||||
#endif /* QEMU_PCI_BRIDGE_H */
|
||||
|
Loading…
Reference in New Issue
Block a user