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 "monitor/hmp.h"
19 #include "monitor/monitor.h"
20 #include "pci-internal.h"
21 #include "qapi/error.h"
22 #include "qapi/qmp/qdict.h"
23 #include "qapi/qapi-commands-pci.h"
24 #include "qemu/cutils.h"
26 static void hmp_info_pci_device(Monitor
*mon
, const PciDeviceInfo
*dev
)
28 PciMemoryRegionList
*region
;
30 monitor_printf(mon
, " Bus %2" PRId64
", ", dev
->bus
);
31 monitor_printf(mon
, "device %3" PRId64
", function %" PRId64
":\n",
32 dev
->slot
, dev
->function
);
33 monitor_printf(mon
, " ");
35 if (dev
->class_info
->desc
) {
36 monitor_puts(mon
, dev
->class_info
->desc
);
38 monitor_printf(mon
, "Class %04" PRId64
, dev
->class_info
->q_class
);
41 monitor_printf(mon
, ": PCI device %04" PRIx64
":%04" PRIx64
"\n",
42 dev
->id
->vendor
, dev
->id
->device
);
43 if (dev
->id
->has_subsystem_vendor
&& dev
->id
->has_subsystem
) {
44 monitor_printf(mon
, " PCI subsystem %04" PRIx64
":%04" PRIx64
"\n",
45 dev
->id
->subsystem_vendor
, dev
->id
->subsystem
);
49 monitor_printf(mon
, " IRQ %" PRId64
", pin %c\n",
50 dev
->irq
, (char)('A' + dev
->irq_pin
- 1));
53 if (dev
->pci_bridge
) {
54 monitor_printf(mon
, " BUS %" PRId64
".\n",
55 dev
->pci_bridge
->bus
->number
);
56 monitor_printf(mon
, " secondary bus %" PRId64
".\n",
57 dev
->pci_bridge
->bus
->secondary
);
58 monitor_printf(mon
, " subordinate bus %" PRId64
".\n",
59 dev
->pci_bridge
->bus
->subordinate
);
61 monitor_printf(mon
, " IO range [0x%04"PRIx64
", 0x%04"PRIx64
"]\n",
62 dev
->pci_bridge
->bus
->io_range
->base
,
63 dev
->pci_bridge
->bus
->io_range
->limit
);
66 " memory range [0x%08"PRIx64
", 0x%08"PRIx64
"]\n",
67 dev
->pci_bridge
->bus
->memory_range
->base
,
68 dev
->pci_bridge
->bus
->memory_range
->limit
);
70 monitor_printf(mon
, " prefetchable memory range "
71 "[0x%08"PRIx64
", 0x%08"PRIx64
"]\n",
72 dev
->pci_bridge
->bus
->prefetchable_range
->base
,
73 dev
->pci_bridge
->bus
->prefetchable_range
->limit
);
76 for (region
= dev
->regions
; region
; region
= region
->next
) {
79 addr
= region
->value
->address
;
80 size
= region
->value
->size
;
82 monitor_printf(mon
, " BAR%" PRId64
": ", region
->value
->bar
);
84 if (!strcmp(region
->value
->type
, "io")) {
85 monitor_printf(mon
, "I/O at 0x%04" PRIx64
86 " [0x%04" PRIx64
"].\n",
87 addr
, addr
+ size
- 1);
89 monitor_printf(mon
, "%d bit%s memory at 0x%08" PRIx64
90 " [0x%08" PRIx64
"].\n",
91 region
->value
->mem_type_64
? 64 : 32,
92 region
->value
->prefetch
? " prefetchable" : "",
93 addr
, addr
+ size
- 1);
97 monitor_printf(mon
, " id \"%s\"\n", dev
->qdev_id
);
99 if (dev
->pci_bridge
) {
100 if (dev
->pci_bridge
->has_devices
) {
101 PciDeviceInfoList
*cdev
;
102 for (cdev
= dev
->pci_bridge
->devices
; cdev
; cdev
= cdev
->next
) {
103 hmp_info_pci_device(mon
, cdev
->value
);
109 void hmp_info_pci(Monitor
*mon
, const QDict
*qdict
)
111 PciInfoList
*info_list
, *info
;
113 info_list
= qmp_query_pci(&error_abort
);
115 for (info
= info_list
; info
; info
= info
->next
) {
116 PciDeviceInfoList
*dev
;
118 for (dev
= info
->value
->devices
; dev
; dev
= dev
->next
) {
119 hmp_info_pci_device(mon
, dev
->value
);
123 qapi_free_PciInfoList(info_list
);
126 void pcibus_dev_print(Monitor
*mon
, DeviceState
*dev
, int indent
)
128 PCIDevice
*d
= (PCIDevice
*)dev
;
129 int class = pci_get_word(d
->config
+ PCI_CLASS_DEVICE
);
130 const pci_class_desc
*desc
= get_class_desc(class);
136 snprintf(ctxt
, sizeof(ctxt
), "%s", desc
->desc
);
138 snprintf(ctxt
, sizeof(ctxt
), "Class %04x", class);
141 monitor_printf(mon
, "%*sclass %s, addr %02x:%02x.%x, "
142 "pci id %04x:%04x (sub %04x:%04x)\n",
143 indent
, "", ctxt
, pci_dev_bus_num(d
),
144 PCI_SLOT(d
->devfn
), PCI_FUNC(d
->devfn
),
145 pci_get_word(d
->config
+ PCI_VENDOR_ID
),
146 pci_get_word(d
->config
+ PCI_DEVICE_ID
),
147 pci_get_word(d
->config
+ PCI_SUBSYSTEM_VENDOR_ID
),
148 pci_get_word(d
->config
+ PCI_SUBSYSTEM_ID
));
149 for (i
= 0; i
< PCI_NUM_REGIONS
; i
++) {
150 r
= &d
->io_regions
[i
];
154 monitor_printf(mon
, "%*sbar %d: %s at 0x%"FMT_PCIBUS
155 " [0x%"FMT_PCIBUS
"]\n",
157 i
, r
->type
& PCI_BASE_ADDRESS_SPACE_IO
? "i/o" : "mem",
158 r
->addr
, r
->addr
+ r
->size
- 1);
162 void hmp_pcie_aer_inject_error(Monitor
*mon
, const QDict
*qdict
)
165 const char *id
= qdict_get_str(qdict
, "id");
166 const char *error_name
;
167 uint32_t error_status
;
174 ret
= pci_qdev_find_device(id
, &dev
);
175 if (ret
== -ENODEV
) {
176 error_setg(&err
, "device '%s' not found", id
);
179 if (ret
< 0 || !pci_is_express(dev
)) {
180 error_setg(&err
, "device '%s' is not a PCIe device", id
);
184 error_name
= qdict_get_str(qdict
, "error_status");
185 if (pcie_aer_parse_error_string(error_name
, &error_status
, &correctable
)) {
186 if (qemu_strtoui(error_name
, NULL
, 0, &num
) < 0) {
187 error_setg(&err
, "invalid error status value '%s'", error_name
);
191 correctable
= qdict_get_try_bool(qdict
, "correctable", false);
193 if (qdict_haskey(qdict
, "correctable")) {
194 error_setg(&err
, "-c is only valid with numeric error status");
198 aer_err
.status
= error_status
;
199 aer_err
.source_id
= pci_requester_id(dev
);
203 aer_err
.flags
|= PCIE_AER_ERR_IS_CORRECTABLE
;
205 if (qdict_get_try_bool(qdict
, "advisory_non_fatal", false)) {
206 aer_err
.flags
|= PCIE_AER_ERR_MAYBE_ADVISORY
;
208 if (qdict_haskey(qdict
, "header0")) {
209 aer_err
.flags
|= PCIE_AER_ERR_HEADER_VALID
;
211 if (qdict_haskey(qdict
, "prefix0")) {
212 aer_err
.flags
|= PCIE_AER_ERR_TLP_PREFIX_PRESENT
;
215 aer_err
.header
[0] = qdict_get_try_int(qdict
, "header0", 0);
216 aer_err
.header
[1] = qdict_get_try_int(qdict
, "header1", 0);
217 aer_err
.header
[2] = qdict_get_try_int(qdict
, "header2", 0);
218 aer_err
.header
[3] = qdict_get_try_int(qdict
, "header3", 0);
220 aer_err
.prefix
[0] = qdict_get_try_int(qdict
, "prefix0", 0);
221 aer_err
.prefix
[1] = qdict_get_try_int(qdict
, "prefix1", 0);
222 aer_err
.prefix
[2] = qdict_get_try_int(qdict
, "prefix2", 0);
223 aer_err
.prefix
[3] = qdict_get_try_int(qdict
, "prefix3", 0);
225 ret
= pcie_aer_inject_error(dev
, &aer_err
);
227 error_setg_errno(&err
, -ret
, "failed to inject error");
232 monitor_printf(mon
, "OK id: %s root bus: %s, bus: %x devfn: %x.%x\n",
233 id
, pci_root_bus_path(dev
), pci_dev_bus_num(dev
),
234 PCI_SLOT(dev
->devfn
), PCI_FUNC(dev
->devfn
));
237 hmp_handle_error(mon
, err
);