xref: /openbmc/qemu/hw/pci/pci-qmp-cmds.c (revision 33698d3abf8ce65c38bb4b12b600b130d2682c79)
1*987b73b3SMarkus Armbruster /*
2*987b73b3SMarkus Armbruster  * QMP commands related to PCI
3*987b73b3SMarkus Armbruster  *
4*987b73b3SMarkus Armbruster  * Copyright (c) 2004 Fabrice Bellard
5*987b73b3SMarkus Armbruster  *
6*987b73b3SMarkus Armbruster  * Permission is hereby granted, free of charge, to any person obtaining a copy
7*987b73b3SMarkus Armbruster  * of this software and associated documentation files (the "Software"), to deal
8*987b73b3SMarkus Armbruster  * in the Software without restriction, including without limitation the rights
9*987b73b3SMarkus Armbruster  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10*987b73b3SMarkus Armbruster  * copies of the Software, and to permit persons to whom the Software is
11*987b73b3SMarkus Armbruster  * furnished to do so, subject to the following conditions:
12*987b73b3SMarkus Armbruster  *
13*987b73b3SMarkus Armbruster  * The above copyright notice and this permission notice shall be included in
14*987b73b3SMarkus Armbruster  * all copies or substantial portions of the Software.
15*987b73b3SMarkus Armbruster  *
16*987b73b3SMarkus Armbruster  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*987b73b3SMarkus Armbruster  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*987b73b3SMarkus Armbruster  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19*987b73b3SMarkus Armbruster  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*987b73b3SMarkus Armbruster  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21*987b73b3SMarkus Armbruster  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22*987b73b3SMarkus Armbruster  * THE SOFTWARE.
23*987b73b3SMarkus Armbruster  */
24*987b73b3SMarkus Armbruster 
25*987b73b3SMarkus Armbruster #include "qemu/osdep.h"
26*987b73b3SMarkus Armbruster #include "hw/pci/pci.h"
27*987b73b3SMarkus Armbruster #include "hw/pci/pci_bridge.h"
28*987b73b3SMarkus Armbruster #include "pci-internal.h"
29*987b73b3SMarkus Armbruster #include "qapi/qapi-commands-pci.h"
30*987b73b3SMarkus Armbruster 
31*987b73b3SMarkus Armbruster static PciDeviceInfoList *qmp_query_pci_devices(PCIBus *bus, int bus_num);
32*987b73b3SMarkus Armbruster 
qmp_query_pci_regions(const PCIDevice * dev)33*987b73b3SMarkus Armbruster static PciMemoryRegionList *qmp_query_pci_regions(const PCIDevice *dev)
34*987b73b3SMarkus Armbruster {
35*987b73b3SMarkus Armbruster     PciMemoryRegionList *head = NULL, **tail = &head;
36*987b73b3SMarkus Armbruster     int i;
37*987b73b3SMarkus Armbruster 
38*987b73b3SMarkus Armbruster     for (i = 0; i < PCI_NUM_REGIONS; i++) {
39*987b73b3SMarkus Armbruster         const PCIIORegion *r = &dev->io_regions[i];
40*987b73b3SMarkus Armbruster         PciMemoryRegion *region;
41*987b73b3SMarkus Armbruster 
42*987b73b3SMarkus Armbruster         if (!r->size) {
43*987b73b3SMarkus Armbruster             continue;
44*987b73b3SMarkus Armbruster         }
45*987b73b3SMarkus Armbruster 
46*987b73b3SMarkus Armbruster         region = g_malloc0(sizeof(*region));
47*987b73b3SMarkus Armbruster 
48*987b73b3SMarkus Armbruster         if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
49*987b73b3SMarkus Armbruster             region->type = g_strdup("io");
50*987b73b3SMarkus Armbruster         } else {
51*987b73b3SMarkus Armbruster             region->type = g_strdup("memory");
52*987b73b3SMarkus Armbruster             region->has_prefetch = true;
53*987b73b3SMarkus Armbruster             region->prefetch = !!(r->type & PCI_BASE_ADDRESS_MEM_PREFETCH);
54*987b73b3SMarkus Armbruster             region->has_mem_type_64 = true;
55*987b73b3SMarkus Armbruster             region->mem_type_64 = !!(r->type & PCI_BASE_ADDRESS_MEM_TYPE_64);
56*987b73b3SMarkus Armbruster         }
57*987b73b3SMarkus Armbruster 
58*987b73b3SMarkus Armbruster         region->bar = i;
59*987b73b3SMarkus Armbruster         region->address = r->addr;
60*987b73b3SMarkus Armbruster         region->size = r->size;
61*987b73b3SMarkus Armbruster 
62*987b73b3SMarkus Armbruster         QAPI_LIST_APPEND(tail, region);
63*987b73b3SMarkus Armbruster     }
64*987b73b3SMarkus Armbruster 
65*987b73b3SMarkus Armbruster     return head;
66*987b73b3SMarkus Armbruster }
67*987b73b3SMarkus Armbruster 
qmp_query_pci_bridge(PCIDevice * dev,PCIBus * bus,int bus_num)68*987b73b3SMarkus Armbruster static PciBridgeInfo *qmp_query_pci_bridge(PCIDevice *dev, PCIBus *bus,
69*987b73b3SMarkus Armbruster                                            int bus_num)
70*987b73b3SMarkus Armbruster {
71*987b73b3SMarkus Armbruster     PciBridgeInfo *info;
72*987b73b3SMarkus Armbruster     PciMemoryRange *range;
73*987b73b3SMarkus Armbruster 
74*987b73b3SMarkus Armbruster     info = g_new0(PciBridgeInfo, 1);
75*987b73b3SMarkus Armbruster 
76*987b73b3SMarkus Armbruster     info->bus = g_new0(PciBusInfo, 1);
77*987b73b3SMarkus Armbruster     info->bus->number = dev->config[PCI_PRIMARY_BUS];
78*987b73b3SMarkus Armbruster     info->bus->secondary = dev->config[PCI_SECONDARY_BUS];
79*987b73b3SMarkus Armbruster     info->bus->subordinate = dev->config[PCI_SUBORDINATE_BUS];
80*987b73b3SMarkus Armbruster 
81*987b73b3SMarkus Armbruster     range = info->bus->io_range = g_new0(PciMemoryRange, 1);
82*987b73b3SMarkus Armbruster     range->base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_IO);
83*987b73b3SMarkus Armbruster     range->limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_IO);
84*987b73b3SMarkus Armbruster 
85*987b73b3SMarkus Armbruster     range = info->bus->memory_range = g_new0(PciMemoryRange, 1);
86*987b73b3SMarkus Armbruster     range->base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_MEMORY);
87*987b73b3SMarkus Armbruster     range->limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_MEMORY);
88*987b73b3SMarkus Armbruster 
89*987b73b3SMarkus Armbruster     range = info->bus->prefetchable_range = g_new0(PciMemoryRange, 1);
90*987b73b3SMarkus Armbruster     range->base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_MEM_PREFETCH);
91*987b73b3SMarkus Armbruster     range->limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_MEM_PREFETCH);
92*987b73b3SMarkus Armbruster 
93*987b73b3SMarkus Armbruster     if (dev->config[PCI_SECONDARY_BUS] != 0) {
94*987b73b3SMarkus Armbruster         PCIBus *child_bus = pci_find_bus_nr(bus,
95*987b73b3SMarkus Armbruster                                             dev->config[PCI_SECONDARY_BUS]);
96*987b73b3SMarkus Armbruster         if (child_bus) {
97*987b73b3SMarkus Armbruster             info->has_devices = true;
98*987b73b3SMarkus Armbruster             info->devices = qmp_query_pci_devices(child_bus,
99*987b73b3SMarkus Armbruster                                             dev->config[PCI_SECONDARY_BUS]);
100*987b73b3SMarkus Armbruster         }
101*987b73b3SMarkus Armbruster     }
102*987b73b3SMarkus Armbruster 
103*987b73b3SMarkus Armbruster     return info;
104*987b73b3SMarkus Armbruster }
105*987b73b3SMarkus Armbruster 
qmp_query_pci_device(PCIDevice * dev,PCIBus * bus,int bus_num)106*987b73b3SMarkus Armbruster static PciDeviceInfo *qmp_query_pci_device(PCIDevice *dev, PCIBus *bus,
107*987b73b3SMarkus Armbruster                                            int bus_num)
108*987b73b3SMarkus Armbruster {
109*987b73b3SMarkus Armbruster     const pci_class_desc *desc;
110*987b73b3SMarkus Armbruster     PciDeviceInfo *info;
111*987b73b3SMarkus Armbruster     uint8_t type;
112*987b73b3SMarkus Armbruster     int class;
113*987b73b3SMarkus Armbruster 
114*987b73b3SMarkus Armbruster     info = g_new0(PciDeviceInfo, 1);
115*987b73b3SMarkus Armbruster     info->bus = bus_num;
116*987b73b3SMarkus Armbruster     info->slot = PCI_SLOT(dev->devfn);
117*987b73b3SMarkus Armbruster     info->function = PCI_FUNC(dev->devfn);
118*987b73b3SMarkus Armbruster 
119*987b73b3SMarkus Armbruster     info->class_info = g_new0(PciDeviceClass, 1);
120*987b73b3SMarkus Armbruster     class = pci_get_word(dev->config + PCI_CLASS_DEVICE);
121*987b73b3SMarkus Armbruster     info->class_info->q_class = class;
122*987b73b3SMarkus Armbruster     desc = get_class_desc(class);
123*987b73b3SMarkus Armbruster     if (desc->desc) {
124*987b73b3SMarkus Armbruster         info->class_info->desc = g_strdup(desc->desc);
125*987b73b3SMarkus Armbruster     }
126*987b73b3SMarkus Armbruster 
127*987b73b3SMarkus Armbruster     info->id = g_new0(PciDeviceId, 1);
128*987b73b3SMarkus Armbruster     info->id->vendor = pci_get_word(dev->config + PCI_VENDOR_ID);
129*987b73b3SMarkus Armbruster     info->id->device = pci_get_word(dev->config + PCI_DEVICE_ID);
130*987b73b3SMarkus Armbruster     info->regions = qmp_query_pci_regions(dev);
131*987b73b3SMarkus Armbruster     info->qdev_id = g_strdup(dev->qdev.id ? dev->qdev.id : "");
132*987b73b3SMarkus Armbruster 
133*987b73b3SMarkus Armbruster     info->irq_pin = dev->config[PCI_INTERRUPT_PIN];
134*987b73b3SMarkus Armbruster     if (dev->config[PCI_INTERRUPT_PIN] != 0) {
135*987b73b3SMarkus Armbruster         info->has_irq = true;
136*987b73b3SMarkus Armbruster         info->irq = dev->config[PCI_INTERRUPT_LINE];
137*987b73b3SMarkus Armbruster     }
138*987b73b3SMarkus Armbruster 
139*987b73b3SMarkus Armbruster     type = dev->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION;
140*987b73b3SMarkus Armbruster     if (type == PCI_HEADER_TYPE_BRIDGE) {
141*987b73b3SMarkus Armbruster         info->pci_bridge = qmp_query_pci_bridge(dev, bus, bus_num);
142*987b73b3SMarkus Armbruster     } else if (type == PCI_HEADER_TYPE_NORMAL) {
143*987b73b3SMarkus Armbruster         info->id->has_subsystem = info->id->has_subsystem_vendor = true;
144*987b73b3SMarkus Armbruster         info->id->subsystem = pci_get_word(dev->config + PCI_SUBSYSTEM_ID);
145*987b73b3SMarkus Armbruster         info->id->subsystem_vendor =
146*987b73b3SMarkus Armbruster             pci_get_word(dev->config + PCI_SUBSYSTEM_VENDOR_ID);
147*987b73b3SMarkus Armbruster     } else if (type == PCI_HEADER_TYPE_CARDBUS) {
148*987b73b3SMarkus Armbruster         info->id->has_subsystem = info->id->has_subsystem_vendor = true;
149*987b73b3SMarkus Armbruster         info->id->subsystem = pci_get_word(dev->config + PCI_CB_SUBSYSTEM_ID);
150*987b73b3SMarkus Armbruster         info->id->subsystem_vendor =
151*987b73b3SMarkus Armbruster             pci_get_word(dev->config + PCI_CB_SUBSYSTEM_VENDOR_ID);
152*987b73b3SMarkus Armbruster     }
153*987b73b3SMarkus Armbruster 
154*987b73b3SMarkus Armbruster     return info;
155*987b73b3SMarkus Armbruster }
156*987b73b3SMarkus Armbruster 
qmp_query_pci_devices(PCIBus * bus,int bus_num)157*987b73b3SMarkus Armbruster static PciDeviceInfoList *qmp_query_pci_devices(PCIBus *bus, int bus_num)
158*987b73b3SMarkus Armbruster {
159*987b73b3SMarkus Armbruster     PciDeviceInfoList *head = NULL, **tail = &head;
160*987b73b3SMarkus Armbruster     PCIDevice *dev;
161*987b73b3SMarkus Armbruster     int devfn;
162*987b73b3SMarkus Armbruster 
163*987b73b3SMarkus Armbruster     for (devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) {
164*987b73b3SMarkus Armbruster         dev = bus->devices[devfn];
165*987b73b3SMarkus Armbruster         if (dev) {
166*987b73b3SMarkus Armbruster             QAPI_LIST_APPEND(tail, qmp_query_pci_device(dev, bus, bus_num));
167*987b73b3SMarkus Armbruster         }
168*987b73b3SMarkus Armbruster     }
169*987b73b3SMarkus Armbruster 
170*987b73b3SMarkus Armbruster     return head;
171*987b73b3SMarkus Armbruster }
172*987b73b3SMarkus Armbruster 
qmp_query_pci_bus(PCIBus * bus,int bus_num)173*987b73b3SMarkus Armbruster static PciInfo *qmp_query_pci_bus(PCIBus *bus, int bus_num)
174*987b73b3SMarkus Armbruster {
175*987b73b3SMarkus Armbruster     PciInfo *info = NULL;
176*987b73b3SMarkus Armbruster 
177*987b73b3SMarkus Armbruster     bus = pci_find_bus_nr(bus, bus_num);
178*987b73b3SMarkus Armbruster     if (bus) {
179*987b73b3SMarkus Armbruster         info = g_malloc0(sizeof(*info));
180*987b73b3SMarkus Armbruster         info->bus = bus_num;
181*987b73b3SMarkus Armbruster         info->devices = qmp_query_pci_devices(bus, bus_num);
182*987b73b3SMarkus Armbruster     }
183*987b73b3SMarkus Armbruster 
184*987b73b3SMarkus Armbruster     return info;
185*987b73b3SMarkus Armbruster }
186*987b73b3SMarkus Armbruster 
qmp_query_pci(Error ** errp)187*987b73b3SMarkus Armbruster PciInfoList *qmp_query_pci(Error **errp)
188*987b73b3SMarkus Armbruster {
189*987b73b3SMarkus Armbruster     PciInfoList *head = NULL, **tail = &head;
190*987b73b3SMarkus Armbruster     PCIHostState *host_bridge;
191*987b73b3SMarkus Armbruster 
192*987b73b3SMarkus Armbruster     QLIST_FOREACH(host_bridge, &pci_host_bridges, next) {
193*987b73b3SMarkus Armbruster         QAPI_LIST_APPEND(tail,
194*987b73b3SMarkus Armbruster                          qmp_query_pci_bus(host_bridge->bus,
195*987b73b3SMarkus Armbruster                                            pci_bus_num(host_bridge->bus)));
196*987b73b3SMarkus Armbruster     }
197*987b73b3SMarkus Armbruster 
198*987b73b3SMarkus Armbruster     return head;
199*987b73b3SMarkus Armbruster }
200