1 /* 2 * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator 3 * 4 * PAPR Virtualized Interrupt System, aka ICS/ICP aka xics 5 * 6 * Copyright (c) 2010,2011 David Gibson, IBM Corporation. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a copy 9 * of this software and associated documentation files (the "Software"), to deal 10 * in the Software without restriction, including without limitation the rights 11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 * copies of the Software, and to permit persons to whom the Software is 13 * furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice shall be included in 16 * all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 * THE SOFTWARE. 25 * 26 */ 27 28 #include "qemu/osdep.h" 29 #include "qapi/error.h" 30 #include "cpu.h" 31 #include "hw/hw.h" 32 #include "trace.h" 33 #include "qemu/timer.h" 34 #include "hw/ppc/xics.h" 35 #include "qemu/error-report.h" 36 #include "qemu/module.h" 37 #include "qapi/visitor.h" 38 #include "monitor/monitor.h" 39 #include "hw/intc/intc.h" 40 #include "sysemu/kvm.h" 41 42 void icp_pic_print_info(ICPState *icp, Monitor *mon) 43 { 44 int cpu_index = icp->cs ? icp->cs->cpu_index : -1; 45 46 if (!icp->output) { 47 return; 48 } 49 50 if (kvm_irqchip_in_kernel()) { 51 icp_synchronize_state(icp); 52 } 53 54 monitor_printf(mon, "CPU %d XIRR=%08x (%p) PP=%02x MFRR=%02x\n", 55 cpu_index, icp->xirr, icp->xirr_owner, 56 icp->pending_priority, icp->mfrr); 57 } 58 59 void ics_pic_print_info(ICSState *ics, Monitor *mon) 60 { 61 uint32_t i; 62 63 monitor_printf(mon, "ICS %4x..%4x %p\n", 64 ics->offset, ics->offset + ics->nr_irqs - 1, ics); 65 66 if (!ics->irqs) { 67 return; 68 } 69 70 if (kvm_irqchip_in_kernel()) { 71 ics_synchronize_state(ics); 72 } 73 74 for (i = 0; i < ics->nr_irqs; i++) { 75 ICSIRQState *irq = ics->irqs + i; 76 77 if (!(irq->flags & XICS_FLAGS_IRQ_MASK)) { 78 continue; 79 } 80 monitor_printf(mon, " %4x %s %02x %02x\n", 81 ics->offset + i, 82 (irq->flags & XICS_FLAGS_IRQ_LSI) ? 83 "LSI" : "MSI", 84 irq->priority, irq->status); 85 } 86 } 87 88 /* 89 * ICP: Presentation layer 90 */ 91 92 #define XISR_MASK 0x00ffffff 93 #define CPPR_MASK 0xff000000 94 95 #define XISR(icp) (((icp)->xirr) & XISR_MASK) 96 #define CPPR(icp) (((icp)->xirr) >> 24) 97 98 static void ics_reject(ICSState *ics, uint32_t nr) 99 { 100 ICSStateClass *k = ICS_BASE_GET_CLASS(ics); 101 102 if (k->reject) { 103 k->reject(ics, nr); 104 } 105 } 106 107 void ics_resend(ICSState *ics) 108 { 109 ICSStateClass *k = ICS_BASE_GET_CLASS(ics); 110 111 if (k->resend) { 112 k->resend(ics); 113 } 114 } 115 116 static void ics_eoi(ICSState *ics, int nr) 117 { 118 ICSStateClass *k = ICS_BASE_GET_CLASS(ics); 119 120 if (k->eoi) { 121 k->eoi(ics, nr); 122 } 123 } 124 125 static void icp_check_ipi(ICPState *icp) 126 { 127 if (XISR(icp) && (icp->pending_priority <= icp->mfrr)) { 128 return; 129 } 130 131 trace_xics_icp_check_ipi(icp->cs->cpu_index, icp->mfrr); 132 133 if (XISR(icp) && icp->xirr_owner) { 134 ics_reject(icp->xirr_owner, XISR(icp)); 135 } 136 137 icp->xirr = (icp->xirr & ~XISR_MASK) | XICS_IPI; 138 icp->pending_priority = icp->mfrr; 139 icp->xirr_owner = NULL; 140 qemu_irq_raise(icp->output); 141 } 142 143 void icp_resend(ICPState *icp) 144 { 145 XICSFabric *xi = icp->xics; 146 XICSFabricClass *xic = XICS_FABRIC_GET_CLASS(xi); 147 148 if (icp->mfrr < CPPR(icp)) { 149 icp_check_ipi(icp); 150 } 151 152 xic->ics_resend(xi); 153 } 154 155 void icp_set_cppr(ICPState *icp, uint8_t cppr) 156 { 157 uint8_t old_cppr; 158 uint32_t old_xisr; 159 160 old_cppr = CPPR(icp); 161 icp->xirr = (icp->xirr & ~CPPR_MASK) | (cppr << 24); 162 163 if (cppr < old_cppr) { 164 if (XISR(icp) && (cppr <= icp->pending_priority)) { 165 old_xisr = XISR(icp); 166 icp->xirr &= ~XISR_MASK; /* Clear XISR */ 167 icp->pending_priority = 0xff; 168 qemu_irq_lower(icp->output); 169 if (icp->xirr_owner) { 170 ics_reject(icp->xirr_owner, old_xisr); 171 icp->xirr_owner = NULL; 172 } 173 } 174 } else { 175 if (!XISR(icp)) { 176 icp_resend(icp); 177 } 178 } 179 } 180 181 void icp_set_mfrr(ICPState *icp, uint8_t mfrr) 182 { 183 icp->mfrr = mfrr; 184 if (mfrr < CPPR(icp)) { 185 icp_check_ipi(icp); 186 } 187 } 188 189 uint32_t icp_accept(ICPState *icp) 190 { 191 uint32_t xirr = icp->xirr; 192 193 qemu_irq_lower(icp->output); 194 icp->xirr = icp->pending_priority << 24; 195 icp->pending_priority = 0xff; 196 icp->xirr_owner = NULL; 197 198 trace_xics_icp_accept(xirr, icp->xirr); 199 200 return xirr; 201 } 202 203 uint32_t icp_ipoll(ICPState *icp, uint32_t *mfrr) 204 { 205 if (mfrr) { 206 *mfrr = icp->mfrr; 207 } 208 return icp->xirr; 209 } 210 211 void icp_eoi(ICPState *icp, uint32_t xirr) 212 { 213 XICSFabric *xi = icp->xics; 214 XICSFabricClass *xic = XICS_FABRIC_GET_CLASS(xi); 215 ICSState *ics; 216 uint32_t irq; 217 218 /* Send EOI -> ICS */ 219 icp->xirr = (icp->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK); 220 trace_xics_icp_eoi(icp->cs->cpu_index, xirr, icp->xirr); 221 irq = xirr & XISR_MASK; 222 223 ics = xic->ics_get(xi, irq); 224 if (ics) { 225 ics_eoi(ics, irq); 226 } 227 if (!XISR(icp)) { 228 icp_resend(icp); 229 } 230 } 231 232 static void icp_irq(ICSState *ics, int server, int nr, uint8_t priority) 233 { 234 ICPState *icp = xics_icp_get(ics->xics, server); 235 236 trace_xics_icp_irq(server, nr, priority); 237 238 if ((priority >= CPPR(icp)) 239 || (XISR(icp) && (icp->pending_priority <= priority))) { 240 ics_reject(ics, nr); 241 } else { 242 if (XISR(icp) && icp->xirr_owner) { 243 ics_reject(icp->xirr_owner, XISR(icp)); 244 icp->xirr_owner = NULL; 245 } 246 icp->xirr = (icp->xirr & ~XISR_MASK) | (nr & XISR_MASK); 247 icp->xirr_owner = ics; 248 icp->pending_priority = priority; 249 trace_xics_icp_raise(icp->xirr, icp->pending_priority); 250 qemu_irq_raise(icp->output); 251 } 252 } 253 254 static int icp_pre_save(void *opaque) 255 { 256 ICPState *icp = opaque; 257 258 if (kvm_irqchip_in_kernel()) { 259 icp_get_kvm_state(icp); 260 } 261 262 return 0; 263 } 264 265 static int icp_post_load(void *opaque, int version_id) 266 { 267 ICPState *icp = opaque; 268 269 if (kvm_irqchip_in_kernel()) { 270 return icp_set_kvm_state(icp); 271 } 272 273 return 0; 274 } 275 276 static const VMStateDescription vmstate_icp_server = { 277 .name = "icp/server", 278 .version_id = 1, 279 .minimum_version_id = 1, 280 .pre_save = icp_pre_save, 281 .post_load = icp_post_load, 282 .fields = (VMStateField[]) { 283 /* Sanity check */ 284 VMSTATE_UINT32(xirr, ICPState), 285 VMSTATE_UINT8(pending_priority, ICPState), 286 VMSTATE_UINT8(mfrr, ICPState), 287 VMSTATE_END_OF_LIST() 288 }, 289 }; 290 291 static void icp_reset_handler(void *dev) 292 { 293 ICPState *icp = ICP(dev); 294 295 icp->xirr = 0; 296 icp->pending_priority = 0xff; 297 icp->mfrr = 0xff; 298 299 /* Make all outputs are deasserted */ 300 qemu_set_irq(icp->output, 0); 301 302 if (kvm_irqchip_in_kernel()) { 303 icp_set_kvm_state(ICP(dev)); 304 } 305 } 306 307 static void icp_realize(DeviceState *dev, Error **errp) 308 { 309 ICPState *icp = ICP(dev); 310 PowerPCCPU *cpu; 311 CPUPPCState *env; 312 Object *obj; 313 Error *err = NULL; 314 315 obj = object_property_get_link(OBJECT(dev), ICP_PROP_XICS, &err); 316 if (!obj) { 317 error_propagate_prepend(errp, err, 318 "required link '" ICP_PROP_XICS 319 "' not found: "); 320 return; 321 } 322 323 icp->xics = XICS_FABRIC(obj); 324 325 obj = object_property_get_link(OBJECT(dev), ICP_PROP_CPU, &err); 326 if (!obj) { 327 error_propagate_prepend(errp, err, 328 "required link '" ICP_PROP_CPU 329 "' not found: "); 330 return; 331 } 332 333 cpu = POWERPC_CPU(obj); 334 icp->cs = CPU(obj); 335 336 env = &cpu->env; 337 switch (PPC_INPUT(env)) { 338 case PPC_FLAGS_INPUT_POWER7: 339 icp->output = env->irq_inputs[POWER7_INPUT_INT]; 340 break; 341 case PPC_FLAGS_INPUT_POWER9: /* For SPAPR xics emulation */ 342 icp->output = env->irq_inputs[POWER9_INPUT_INT]; 343 break; 344 345 case PPC_FLAGS_INPUT_970: 346 icp->output = env->irq_inputs[PPC970_INPUT_INT]; 347 break; 348 349 default: 350 error_setg(errp, "XICS interrupt controller does not support this CPU bus model"); 351 return; 352 } 353 354 /* Connect the presenter to the VCPU (required for CPU hotplug) */ 355 if (kvm_irqchip_in_kernel()) { 356 icp_kvm_realize(dev, &err); 357 if (err) { 358 error_propagate(errp, err); 359 return; 360 } 361 } 362 363 qemu_register_reset(icp_reset_handler, dev); 364 vmstate_register(NULL, icp->cs->cpu_index, &vmstate_icp_server, icp); 365 } 366 367 static void icp_unrealize(DeviceState *dev, Error **errp) 368 { 369 ICPState *icp = ICP(dev); 370 371 vmstate_unregister(NULL, &vmstate_icp_server, icp); 372 qemu_unregister_reset(icp_reset_handler, dev); 373 } 374 375 static void icp_class_init(ObjectClass *klass, void *data) 376 { 377 DeviceClass *dc = DEVICE_CLASS(klass); 378 379 dc->realize = icp_realize; 380 dc->unrealize = icp_unrealize; 381 } 382 383 static const TypeInfo icp_info = { 384 .name = TYPE_ICP, 385 .parent = TYPE_DEVICE, 386 .instance_size = sizeof(ICPState), 387 .class_init = icp_class_init, 388 .class_size = sizeof(ICPStateClass), 389 }; 390 391 Object *icp_create(Object *cpu, const char *type, XICSFabric *xi, Error **errp) 392 { 393 Error *local_err = NULL; 394 Object *obj; 395 396 obj = object_new(type); 397 object_property_add_child(cpu, type, obj, &error_abort); 398 object_unref(obj); 399 object_property_add_const_link(obj, ICP_PROP_XICS, OBJECT(xi), 400 &error_abort); 401 object_property_add_const_link(obj, ICP_PROP_CPU, cpu, &error_abort); 402 object_property_set_bool(obj, true, "realized", &local_err); 403 if (local_err) { 404 object_unparent(obj); 405 error_propagate(errp, local_err); 406 obj = NULL; 407 } 408 409 return obj; 410 } 411 412 /* 413 * ICS: Source layer 414 */ 415 static void ics_simple_resend_msi(ICSState *ics, int srcno) 416 { 417 ICSIRQState *irq = ics->irqs + srcno; 418 419 /* FIXME: filter by server#? */ 420 if (irq->status & XICS_STATUS_REJECTED) { 421 irq->status &= ~XICS_STATUS_REJECTED; 422 if (irq->priority != 0xff) { 423 icp_irq(ics, irq->server, srcno + ics->offset, irq->priority); 424 } 425 } 426 } 427 428 static void ics_simple_resend_lsi(ICSState *ics, int srcno) 429 { 430 ICSIRQState *irq = ics->irqs + srcno; 431 432 if ((irq->priority != 0xff) 433 && (irq->status & XICS_STATUS_ASSERTED) 434 && !(irq->status & XICS_STATUS_SENT)) { 435 irq->status |= XICS_STATUS_SENT; 436 icp_irq(ics, irq->server, srcno + ics->offset, irq->priority); 437 } 438 } 439 440 static void ics_simple_set_irq_msi(ICSState *ics, int srcno, int val) 441 { 442 ICSIRQState *irq = ics->irqs + srcno; 443 444 trace_xics_ics_simple_set_irq_msi(srcno, srcno + ics->offset); 445 446 if (val) { 447 if (irq->priority == 0xff) { 448 irq->status |= XICS_STATUS_MASKED_PENDING; 449 trace_xics_masked_pending(); 450 } else { 451 icp_irq(ics, irq->server, srcno + ics->offset, irq->priority); 452 } 453 } 454 } 455 456 static void ics_simple_set_irq_lsi(ICSState *ics, int srcno, int val) 457 { 458 ICSIRQState *irq = ics->irqs + srcno; 459 460 trace_xics_ics_simple_set_irq_lsi(srcno, srcno + ics->offset); 461 if (val) { 462 irq->status |= XICS_STATUS_ASSERTED; 463 } else { 464 irq->status &= ~XICS_STATUS_ASSERTED; 465 } 466 ics_simple_resend_lsi(ics, srcno); 467 } 468 469 void ics_simple_set_irq(void *opaque, int srcno, int val) 470 { 471 ICSState *ics = (ICSState *)opaque; 472 473 if (kvm_irqchip_in_kernel()) { 474 ics_kvm_set_irq(ics, srcno, val); 475 return; 476 } 477 478 if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) { 479 ics_simple_set_irq_lsi(ics, srcno, val); 480 } else { 481 ics_simple_set_irq_msi(ics, srcno, val); 482 } 483 } 484 485 static void ics_simple_write_xive_msi(ICSState *ics, int srcno) 486 { 487 ICSIRQState *irq = ics->irqs + srcno; 488 489 if (!(irq->status & XICS_STATUS_MASKED_PENDING) 490 || (irq->priority == 0xff)) { 491 return; 492 } 493 494 irq->status &= ~XICS_STATUS_MASKED_PENDING; 495 icp_irq(ics, irq->server, srcno + ics->offset, irq->priority); 496 } 497 498 static void ics_simple_write_xive_lsi(ICSState *ics, int srcno) 499 { 500 ics_simple_resend_lsi(ics, srcno); 501 } 502 503 void ics_simple_write_xive(ICSState *ics, int srcno, int server, 504 uint8_t priority, uint8_t saved_priority) 505 { 506 ICSIRQState *irq = ics->irqs + srcno; 507 508 irq->server = server; 509 irq->priority = priority; 510 irq->saved_priority = saved_priority; 511 512 trace_xics_ics_simple_write_xive(ics->offset + srcno, srcno, server, 513 priority); 514 515 if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) { 516 ics_simple_write_xive_lsi(ics, srcno); 517 } else { 518 ics_simple_write_xive_msi(ics, srcno); 519 } 520 } 521 522 static void ics_simple_reject(ICSState *ics, uint32_t nr) 523 { 524 ICSIRQState *irq = ics->irqs + nr - ics->offset; 525 526 trace_xics_ics_simple_reject(nr, nr - ics->offset); 527 if (irq->flags & XICS_FLAGS_IRQ_MSI) { 528 irq->status |= XICS_STATUS_REJECTED; 529 } else if (irq->flags & XICS_FLAGS_IRQ_LSI) { 530 irq->status &= ~XICS_STATUS_SENT; 531 } 532 } 533 534 static void ics_simple_resend(ICSState *ics) 535 { 536 int i; 537 538 for (i = 0; i < ics->nr_irqs; i++) { 539 /* FIXME: filter by server#? */ 540 if (ics->irqs[i].flags & XICS_FLAGS_IRQ_LSI) { 541 ics_simple_resend_lsi(ics, i); 542 } else { 543 ics_simple_resend_msi(ics, i); 544 } 545 } 546 } 547 548 static void ics_simple_eoi(ICSState *ics, uint32_t nr) 549 { 550 int srcno = nr - ics->offset; 551 ICSIRQState *irq = ics->irqs + srcno; 552 553 trace_xics_ics_simple_eoi(nr); 554 555 if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) { 556 irq->status &= ~XICS_STATUS_SENT; 557 } 558 } 559 560 static void ics_simple_reset(DeviceState *dev) 561 { 562 ICSStateClass *icsc = ICS_BASE_GET_CLASS(dev); 563 564 icsc->parent_reset(dev); 565 566 if (kvm_irqchip_in_kernel()) { 567 ics_set_kvm_state(ICS_BASE(dev)); 568 } 569 } 570 571 static void ics_simple_reset_handler(void *dev) 572 { 573 ics_simple_reset(dev); 574 } 575 576 static void ics_simple_realize(DeviceState *dev, Error **errp) 577 { 578 ICSState *ics = ICS_SIMPLE(dev); 579 ICSStateClass *icsc = ICS_BASE_GET_CLASS(ics); 580 Error *local_err = NULL; 581 582 icsc->parent_realize(dev, &local_err); 583 if (local_err) { 584 error_propagate(errp, local_err); 585 return; 586 } 587 588 qemu_register_reset(ics_simple_reset_handler, ics); 589 } 590 591 static void ics_simple_class_init(ObjectClass *klass, void *data) 592 { 593 DeviceClass *dc = DEVICE_CLASS(klass); 594 ICSStateClass *isc = ICS_BASE_CLASS(klass); 595 596 device_class_set_parent_realize(dc, ics_simple_realize, 597 &isc->parent_realize); 598 device_class_set_parent_reset(dc, ics_simple_reset, 599 &isc->parent_reset); 600 601 isc->reject = ics_simple_reject; 602 isc->resend = ics_simple_resend; 603 isc->eoi = ics_simple_eoi; 604 } 605 606 static const TypeInfo ics_simple_info = { 607 .name = TYPE_ICS_SIMPLE, 608 .parent = TYPE_ICS_BASE, 609 .instance_size = sizeof(ICSState), 610 .class_init = ics_simple_class_init, 611 .class_size = sizeof(ICSStateClass), 612 }; 613 614 static void ics_reset_irq(ICSIRQState *irq) 615 { 616 irq->priority = 0xff; 617 irq->saved_priority = 0xff; 618 } 619 620 static void ics_base_reset(DeviceState *dev) 621 { 622 ICSState *ics = ICS_BASE(dev); 623 int i; 624 uint8_t flags[ics->nr_irqs]; 625 626 for (i = 0; i < ics->nr_irqs; i++) { 627 flags[i] = ics->irqs[i].flags; 628 } 629 630 memset(ics->irqs, 0, sizeof(ICSIRQState) * ics->nr_irqs); 631 632 for (i = 0; i < ics->nr_irqs; i++) { 633 ics_reset_irq(ics->irqs + i); 634 ics->irqs[i].flags = flags[i]; 635 } 636 } 637 638 static void ics_base_realize(DeviceState *dev, Error **errp) 639 { 640 ICSState *ics = ICS_BASE(dev); 641 Object *obj; 642 Error *err = NULL; 643 644 obj = object_property_get_link(OBJECT(dev), ICS_PROP_XICS, &err); 645 if (!obj) { 646 error_propagate_prepend(errp, err, 647 "required link '" ICS_PROP_XICS 648 "' not found: "); 649 return; 650 } 651 ics->xics = XICS_FABRIC(obj); 652 653 if (!ics->nr_irqs) { 654 error_setg(errp, "Number of interrupts needs to be greater 0"); 655 return; 656 } 657 ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState)); 658 } 659 660 static void ics_base_instance_init(Object *obj) 661 { 662 ICSState *ics = ICS_BASE(obj); 663 664 ics->offset = XICS_IRQ_BASE; 665 } 666 667 static int ics_base_pre_save(void *opaque) 668 { 669 ICSState *ics = opaque; 670 671 if (kvm_irqchip_in_kernel()) { 672 ics_get_kvm_state(ics); 673 } 674 675 return 0; 676 } 677 678 static int ics_base_post_load(void *opaque, int version_id) 679 { 680 ICSState *ics = opaque; 681 682 if (kvm_irqchip_in_kernel()) { 683 return ics_set_kvm_state(ics); 684 } 685 686 return 0; 687 } 688 689 static const VMStateDescription vmstate_ics_base_irq = { 690 .name = "ics/irq", 691 .version_id = 2, 692 .minimum_version_id = 1, 693 .fields = (VMStateField[]) { 694 VMSTATE_UINT32(server, ICSIRQState), 695 VMSTATE_UINT8(priority, ICSIRQState), 696 VMSTATE_UINT8(saved_priority, ICSIRQState), 697 VMSTATE_UINT8(status, ICSIRQState), 698 VMSTATE_UINT8(flags, ICSIRQState), 699 VMSTATE_END_OF_LIST() 700 }, 701 }; 702 703 static const VMStateDescription vmstate_ics_base = { 704 .name = "ics", 705 .version_id = 1, 706 .minimum_version_id = 1, 707 .pre_save = ics_base_pre_save, 708 .post_load = ics_base_post_load, 709 .fields = (VMStateField[]) { 710 /* Sanity check */ 711 VMSTATE_UINT32_EQUAL(nr_irqs, ICSState, NULL), 712 713 VMSTATE_STRUCT_VARRAY_POINTER_UINT32(irqs, ICSState, nr_irqs, 714 vmstate_ics_base_irq, 715 ICSIRQState), 716 VMSTATE_END_OF_LIST() 717 }, 718 }; 719 720 static Property ics_base_properties[] = { 721 DEFINE_PROP_UINT32("nr-irqs", ICSState, nr_irqs, 0), 722 DEFINE_PROP_END_OF_LIST(), 723 }; 724 725 static void ics_base_class_init(ObjectClass *klass, void *data) 726 { 727 DeviceClass *dc = DEVICE_CLASS(klass); 728 729 dc->realize = ics_base_realize; 730 dc->props = ics_base_properties; 731 dc->reset = ics_base_reset; 732 dc->vmsd = &vmstate_ics_base; 733 } 734 735 static const TypeInfo ics_base_info = { 736 .name = TYPE_ICS_BASE, 737 .parent = TYPE_DEVICE, 738 .abstract = true, 739 .instance_size = sizeof(ICSState), 740 .instance_init = ics_base_instance_init, 741 .class_init = ics_base_class_init, 742 .class_size = sizeof(ICSStateClass), 743 }; 744 745 static const TypeInfo xics_fabric_info = { 746 .name = TYPE_XICS_FABRIC, 747 .parent = TYPE_INTERFACE, 748 .class_size = sizeof(XICSFabricClass), 749 }; 750 751 /* 752 * Exported functions 753 */ 754 ICPState *xics_icp_get(XICSFabric *xi, int server) 755 { 756 XICSFabricClass *xic = XICS_FABRIC_GET_CLASS(xi); 757 758 return xic->icp_get(xi, server); 759 } 760 761 void ics_set_irq_type(ICSState *ics, int srcno, bool lsi) 762 { 763 assert(!(ics->irqs[srcno].flags & XICS_FLAGS_IRQ_MASK)); 764 765 ics->irqs[srcno].flags |= 766 lsi ? XICS_FLAGS_IRQ_LSI : XICS_FLAGS_IRQ_MSI; 767 768 if (kvm_irqchip_in_kernel()) { 769 ics_reset_irq(ics->irqs + srcno); 770 ics_set_kvm_state_one(ics, srcno); 771 } 772 } 773 774 static void xics_register_types(void) 775 { 776 type_register_static(&ics_simple_info); 777 type_register_static(&ics_base_info); 778 type_register_static(&icp_info); 779 type_register_static(&xics_fabric_info); 780 } 781 782 type_init(xics_register_types) 783