xref: /openbmc/qemu/hw/pci/pci_bridge.c (revision 9eb9350c0e519be97716f6b27f664bd0a3c41a36)
1315a1350SMichael S. Tsirkin /*
2315a1350SMichael S. Tsirkin  * QEMU PCI bus manager
3315a1350SMichael S. Tsirkin  *
4315a1350SMichael S. Tsirkin  * Copyright (c) 2004 Fabrice Bellard
5315a1350SMichael S. Tsirkin  *
6315a1350SMichael S. Tsirkin  * Permission is hereby granted, free of charge, to any person obtaining a copy
7315a1350SMichael S. Tsirkin  * of this software and associated documentation files (the "Software"), to dea
8315a1350SMichael S. Tsirkin 
9315a1350SMichael S. Tsirkin  * in the Software without restriction, including without limitation the rights
10315a1350SMichael S. Tsirkin  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11315a1350SMichael S. Tsirkin  * copies of the Software, and to permit persons to whom the Software is
12315a1350SMichael S. Tsirkin  * furnished to do so, subject to the following conditions:
13315a1350SMichael S. Tsirkin  *
14315a1350SMichael S. Tsirkin  * The above copyright notice and this permission notice shall be included in
15315a1350SMichael S. Tsirkin  * all copies or substantial portions of the Software.
16315a1350SMichael S. Tsirkin  *
17315a1350SMichael S. Tsirkin  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18315a1350SMichael S. Tsirkin  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19315a1350SMichael S. Tsirkin  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20315a1350SMichael S. Tsirkin  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21315a1350SMichael S. Tsirkin  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM
22315a1350SMichael S. Tsirkin 
23315a1350SMichael S. Tsirkin  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24315a1350SMichael S. Tsirkin  * THE SOFTWARE.
25315a1350SMichael S. Tsirkin  */
26315a1350SMichael S. Tsirkin /*
27315a1350SMichael S. Tsirkin  * split out from pci.c
28315a1350SMichael S. Tsirkin  * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
29315a1350SMichael S. Tsirkin  *                    VA Linux Systems Japan K.K.
30315a1350SMichael S. Tsirkin  */
31315a1350SMichael S. Tsirkin 
3297d5408fSPeter Maydell #include "qemu/osdep.h"
332dc48da2SPhilippe Mathieu-Daudé #include "qemu/units.h"
34c759b24fSMichael S. Tsirkin #include "hw/pci/pci_bridge.h"
3506aac7bdSMichael S. Tsirkin #include "hw/pci/pci_bus.h"
360b8fa32fSMarkus Armbruster #include "qemu/module.h"
371de7afc9SPaolo Bonzini #include "qemu/range.h"
389a7c2a59SMao Zhongyi #include "qapi/error.h"
39d78644c7SIgor Mammedov #include "hw/acpi/acpi_aml_interface.h"
406c36ec46SIgor Mammedov #include "hw/acpi/pci.h"
414565917bSMichael S. Tsirkin #include "hw/qdev-properties.h"
42315a1350SMichael S. Tsirkin 
43315a1350SMichael S. Tsirkin /* PCI bridge subsystem vendor ID helper functions */
44315a1350SMichael S. Tsirkin #define PCI_SSVID_SIZEOF        8
45315a1350SMichael S. Tsirkin #define PCI_SSVID_SVID          4
46315a1350SMichael S. Tsirkin #define PCI_SSVID_SSID          6
47315a1350SMichael S. Tsirkin 
pci_bridge_ssvid_init(PCIDevice * dev,uint8_t offset,uint16_t svid,uint16_t ssid,Error ** errp)48315a1350SMichael S. Tsirkin int pci_bridge_ssvid_init(PCIDevice *dev, uint8_t offset,
49f8cd1b02SMao Zhongyi                           uint16_t svid, uint16_t ssid,
50f8cd1b02SMao Zhongyi                           Error **errp)
51315a1350SMichael S. Tsirkin {
52315a1350SMichael S. Tsirkin     int pos;
539a7c2a59SMao Zhongyi 
549a7c2a59SMao Zhongyi     pos = pci_add_capability(dev, PCI_CAP_ID_SSVID, offset,
55f8cd1b02SMao Zhongyi                              PCI_SSVID_SIZEOF, errp);
56315a1350SMichael S. Tsirkin     if (pos < 0) {
57315a1350SMichael S. Tsirkin         return pos;
58315a1350SMichael S. Tsirkin     }
59315a1350SMichael S. Tsirkin 
60315a1350SMichael S. Tsirkin     pci_set_word(dev->config + pos + PCI_SSVID_SVID, svid);
61315a1350SMichael S. Tsirkin     pci_set_word(dev->config + pos + PCI_SSVID_SSID, ssid);
62315a1350SMichael S. Tsirkin     return pos;
63315a1350SMichael S. Tsirkin }
64315a1350SMichael S. Tsirkin 
65315a1350SMichael S. Tsirkin /* Accessor function to get parent bridge device from pci bus. */
pci_bridge_get_device(PCIBus * bus)66315a1350SMichael S. Tsirkin PCIDevice *pci_bridge_get_device(PCIBus *bus)
67315a1350SMichael S. Tsirkin {
68315a1350SMichael S. Tsirkin     return bus->parent_dev;
69315a1350SMichael S. Tsirkin }
70315a1350SMichael S. Tsirkin 
71315a1350SMichael S. Tsirkin /* Accessor function to get secondary bus from pci-to-pci bridge device */
pci_bridge_get_sec_bus(PCIBridge * br)72315a1350SMichael S. Tsirkin PCIBus *pci_bridge_get_sec_bus(PCIBridge *br)
73315a1350SMichael S. Tsirkin {
74315a1350SMichael S. Tsirkin     return &br->sec_bus;
75315a1350SMichael S. Tsirkin }
76315a1350SMichael S. Tsirkin 
pci_config_get_io_base(const PCIDevice * d,uint32_t base,uint32_t base_upper16)77315a1350SMichael S. Tsirkin static uint32_t pci_config_get_io_base(const PCIDevice *d,
78315a1350SMichael S. Tsirkin                                        uint32_t base, uint32_t base_upper16)
79315a1350SMichael S. Tsirkin {
80315a1350SMichael S. Tsirkin     uint32_t val;
81315a1350SMichael S. Tsirkin 
82315a1350SMichael S. Tsirkin     val = ((uint32_t)d->config[base] & PCI_IO_RANGE_MASK) << 8;
83315a1350SMichael S. Tsirkin     if (d->config[base] & PCI_IO_RANGE_TYPE_32) {
84315a1350SMichael S. Tsirkin         val |= (uint32_t)pci_get_word(d->config + base_upper16) << 16;
85315a1350SMichael S. Tsirkin     }
86315a1350SMichael S. Tsirkin     return val;
87315a1350SMichael S. Tsirkin }
88315a1350SMichael S. Tsirkin 
pci_config_get_memory_base(const PCIDevice * d,uint32_t base)89315a1350SMichael S. Tsirkin static pcibus_t pci_config_get_memory_base(const PCIDevice *d, uint32_t base)
90315a1350SMichael S. Tsirkin {
91315a1350SMichael S. Tsirkin     return ((pcibus_t)pci_get_word(d->config + base) & PCI_MEMORY_RANGE_MASK)
92315a1350SMichael S. Tsirkin         << 16;
93315a1350SMichael S. Tsirkin }
94315a1350SMichael S. Tsirkin 
pci_config_get_pref_base(const PCIDevice * d,uint32_t base,uint32_t upper)95315a1350SMichael S. Tsirkin static pcibus_t pci_config_get_pref_base(const PCIDevice *d,
96315a1350SMichael S. Tsirkin                                          uint32_t base, uint32_t upper)
97315a1350SMichael S. Tsirkin {
98315a1350SMichael S. Tsirkin     pcibus_t tmp;
99315a1350SMichael S. Tsirkin     pcibus_t val;
100315a1350SMichael S. Tsirkin 
101315a1350SMichael S. Tsirkin     tmp = (pcibus_t)pci_get_word(d->config + base);
102315a1350SMichael S. Tsirkin     val = (tmp & PCI_PREF_RANGE_MASK) << 16;
103315a1350SMichael S. Tsirkin     if (tmp & PCI_PREF_RANGE_TYPE_64) {
104315a1350SMichael S. Tsirkin         val |= (pcibus_t)pci_get_long(d->config + upper) << 32;
105315a1350SMichael S. Tsirkin     }
106315a1350SMichael S. Tsirkin     return val;
107315a1350SMichael S. Tsirkin }
108315a1350SMichael S. Tsirkin 
109315a1350SMichael S. Tsirkin /* accessor function to get bridge filtering base address */
pci_bridge_get_base(const PCIDevice * bridge,uint8_t type)110315a1350SMichael S. Tsirkin pcibus_t pci_bridge_get_base(const PCIDevice *bridge, uint8_t type)
111315a1350SMichael S. Tsirkin {
112315a1350SMichael S. Tsirkin     pcibus_t base;
113315a1350SMichael S. Tsirkin     if (type & PCI_BASE_ADDRESS_SPACE_IO) {
114315a1350SMichael S. Tsirkin         base = pci_config_get_io_base(bridge,
115315a1350SMichael S. Tsirkin                                       PCI_IO_BASE, PCI_IO_BASE_UPPER16);
116315a1350SMichael S. Tsirkin     } else {
117315a1350SMichael S. Tsirkin         if (type & PCI_BASE_ADDRESS_MEM_PREFETCH) {
118315a1350SMichael S. Tsirkin             base = pci_config_get_pref_base(
119315a1350SMichael S. Tsirkin                 bridge, PCI_PREF_MEMORY_BASE, PCI_PREF_BASE_UPPER32);
120315a1350SMichael S. Tsirkin         } else {
121315a1350SMichael S. Tsirkin             base = pci_config_get_memory_base(bridge, PCI_MEMORY_BASE);
122315a1350SMichael S. Tsirkin         }
123315a1350SMichael S. Tsirkin     }
124315a1350SMichael S. Tsirkin 
125315a1350SMichael S. Tsirkin     return base;
126315a1350SMichael S. Tsirkin }
127315a1350SMichael S. Tsirkin 
128cb8d4c8fSStefan Weil /* accessor function to get bridge filtering limit */
pci_bridge_get_limit(const PCIDevice * bridge,uint8_t type)129315a1350SMichael S. Tsirkin pcibus_t pci_bridge_get_limit(const PCIDevice *bridge, uint8_t type)
130315a1350SMichael S. Tsirkin {
131315a1350SMichael S. Tsirkin     pcibus_t limit;
132315a1350SMichael S. Tsirkin     if (type & PCI_BASE_ADDRESS_SPACE_IO) {
133315a1350SMichael S. Tsirkin         limit = pci_config_get_io_base(bridge,
134315a1350SMichael S. Tsirkin                                       PCI_IO_LIMIT, PCI_IO_LIMIT_UPPER16);
135315a1350SMichael S. Tsirkin         limit |= 0xfff;         /* PCI bridge spec 3.2.5.6. */
136315a1350SMichael S. Tsirkin     } else {
137315a1350SMichael S. Tsirkin         if (type & PCI_BASE_ADDRESS_MEM_PREFETCH) {
138315a1350SMichael S. Tsirkin             limit = pci_config_get_pref_base(
139315a1350SMichael S. Tsirkin                 bridge, PCI_PREF_MEMORY_LIMIT, PCI_PREF_LIMIT_UPPER32);
140315a1350SMichael S. Tsirkin         } else {
141315a1350SMichael S. Tsirkin             limit = pci_config_get_memory_base(bridge, PCI_MEMORY_LIMIT);
142315a1350SMichael S. Tsirkin         }
143315a1350SMichael S. Tsirkin         limit |= 0xfffff;       /* PCI bridge spec 3.2.5.{1, 8}. */
144315a1350SMichael S. Tsirkin     }
145315a1350SMichael S. Tsirkin     return limit;
146315a1350SMichael S. Tsirkin }
147315a1350SMichael S. Tsirkin 
pci_bridge_init_alias(PCIBridge * bridge,MemoryRegion * alias,uint8_t type,const char * name,MemoryRegion * space,MemoryRegion * parent_space,bool enabled)148315a1350SMichael S. Tsirkin static void pci_bridge_init_alias(PCIBridge *bridge, MemoryRegion *alias,
149315a1350SMichael S. Tsirkin                                   uint8_t type, const char *name,
150315a1350SMichael S. Tsirkin                                   MemoryRegion *space,
151315a1350SMichael S. Tsirkin                                   MemoryRegion *parent_space,
152315a1350SMichael S. Tsirkin                                   bool enabled)
153315a1350SMichael S. Tsirkin {
154f055e96bSAndreas Färber     PCIDevice *bridge_dev = PCI_DEVICE(bridge);
155f055e96bSAndreas Färber     pcibus_t base = pci_bridge_get_base(bridge_dev, type);
156f055e96bSAndreas Färber     pcibus_t limit = pci_bridge_get_limit(bridge_dev, type);
157315a1350SMichael S. Tsirkin     /* TODO: this doesn't handle base = 0 limit = 2^64 - 1 correctly.
158315a1350SMichael S. Tsirkin      * Apparently no way to do this with existing memory APIs. */
159315a1350SMichael S. Tsirkin     pcibus_t size = enabled && limit >= base ? limit + 1 - base : 0;
160315a1350SMichael S. Tsirkin 
16140c5dce9SPaolo Bonzini     memory_region_init_alias(alias, OBJECT(bridge), name, space, base, size);
162315a1350SMichael S. Tsirkin     memory_region_add_subregion_overlap(parent_space, base, alias, 1);
163315a1350SMichael S. Tsirkin }
164315a1350SMichael S. Tsirkin 
pci_bridge_init_vga_aliases(PCIBridge * br,PCIBus * parent,MemoryRegion * alias_vga)165ba7d8515SAlex Williamson static void pci_bridge_init_vga_aliases(PCIBridge *br, PCIBus *parent,
166ba7d8515SAlex Williamson                                         MemoryRegion *alias_vga)
167ba7d8515SAlex Williamson {
168f055e96bSAndreas Färber     PCIDevice *pd = PCI_DEVICE(br);
169f055e96bSAndreas Färber     uint16_t brctl = pci_get_word(pd->config + PCI_BRIDGE_CONTROL);
170ba7d8515SAlex Williamson 
17140c5dce9SPaolo Bonzini     memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_IO_LO], OBJECT(br),
172ba7d8515SAlex Williamson                              "pci_bridge_vga_io_lo", &br->address_space_io,
173ba7d8515SAlex Williamson                              QEMU_PCI_VGA_IO_LO_BASE, QEMU_PCI_VGA_IO_LO_SIZE);
17440c5dce9SPaolo Bonzini     memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_IO_HI], OBJECT(br),
175ba7d8515SAlex Williamson                              "pci_bridge_vga_io_hi", &br->address_space_io,
176ba7d8515SAlex Williamson                              QEMU_PCI_VGA_IO_HI_BASE, QEMU_PCI_VGA_IO_HI_SIZE);
17740c5dce9SPaolo Bonzini     memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_MEM], OBJECT(br),
178ba7d8515SAlex Williamson                              "pci_bridge_vga_mem", &br->address_space_mem,
179ba7d8515SAlex Williamson                              QEMU_PCI_VGA_MEM_BASE, QEMU_PCI_VGA_MEM_SIZE);
180ba7d8515SAlex Williamson 
181ba7d8515SAlex Williamson     if (brctl & PCI_BRIDGE_CTL_VGA) {
182f055e96bSAndreas Färber         pci_register_vga(pd, &alias_vga[QEMU_PCI_VGA_MEM],
183ba7d8515SAlex Williamson                          &alias_vga[QEMU_PCI_VGA_IO_LO],
184ba7d8515SAlex Williamson                          &alias_vga[QEMU_PCI_VGA_IO_HI]);
185ba7d8515SAlex Williamson     }
186ba7d8515SAlex Williamson }
187ba7d8515SAlex Williamson 
pci_bridge_region_init(PCIBridge * br)188b2999ed8SJonathan Cameron static void pci_bridge_region_init(PCIBridge *br)
189315a1350SMichael S. Tsirkin {
190f055e96bSAndreas Färber     PCIDevice *pd = PCI_DEVICE(br);
191fd56e061SDavid Gibson     PCIBus *parent = pci_get_bus(pd);
192b2999ed8SJonathan Cameron     PCIBridgeWindows *w = &br->windows;
193f055e96bSAndreas Färber     uint16_t cmd = pci_get_word(pd->config + PCI_COMMAND);
194315a1350SMichael S. Tsirkin 
195315a1350SMichael S. Tsirkin     pci_bridge_init_alias(br, &w->alias_pref_mem,
196315a1350SMichael S. Tsirkin                           PCI_BASE_ADDRESS_MEM_PREFETCH,
197315a1350SMichael S. Tsirkin                           "pci_bridge_pref_mem",
198315a1350SMichael S. Tsirkin                           &br->address_space_mem,
199315a1350SMichael S. Tsirkin                           parent->address_space_mem,
200315a1350SMichael S. Tsirkin                           cmd & PCI_COMMAND_MEMORY);
201315a1350SMichael S. Tsirkin     pci_bridge_init_alias(br, &w->alias_mem,
202315a1350SMichael S. Tsirkin                           PCI_BASE_ADDRESS_SPACE_MEMORY,
203315a1350SMichael S. Tsirkin                           "pci_bridge_mem",
204315a1350SMichael S. Tsirkin                           &br->address_space_mem,
205315a1350SMichael S. Tsirkin                           parent->address_space_mem,
206315a1350SMichael S. Tsirkin                           cmd & PCI_COMMAND_MEMORY);
207315a1350SMichael S. Tsirkin     pci_bridge_init_alias(br, &w->alias_io,
208315a1350SMichael S. Tsirkin                           PCI_BASE_ADDRESS_SPACE_IO,
209315a1350SMichael S. Tsirkin                           "pci_bridge_io",
210315a1350SMichael S. Tsirkin                           &br->address_space_io,
211315a1350SMichael S. Tsirkin                           parent->address_space_io,
212315a1350SMichael S. Tsirkin                           cmd & PCI_COMMAND_IO);
213ba7d8515SAlex Williamson 
214ba7d8515SAlex Williamson     pci_bridge_init_vga_aliases(br, parent, w->alias_vga);
215315a1350SMichael S. Tsirkin }
216315a1350SMichael S. Tsirkin 
pci_bridge_region_del(PCIBridge * br,PCIBridgeWindows * w)217315a1350SMichael S. Tsirkin static void pci_bridge_region_del(PCIBridge *br, PCIBridgeWindows *w)
218315a1350SMichael S. Tsirkin {
219f055e96bSAndreas Färber     PCIDevice *pd = PCI_DEVICE(br);
220fd56e061SDavid Gibson     PCIBus *parent = pci_get_bus(pd);
221315a1350SMichael S. Tsirkin 
222315a1350SMichael S. Tsirkin     memory_region_del_subregion(parent->address_space_io, &w->alias_io);
223315a1350SMichael S. Tsirkin     memory_region_del_subregion(parent->address_space_mem, &w->alias_mem);
224315a1350SMichael S. Tsirkin     memory_region_del_subregion(parent->address_space_mem, &w->alias_pref_mem);
225f055e96bSAndreas Färber     pci_unregister_vga(pd);
226315a1350SMichael S. Tsirkin }
227315a1350SMichael S. Tsirkin 
pci_bridge_region_cleanup(PCIBridge * br,PCIBridgeWindows * w)228315a1350SMichael S. Tsirkin static void pci_bridge_region_cleanup(PCIBridge *br, PCIBridgeWindows *w)
229315a1350SMichael S. Tsirkin {
2309f6b2f1cSPaolo Bonzini     object_unparent(OBJECT(&w->alias_io));
2319f6b2f1cSPaolo Bonzini     object_unparent(OBJECT(&w->alias_mem));
2329f6b2f1cSPaolo Bonzini     object_unparent(OBJECT(&w->alias_pref_mem));
2339f6b2f1cSPaolo Bonzini     object_unparent(OBJECT(&w->alias_vga[QEMU_PCI_VGA_IO_LO]));
2349f6b2f1cSPaolo Bonzini     object_unparent(OBJECT(&w->alias_vga[QEMU_PCI_VGA_IO_HI]));
2359f6b2f1cSPaolo Bonzini     object_unparent(OBJECT(&w->alias_vga[QEMU_PCI_VGA_MEM]));
236315a1350SMichael S. Tsirkin }
237315a1350SMichael S. Tsirkin 
pci_bridge_update_mappings(PCIBridge * br)238e78e9ae4SDon Koch void pci_bridge_update_mappings(PCIBridge *br)
239315a1350SMichael S. Tsirkin {
240b2999ed8SJonathan Cameron     PCIBridgeWindows *w = &br->windows;
241315a1350SMichael S. Tsirkin 
242315a1350SMichael S. Tsirkin     /* Make updates atomic to: handle the case of one VCPU updating the bridge
243315a1350SMichael S. Tsirkin      * while another accesses an unaffected region. */
244315a1350SMichael S. Tsirkin     memory_region_transaction_begin();
245b2999ed8SJonathan Cameron     pci_bridge_region_del(br, w);
246e7176cdbSMatthias Weckbecker     pci_bridge_region_cleanup(br, w);
247b2999ed8SJonathan Cameron     pci_bridge_region_init(br);
248315a1350SMichael S. Tsirkin     memory_region_transaction_commit();
249315a1350SMichael S. Tsirkin }
250315a1350SMichael S. Tsirkin 
251315a1350SMichael S. Tsirkin /* default write_config function for PCI-to-PCI bridge */
pci_bridge_write_config(PCIDevice * d,uint32_t address,uint32_t val,int len)252315a1350SMichael S. Tsirkin void pci_bridge_write_config(PCIDevice *d,
253315a1350SMichael S. Tsirkin                              uint32_t address, uint32_t val, int len)
254315a1350SMichael S. Tsirkin {
255f055e96bSAndreas Färber     PCIBridge *s = PCI_BRIDGE(d);
256315a1350SMichael S. Tsirkin     uint16_t oldctl = pci_get_word(d->config + PCI_BRIDGE_CONTROL);
257315a1350SMichael S. Tsirkin     uint16_t newctl;
258315a1350SMichael S. Tsirkin 
259315a1350SMichael S. Tsirkin     pci_default_write_config(d, address, val, len);
260315a1350SMichael S. Tsirkin 
261315a1350SMichael S. Tsirkin     if (ranges_overlap(address, len, PCI_COMMAND, 2) ||
262315a1350SMichael S. Tsirkin 
263315a1350SMichael S. Tsirkin         /* io base/limit */
264315a1350SMichael S. Tsirkin         ranges_overlap(address, len, PCI_IO_BASE, 2) ||
265315a1350SMichael S. Tsirkin 
266315a1350SMichael S. Tsirkin         /* memory base/limit, prefetchable base/limit and
267315a1350SMichael S. Tsirkin            io base/limit upper 16 */
268ba7d8515SAlex Williamson         ranges_overlap(address, len, PCI_MEMORY_BASE, 20) ||
269ba7d8515SAlex Williamson 
270ba7d8515SAlex Williamson         /* vga enable */
271ba7d8515SAlex Williamson         ranges_overlap(address, len, PCI_BRIDGE_CONTROL, 2)) {
272315a1350SMichael S. Tsirkin         pci_bridge_update_mappings(s);
273315a1350SMichael S. Tsirkin     }
274315a1350SMichael S. Tsirkin 
275315a1350SMichael S. Tsirkin     newctl = pci_get_word(d->config + PCI_BRIDGE_CONTROL);
276315a1350SMichael S. Tsirkin     if (~oldctl & newctl & PCI_BRIDGE_CTL_BUS_RESET) {
277315a1350SMichael S. Tsirkin         /* Trigger hot reset on 0->1 transition. */
27878e4d5cbSPeter Maydell         bus_cold_reset(BUS(&s->sec_bus));
279315a1350SMichael S. Tsirkin     }
280315a1350SMichael S. Tsirkin }
281315a1350SMichael S. Tsirkin 
pci_bridge_disable_base_limit(PCIDevice * dev)282315a1350SMichael S. Tsirkin void pci_bridge_disable_base_limit(PCIDevice *dev)
283315a1350SMichael S. Tsirkin {
284315a1350SMichael S. Tsirkin     uint8_t *conf = dev->config;
285315a1350SMichael S. Tsirkin 
286315a1350SMichael S. Tsirkin     pci_byte_test_and_set_mask(conf + PCI_IO_BASE,
287315a1350SMichael S. Tsirkin                                PCI_IO_RANGE_MASK & 0xff);
288315a1350SMichael S. Tsirkin     pci_byte_test_and_clear_mask(conf + PCI_IO_LIMIT,
289315a1350SMichael S. Tsirkin                                  PCI_IO_RANGE_MASK & 0xff);
290315a1350SMichael S. Tsirkin     pci_word_test_and_set_mask(conf + PCI_MEMORY_BASE,
291315a1350SMichael S. Tsirkin                                PCI_MEMORY_RANGE_MASK & 0xffff);
292315a1350SMichael S. Tsirkin     pci_word_test_and_clear_mask(conf + PCI_MEMORY_LIMIT,
293315a1350SMichael S. Tsirkin                                  PCI_MEMORY_RANGE_MASK & 0xffff);
294315a1350SMichael S. Tsirkin     pci_word_test_and_set_mask(conf + PCI_PREF_MEMORY_BASE,
295315a1350SMichael S. Tsirkin                                PCI_PREF_RANGE_MASK & 0xffff);
296315a1350SMichael S. Tsirkin     pci_word_test_and_clear_mask(conf + PCI_PREF_MEMORY_LIMIT,
297315a1350SMichael S. Tsirkin                                  PCI_PREF_RANGE_MASK & 0xffff);
298315a1350SMichael S. Tsirkin     pci_set_long(conf + PCI_PREF_BASE_UPPER32, 0);
299315a1350SMichael S. Tsirkin     pci_set_long(conf + PCI_PREF_LIMIT_UPPER32, 0);
300315a1350SMichael S. Tsirkin }
301315a1350SMichael S. Tsirkin 
302315a1350SMichael S. Tsirkin /* reset bridge specific configuration registers */
pci_bridge_reset(DeviceState * qdev)303315a1350SMichael S. Tsirkin void pci_bridge_reset(DeviceState *qdev)
304315a1350SMichael S. Tsirkin {
305315a1350SMichael S. Tsirkin     PCIDevice *dev = PCI_DEVICE(qdev);
306315a1350SMichael S. Tsirkin     uint8_t *conf = dev->config;
307315a1350SMichael S. Tsirkin 
308315a1350SMichael S. Tsirkin     conf[PCI_PRIMARY_BUS] = 0;
309315a1350SMichael S. Tsirkin     conf[PCI_SECONDARY_BUS] = 0;
310315a1350SMichael S. Tsirkin     conf[PCI_SUBORDINATE_BUS] = 0;
311315a1350SMichael S. Tsirkin     conf[PCI_SEC_LATENCY_TIMER] = 0;
312315a1350SMichael S. Tsirkin 
313315a1350SMichael S. Tsirkin     /*
314315a1350SMichael S. Tsirkin      * the default values for base/limit registers aren't specified
3155892cfc7SMao Zhongyi      * in the PCI-to-PCI-bridge spec. So we don't touch them here.
316315a1350SMichael S. Tsirkin      * Each implementation can override it.
317315a1350SMichael S. Tsirkin      * typical implementation does
318315a1350SMichael S. Tsirkin      * zero base/limit registers or
319315a1350SMichael S. Tsirkin      * disable forwarding: pci_bridge_disable_base_limit()
320315a1350SMichael S. Tsirkin      * If disable forwarding is wanted, call pci_bridge_disable_base_limit()
321315a1350SMichael S. Tsirkin      * after this function.
322315a1350SMichael S. Tsirkin      */
323315a1350SMichael S. Tsirkin     pci_byte_test_and_clear_mask(conf + PCI_IO_BASE,
324315a1350SMichael S. Tsirkin                                  PCI_IO_RANGE_MASK & 0xff);
325315a1350SMichael S. Tsirkin     pci_byte_test_and_clear_mask(conf + PCI_IO_LIMIT,
326315a1350SMichael S. Tsirkin                                  PCI_IO_RANGE_MASK & 0xff);
327315a1350SMichael S. Tsirkin     pci_word_test_and_clear_mask(conf + PCI_MEMORY_BASE,
328315a1350SMichael S. Tsirkin                                  PCI_MEMORY_RANGE_MASK & 0xffff);
329315a1350SMichael S. Tsirkin     pci_word_test_and_clear_mask(conf + PCI_MEMORY_LIMIT,
330315a1350SMichael S. Tsirkin                                  PCI_MEMORY_RANGE_MASK & 0xffff);
331315a1350SMichael S. Tsirkin     pci_word_test_and_clear_mask(conf + PCI_PREF_MEMORY_BASE,
332315a1350SMichael S. Tsirkin                                  PCI_PREF_RANGE_MASK & 0xffff);
333315a1350SMichael S. Tsirkin     pci_word_test_and_clear_mask(conf + PCI_PREF_MEMORY_LIMIT,
334315a1350SMichael S. Tsirkin                                  PCI_PREF_RANGE_MASK & 0xffff);
335315a1350SMichael S. Tsirkin     pci_set_long(conf + PCI_PREF_BASE_UPPER32, 0);
336315a1350SMichael S. Tsirkin     pci_set_long(conf + PCI_PREF_LIMIT_UPPER32, 0);
337315a1350SMichael S. Tsirkin 
338315a1350SMichael S. Tsirkin     pci_set_word(conf + PCI_BRIDGE_CONTROL, 0);
339315a1350SMichael S. Tsirkin }
340315a1350SMichael S. Tsirkin 
341315a1350SMichael S. Tsirkin /* default qdev initialization function for PCI-to-PCI bridge */
pci_bridge_initfn(PCIDevice * dev,const char * typename)3429cfaa007SCao jin void pci_bridge_initfn(PCIDevice *dev, const char *typename)
343315a1350SMichael S. Tsirkin {
344fd56e061SDavid Gibson     PCIBus *parent = pci_get_bus(dev);
345f055e96bSAndreas Färber     PCIBridge *br = PCI_BRIDGE(dev);
346315a1350SMichael S. Tsirkin     PCIBus *sec_bus = &br->sec_bus;
347315a1350SMichael S. Tsirkin 
348315a1350SMichael S. Tsirkin     pci_word_test_and_set_mask(dev->config + PCI_STATUS,
349315a1350SMichael S. Tsirkin                                PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK);
350ba7d8515SAlex Williamson 
351ba7d8515SAlex Williamson     /*
352ba7d8515SAlex Williamson      * TODO: We implement VGA Enable in the Bridge Control Register
353ba7d8515SAlex Williamson      * therefore per the PCI to PCI bridge spec we must also implement
354ba7d8515SAlex Williamson      * VGA Palette Snooping.  When done, set this bit writable:
355ba7d8515SAlex Williamson      *
356ba7d8515SAlex Williamson      * pci_word_test_and_set_mask(dev->wmask + PCI_COMMAND,
357ba7d8515SAlex Williamson      *                            PCI_COMMAND_VGA_PALETTE);
358ba7d8515SAlex Williamson      */
359ba7d8515SAlex Williamson 
360315a1350SMichael S. Tsirkin     pci_config_set_class(dev->config, PCI_CLASS_BRIDGE_PCI);
361315a1350SMichael S. Tsirkin     dev->config[PCI_HEADER_TYPE] =
362315a1350SMichael S. Tsirkin         (dev->config[PCI_HEADER_TYPE] & PCI_HEADER_TYPE_MULTI_FUNCTION) |
363315a1350SMichael S. Tsirkin         PCI_HEADER_TYPE_BRIDGE;
364315a1350SMichael S. Tsirkin     pci_set_word(dev->config + PCI_SEC_STATUS,
365315a1350SMichael S. Tsirkin                  PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK);
366315a1350SMichael S. Tsirkin 
367315a1350SMichael S. Tsirkin     /*
368315a1350SMichael S. Tsirkin      * If we don't specify the name, the bus will be addressed as <id>.0, where
369315a1350SMichael S. Tsirkin      * id is the device id.
370315a1350SMichael S. Tsirkin      * Since PCI Bridge devices have a single bus each, we don't need the index:
371315a1350SMichael S. Tsirkin      * let users address the bus using the device name.
372315a1350SMichael S. Tsirkin      */
373315a1350SMichael S. Tsirkin     if (!br->bus_name && dev->qdev.id && *dev->qdev.id) {
374315a1350SMichael S. Tsirkin             br->bus_name = dev->qdev.id;
375315a1350SMichael S. Tsirkin     }
376315a1350SMichael S. Tsirkin 
377d637e1dcSPeter Maydell     qbus_init(sec_bus, sizeof(br->sec_bus), typename, DEVICE(dev),
378fb17dfe0SAndreas Färber               br->bus_name);
379315a1350SMichael S. Tsirkin     sec_bus->parent_dev = dev;
380659fefeeSAlex Williamson     sec_bus->map_irq = br->map_irq ? br->map_irq : pci_swizzle_map_irq_fn;
381315a1350SMichael S. Tsirkin     sec_bus->address_space_mem = &br->address_space_mem;
382cf252e51SMichael S. Tsirkin     memory_region_init(&br->address_space_mem, OBJECT(br), "pci_bridge_pci", UINT64_MAX);
383*55fa4be6SGao Shiyuan     address_space_init(&br->as_mem, &br->address_space_mem,
384*55fa4be6SGao Shiyuan                        "pci_bridge_pci_mem");
385315a1350SMichael S. Tsirkin     sec_bus->address_space_io = &br->address_space_io;
3869cd1e97aSMark Cave-Ayland     memory_region_init(&br->address_space_io, OBJECT(br), "pci_bridge_io",
3872dc48da2SPhilippe Mathieu-Daudé                        4 * GiB);
388*55fa4be6SGao Shiyuan     address_space_init(&br->as_io, &br->address_space_io, "pci_bridge_pci_io");
389b2999ed8SJonathan Cameron     pci_bridge_region_init(br);
390315a1350SMichael S. Tsirkin     QLIST_INIT(&sec_bus->child);
391315a1350SMichael S. Tsirkin     QLIST_INSERT_HEAD(&parent->child, sec_bus, sibling);
3924565917bSMichael S. Tsirkin 
3934565917bSMichael S. Tsirkin     /* For express secondary buses, secondary latency timer is RO 0 */
3944565917bSMichael S. Tsirkin     if (pci_bus_is_express(sec_bus) && !br->pcie_writeable_slt_bug) {
3954565917bSMichael S. Tsirkin         dev->wmask[PCI_SEC_LATENCY_TIMER] = 0;
3964565917bSMichael S. Tsirkin     }
397315a1350SMichael S. Tsirkin }
398315a1350SMichael S. Tsirkin 
399315a1350SMichael S. Tsirkin /* default qdev clean up function for PCI-to-PCI bridge */
pci_bridge_exitfn(PCIDevice * pci_dev)400315a1350SMichael S. Tsirkin void pci_bridge_exitfn(PCIDevice *pci_dev)
401315a1350SMichael S. Tsirkin {
402f055e96bSAndreas Färber     PCIBridge *s = PCI_BRIDGE(pci_dev);
403315a1350SMichael S. Tsirkin     assert(QLIST_EMPTY(&s->sec_bus.child));
404315a1350SMichael S. Tsirkin     QLIST_REMOVE(&s->sec_bus, sibling);
405*55fa4be6SGao Shiyuan     address_space_destroy(&s->as_mem);
406*55fa4be6SGao Shiyuan     address_space_destroy(&s->as_io);
407b2999ed8SJonathan Cameron     pci_bridge_region_del(s, &s->windows);
408b2999ed8SJonathan Cameron     pci_bridge_region_cleanup(s, &s->windows);
4096780a22cSStefan Hajnoczi     /* object_unparent() is called automatically during device deletion */
410315a1350SMichael S. Tsirkin }
411315a1350SMichael S. Tsirkin 
412315a1350SMichael S. Tsirkin /*
413315a1350SMichael S. Tsirkin  * before qdev initialization(qdev_init()), this function sets bus_name and
414d05eec73SMao Zhongyi  * map_irq callback which are necessary for pci_bridge_initfn() to
415315a1350SMichael S. Tsirkin  * initialize bus.
416315a1350SMichael S. Tsirkin  */
pci_bridge_map_irq(PCIBridge * br,const char * bus_name,pci_map_irq_fn map_irq)417315a1350SMichael S. Tsirkin void pci_bridge_map_irq(PCIBridge *br, const char* bus_name,
418315a1350SMichael S. Tsirkin                         pci_map_irq_fn map_irq)
419315a1350SMichael S. Tsirkin {
420315a1350SMichael S. Tsirkin     br->map_irq = map_irq;
421315a1350SMichael S. Tsirkin     br->bus_name = bus_name;
422315a1350SMichael S. Tsirkin }
423f055e96bSAndreas Färber 
42470e1ee59SAleksandr Bezzubikov 
pci_bridge_qemu_reserve_cap_init(PCIDevice * dev,int cap_offset,PCIResReserve res_reserve,Error ** errp)42570e1ee59SAleksandr Bezzubikov int pci_bridge_qemu_reserve_cap_init(PCIDevice *dev, int cap_offset,
4269e899399SJing Liu                                      PCIResReserve res_reserve, Error **errp)
42770e1ee59SAleksandr Bezzubikov {
4289e899399SJing Liu     if (res_reserve.mem_pref_32 != (uint64_t)-1 &&
4299e899399SJing Liu         res_reserve.mem_pref_64 != (uint64_t)-1) {
43070e1ee59SAleksandr Bezzubikov         error_setg(errp,
43170e1ee59SAleksandr Bezzubikov                    "PCI resource reserve cap: PREF32 and PREF64 conflict");
43270e1ee59SAleksandr Bezzubikov         return -EINVAL;
43370e1ee59SAleksandr Bezzubikov     }
43470e1ee59SAleksandr Bezzubikov 
4359e899399SJing Liu     if (res_reserve.mem_non_pref != (uint64_t)-1 &&
43637e7211cSPhilippe Mathieu-Daudé         res_reserve.mem_non_pref >= 4 * GiB) {
437fc67208fSMarcel Apfelbaum         error_setg(errp,
438fc67208fSMarcel Apfelbaum                    "PCI resource reserve cap: mem-reserve must be less than 4G");
439fc67208fSMarcel Apfelbaum         return -EINVAL;
440fc67208fSMarcel Apfelbaum     }
441fc67208fSMarcel Apfelbaum 
4429e899399SJing Liu     if (res_reserve.mem_pref_32 != (uint64_t)-1 &&
44337e7211cSPhilippe Mathieu-Daudé         res_reserve.mem_pref_32 >= 4 * GiB) {
444fc67208fSMarcel Apfelbaum         error_setg(errp,
445fc67208fSMarcel Apfelbaum                    "PCI resource reserve cap: pref32-reserve  must be less than 4G");
446fc67208fSMarcel Apfelbaum         return -EINVAL;
447fc67208fSMarcel Apfelbaum     }
448fc67208fSMarcel Apfelbaum 
4499e899399SJing Liu     if (res_reserve.bus == (uint32_t)-1 &&
4509e899399SJing Liu         res_reserve.io == (uint64_t)-1 &&
4519e899399SJing Liu         res_reserve.mem_non_pref == (uint64_t)-1 &&
4529e899399SJing Liu         res_reserve.mem_pref_32 == (uint64_t)-1 &&
4539e899399SJing Liu         res_reserve.mem_pref_64 == (uint64_t)-1) {
45470e1ee59SAleksandr Bezzubikov         return 0;
45570e1ee59SAleksandr Bezzubikov     }
45670e1ee59SAleksandr Bezzubikov 
45770e1ee59SAleksandr Bezzubikov     size_t cap_len = sizeof(PCIBridgeQemuCap);
45870e1ee59SAleksandr Bezzubikov     PCIBridgeQemuCap cap = {
45970e1ee59SAleksandr Bezzubikov             .len = cap_len,
46070e1ee59SAleksandr Bezzubikov             .type = REDHAT_PCI_CAP_RESOURCE_RESERVE,
4610e464f7dSMichael S. Tsirkin             .bus_res = cpu_to_le32(res_reserve.bus),
4620e464f7dSMichael S. Tsirkin             .io = cpu_to_le64(res_reserve.io),
4630e464f7dSMichael S. Tsirkin             .mem = cpu_to_le32(res_reserve.mem_non_pref),
4640e464f7dSMichael S. Tsirkin             .mem_pref_32 = cpu_to_le32(res_reserve.mem_pref_32),
4650e464f7dSMichael S. Tsirkin             .mem_pref_64 = cpu_to_le64(res_reserve.mem_pref_64)
46670e1ee59SAleksandr Bezzubikov     };
46770e1ee59SAleksandr Bezzubikov 
46870e1ee59SAleksandr Bezzubikov     int offset = pci_add_capability(dev, PCI_CAP_ID_VNDR,
46970e1ee59SAleksandr Bezzubikov                                     cap_offset, cap_len, errp);
47070e1ee59SAleksandr Bezzubikov     if (offset < 0) {
47170e1ee59SAleksandr Bezzubikov         return offset;
47270e1ee59SAleksandr Bezzubikov     }
47370e1ee59SAleksandr Bezzubikov 
47470e1ee59SAleksandr Bezzubikov     memcpy(dev->config + offset + PCI_CAP_FLAGS,
47570e1ee59SAleksandr Bezzubikov            (char *)&cap + PCI_CAP_FLAGS,
47670e1ee59SAleksandr Bezzubikov            cap_len - PCI_CAP_FLAGS);
47770e1ee59SAleksandr Bezzubikov     return 0;
47870e1ee59SAleksandr Bezzubikov }
47970e1ee59SAleksandr Bezzubikov 
4804565917bSMichael S. Tsirkin static Property pci_bridge_properties[] = {
4814565917bSMichael S. Tsirkin     DEFINE_PROP_BOOL("x-pci-express-writeable-slt-bug", PCIBridge,
4824565917bSMichael S. Tsirkin                      pcie_writeable_slt_bug, false),
4834565917bSMichael S. Tsirkin     DEFINE_PROP_END_OF_LIST(),
4844565917bSMichael S. Tsirkin };
4854565917bSMichael S. Tsirkin 
pci_bridge_class_init(ObjectClass * klass,void * data)4866c36ec46SIgor Mammedov static void pci_bridge_class_init(ObjectClass *klass, void *data)
4876c36ec46SIgor Mammedov {
4886c36ec46SIgor Mammedov     AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass);
4894565917bSMichael S. Tsirkin     DeviceClass *k = DEVICE_CLASS(klass);
4906c36ec46SIgor Mammedov 
4914565917bSMichael S. Tsirkin     device_class_set_props(k, pci_bridge_properties);
4926c36ec46SIgor Mammedov     adevc->build_dev_aml = build_pci_bridge_aml;
4936c36ec46SIgor Mammedov }
4946c36ec46SIgor Mammedov 
495f055e96bSAndreas Färber static const TypeInfo pci_bridge_type_info = {
496f055e96bSAndreas Färber     .name = TYPE_PCI_BRIDGE,
497f055e96bSAndreas Färber     .parent = TYPE_PCI_DEVICE,
498f055e96bSAndreas Färber     .instance_size = sizeof(PCIBridge),
4996c36ec46SIgor Mammedov     .class_init = pci_bridge_class_init,
500f055e96bSAndreas Färber     .abstract = true,
501d78644c7SIgor Mammedov     .interfaces = (InterfaceInfo[]) {
502d78644c7SIgor Mammedov         { TYPE_ACPI_DEV_AML_IF },
503d78644c7SIgor Mammedov         { },
504d78644c7SIgor Mammedov     },
505f055e96bSAndreas Färber };
506f055e96bSAndreas Färber 
pci_bridge_register_types(void)507f055e96bSAndreas Färber static void pci_bridge_register_types(void)
508f055e96bSAndreas Färber {
509f055e96bSAndreas Färber     type_register_static(&pci_bridge_type_info);
510f055e96bSAndreas Färber }
511f055e96bSAndreas Färber 
512f055e96bSAndreas Färber type_init(pci_bridge_register_types)
513