master
c 309 lines 9.91 KB
Raw
1 /*
2 * USB xHCI controller with PCI bus emulation
3 *
4 * SPDX-FileCopyrightText: 2011 Securiforest
5 * SPDX-FileContributor: Hector Martin <hector@marcansoft.com>
6 * SPDX-sourceInfo: Based on usb-ohci.c, emulates Renesas NEC USB 3.0
7 * SPDX-FileCopyrightText: 2020 Xilinx
8 * SPDX-FileContributor: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
9 * SPDX-sourceInfo: Moved the pci specific content for hcd-xhci.c to
10 * hcd-xhci-pci.c
11 *
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
16 *
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
21 *
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
24 */
25 #include "qemu/osdep.h"
26 #include "hw/pci/pci.h"
27 #include "hw/core/qdev-properties.h"
28 #include "migration/vmstate.h"
29 #include "hw/pci/msi.h"
30 #include "hw/pci/msix.h"
31 #include "hcd-xhci-pci.h"
32 #include "trace.h"
33 #include "qapi/error.h"
34
35 #define OFF_MSIX_TABLE 0x3000
36 #define OFF_MSIX_PBA 0x3800
37
38 static void xhci_pci_intr_update(XHCIState *xhci, int n, bool enable)
39 {
40 XHCIPciState *s = container_of(xhci, XHCIPciState, xhci);
41 PCIDevice *pci_dev = PCI_DEVICE(s);
42
43 if (!msix_enabled(pci_dev)) {
44 return;
45 }
46 if (enable == !!xhci->intr[n].msix_used) {
47 return;
48 }
49 if (enable) {
50 trace_usb_xhci_irq_msix_use(n);
51 msix_vector_use(pci_dev, n);
52 xhci->intr[n].msix_used = true;
53 } else {
54 trace_usb_xhci_irq_msix_unuse(n);
55 msix_vector_unuse(pci_dev, n);
56 xhci->intr[n].msix_used = false;
57 }
58 }
59
60 static bool xhci_pci_intr_raise(XHCIState *xhci, int n, bool level)
61 {
62 XHCIPciState *s = container_of(xhci, XHCIPciState, xhci);
63 PCIDevice *pci_dev = PCI_DEVICE(s);
64
65 if (n == 0 &&
66 !(msix_enabled(pci_dev) ||
67 msi_enabled(pci_dev))) {
68 pci_set_irq(pci_dev, level);
69 }
70
71 if (msix_enabled(pci_dev) && level) {
72 msix_notify(pci_dev, n);
73 return true;
74 }
75
76 if (msi_enabled(pci_dev) && level) {
77 n %= msi_nr_vectors_allocated(pci_dev);
78 msi_notify(pci_dev, n);
79 return true;
80 }
81
82 return false;
83 }
84
85 static bool xhci_pci_intr_mapping_conditional(XHCIState *xhci)
86 {
87 XHCIPciState *s = container_of(xhci, XHCIPciState, xhci);
88 PCIDevice *pci_dev = PCI_DEVICE(s);
89
90 /*
91 * Implementation of the "conditional-intr-mapping" property, which only
92 * enables interrupter mapping if MSI or MSI-X is available and active.
93 * Forces all events onto interrupter/event ring 0 in pin-based IRQ mode.
94 * Provides compatibility with macOS guests on machine types where MSI(-X)
95 * is not available.
96 */
97 return msix_enabled(pci_dev) || msi_enabled(pci_dev);
98 }
99
100 static void xhci_pci_reset(DeviceState *dev)
101 {
102 XHCIPciState *s = XHCI_PCI(dev);
103
104 device_cold_reset(DEVICE(&s->xhci));
105 }
106
107 static int xhci_pci_vmstate_post_load(void *opaque, int version_id)
108 {
109 XHCIPciState *s = XHCI_PCI(opaque);
110 PCIDevice *pci_dev = PCI_DEVICE(s);
111 int intr;
112
113 for (intr = 0; intr < s->xhci.numintrs; intr++) {
114 if (s->xhci.intr[intr].msix_used) {
115 msix_vector_use(pci_dev, intr);
116 } else {
117 msix_vector_unuse(pci_dev, intr);
118 }
119 }
120 return 0;
121 }
122
123 static void usb_xhci_pci_realize(struct PCIDevice *dev, Error **errp)
124 {
125 int ret;
126 Error *err = NULL;
127 XHCIPciState *s = XHCI_PCI(dev);
128
129 dev->config[PCI_CLASS_PROG] = 0x30; /* xHCI */
130 dev->config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin 1 */
131 dev->config[PCI_CACHE_LINE_SIZE] = 0x10;
132 dev->config[0x60] = 0x30; /* release number */
133
134 object_property_set_link(OBJECT(&s->xhci), "host", OBJECT(s), NULL);
135 s->xhci.intr_update = xhci_pci_intr_update;
136 s->xhci.intr_raise = xhci_pci_intr_raise;
137 if (s->conditional_intr_mapping) {
138 s->xhci.intr_mapping_supported = xhci_pci_intr_mapping_conditional;
139 }
140 if (!qdev_realize(DEVICE(&s->xhci), NULL, errp)) {
141 return;
142 }
143 if (strcmp(object_get_typename(OBJECT(dev)), TYPE_NEC_XHCI) == 0) {
144 s->xhci.nec_quirks = true;
145 }
146
147 if (s->msi != ON_OFF_AUTO_OFF) {
148 ret = msi_init(dev, 0x70, s->xhci.numintrs, true, false, &err);
149 /*
150 * Any error other than -ENOTSUP(board's MSI support is broken)
151 * is a programming error
152 */
153 assert(!ret || ret == -ENOTSUP);
154 if (ret && s->msi == ON_OFF_AUTO_ON) {
155 /* Can't satisfy user's explicit msi=on request, fail */
156 error_append_hint(&err, "You have to use msi=auto (default) or "
157 "msi=off with this machine type.\n");
158 error_propagate(errp, err);
159 return;
160 }
161 assert(!err || s->msi == ON_OFF_AUTO_AUTO);
162 /* With msi=auto, we fall back to MSI off silently */
163 error_free(err);
164 }
165 pci_register_bar(dev, 0,
166 PCI_BASE_ADDRESS_SPACE_MEMORY |
167 PCI_BASE_ADDRESS_MEM_TYPE_64,
168 &s->xhci.mem);
169
170 if (pci_bus_is_express(pci_get_bus(dev))) {
171 ret = pcie_endpoint_cap_init(dev, 0xa0);
172 assert(ret > 0);
173 }
174
175 if (s->msix != ON_OFF_AUTO_OFF) {
176 ret = msix_init(dev, s->xhci.numintrs,
177 &s->xhci.mem, 0, OFF_MSIX_TABLE,
178 &s->xhci.mem, 0, OFF_MSIX_PBA,
179 0x90, s->msix == ON_OFF_AUTO_ON ? errp : NULL);
180
181 if (ret < 0) {
182 if (s->msix == ON_OFF_AUTO_ON) {
183 return;
184 }
185 s->msix = ON_OFF_AUTO_OFF;
186 }
187 }
188 s->xhci.as = pci_get_address_space(dev);
189 }
190
191 static void usb_xhci_pci_exit(PCIDevice *dev)
192 {
193 XHCIPciState *s = XHCI_PCI(dev);
194 /* destroy msix memory region */
195 if (dev->msix_table && dev->msix_pba
196 && dev->msix_entry_used) {
197 msix_uninit(dev, &s->xhci.mem, &s->xhci.mem);
198 }
199 /*
200 * The embedded xhci-core child holds a strong "host" link back to this
201 * PCI device (set in usb_xhci_pci_realize()), forming a refcount cycle:
202 * the PCI device owns the child, and the child's strong link pins the PCI
203 * device. On unplug, object_unparent() only drops the parent/bus refs, so
204 * the link ref keeps this device at refcount 1 forever and
205 * device_finalize() never runs. Unrealize the child first (so the
206 * realized-check in set_link passes), then clear the link to break the
207 * cycle.
208 */
209 qdev_unrealize(DEVICE(&s->xhci));
210 object_property_set_link(OBJECT(&s->xhci), "host", NULL, &error_abort);
211 }
212
213 static const VMStateDescription vmstate_xhci_pci = {
214 .name = "xhci",
215 .version_id = 1,
216 .post_load = xhci_pci_vmstate_post_load,
217 .fields = (const VMStateField[]) {
218 VMSTATE_PCI_DEVICE(parent_obj, XHCIPciState),
219 VMSTATE_MSIX(parent_obj, XHCIPciState),
220 VMSTATE_STRUCT(xhci, XHCIPciState, 1, vmstate_xhci, XHCIState),
221 VMSTATE_END_OF_LIST()
222 }
223 };
224
225 static void xhci_instance_init(Object *obj)
226 {
227 XHCIPciState *s = XHCI_PCI(obj);
228 /*
229 * QEMU_PCI_CAP_EXPRESS initialization does not depend on QEMU command
230 * line, therefore, no need to wait to realize like other devices
231 */
232 PCI_DEVICE(obj)->cap_present |= QEMU_PCI_CAP_EXPRESS;
233 object_initialize_child(obj, "xhci-core", &s->xhci, TYPE_XHCI);
234 qdev_alias_all_properties(DEVICE(&s->xhci), obj);
235 }
236
237 static const Property xhci_pci_properties[] = {
238 DEFINE_PROP_ON_OFF_AUTO("msi", XHCIPciState, msi, ON_OFF_AUTO_AUTO),
239 DEFINE_PROP_ON_OFF_AUTO("msix", XHCIPciState, msix, ON_OFF_AUTO_AUTO),
240 DEFINE_PROP_BOOL("conditional-intr-mapping", XHCIPciState,
241 conditional_intr_mapping, false),
242 };
243
244 static void xhci_class_init(ObjectClass *klass, const void *data)
245 {
246 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
247 DeviceClass *dc = DEVICE_CLASS(klass);
248
249 device_class_set_legacy_reset(dc, xhci_pci_reset);
250 dc->vmsd = &vmstate_xhci_pci;
251 set_bit(DEVICE_CATEGORY_USB, dc->categories);
252 k->realize = usb_xhci_pci_realize;
253 k->exit = usb_xhci_pci_exit;
254 k->class_id = PCI_CLASS_SERIAL_USB;
255 device_class_set_props(dc, xhci_pci_properties);
256 object_class_property_set_description(klass, "conditional-intr-mapping",
257 "When true, disables interrupter mapping for pin-based IRQ mode. "
258 "Intended to be used with guest drivers with questionable behaviour, "
259 "such as macOS's.");
260 }
261
262 static const TypeInfo xhci_pci_info = {
263 .name = TYPE_XHCI_PCI,
264 .parent = TYPE_PCI_DEVICE,
265 .instance_size = sizeof(XHCIPciState),
266 .class_init = xhci_class_init,
267 .instance_init = xhci_instance_init,
268 .abstract = true,
269 .interfaces = (const InterfaceInfo[]) {
270 { INTERFACE_PCIE_DEVICE },
271 { INTERFACE_CONVENTIONAL_PCI_DEVICE },
272 { }
273 },
274 };
275
276 static void qemu_xhci_class_init(ObjectClass *klass, const void *data)
277 {
278 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
279
280 k->vendor_id = PCI_VENDOR_ID_REDHAT;
281 k->device_id = PCI_DEVICE_ID_REDHAT_XHCI;
282 k->revision = 0x01;
283 }
284
285 static void qemu_xhci_instance_init(Object *obj)
286 {
287 XHCIPciState *s = XHCI_PCI(obj);
288 XHCIState *xhci = &s->xhci;
289
290 s->msi = ON_OFF_AUTO_OFF;
291 s->msix = ON_OFF_AUTO_AUTO;
292 xhci->numintrs = XHCI_MAXINTRS;
293 xhci->numslots = XHCI_MAXSLOTS;
294 }
295
296 static const TypeInfo qemu_xhci_info = {
297 .name = TYPE_QEMU_XHCI,
298 .parent = TYPE_XHCI_PCI,
299 .class_init = qemu_xhci_class_init,
300 .instance_init = qemu_xhci_instance_init,
301 };
302
303 static void xhci_register_types(void)
304 {
305 type_register_static(&xhci_pci_info);
306 type_register_static(&qemu_xhci_info);
307 }
308
309 type_init(xhci_register_types)