2 * HMP commands related to PCI
4 * Copyright IBM, Corp. 2011
7 * Anthony Liguori <aliguori@us.ibm.com>
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
12 * Contributions after 2012-01-13 are licensed under the terms of the
13 * GNU GPL, version 2 or (at your option) any later version.
16 #include "qemu/osdep.h"
17 #include "hw/pci/pci.h"
18 #include "hw/pci/pci_device.h"
19 #include "monitor/hmp.h"
20 #include "monitor/monitor.h"
21 #include "pci-internal.h"
22 #include "qapi/error.h"
23 #include "qapi/qmp/qdict.h"
24 #include "qapi/qapi-commands-pci.h"
25 #include "qemu/cutils.h"
27 static void hmp_info_pci_device(Monitor
*mon
, const PciDeviceInfo
*dev
)
29 PciMemoryRegionList
*region
;
31 monitor_printf(mon
, " Bus %2" PRId64
", ", dev
->bus
);
32 monitor_printf(mon
, "device %3" PRId64
", function %" PRId64
":\n",
33 dev
->slot
, dev
->function
);
34 monitor_printf(mon
, " ");
36 if (dev
->class_info
->desc
) {
37 monitor_puts(mon
, dev
->class_info
->desc
);
39 monitor_printf(mon
, "Class %04" PRId64
, dev
->class_info
->q_class
);
42 monitor_printf(mon
, ": PCI device %04" PRIx64
":%04" PRIx64
"\n",
43 dev
->id
->vendor
, dev
->id
->device
);
44 if (dev
->id
->has_subsystem_vendor
&& dev
->id
->has_subsystem
) {
45 monitor_printf(mon
, " PCI subsystem %04" PRIx64
":%04" PRIx64
"\n",
46 dev
->id
->subsystem_vendor
, dev
->id
->subsystem
);
50 monitor_printf(mon
, " IRQ %" PRId64
", pin %c\n",
51 dev
->irq
, (char)('A' + dev
->irq_pin
- 1));
54 if (dev
->pci_bridge
) {
55 monitor_printf(mon
, " BUS %" PRId64
".\n",
56 dev
->pci_bridge
->bus
->number
);
57 monitor_printf(mon
, " secondary bus %" PRId64
".\n",
58 dev
->pci_bridge
->bus
->secondary
);
59 monitor_printf(mon
, " subordinate bus %" PRId64
".\n",
60 dev
->pci_bridge
->bus
->subordinate
);
62 monitor_printf(mon
, " IO range [0x%04"PRIx64
", 0x%04"PRIx64
"]\n",
63 dev
->pci_bridge
->bus
->io_range
->base
,
64 dev
->pci_bridge
->bus
->io_range
->limit
);
67 " memory range [0x%08"PRIx64
", 0x%08"PRIx64
"]\n",
68 dev
->pci_bridge
->bus
->memory_range
->base
,
69 dev
->pci_bridge
->bus
->memory_range
->limit
);
71 monitor_printf(mon
, " prefetchable memory range "
72 "[0x%08"PRIx64
", 0x%08"PRIx64
"]\n",
73 dev
->pci_bridge
->bus
->prefetchable_range
->base
,
74 dev
->pci_bridge
->bus
->prefetchable_range
->limit
);
77 for (region
= dev
->regions
; region
; region
= region
->next
) {
80 addr
= region
->value
->address
;
81 size
= region
->value
->size
;
83 monitor_printf(mon
, " BAR%" PRId64
": ", region
->value
->bar
);
85 if (!strcmp(region
->value
->type
, "io")) {
86 monitor_printf(mon
, "I/O at 0x%04" PRIx64
87 " [0x%04" PRIx64
"].\n",
88 addr
, addr
+ size
- 1);
90 monitor_printf(mon
, "%d bit%s memory at 0x%08" PRIx64
91 " [0x%08" PRIx64
"].\n",
92 region
->value
->mem_type_64
? 64 : 32,
93 region
->value
->prefetch
? " prefetchable" : "",
94 addr
, addr
+ size
- 1);
98 monitor_printf(mon
, " id \"%s\"\n", dev
->qdev_id
);
100 if (dev
->pci_bridge
) {
101 if (dev
->pci_bridge
->has_devices
) {
102 PciDeviceInfoList
*cdev
;
103 for (cdev
= dev
->pci_bridge
->devices
; cdev
; cdev
= cdev
->next
) {
104 hmp_info_pci_device(mon
, cdev
->value
);
110 void hmp_info_pci(Monitor
*mon
, const QDict
*qdict
)
112 PciInfoList
*info_list
, *info
;
114 info_list
= qmp_query_pci(&error_abort
);
116 for (info
= info_list
; info
; info
= info
->next
) {
117 PciDeviceInfoList
*dev
;
119 for (dev
= info
->value
->devices
; dev
; dev
= dev
->next
) {
120 hmp_info_pci_device(mon
, dev
->value
);
124 qapi_free_PciInfoList(info_list
);
127 void pcibus_dev_print(Monitor
*mon
, DeviceState
*dev
, int indent
)
129 PCIDevice
*d
= (PCIDevice
*)dev
;
130 int class = pci_get_word(d
->config
+ PCI_CLASS_DEVICE
);
131 const pci_class_desc
*desc
= get_class_desc(class);
137 snprintf(ctxt
, sizeof(ctxt
), "%s", desc
->desc
);
139 snprintf(ctxt
, sizeof(ctxt
), "Class %04x", class);
142 monitor_printf(mon
, "%*sclass %s, addr %02x:%02x.%x, "
143 "pci id %04x:%04x (sub %04x:%04x)\n",
144 indent
, "", ctxt
, pci_dev_bus_num(d
),
145 PCI_SLOT(d
->devfn
), PCI_FUNC(d
->devfn
),
146 pci_get_word(d
->config
+ PCI_VENDOR_ID
),
147 pci_get_word(d
->config
+ PCI_DEVICE_ID
),
148 pci_get_word(d
->config
+ PCI_SUBSYSTEM_VENDOR_ID
),
149 pci_get_word(d
->config
+ PCI_SUBSYSTEM_ID
));
150 for (i
= 0; i
< PCI_NUM_REGIONS
; i
++) {
151 r
= &d
->io_regions
[i
];
155 monitor_printf(mon
, "%*sbar %d: %s at 0x%"FMT_PCIBUS
156 " [0x%"FMT_PCIBUS
"]\n",
158 i
, r
->type
& PCI_BASE_ADDRESS_SPACE_IO
? "i/o" : "mem",
159 r
->addr
, r
->addr
+ r
->size
- 1);
163 void hmp_pcie_aer_inject_error(Monitor
*mon
, const QDict
*qdict
)
166 const char *id
= qdict_get_str(qdict
, "id");
167 const char *error_name
;
168 uint32_t error_status
;
175 ret
= pci_qdev_find_device(id
, &dev
);
176 if (ret
== -ENODEV
) {
177 error_setg(&err
, "device '%s' not found", id
);
180 if (ret
< 0 || !pci_is_express(dev
)) {
181 error_setg(&err
, "device '%s' is not a PCIe device", id
);
185 error_name
= qdict_get_str(qdict
, "error_status");
186 if (pcie_aer_parse_error_string(error_name
, &error_status
, &correctable
)) {
187 if (qemu_strtoui(error_name
, NULL
, 0, &num
) < 0) {
188 error_setg(&err
, "invalid error status value '%s'", error_name
);
192 correctable
= qdict_get_try_bool(qdict
, "correctable", false);
194 if (qdict_haskey(qdict
, "correctable")) {
195 error_setg(&err
, "-c is only valid with numeric error status");
199 aer_err
.status
= error_status
;
200 aer_err
.source_id
= pci_requester_id(dev
);
204 aer_err
.flags
|= PCIE_AER_ERR_IS_CORRECTABLE
;
206 if (qdict_get_try_bool(qdict
, "advisory_non_fatal", false)) {
207 aer_err
.flags
|= PCIE_AER_ERR_MAYBE_ADVISORY
;
209 if (qdict_haskey(qdict
, "header0")) {
210 aer_err
.flags
|= PCIE_AER_ERR_HEADER_VALID
;
212 if (qdict_haskey(qdict
, "prefix0")) {
213 aer_err
.flags
|= PCIE_AER_ERR_TLP_PREFIX_PRESENT
;
216 aer_err
.header
[0] = qdict_get_try_int(qdict
, "header0", 0);
217 aer_err
.header
[1] = qdict_get_try_int(qdict
, "header1", 0);
218 aer_err
.header
[2] = qdict_get_try_int(qdict
, "header2", 0);
219 aer_err
.header
[3] = qdict_get_try_int(qdict
, "header3", 0);
221 aer_err
.prefix
[0] = qdict_get_try_int(qdict
, "prefix0", 0);
222 aer_err
.prefix
[1] = qdict_get_try_int(qdict
, "prefix1", 0);
223 aer_err
.prefix
[2] = qdict_get_try_int(qdict
, "prefix2", 0);
224 aer_err
.prefix
[3] = qdict_get_try_int(qdict
, "prefix3", 0);
226 ret
= pcie_aer_inject_error(dev
, &aer_err
);
228 error_setg_errno(&err
, -ret
, "failed to inject error");
233 monitor_printf(mon
, "OK id: %s root bus: %s, bus: %x devfn: %x.%x\n",
234 id
, pci_root_bus_path(dev
), pci_dev_bus_num(dev
),
235 PCI_SLOT(dev
->devfn
), PCI_FUNC(dev
->devfn
));
238 hmp_handle_error(mon
, err
);