| File: | hw/pci-host/q35.c |
| Location: | line 236, column 9 |
| Description: | Value stored to 'enable' is never read |
| 1 | /* |
| 2 | * QEMU MCH/ICH9 PCI Bridge Emulation |
| 3 | * |
| 4 | * Copyright (c) 2006 Fabrice Bellard |
| 5 | * Copyright (c) 2009, 2010, 2011 |
| 6 | * Isaku Yamahata <yamahata at valinux co jp> |
| 7 | * VA Linux Systems Japan K.K. |
| 8 | * Copyright (C) 2012 Jason Baron <jbaron@redhat.com> |
| 9 | * |
| 10 | * This is based on piix_pci.c, but heavily modified. |
| 11 | * |
| 12 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
| 13 | * of this software and associated documentation files (the "Software"), to deal |
| 14 | * in the Software without restriction, including without limitation the rights |
| 15 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 16 | * copies of the Software, and to permit persons to whom the Software is |
| 17 | * furnished to do so, subject to the following conditions: |
| 18 | * |
| 19 | * The above copyright notice and this permission notice shall be included in |
| 20 | * all copies or substantial portions of the Software. |
| 21 | * |
| 22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 23 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 24 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| 25 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 26 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 27 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| 28 | * THE SOFTWARE. |
| 29 | */ |
| 30 | #include "hw/hw.h" |
| 31 | #include "hw/pci-host/q35.h" |
| 32 | #include "qapi/visitor.h" |
| 33 | |
| 34 | /**************************************************************************** |
| 35 | * Q35 host |
| 36 | */ |
| 37 | |
| 38 | static void q35_host_realize(DeviceState *dev, Error **errp) |
| 39 | { |
| 40 | PCIHostState *pci = PCI_HOST_BRIDGE(dev)((PCIHostState *)object_dynamic_cast_assert(((Object *)((dev) )), ("pci-host-bridge"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 40, __func__)); |
| 41 | Q35PCIHost *s = Q35_HOST_DEVICE(dev)((Q35PCIHost *)object_dynamic_cast_assert(((Object *)((dev))) , ("q35-pcihost"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 41, __func__)); |
| 42 | SysBusDevice *sbd = SYS_BUS_DEVICE(dev)((SysBusDevice *)object_dynamic_cast_assert(((Object *)((dev) )), ("sys-bus-device"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 42, __func__)); |
| 43 | |
| 44 | sysbus_add_io(sbd, MCH_HOST_BRIDGE_CONFIG_ADDR0xcf8, &pci->conf_mem); |
| 45 | sysbus_init_ioports(sbd, MCH_HOST_BRIDGE_CONFIG_ADDR0xcf8, 4); |
| 46 | |
| 47 | sysbus_add_io(sbd, MCH_HOST_BRIDGE_CONFIG_DATA0xcfc, &pci->data_mem); |
| 48 | sysbus_init_ioports(sbd, MCH_HOST_BRIDGE_CONFIG_DATA0xcfc, 4); |
| 49 | |
| 50 | if (pcie_host_init(PCIE_HOST_BRIDGE(s)((PCIExpressHost *)object_dynamic_cast_assert(((Object *)((s) )), ("pcie-host-bridge"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 50, __func__))) < 0) { |
| 51 | error_setg(errp, "failed to initialize pcie host")error_set(errp, ERROR_CLASS_GENERIC_ERROR, "failed to initialize pcie host" ); |
| 52 | return; |
| 53 | } |
| 54 | pci->bus = pci_bus_new(DEVICE(s)((DeviceState *)object_dynamic_cast_assert(((Object *)((s))), ("device"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 54, __func__)), "pcie.0", |
| 55 | s->mch.pci_address_space, s->mch.address_space_io, |
| 56 | 0, TYPE_PCIE_BUS"PCIE"); |
| 57 | qdev_set_parent_bus(DEVICE(&s->mch)((DeviceState *)object_dynamic_cast_assert(((Object *)((& s->mch))), ("device"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 57, __func__)), BUS(pci->bus)((BusState *)object_dynamic_cast_assert(((Object *)((pci-> bus))), ("bus"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 57, __func__))); |
| 58 | qdev_init_nofail(DEVICE(&s->mch)((DeviceState *)object_dynamic_cast_assert(((Object *)((& s->mch))), ("device"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 58, __func__))); |
| 59 | } |
| 60 | |
| 61 | static const char *q35_host_root_bus_path(PCIHostState *host_bridge, |
| 62 | PCIBus *rootbus) |
| 63 | { |
| 64 | Q35PCIHost *s = Q35_HOST_DEVICE(host_bridge)((Q35PCIHost *)object_dynamic_cast_assert(((Object *)((host_bridge ))), ("q35-pcihost"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 64, __func__)); |
| 65 | |
| 66 | /* For backwards compat with old device paths */ |
| 67 | if (s->mch.short_root_bus) { |
| 68 | return "0000"; |
| 69 | } |
| 70 | return "0000:00"; |
| 71 | } |
| 72 | |
| 73 | static void q35_host_get_pci_hole_start(Object *obj, Visitor *v, |
| 74 | void *opaque, const char *name, |
| 75 | Error **errp) |
| 76 | { |
| 77 | Q35PCIHost *s = Q35_HOST_DEVICE(obj)((Q35PCIHost *)object_dynamic_cast_assert(((Object *)((obj))) , ("q35-pcihost"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 77, __func__)); |
| 78 | uint32_t value = s->mch.pci_info.w32.begin; |
| 79 | |
| 80 | visit_type_uint32(v, &value, name, errp); |
| 81 | } |
| 82 | |
| 83 | static void q35_host_get_pci_hole_end(Object *obj, Visitor *v, |
| 84 | void *opaque, const char *name, |
| 85 | Error **errp) |
| 86 | { |
| 87 | Q35PCIHost *s = Q35_HOST_DEVICE(obj)((Q35PCIHost *)object_dynamic_cast_assert(((Object *)((obj))) , ("q35-pcihost"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 87, __func__)); |
| 88 | uint32_t value = s->mch.pci_info.w32.end; |
| 89 | |
| 90 | visit_type_uint32(v, &value, name, errp); |
| 91 | } |
| 92 | |
| 93 | static void q35_host_get_pci_hole64_start(Object *obj, Visitor *v, |
| 94 | void *opaque, const char *name, |
| 95 | Error **errp) |
| 96 | { |
| 97 | PCIHostState *h = PCI_HOST_BRIDGE(obj)((PCIHostState *)object_dynamic_cast_assert(((Object *)((obj) )), ("pci-host-bridge"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 97, __func__)); |
| 98 | Range w64; |
| 99 | |
| 100 | pci_bus_get_w64_range(h->bus, &w64); |
| 101 | |
| 102 | visit_type_uint64(v, &w64.begin, name, errp); |
| 103 | } |
| 104 | |
| 105 | static void q35_host_get_pci_hole64_end(Object *obj, Visitor *v, |
| 106 | void *opaque, const char *name, |
| 107 | Error **errp) |
| 108 | { |
| 109 | PCIHostState *h = PCI_HOST_BRIDGE(obj)((PCIHostState *)object_dynamic_cast_assert(((Object *)((obj) )), ("pci-host-bridge"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 109, __func__)); |
| 110 | Range w64; |
| 111 | |
| 112 | pci_bus_get_w64_range(h->bus, &w64); |
| 113 | |
| 114 | visit_type_uint64(v, &w64.end, name, errp); |
| 115 | } |
| 116 | |
| 117 | static void q35_host_get_mmcfg_size(Object *obj, Visitor *v, |
| 118 | void *opaque, const char *name, |
| 119 | Error **errp) |
| 120 | { |
| 121 | PCIExpressHost *e = PCIE_HOST_BRIDGE(obj)((PCIExpressHost *)object_dynamic_cast_assert(((Object *)((obj ))), ("pcie-host-bridge"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 121, __func__)); |
| 122 | uint32_t value = e->size; |
| 123 | |
| 124 | visit_type_uint32(v, &value, name, errp); |
| 125 | } |
| 126 | |
| 127 | static Property mch_props[] = { |
| 128 | DEFINE_PROP_UINT64(PCIE_HOST_MCFG_BASE, Q35PCIHost, parent_obj.base_addr,{ .name = ("MCFG"), .info = &(qdev_prop_uint64), .offset = __builtin_offsetof(Q35PCIHost, parent_obj.base_addr) + ((uint64_t *)0 - (typeof(((Q35PCIHost *)0)->parent_obj.base_addr)*)0) , .qtype = QTYPE_QINT, .defval = (uint64_t)0xb0000000, } |
| 129 | MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT){ .name = ("MCFG"), .info = &(qdev_prop_uint64), .offset = __builtin_offsetof(Q35PCIHost, parent_obj.base_addr) + ((uint64_t *)0 - (typeof(((Q35PCIHost *)0)->parent_obj.base_addr)*)0) , .qtype = QTYPE_QINT, .defval = (uint64_t)0xb0000000, }, |
| 130 | DEFINE_PROP_SIZE(PCI_HOST_PROP_PCI_HOLE64_SIZE, Q35PCIHost,{ .name = ("pci-hole64-size"), .info = &(qdev_prop_size), .offset = __builtin_offsetof(Q35PCIHost, mch.pci_hole64_size ) + ((uint64_t*)0 - (typeof(((Q35PCIHost *)0)->mch.pci_hole64_size )*)0), .qtype = QTYPE_QINT, .defval = (uint64_t)(~0x0ULL), } |
| 131 | mch.pci_hole64_size, DEFAULT_PCI_HOLE64_SIZE){ .name = ("pci-hole64-size"), .info = &(qdev_prop_size), .offset = __builtin_offsetof(Q35PCIHost, mch.pci_hole64_size ) + ((uint64_t*)0 - (typeof(((Q35PCIHost *)0)->mch.pci_hole64_size )*)0), .qtype = QTYPE_QINT, .defval = (uint64_t)(~0x0ULL), }, |
| 132 | DEFINE_PROP_UINT32("short_root_bus", Q35PCIHost, mch.short_root_bus, 0){ .name = ("short_root_bus"), .info = &(qdev_prop_uint32) , .offset = __builtin_offsetof(Q35PCIHost, mch.short_root_bus ) + ((uint32_t*)0 - (typeof(((Q35PCIHost *)0)->mch.short_root_bus )*)0), .qtype = QTYPE_QINT, .defval = (uint32_t)0, }, |
| 133 | DEFINE_PROP_END_OF_LIST(){}, |
| 134 | }; |
| 135 | |
| 136 | static void q35_host_class_init(ObjectClass *klass, void *data) |
| 137 | { |
| 138 | DeviceClass *dc = DEVICE_CLASS(klass)((DeviceClass *)object_class_dynamic_cast_assert(((ObjectClass *)((klass))), ("device"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 138, __func__)); |
| 139 | PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass)((PCIHostBridgeClass *)object_class_dynamic_cast_assert(((ObjectClass *)((klass))), ("pci-host-bridge"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 139, __func__)); |
| 140 | |
| 141 | hc->root_bus_path = q35_host_root_bus_path; |
| 142 | dc->realize = q35_host_realize; |
| 143 | dc->props = mch_props; |
| 144 | set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); |
| 145 | dc->fw_name = "pci"; |
| 146 | } |
| 147 | |
| 148 | static void q35_host_initfn(Object *obj) |
| 149 | { |
| 150 | Q35PCIHost *s = Q35_HOST_DEVICE(obj)((Q35PCIHost *)object_dynamic_cast_assert(((Object *)((obj))) , ("q35-pcihost"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 150, __func__)); |
| 151 | PCIHostState *phb = PCI_HOST_BRIDGE(obj)((PCIHostState *)object_dynamic_cast_assert(((Object *)((obj) )), ("pci-host-bridge"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 151, __func__)); |
| 152 | |
| 153 | memory_region_init_io(&phb->conf_mem, obj, &pci_host_conf_le_ops, phb, |
| 154 | "pci-conf-idx", 4); |
| 155 | memory_region_init_io(&phb->data_mem, obj, &pci_host_data_le_ops, phb, |
| 156 | "pci-conf-data", 4); |
| 157 | |
| 158 | object_initialize(&s->mch, sizeof(s->mch), TYPE_MCH_PCI_DEVICE"mch"); |
| 159 | object_property_add_child(OBJECT(s)((Object *)(s)), "mch", OBJECT(&s->mch)((Object *)(&s->mch)), NULL((void*)0)); |
| 160 | qdev_prop_set_uint32(DEVICE(&s->mch)((DeviceState *)object_dynamic_cast_assert(((Object *)((& s->mch))), ("device"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 160, __func__)), "addr", PCI_DEVFN(0, 0)((((0) & 0x1f) << 3) | ((0) & 0x07))); |
| 161 | qdev_prop_set_bit(DEVICE(&s->mch)((DeviceState *)object_dynamic_cast_assert(((Object *)((& s->mch))), ("device"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 161, __func__)), "multifunction", false0); |
| 162 | |
| 163 | object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START"pci-hole-start", "int", |
| 164 | q35_host_get_pci_hole_start, |
| 165 | NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0)); |
| 166 | |
| 167 | object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_END"pci-hole-end", "int", |
| 168 | q35_host_get_pci_hole_end, |
| 169 | NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0)); |
| 170 | |
| 171 | object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_START"pci-hole64-start", "int", |
| 172 | q35_host_get_pci_hole64_start, |
| 173 | NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0)); |
| 174 | |
| 175 | object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END"pci-hole64-end", "int", |
| 176 | q35_host_get_pci_hole64_end, |
| 177 | NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0)); |
| 178 | |
| 179 | object_property_add(obj, PCIE_HOST_MCFG_SIZE"mcfg_size", "int", |
| 180 | q35_host_get_mmcfg_size, |
| 181 | NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0)); |
| 182 | |
| 183 | /* Leave enough space for the biggest MCFG BAR */ |
| 184 | /* TODO: this matches current bios behaviour, but |
| 185 | * it's not a power of two, which means an MTRR |
| 186 | * can't cover it exactly. |
| 187 | */ |
| 188 | s->mch.pci_info.w32.begin = MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT0xb0000000 + |
| 189 | MCH_HOST_BRIDGE_PCIEXBAR_MAX(0x10000000); |
| 190 | s->mch.pci_info.w32.end = IO_APIC_DEFAULT_ADDRESS0xfec00000; |
| 191 | } |
| 192 | |
| 193 | static const TypeInfo q35_host_info = { |
| 194 | .name = TYPE_Q35_HOST_DEVICE"q35-pcihost", |
| 195 | .parent = TYPE_PCIE_HOST_BRIDGE"pcie-host-bridge", |
| 196 | .instance_size = sizeof(Q35PCIHost), |
| 197 | .instance_init = q35_host_initfn, |
| 198 | .class_init = q35_host_class_init, |
| 199 | }; |
| 200 | |
| 201 | /**************************************************************************** |
| 202 | * MCH D0:F0 |
| 203 | */ |
| 204 | |
| 205 | /* PCIe MMCFG */ |
| 206 | static void mch_update_pciexbar(MCHPCIState *mch) |
| 207 | { |
| 208 | PCIDevice *pci_dev = PCI_DEVICE(mch)((PCIDevice *)object_dynamic_cast_assert(((Object *)((mch))), ("pci-device"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 208, __func__)); |
| 209 | BusState *bus = qdev_get_parent_bus(DEVICE(mch)((DeviceState *)object_dynamic_cast_assert(((Object *)((mch)) ), ("device"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 209, __func__))); |
| 210 | PCIExpressHost *pehb = PCIE_HOST_BRIDGE(bus->parent)((PCIExpressHost *)object_dynamic_cast_assert(((Object *)((bus ->parent))), ("pcie-host-bridge"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 210, __func__)); |
| 211 | |
| 212 | uint64_t pciexbar; |
| 213 | int enable; |
| 214 | uint64_t addr; |
| 215 | uint64_t addr_mask; |
| 216 | uint32_t length; |
| 217 | |
| 218 | pciexbar = pci_get_quad(pci_dev->config + MCH_HOST_BRIDGE_PCIEXBAR0x60); |
| 219 | enable = pciexbar & MCH_HOST_BRIDGE_PCIEXBAREN((uint64_t)1); |
| 220 | addr_mask = MCH_HOST_BRIDGE_PCIEXBAR_ADMSK((uint64_t)(((1ULL << ((35) + 1)) - 1) & ~((1ULL << 28) - 1))); |
| 221 | switch (pciexbar & MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_MASK((uint64_t)(0x3 << 1))) { |
| 222 | case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_256M((uint64_t)(0x0 << 1)): |
| 223 | length = 256 * 1024 * 1024; |
| 224 | break; |
| 225 | case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_128M((uint64_t)(0x1 << 1)): |
| 226 | length = 128 * 1024 * 1024; |
| 227 | addr_mask |= MCH_HOST_BRIDGE_PCIEXBAR_128ADMSK((uint64_t)(1 << 26)) | |
| 228 | MCH_HOST_BRIDGE_PCIEXBAR_64ADMSK((uint64_t)(1 << 25)); |
| 229 | break; |
| 230 | case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_64M((uint64_t)(0x2 << 1)): |
| 231 | length = 64 * 1024 * 1024; |
| 232 | addr_mask |= MCH_HOST_BRIDGE_PCIEXBAR_64ADMSK((uint64_t)(1 << 25)); |
| 233 | break; |
| 234 | case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_RVD((uint64_t)(0x3 << 1)): |
| 235 | default: |
| 236 | enable = 0; |
Value stored to 'enable' is never read | |
| 237 | length = 0; |
| 238 | abort(); |
| 239 | break; |
| 240 | } |
| 241 | addr = pciexbar & addr_mask; |
| 242 | pcie_host_mmcfg_update(pehb, enable, addr, length); |
| 243 | /* Leave enough space for the MCFG BAR */ |
| 244 | /* |
| 245 | * TODO: this matches current bios behaviour, but it's not a power of two, |
| 246 | * which means an MTRR can't cover it exactly. |
| 247 | */ |
| 248 | if (enable) { |
| 249 | mch->pci_info.w32.begin = addr + length; |
| 250 | } else { |
| 251 | mch->pci_info.w32.begin = MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT0xb0000000; |
| 252 | } |
| 253 | } |
| 254 | |
| 255 | /* PAM */ |
| 256 | static void mch_update_pam(MCHPCIState *mch) |
| 257 | { |
| 258 | PCIDevice *pd = PCI_DEVICE(mch)((PCIDevice *)object_dynamic_cast_assert(((Object *)((mch))), ("pci-device"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 258, __func__)); |
| 259 | int i; |
| 260 | |
| 261 | memory_region_transaction_begin(); |
| 262 | for (i = 0; i < 13; i++) { |
| 263 | pam_update(&mch->pam_regions[i], i, |
| 264 | pd->config[MCH_HOST_BRIDGE_PAM00x90 + ((i + 1) / 2)]); |
| 265 | } |
| 266 | memory_region_transaction_commit(); |
| 267 | } |
| 268 | |
| 269 | /* SMRAM */ |
| 270 | static void mch_update_smram(MCHPCIState *mch) |
| 271 | { |
| 272 | PCIDevice *pd = PCI_DEVICE(mch)((PCIDevice *)object_dynamic_cast_assert(((Object *)((mch))), ("pci-device"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 272, __func__)); |
| 273 | |
| 274 | memory_region_transaction_begin(); |
| 275 | smram_update(&mch->smram_region, pd->config[MCH_HOST_BRDIGE_SMRAM0x9d], |
| 276 | mch->smm_enabled); |
| 277 | memory_region_transaction_commit(); |
| 278 | } |
| 279 | |
| 280 | static void mch_set_smm(int smm, void *arg) |
| 281 | { |
| 282 | MCHPCIState *mch = arg; |
| 283 | PCIDevice *pd = PCI_DEVICE(mch)((PCIDevice *)object_dynamic_cast_assert(((Object *)((mch))), ("pci-device"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 283, __func__)); |
| 284 | |
| 285 | memory_region_transaction_begin(); |
| 286 | smram_set_smm(&mch->smm_enabled, smm, pd->config[MCH_HOST_BRDIGE_SMRAM0x9d], |
| 287 | &mch->smram_region); |
| 288 | memory_region_transaction_commit(); |
| 289 | } |
| 290 | |
| 291 | static void mch_write_config(PCIDevice *d, |
| 292 | uint32_t address, uint32_t val, int len) |
| 293 | { |
| 294 | MCHPCIState *mch = MCH_PCI_DEVICE(d)((MCHPCIState *)object_dynamic_cast_assert(((Object *)((d))), ("mch"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 294, __func__)); |
| 295 | |
| 296 | /* XXX: implement SMRAM.D_LOCK */ |
| 297 | pci_default_write_config(d, address, val, len); |
| 298 | |
| 299 | if (ranges_overlap(address, len, MCH_HOST_BRIDGE_PAM00x90, |
| 300 | MCH_HOST_BRIDGE_PAM_SIZE7)) { |
| 301 | mch_update_pam(mch); |
| 302 | } |
| 303 | |
| 304 | if (ranges_overlap(address, len, MCH_HOST_BRIDGE_PCIEXBAR0x60, |
| 305 | MCH_HOST_BRIDGE_PCIEXBAR_SIZE8)) { |
| 306 | mch_update_pciexbar(mch); |
| 307 | } |
| 308 | |
| 309 | if (ranges_overlap(address, len, MCH_HOST_BRDIGE_SMRAM0x9d, |
| 310 | MCH_HOST_BRDIGE_SMRAM_SIZE1)) { |
| 311 | mch_update_smram(mch); |
| 312 | } |
| 313 | } |
| 314 | |
| 315 | static void mch_update(MCHPCIState *mch) |
| 316 | { |
| 317 | mch_update_pciexbar(mch); |
| 318 | mch_update_pam(mch); |
| 319 | mch_update_smram(mch); |
| 320 | } |
| 321 | |
| 322 | static int mch_post_load(void *opaque, int version_id) |
| 323 | { |
| 324 | MCHPCIState *mch = opaque; |
| 325 | mch_update(mch); |
| 326 | return 0; |
| 327 | } |
| 328 | |
| 329 | static const VMStateDescription vmstate_mch = { |
| 330 | .name = "mch", |
| 331 | .version_id = 1, |
| 332 | .minimum_version_id = 1, |
| 333 | .minimum_version_id_old = 1, |
| 334 | .post_load = mch_post_load, |
| 335 | .fields = (VMStateField []) { |
| 336 | VMSTATE_PCI_DEVICE(parent_obj, MCHPCIState){ .name = ("parent_obj"), .size = sizeof(PCIDevice), .vmsd = & vmstate_pci_device, .flags = VMS_STRUCT, .offset = (__builtin_offsetof (MCHPCIState, parent_obj) + ((PCIDevice*)0 - (typeof(((MCHPCIState *)0)->parent_obj)*)0)), }, |
| 337 | VMSTATE_UINT8(smm_enabled, MCHPCIState){ .name = ("smm_enabled"), .version_id = (0), .field_exists = (((void*)0)), .size = sizeof(uint8_t), .info = &(vmstate_info_uint8 ), .flags = VMS_SINGLE, .offset = (__builtin_offsetof(MCHPCIState , smm_enabled) + ((uint8_t*)0 - (typeof(((MCHPCIState *)0)-> smm_enabled)*)0)), }, |
| 338 | VMSTATE_END_OF_LIST(){} |
| 339 | } |
| 340 | }; |
| 341 | |
| 342 | static void mch_reset(DeviceState *qdev) |
| 343 | { |
| 344 | PCIDevice *d = PCI_DEVICE(qdev)((PCIDevice *)object_dynamic_cast_assert(((Object *)((qdev))) , ("pci-device"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 344, __func__)); |
| 345 | MCHPCIState *mch = MCH_PCI_DEVICE(d)((MCHPCIState *)object_dynamic_cast_assert(((Object *)((d))), ("mch"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 345, __func__)); |
| 346 | |
| 347 | pci_set_quad(d->config + MCH_HOST_BRIDGE_PCIEXBAR0x60, |
| 348 | MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT0xb0000000); |
| 349 | |
| 350 | d->config[MCH_HOST_BRDIGE_SMRAM0x9d] = MCH_HOST_BRIDGE_SMRAM_DEFAULT((uint8_t)0x2); |
| 351 | |
| 352 | mch_update(mch); |
| 353 | } |
| 354 | |
| 355 | static int mch_init(PCIDevice *d) |
| 356 | { |
| 357 | int i; |
| 358 | MCHPCIState *mch = MCH_PCI_DEVICE(d)((MCHPCIState *)object_dynamic_cast_assert(((Object *)((d))), ("mch"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 358, __func__)); |
| 359 | |
| 360 | /* setup pci memory mapping */ |
| 361 | pc_pci_as_mapping_init(OBJECT(mch)((Object *)(mch)), mch->system_memory, |
| 362 | mch->pci_address_space); |
| 363 | |
| 364 | /* smram */ |
| 365 | cpu_smm_register(&mch_set_smm, mch); |
| 366 | memory_region_init_alias(&mch->smram_region, OBJECT(mch)((Object *)(mch)), "smram-region", |
| 367 | mch->pci_address_space, 0xa0000, 0x20000); |
| 368 | memory_region_add_subregion_overlap(mch->system_memory, 0xa0000, |
| 369 | &mch->smram_region, 1); |
| 370 | memory_region_set_enabled(&mch->smram_region, false0); |
| 371 | init_pam(DEVICE(mch)((DeviceState *)object_dynamic_cast_assert(((Object *)((mch)) ), ("device"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 371, __func__)), mch->ram_memory, mch->system_memory, mch->pci_address_space, |
| 372 | &mch->pam_regions[0], PAM_BIOS_BASE0xf0000, PAM_BIOS_SIZE0x10000); |
| 373 | for (i = 0; i < 12; ++i) { |
| 374 | init_pam(DEVICE(mch)((DeviceState *)object_dynamic_cast_assert(((Object *)((mch)) ), ("device"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 374, __func__)), mch->ram_memory, mch->system_memory, mch->pci_address_space, |
| 375 | &mch->pam_regions[i+1], PAM_EXPAN_BASE0xc0000 + i * PAM_EXPAN_SIZE0x04000, |
| 376 | PAM_EXPAN_SIZE0x04000); |
| 377 | } |
| 378 | return 0; |
| 379 | } |
| 380 | |
| 381 | uint64_t mch_mcfg_base(void) |
| 382 | { |
| 383 | bool_Bool ambiguous; |
| 384 | Object *o = object_resolve_path_type("", TYPE_MCH_PCI_DEVICE"mch", &ambiguous); |
| 385 | if (!o) { |
| 386 | return 0; |
| 387 | } |
| 388 | return MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT0xb0000000; |
| 389 | } |
| 390 | |
| 391 | static void mch_class_init(ObjectClass *klass, void *data) |
| 392 | { |
| 393 | PCIDeviceClass *k = PCI_DEVICE_CLASS(klass)((PCIDeviceClass *)object_class_dynamic_cast_assert(((ObjectClass *)((klass))), ("pci-device"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 393, __func__)); |
| 394 | DeviceClass *dc = DEVICE_CLASS(klass)((DeviceClass *)object_class_dynamic_cast_assert(((ObjectClass *)((klass))), ("device"), "/home/stefan/src/qemu/qemu.org/qemu/hw/pci-host/q35.c" , 394, __func__)); |
| 395 | |
| 396 | k->init = mch_init; |
| 397 | k->config_write = mch_write_config; |
| 398 | dc->reset = mch_reset; |
| 399 | set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); |
| 400 | dc->desc = "Host bridge"; |
| 401 | dc->vmsd = &vmstate_mch; |
| 402 | k->vendor_id = PCI_VENDOR_ID_INTEL0x8086; |
| 403 | k->device_id = PCI_DEVICE_ID_INTEL_Q35_MCH0x29c0; |
| 404 | k->revision = MCH_HOST_BRIDGE_REVISION_DEFAULT0x0; |
| 405 | k->class_id = PCI_CLASS_BRIDGE_HOST0x0600; |
| 406 | /* |
| 407 | * PCI-facing part of the host bridge, not usable without the |
| 408 | * host-facing part, which can't be device_add'ed, yet. |
| 409 | */ |
| 410 | dc->cannot_instantiate_with_device_add_yet = true1; |
| 411 | } |
| 412 | |
| 413 | static const TypeInfo mch_info = { |
| 414 | .name = TYPE_MCH_PCI_DEVICE"mch", |
| 415 | .parent = TYPE_PCI_DEVICE"pci-device", |
| 416 | .instance_size = sizeof(MCHPCIState), |
| 417 | .class_init = mch_class_init, |
| 418 | }; |
| 419 | |
| 420 | static void q35_register(void) |
| 421 | { |
| 422 | type_register_static(&mch_info); |
| 423 | type_register_static(&q35_host_info); |
| 424 | } |
| 425 | |
| 426 | type_init(q35_register)static void __attribute__((constructor)) do_qemu_init_q35_register (void) { register_module_init(q35_register, MODULE_INIT_QOM); }; |