1 /* 2 * s390 PCI BUS 3 * 4 * Copyright 2014 IBM Corp. 5 * Author(s): Frank Blaschka <frank.blaschka@de.ibm.com> 6 * Hong Bo Li <lihbbj@cn.ibm.com> 7 * Yi Min Zhao <zyimin@cn.ibm.com> 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2 or (at 10 * your option) any later version. See the COPYING file in the top-level 11 * directory. 12 */ 13 14 #include "qemu/osdep.h" 15 #include "qemu-common.h" 16 #include "cpu.h" 17 #include "s390-pci-bus.h" 18 #include "s390-pci-inst.h" 19 #include <hw/pci/pci_bus.h> 20 #include <hw/pci/msi.h> 21 #include <qemu/error-report.h> 22 23 /* #define DEBUG_S390PCI_BUS */ 24 #ifdef DEBUG_S390PCI_BUS 25 #define DPRINTF(fmt, ...) \ 26 do { fprintf(stderr, "S390pci-bus: " fmt, ## __VA_ARGS__); } while (0) 27 #else 28 #define DPRINTF(fmt, ...) \ 29 do { } while (0) 30 #endif 31 32 int chsc_sei_nt2_get_event(void *res) 33 { 34 ChscSeiNt2Res *nt2_res = (ChscSeiNt2Res *)res; 35 PciCcdfAvail *accdf; 36 PciCcdfErr *eccdf; 37 int rc = 1; 38 SeiContainer *sei_cont; 39 S390pciState *s = S390_PCI_HOST_BRIDGE( 40 object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL)); 41 42 if (!s) { 43 return rc; 44 } 45 46 sei_cont = QTAILQ_FIRST(&s->pending_sei); 47 if (sei_cont) { 48 QTAILQ_REMOVE(&s->pending_sei, sei_cont, link); 49 nt2_res->nt = 2; 50 nt2_res->cc = sei_cont->cc; 51 nt2_res->length = cpu_to_be16(sizeof(ChscSeiNt2Res)); 52 switch (sei_cont->cc) { 53 case 1: /* error event */ 54 eccdf = (PciCcdfErr *)nt2_res->ccdf; 55 eccdf->fid = cpu_to_be32(sei_cont->fid); 56 eccdf->fh = cpu_to_be32(sei_cont->fh); 57 eccdf->e = cpu_to_be32(sei_cont->e); 58 eccdf->faddr = cpu_to_be64(sei_cont->faddr); 59 eccdf->pec = cpu_to_be16(sei_cont->pec); 60 break; 61 case 2: /* availability event */ 62 accdf = (PciCcdfAvail *)nt2_res->ccdf; 63 accdf->fid = cpu_to_be32(sei_cont->fid); 64 accdf->fh = cpu_to_be32(sei_cont->fh); 65 accdf->pec = cpu_to_be16(sei_cont->pec); 66 break; 67 default: 68 abort(); 69 } 70 g_free(sei_cont); 71 rc = 0; 72 } 73 74 return rc; 75 } 76 77 int chsc_sei_nt2_have_event(void) 78 { 79 S390pciState *s = S390_PCI_HOST_BRIDGE( 80 object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL)); 81 82 if (!s) { 83 return 0; 84 } 85 86 return !QTAILQ_EMPTY(&s->pending_sei); 87 } 88 89 S390PCIBusDevice *s390_pci_find_dev_by_fid(uint32_t fid) 90 { 91 S390PCIBusDevice *pbdev; 92 int i; 93 S390pciState *s = S390_PCI_HOST_BRIDGE( 94 object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL)); 95 96 if (!s) { 97 return NULL; 98 } 99 100 for (i = 0; i < PCI_SLOT_MAX; i++) { 101 pbdev = &s->pbdev[i]; 102 if ((pbdev->fh != 0) && (pbdev->fid == fid)) { 103 return pbdev; 104 } 105 } 106 107 return NULL; 108 } 109 110 void s390_pci_sclp_configure(SCCB *sccb) 111 { 112 PciCfgSccb *psccb = (PciCfgSccb *)sccb; 113 S390PCIBusDevice *pbdev = s390_pci_find_dev_by_fid(be32_to_cpu(psccb->aid)); 114 uint16_t rc; 115 116 if (be16_to_cpu(sccb->h.length) < 16) { 117 rc = SCLP_RC_INSUFFICIENT_SCCB_LENGTH; 118 goto out; 119 } 120 121 if (pbdev) { 122 if (pbdev->configured) { 123 rc = SCLP_RC_NO_ACTION_REQUIRED; 124 } else { 125 pbdev->configured = true; 126 rc = SCLP_RC_NORMAL_COMPLETION; 127 } 128 } else { 129 DPRINTF("sclp config no dev found\n"); 130 rc = SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED; 131 } 132 out: 133 psccb->header.response_code = cpu_to_be16(rc); 134 } 135 136 void s390_pci_sclp_deconfigure(SCCB *sccb) 137 { 138 PciCfgSccb *psccb = (PciCfgSccb *)sccb; 139 S390PCIBusDevice *pbdev = s390_pci_find_dev_by_fid(be32_to_cpu(psccb->aid)); 140 uint16_t rc; 141 142 if (be16_to_cpu(sccb->h.length) < 16) { 143 rc = SCLP_RC_INSUFFICIENT_SCCB_LENGTH; 144 goto out; 145 } 146 147 if (pbdev) { 148 if (!pbdev->configured) { 149 rc = SCLP_RC_NO_ACTION_REQUIRED; 150 } else { 151 if (pbdev->summary_ind) { 152 pci_dereg_irqs(pbdev); 153 } 154 if (pbdev->iommu_enabled) { 155 pci_dereg_ioat(pbdev); 156 } 157 pbdev->configured = false; 158 rc = SCLP_RC_NORMAL_COMPLETION; 159 } 160 } else { 161 DPRINTF("sclp deconfig no dev found\n"); 162 rc = SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED; 163 } 164 out: 165 psccb->header.response_code = cpu_to_be16(rc); 166 } 167 168 static uint32_t s390_pci_get_pfid(PCIDevice *pdev) 169 { 170 return PCI_SLOT(pdev->devfn); 171 } 172 173 static uint32_t s390_pci_get_pfh(PCIDevice *pdev) 174 { 175 return PCI_SLOT(pdev->devfn) | FH_VIRT; 176 } 177 178 S390PCIBusDevice *s390_pci_find_dev_by_idx(uint32_t idx) 179 { 180 S390PCIBusDevice *pbdev; 181 int i; 182 int j = 0; 183 S390pciState *s = S390_PCI_HOST_BRIDGE( 184 object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL)); 185 186 if (!s) { 187 return NULL; 188 } 189 190 for (i = 0; i < PCI_SLOT_MAX; i++) { 191 pbdev = &s->pbdev[i]; 192 193 if (pbdev->fh == 0) { 194 continue; 195 } 196 197 if (j == idx) { 198 return pbdev; 199 } 200 j++; 201 } 202 203 return NULL; 204 } 205 206 S390PCIBusDevice *s390_pci_find_dev_by_fh(uint32_t fh) 207 { 208 S390PCIBusDevice *pbdev; 209 int i; 210 S390pciState *s = S390_PCI_HOST_BRIDGE( 211 object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL)); 212 213 if (!s || !fh) { 214 return NULL; 215 } 216 217 for (i = 0; i < PCI_SLOT_MAX; i++) { 218 pbdev = &s->pbdev[i]; 219 if (pbdev->fh == fh) { 220 return pbdev; 221 } 222 } 223 224 return NULL; 225 } 226 227 static void s390_pci_generate_event(uint8_t cc, uint16_t pec, uint32_t fh, 228 uint32_t fid, uint64_t faddr, uint32_t e) 229 { 230 SeiContainer *sei_cont; 231 S390pciState *s = S390_PCI_HOST_BRIDGE( 232 object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL)); 233 234 if (!s) { 235 return; 236 } 237 238 sei_cont = g_malloc0(sizeof(SeiContainer)); 239 sei_cont->fh = fh; 240 sei_cont->fid = fid; 241 sei_cont->cc = cc; 242 sei_cont->pec = pec; 243 sei_cont->faddr = faddr; 244 sei_cont->e = e; 245 246 QTAILQ_INSERT_TAIL(&s->pending_sei, sei_cont, link); 247 css_generate_css_crws(0); 248 } 249 250 static void s390_pci_generate_plug_event(uint16_t pec, uint32_t fh, 251 uint32_t fid) 252 { 253 s390_pci_generate_event(2, pec, fh, fid, 0, 0); 254 } 255 256 static void s390_pci_generate_error_event(uint16_t pec, uint32_t fh, 257 uint32_t fid, uint64_t faddr, 258 uint32_t e) 259 { 260 s390_pci_generate_event(1, pec, fh, fid, faddr, e); 261 } 262 263 static void s390_pci_set_irq(void *opaque, int irq, int level) 264 { 265 /* nothing to do */ 266 } 267 268 static int s390_pci_map_irq(PCIDevice *pci_dev, int irq_num) 269 { 270 /* nothing to do */ 271 return 0; 272 } 273 274 static uint64_t s390_pci_get_table_origin(uint64_t iota) 275 { 276 return iota & ~ZPCI_IOTA_RTTO_FLAG; 277 } 278 279 static unsigned int calc_rtx(dma_addr_t ptr) 280 { 281 return ((unsigned long) ptr >> ZPCI_RT_SHIFT) & ZPCI_INDEX_MASK; 282 } 283 284 static unsigned int calc_sx(dma_addr_t ptr) 285 { 286 return ((unsigned long) ptr >> ZPCI_ST_SHIFT) & ZPCI_INDEX_MASK; 287 } 288 289 static unsigned int calc_px(dma_addr_t ptr) 290 { 291 return ((unsigned long) ptr >> PAGE_SHIFT) & ZPCI_PT_MASK; 292 } 293 294 static uint64_t get_rt_sto(uint64_t entry) 295 { 296 return ((entry & ZPCI_TABLE_TYPE_MASK) == ZPCI_TABLE_TYPE_RTX) 297 ? (entry & ZPCI_RTE_ADDR_MASK) 298 : 0; 299 } 300 301 static uint64_t get_st_pto(uint64_t entry) 302 { 303 return ((entry & ZPCI_TABLE_TYPE_MASK) == ZPCI_TABLE_TYPE_SX) 304 ? (entry & ZPCI_STE_ADDR_MASK) 305 : 0; 306 } 307 308 static uint64_t s390_guest_io_table_walk(uint64_t guest_iota, 309 uint64_t guest_dma_address) 310 { 311 uint64_t sto_a, pto_a, px_a; 312 uint64_t sto, pto, pte; 313 uint32_t rtx, sx, px; 314 315 rtx = calc_rtx(guest_dma_address); 316 sx = calc_sx(guest_dma_address); 317 px = calc_px(guest_dma_address); 318 319 sto_a = guest_iota + rtx * sizeof(uint64_t); 320 sto = address_space_ldq(&address_space_memory, sto_a, 321 MEMTXATTRS_UNSPECIFIED, NULL); 322 sto = get_rt_sto(sto); 323 if (!sto) { 324 pte = 0; 325 goto out; 326 } 327 328 pto_a = sto + sx * sizeof(uint64_t); 329 pto = address_space_ldq(&address_space_memory, pto_a, 330 MEMTXATTRS_UNSPECIFIED, NULL); 331 pto = get_st_pto(pto); 332 if (!pto) { 333 pte = 0; 334 goto out; 335 } 336 337 px_a = pto + px * sizeof(uint64_t); 338 pte = address_space_ldq(&address_space_memory, px_a, 339 MEMTXATTRS_UNSPECIFIED, NULL); 340 341 out: 342 return pte; 343 } 344 345 static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr, 346 bool is_write) 347 { 348 uint64_t pte; 349 uint32_t flags; 350 S390PCIBusDevice *pbdev = container_of(iommu, S390PCIBusDevice, iommu_mr); 351 S390pciState *s; 352 IOMMUTLBEntry ret = { 353 .target_as = &address_space_memory, 354 .iova = 0, 355 .translated_addr = 0, 356 .addr_mask = ~(hwaddr)0, 357 .perm = IOMMU_NONE, 358 }; 359 360 if (!pbdev->configured || !pbdev->pdev || 361 !(pbdev->fh & FH_ENABLED) || !pbdev->iommu_enabled) { 362 return ret; 363 } 364 365 DPRINTF("iommu trans addr 0x%" PRIx64 "\n", addr); 366 367 s = S390_PCI_HOST_BRIDGE(pci_device_root_bus(pbdev->pdev)->qbus.parent); 368 /* s390 does not have an APIC mapped to main storage so we use 369 * a separate AddressSpace only for msix notifications 370 */ 371 if (addr == ZPCI_MSI_ADDR) { 372 ret.target_as = &s->msix_notify_as; 373 ret.iova = addr; 374 ret.translated_addr = addr; 375 ret.addr_mask = 0xfff; 376 ret.perm = IOMMU_RW; 377 return ret; 378 } 379 380 if (!pbdev->g_iota) { 381 pbdev->error_state = true; 382 pbdev->lgstg_blocked = true; 383 s390_pci_generate_error_event(ERR_EVENT_INVALAS, pbdev->fh, pbdev->fid, 384 addr, 0); 385 return ret; 386 } 387 388 if (addr < pbdev->pba || addr > pbdev->pal) { 389 pbdev->error_state = true; 390 pbdev->lgstg_blocked = true; 391 s390_pci_generate_error_event(ERR_EVENT_OORANGE, pbdev->fh, pbdev->fid, 392 addr, 0); 393 return ret; 394 } 395 396 pte = s390_guest_io_table_walk(s390_pci_get_table_origin(pbdev->g_iota), 397 addr); 398 399 if (!pte) { 400 pbdev->error_state = true; 401 pbdev->lgstg_blocked = true; 402 s390_pci_generate_error_event(ERR_EVENT_SERR, pbdev->fh, pbdev->fid, 403 addr, ERR_EVENT_Q_BIT); 404 return ret; 405 } 406 407 flags = pte & ZPCI_PTE_FLAG_MASK; 408 ret.iova = addr; 409 ret.translated_addr = pte & ZPCI_PTE_ADDR_MASK; 410 ret.addr_mask = 0xfff; 411 412 if (flags & ZPCI_PTE_INVALID) { 413 ret.perm = IOMMU_NONE; 414 } else { 415 ret.perm = IOMMU_RW; 416 } 417 418 return ret; 419 } 420 421 static const MemoryRegionIOMMUOps s390_iommu_ops = { 422 .translate = s390_translate_iommu, 423 }; 424 425 static AddressSpace *s390_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn) 426 { 427 S390pciState *s = opaque; 428 429 return &s->pbdev[PCI_SLOT(devfn)].as; 430 } 431 432 static uint8_t set_ind_atomic(uint64_t ind_loc, uint8_t to_be_set) 433 { 434 uint8_t ind_old, ind_new; 435 hwaddr len = 1; 436 uint8_t *ind_addr; 437 438 ind_addr = cpu_physical_memory_map(ind_loc, &len, 1); 439 if (!ind_addr) { 440 s390_pci_generate_error_event(ERR_EVENT_AIRERR, 0, 0, 0, 0); 441 return -1; 442 } 443 do { 444 ind_old = *ind_addr; 445 ind_new = ind_old | to_be_set; 446 } while (atomic_cmpxchg(ind_addr, ind_old, ind_new) != ind_old); 447 cpu_physical_memory_unmap(ind_addr, len, 1, len); 448 449 return ind_old; 450 } 451 452 static void s390_msi_ctrl_write(void *opaque, hwaddr addr, uint64_t data, 453 unsigned int size) 454 { 455 S390PCIBusDevice *pbdev; 456 uint32_t io_int_word; 457 uint32_t fid = data >> ZPCI_MSI_VEC_BITS; 458 uint32_t vec = data & ZPCI_MSI_VEC_MASK; 459 uint64_t ind_bit; 460 uint32_t sum_bit; 461 uint32_t e = 0; 462 463 DPRINTF("write_msix data 0x%" PRIx64 " fid %d vec 0x%x\n", data, fid, vec); 464 465 pbdev = s390_pci_find_dev_by_fid(fid); 466 if (!pbdev) { 467 e |= (vec << ERR_EVENT_MVN_OFFSET); 468 s390_pci_generate_error_event(ERR_EVENT_NOMSI, 0, fid, addr, e); 469 return; 470 } 471 472 if (!(pbdev->fh & FH_ENABLED)) { 473 return; 474 } 475 476 ind_bit = pbdev->routes.adapter.ind_offset; 477 sum_bit = pbdev->routes.adapter.summary_offset; 478 479 set_ind_atomic(pbdev->routes.adapter.ind_addr + (ind_bit + vec) / 8, 480 0x80 >> ((ind_bit + vec) % 8)); 481 if (!set_ind_atomic(pbdev->routes.adapter.summary_addr + sum_bit / 8, 482 0x80 >> (sum_bit % 8))) { 483 io_int_word = (pbdev->isc << 27) | IO_INT_WORD_AI; 484 s390_io_interrupt(0, 0, 0, io_int_word); 485 } 486 } 487 488 static uint64_t s390_msi_ctrl_read(void *opaque, hwaddr addr, unsigned size) 489 { 490 return 0xffffffff; 491 } 492 493 static const MemoryRegionOps s390_msi_ctrl_ops = { 494 .write = s390_msi_ctrl_write, 495 .read = s390_msi_ctrl_read, 496 .endianness = DEVICE_LITTLE_ENDIAN, 497 }; 498 499 void s390_pci_iommu_enable(S390PCIBusDevice *pbdev) 500 { 501 uint64_t size = pbdev->pal - pbdev->pba + 1; 502 503 memory_region_init_iommu(&pbdev->iommu_mr, OBJECT(&pbdev->mr), 504 &s390_iommu_ops, "iommu-s390", size); 505 memory_region_add_subregion(&pbdev->mr, pbdev->pba, &pbdev->iommu_mr); 506 pbdev->iommu_enabled = true; 507 } 508 509 void s390_pci_iommu_disable(S390PCIBusDevice *pbdev) 510 { 511 memory_region_del_subregion(&pbdev->mr, &pbdev->iommu_mr); 512 object_unparent(OBJECT(&pbdev->iommu_mr)); 513 pbdev->iommu_enabled = false; 514 } 515 516 static void s390_pcihost_init_as(S390pciState *s) 517 { 518 int i; 519 S390PCIBusDevice *pbdev; 520 521 for (i = 0; i < PCI_SLOT_MAX; i++) { 522 pbdev = &s->pbdev[i]; 523 memory_region_init(&pbdev->mr, OBJECT(s), 524 "iommu-root-s390", UINT64_MAX); 525 address_space_init(&pbdev->as, &pbdev->mr, "iommu-pci"); 526 } 527 528 memory_region_init_io(&s->msix_notify_mr, OBJECT(s), 529 &s390_msi_ctrl_ops, s, "msix-s390", UINT64_MAX); 530 address_space_init(&s->msix_notify_as, &s->msix_notify_mr, "msix-pci"); 531 } 532 533 static int s390_pcihost_init(SysBusDevice *dev) 534 { 535 PCIBus *b; 536 BusState *bus; 537 PCIHostState *phb = PCI_HOST_BRIDGE(dev); 538 S390pciState *s = S390_PCI_HOST_BRIDGE(dev); 539 540 DPRINTF("host_init\n"); 541 542 b = pci_register_bus(DEVICE(dev), NULL, 543 s390_pci_set_irq, s390_pci_map_irq, NULL, 544 get_system_memory(), get_system_io(), 0, 64, 545 TYPE_PCI_BUS); 546 s390_pcihost_init_as(s); 547 pci_setup_iommu(b, s390_pci_dma_iommu, s); 548 549 bus = BUS(b); 550 qbus_set_hotplug_handler(bus, DEVICE(dev), NULL); 551 phb->bus = b; 552 QTAILQ_INIT(&s->pending_sei); 553 return 0; 554 } 555 556 static int s390_pcihost_setup_msix(S390PCIBusDevice *pbdev) 557 { 558 uint8_t pos; 559 uint16_t ctrl; 560 uint32_t table, pba; 561 562 pos = pci_find_capability(pbdev->pdev, PCI_CAP_ID_MSIX); 563 if (!pos) { 564 pbdev->msix.available = false; 565 return 0; 566 } 567 568 ctrl = pci_host_config_read_common(pbdev->pdev, pos + PCI_MSIX_FLAGS, 569 pci_config_size(pbdev->pdev), sizeof(ctrl)); 570 table = pci_host_config_read_common(pbdev->pdev, pos + PCI_MSIX_TABLE, 571 pci_config_size(pbdev->pdev), sizeof(table)); 572 pba = pci_host_config_read_common(pbdev->pdev, pos + PCI_MSIX_PBA, 573 pci_config_size(pbdev->pdev), sizeof(pba)); 574 575 pbdev->msix.table_bar = table & PCI_MSIX_FLAGS_BIRMASK; 576 pbdev->msix.table_offset = table & ~PCI_MSIX_FLAGS_BIRMASK; 577 pbdev->msix.pba_bar = pba & PCI_MSIX_FLAGS_BIRMASK; 578 pbdev->msix.pba_offset = pba & ~PCI_MSIX_FLAGS_BIRMASK; 579 pbdev->msix.entries = (ctrl & PCI_MSIX_FLAGS_QSIZE) + 1; 580 pbdev->msix.available = true; 581 return 0; 582 } 583 584 static void s390_pcihost_hot_plug(HotplugHandler *hotplug_dev, 585 DeviceState *dev, Error **errp) 586 { 587 PCIDevice *pci_dev = PCI_DEVICE(dev); 588 S390PCIBusDevice *pbdev; 589 S390pciState *s = S390_PCI_HOST_BRIDGE(pci_device_root_bus(pci_dev) 590 ->qbus.parent); 591 592 pbdev = &s->pbdev[PCI_SLOT(pci_dev->devfn)]; 593 594 pbdev->fid = s390_pci_get_pfid(pci_dev); 595 pbdev->pdev = pci_dev; 596 pbdev->configured = true; 597 pbdev->fh = s390_pci_get_pfh(pci_dev); 598 599 s390_pcihost_setup_msix(pbdev); 600 601 if (dev->hotplugged) { 602 s390_pci_generate_plug_event(HP_EVENT_RESERVED_TO_STANDBY, 603 pbdev->fh, pbdev->fid); 604 s390_pci_generate_plug_event(HP_EVENT_TO_CONFIGURED, 605 pbdev->fh, pbdev->fid); 606 } 607 } 608 609 static void s390_pcihost_hot_unplug(HotplugHandler *hotplug_dev, 610 DeviceState *dev, Error **errp) 611 { 612 PCIDevice *pci_dev = PCI_DEVICE(dev); 613 S390pciState *s = S390_PCI_HOST_BRIDGE(pci_device_root_bus(pci_dev) 614 ->qbus.parent); 615 S390PCIBusDevice *pbdev = &s->pbdev[PCI_SLOT(pci_dev->devfn)]; 616 617 if (pbdev->configured) { 618 pbdev->configured = false; 619 s390_pci_generate_plug_event(HP_EVENT_CONFIGURED_TO_STBRES, 620 pbdev->fh, pbdev->fid); 621 } 622 623 s390_pci_generate_plug_event(HP_EVENT_STANDBY_TO_RESERVED, 624 pbdev->fh, pbdev->fid); 625 pbdev->fh = 0; 626 pbdev->fid = 0; 627 pbdev->pdev = NULL; 628 object_unparent(OBJECT(pci_dev)); 629 } 630 631 static void s390_pcihost_class_init(ObjectClass *klass, void *data) 632 { 633 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); 634 DeviceClass *dc = DEVICE_CLASS(klass); 635 HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); 636 637 dc->cannot_instantiate_with_device_add_yet = true; 638 k->init = s390_pcihost_init; 639 hc->plug = s390_pcihost_hot_plug; 640 hc->unplug = s390_pcihost_hot_unplug; 641 msi_nonbroken = true; 642 } 643 644 static const TypeInfo s390_pcihost_info = { 645 .name = TYPE_S390_PCI_HOST_BRIDGE, 646 .parent = TYPE_PCI_HOST_BRIDGE, 647 .instance_size = sizeof(S390pciState), 648 .class_init = s390_pcihost_class_init, 649 .interfaces = (InterfaceInfo[]) { 650 { TYPE_HOTPLUG_HANDLER }, 651 { } 652 } 653 }; 654 655 static void s390_pci_register_types(void) 656 { 657 type_register_static(&s390_pcihost_info); 658 } 659 660 type_init(s390_pci_register_types) 661