1 /*
2  * PCI Expander Bridge Device Emulation
3  *
4  * Copyright (C) 2015 Red Hat Inc
5  *
6  * Authors:
7  *   Marcel Apfelbaum <marcel@redhat.com>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2 or later.
10  * See the COPYING file in the top-level directory.
11  */
12 
13 #include "hw/pci/pci.h"
14 #include "hw/pci/pci_bus.h"
15 #include "hw/pci/pci_host.h"
16 #include "hw/pci/pci_bus.h"
17 #include "hw/pci/pci_bridge.h"
18 #include "hw/i386/pc.h"
19 #include "qemu/range.h"
20 #include "qemu/error-report.h"
21 #include "sysemu/numa.h"
22 
23 #define TYPE_PXB_BUS "pxb-bus"
24 #define PXB_BUS(obj) OBJECT_CHECK(PXBBus, (obj), TYPE_PXB_BUS)
25 
26 #define TYPE_PXB_PCIE_BUS "pxb-pcie-bus"
27 #define PXB_PCIE_BUS(obj) OBJECT_CHECK(PXBBus, (obj), TYPE_PXB_PCIE_BUS)
28 
29 typedef struct PXBBus {
30     /*< private >*/
31     PCIBus parent_obj;
32     /*< public >*/
33 
34     char bus_path[8];
35 } PXBBus;
36 
37 #define TYPE_PXB_DEVICE "pxb"
38 #define PXB_DEV(obj) OBJECT_CHECK(PXBDev, (obj), TYPE_PXB_DEVICE)
39 
40 #define TYPE_PXB_PCIE_DEVICE "pxb-pcie"
41 #define PXB_PCIE_DEV(obj) OBJECT_CHECK(PXBDev, (obj), TYPE_PXB_PCIE_DEVICE)
42 
43 typedef struct PXBDev {
44     /*< private >*/
45     PCIDevice parent_obj;
46     /*< public >*/
47 
48     uint8_t bus_nr;
49     uint16_t numa_node;
50 } PXBDev;
51 
52 static PXBDev *convert_to_pxb(PCIDevice *dev)
53 {
54     return pci_bus_is_express(dev->bus) ? PXB_PCIE_DEV(dev) : PXB_DEV(dev);
55 }
56 
57 static GList *pxb_dev_list;
58 
59 #define TYPE_PXB_HOST "pxb-host"
60 
61 static int pxb_bus_num(PCIBus *bus)
62 {
63     PXBDev *pxb = convert_to_pxb(bus->parent_dev);
64 
65     return pxb->bus_nr;
66 }
67 
68 static bool pxb_is_root(PCIBus *bus)
69 {
70     return true; /* by definition */
71 }
72 
73 static uint16_t pxb_bus_numa_node(PCIBus *bus)
74 {
75     PXBDev *pxb = convert_to_pxb(bus->parent_dev);
76 
77     return pxb->numa_node;
78 }
79 
80 static void pxb_bus_class_init(ObjectClass *class, void *data)
81 {
82     PCIBusClass *pbc = PCI_BUS_CLASS(class);
83 
84     pbc->bus_num = pxb_bus_num;
85     pbc->is_root = pxb_is_root;
86     pbc->numa_node = pxb_bus_numa_node;
87 }
88 
89 static const TypeInfo pxb_bus_info = {
90     .name          = TYPE_PXB_BUS,
91     .parent        = TYPE_PCI_BUS,
92     .instance_size = sizeof(PXBBus),
93     .class_init    = pxb_bus_class_init,
94 };
95 
96 static const TypeInfo pxb_pcie_bus_info = {
97     .name          = TYPE_PXB_PCIE_BUS,
98     .parent        = TYPE_PCIE_BUS,
99     .instance_size = sizeof(PXBBus),
100     .class_init    = pxb_bus_class_init,
101 };
102 
103 static const char *pxb_host_root_bus_path(PCIHostState *host_bridge,
104                                           PCIBus *rootbus)
105 {
106     PXBBus *bus = pci_bus_is_express(rootbus) ?
107                   PXB_PCIE_BUS(rootbus) : PXB_BUS(rootbus);
108 
109     snprintf(bus->bus_path, 8, "0000:%02x", pxb_bus_num(rootbus));
110     return bus->bus_path;
111 }
112 
113 static char *pxb_host_ofw_unit_address(const SysBusDevice *dev)
114 {
115     const PCIHostState *pxb_host;
116     const PCIBus *pxb_bus;
117     const PXBDev *pxb_dev;
118     int position;
119     const DeviceState *pxb_dev_base;
120     const PCIHostState *main_host;
121     const SysBusDevice *main_host_sbd;
122 
123     pxb_host = PCI_HOST_BRIDGE(dev);
124     pxb_bus = pxb_host->bus;
125     pxb_dev = convert_to_pxb(pxb_bus->parent_dev);
126     position = g_list_index(pxb_dev_list, pxb_dev);
127     assert(position >= 0);
128 
129     pxb_dev_base = DEVICE(pxb_dev);
130     main_host = PCI_HOST_BRIDGE(pxb_dev_base->parent_bus->parent);
131     main_host_sbd = SYS_BUS_DEVICE(main_host);
132 
133     if (main_host_sbd->num_mmio > 0) {
134         return g_strdup_printf(TARGET_FMT_plx ",%x",
135                                main_host_sbd->mmio[0].addr, position + 1);
136     }
137     if (main_host_sbd->num_pio > 0) {
138         return g_strdup_printf("i%04x,%x",
139                                main_host_sbd->pio[0], position + 1);
140     }
141     return NULL;
142 }
143 
144 static void pxb_host_class_init(ObjectClass *class, void *data)
145 {
146     DeviceClass *dc = DEVICE_CLASS(class);
147     SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(class);
148     PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(class);
149 
150     dc->fw_name = "pci";
151     sbc->explicit_ofw_unit_address = pxb_host_ofw_unit_address;
152     hc->root_bus_path = pxb_host_root_bus_path;
153 }
154 
155 static const TypeInfo pxb_host_info = {
156     .name          = TYPE_PXB_HOST,
157     .parent        = TYPE_PCI_HOST_BRIDGE,
158     .class_init    = pxb_host_class_init,
159 };
160 
161 /*
162  * Registers the PXB bus as a child of the i440fx root bus.
163  *
164  * Returns 0 on successs, -1 if i440fx host was not
165  * found or the bus number is already in use.
166  */
167 static int pxb_register_bus(PCIDevice *dev, PCIBus *pxb_bus)
168 {
169     PCIBus *bus = dev->bus;
170     int pxb_bus_num = pci_bus_num(pxb_bus);
171 
172     if (bus->parent_dev) {
173         error_report("PXB devices can be attached only to root bus.");
174         return -1;
175     }
176 
177     QLIST_FOREACH(bus, &bus->child, sibling) {
178         if (pci_bus_num(bus) == pxb_bus_num) {
179             error_report("Bus %d is already in use.", pxb_bus_num);
180             return -1;
181         }
182     }
183     QLIST_INSERT_HEAD(&dev->bus->child, pxb_bus, sibling);
184 
185     return 0;
186 }
187 
188 static int pxb_map_irq_fn(PCIDevice *pci_dev, int pin)
189 {
190     PCIDevice *pxb = pci_dev->bus->parent_dev;
191 
192     /*
193      * The bios does not index the pxb slot number when
194      * it computes the IRQ because it resides on bus 0
195      * and not on the current bus.
196      * However QEMU routes the irq through bus 0 and adds
197      * the pxb slot to the IRQ computation of the PXB
198      * device.
199      *
200      * Synchronize between bios and QEMU by canceling
201      * pxb's effect.
202      */
203     return pin - PCI_SLOT(pxb->devfn);
204 }
205 
206 static gint pxb_compare(gconstpointer a, gconstpointer b)
207 {
208     const PXBDev *pxb_a = a, *pxb_b = b;
209 
210     return pxb_a->bus_nr < pxb_b->bus_nr ? -1 :
211            pxb_a->bus_nr > pxb_b->bus_nr ?  1 :
212            0;
213 }
214 
215 static int pxb_dev_init_common(PCIDevice *dev, bool pcie)
216 {
217     PXBDev *pxb = convert_to_pxb(dev);
218     DeviceState *ds, *bds = NULL;
219     PCIBus *bus;
220     const char *dev_name = NULL;
221 
222     if (pxb->numa_node != NUMA_NODE_UNASSIGNED &&
223         pxb->numa_node >= nb_numa_nodes) {
224         error_report("Illegal numa node %d.", pxb->numa_node);
225         return -EINVAL;
226     }
227 
228     if (dev->qdev.id && *dev->qdev.id) {
229         dev_name = dev->qdev.id;
230     }
231 
232     ds = qdev_create(NULL, TYPE_PXB_HOST);
233     if (pcie) {
234         bus = pci_bus_new(ds, dev_name, NULL, NULL, 0, TYPE_PXB_PCIE_BUS);
235     } else {
236         bus = pci_bus_new(ds, "pxb-internal", NULL, NULL, 0, TYPE_PXB_BUS);
237         bds = qdev_create(BUS(bus), "pci-bridge");
238         bds->id = dev_name;
239         qdev_prop_set_uint8(bds, PCI_BRIDGE_DEV_PROP_CHASSIS_NR, pxb->bus_nr);
240         qdev_prop_set_bit(bds, PCI_BRIDGE_DEV_PROP_SHPC, false);
241     }
242 
243     bus->parent_dev = dev;
244     bus->address_space_mem = dev->bus->address_space_mem;
245     bus->address_space_io = dev->bus->address_space_io;
246     bus->map_irq = pxb_map_irq_fn;
247 
248     PCI_HOST_BRIDGE(ds)->bus = bus;
249 
250     if (pxb_register_bus(dev, bus)) {
251         return -EINVAL;
252     }
253 
254     qdev_init_nofail(ds);
255     if (bds) {
256         qdev_init_nofail(bds);
257     }
258 
259     pci_word_test_and_set_mask(dev->config + PCI_STATUS,
260                                PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK);
261     pci_config_set_class(dev->config, PCI_CLASS_BRIDGE_HOST);
262 
263     pxb_dev_list = g_list_insert_sorted(pxb_dev_list, pxb, pxb_compare);
264     return 0;
265 }
266 
267 static int pxb_dev_initfn(PCIDevice *dev)
268 {
269     if (pci_bus_is_express(dev->bus)) {
270         error_report("pxb devices cannot reside on a PCIe bus!");
271         return -EINVAL;
272     }
273 
274     return pxb_dev_init_common(dev, false);
275 }
276 
277 static void pxb_dev_exitfn(PCIDevice *pci_dev)
278 {
279     PXBDev *pxb = convert_to_pxb(pci_dev);
280 
281     pxb_dev_list = g_list_remove(pxb_dev_list, pxb);
282 }
283 
284 static Property pxb_dev_properties[] = {
285     /* Note: 0 is not a legal a PXB bus number. */
286     DEFINE_PROP_UINT8("bus_nr", PXBDev, bus_nr, 0),
287     DEFINE_PROP_UINT16("numa_node", PXBDev, numa_node, NUMA_NODE_UNASSIGNED),
288     DEFINE_PROP_END_OF_LIST(),
289 };
290 
291 static void pxb_dev_class_init(ObjectClass *klass, void *data)
292 {
293     DeviceClass *dc = DEVICE_CLASS(klass);
294     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
295 
296     k->init = pxb_dev_initfn;
297     k->exit = pxb_dev_exitfn;
298     k->vendor_id = PCI_VENDOR_ID_REDHAT;
299     k->device_id = PCI_DEVICE_ID_REDHAT_PXB;
300     k->class_id = PCI_CLASS_BRIDGE_HOST;
301 
302     dc->desc = "PCI Expander Bridge";
303     dc->props = pxb_dev_properties;
304 }
305 
306 static const TypeInfo pxb_dev_info = {
307     .name          = TYPE_PXB_DEVICE,
308     .parent        = TYPE_PCI_DEVICE,
309     .instance_size = sizeof(PXBDev),
310     .class_init    = pxb_dev_class_init,
311 };
312 
313 static int pxb_pcie_dev_initfn(PCIDevice *dev)
314 {
315     if (!pci_bus_is_express(dev->bus)) {
316         error_report("pxb-pcie devices cannot reside on a PCI bus!");
317         return -EINVAL;
318     }
319 
320     return pxb_dev_init_common(dev, true);
321 }
322 
323 static void pxb_pcie_dev_class_init(ObjectClass *klass, void *data)
324 {
325     DeviceClass *dc = DEVICE_CLASS(klass);
326     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
327 
328     k->init = pxb_pcie_dev_initfn;
329     k->exit = pxb_dev_exitfn;
330     k->vendor_id = PCI_VENDOR_ID_REDHAT;
331     k->device_id = PCI_DEVICE_ID_REDHAT_PXB_PCIE;
332     k->class_id = PCI_CLASS_BRIDGE_HOST;
333 
334     dc->desc = "PCI Express Expander Bridge";
335     dc->props = pxb_dev_properties;
336 }
337 
338 static const TypeInfo pxb_pcie_dev_info = {
339     .name          = TYPE_PXB_PCIE_DEVICE,
340     .parent        = TYPE_PCI_DEVICE,
341     .instance_size = sizeof(PXBDev),
342     .class_init    = pxb_pcie_dev_class_init,
343 };
344 
345 static void pxb_register_types(void)
346 {
347     type_register_static(&pxb_bus_info);
348     type_register_static(&pxb_pcie_bus_info);
349     type_register_static(&pxb_host_info);
350     type_register_static(&pxb_dev_info);
351     type_register_static(&pxb_pcie_dev_info);
352 }
353 
354 type_init(pxb_register_types)
355