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 "qemu-common.h" 31 #include "cpu.h" 32 #include "hw/hw.h" 33 #include "trace.h" 34 #include "qemu/timer.h" 35 #include "hw/ppc/xics.h" 36 #include "qemu/error-report.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 if (kvm_irqchip_in_kernel()) { 355 icp_kvm_realize(dev, &err); 356 if (err) { 357 error_propagate(errp, err); 358 return; 359 } 360 } 361 362 qemu_register_reset(icp_reset_handler, dev); 363 vmstate_register(NULL, icp->cs->cpu_index, &vmstate_icp_server, icp); 364 } 365 366 static void icp_unrealize(DeviceState *dev, Error **errp) 367 { 368 ICPState *icp = ICP(dev); 369 370 vmstate_unregister(NULL, &vmstate_icp_server, icp); 371 qemu_unregister_reset(icp_reset_handler, dev); 372 } 373 374 static void icp_class_init(ObjectClass *klass, void *data) 375 { 376 DeviceClass *dc = DEVICE_CLASS(klass); 377 378 dc->realize = icp_realize; 379 dc->unrealize = icp_unrealize; 380 } 381 382 static const TypeInfo icp_info = { 383 .name = TYPE_ICP, 384 .parent = TYPE_DEVICE, 385 .instance_size = sizeof(ICPState), 386 .class_init = icp_class_init, 387 .class_size = sizeof(ICPStateClass), 388 }; 389 390 Object *icp_create(Object *cpu, const char *type, XICSFabric *xi, Error **errp) 391 { 392 Error *local_err = NULL; 393 Object *obj; 394 395 obj = object_new(type); 396 object_property_add_child(cpu, type, obj, &error_abort); 397 object_unref(obj); 398 object_property_add_const_link(obj, ICP_PROP_XICS, OBJECT(xi), 399 &error_abort); 400 object_property_add_const_link(obj, ICP_PROP_CPU, cpu, &error_abort); 401 object_property_set_bool(obj, true, "realized", &local_err); 402 if (local_err) { 403 object_unparent(obj); 404 error_propagate(errp, local_err); 405 obj = NULL; 406 } 407 408 return obj; 409 } 410 411 /* 412 * ICS: Source layer 413 */ 414 static void ics_simple_resend_msi(ICSState *ics, int srcno) 415 { 416 ICSIRQState *irq = ics->irqs + srcno; 417 418 /* FIXME: filter by server#? */ 419 if (irq->status & XICS_STATUS_REJECTED) { 420 irq->status &= ~XICS_STATUS_REJECTED; 421 if (irq->priority != 0xff) { 422 icp_irq(ics, irq->server, srcno + ics->offset, irq->priority); 423 } 424 } 425 } 426 427 static void ics_simple_resend_lsi(ICSState *ics, int srcno) 428 { 429 ICSIRQState *irq = ics->irqs + srcno; 430 431 if ((irq->priority != 0xff) 432 && (irq->status & XICS_STATUS_ASSERTED) 433 && !(irq->status & XICS_STATUS_SENT)) { 434 irq->status |= XICS_STATUS_SENT; 435 icp_irq(ics, irq->server, srcno + ics->offset, irq->priority); 436 } 437 } 438 439 static void ics_simple_set_irq_msi(ICSState *ics, int srcno, int val) 440 { 441 ICSIRQState *irq = ics->irqs + srcno; 442 443 trace_xics_ics_simple_set_irq_msi(srcno, srcno + ics->offset); 444 445 if (val) { 446 if (irq->priority == 0xff) { 447 irq->status |= XICS_STATUS_MASKED_PENDING; 448 trace_xics_masked_pending(); 449 } else { 450 icp_irq(ics, irq->server, srcno + ics->offset, irq->priority); 451 } 452 } 453 } 454 455 static void ics_simple_set_irq_lsi(ICSState *ics, int srcno, int val) 456 { 457 ICSIRQState *irq = ics->irqs + srcno; 458 459 trace_xics_ics_simple_set_irq_lsi(srcno, srcno + ics->offset); 460 if (val) { 461 irq->status |= XICS_STATUS_ASSERTED; 462 } else { 463 irq->status &= ~XICS_STATUS_ASSERTED; 464 } 465 ics_simple_resend_lsi(ics, srcno); 466 } 467 468 void ics_simple_set_irq(void *opaque, int srcno, int val) 469 { 470 ICSState *ics = (ICSState *)opaque; 471 472 if (kvm_irqchip_in_kernel()) { 473 ics_kvm_set_irq(ics, srcno, val); 474 return; 475 } 476 477 if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) { 478 ics_simple_set_irq_lsi(ics, srcno, val); 479 } else { 480 ics_simple_set_irq_msi(ics, srcno, val); 481 } 482 } 483 484 static void ics_simple_write_xive_msi(ICSState *ics, int srcno) 485 { 486 ICSIRQState *irq = ics->irqs + srcno; 487 488 if (!(irq->status & XICS_STATUS_MASKED_PENDING) 489 || (irq->priority == 0xff)) { 490 return; 491 } 492 493 irq->status &= ~XICS_STATUS_MASKED_PENDING; 494 icp_irq(ics, irq->server, srcno + ics->offset, irq->priority); 495 } 496 497 static void ics_simple_write_xive_lsi(ICSState *ics, int srcno) 498 { 499 ics_simple_resend_lsi(ics, srcno); 500 } 501 502 void ics_simple_write_xive(ICSState *ics, int srcno, int server, 503 uint8_t priority, uint8_t saved_priority) 504 { 505 ICSIRQState *irq = ics->irqs + srcno; 506 507 irq->server = server; 508 irq->priority = priority; 509 irq->saved_priority = saved_priority; 510 511 trace_xics_ics_simple_write_xive(ics->offset + srcno, srcno, server, 512 priority); 513 514 if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) { 515 ics_simple_write_xive_lsi(ics, srcno); 516 } else { 517 ics_simple_write_xive_msi(ics, srcno); 518 } 519 } 520 521 static void ics_simple_reject(ICSState *ics, uint32_t nr) 522 { 523 ICSIRQState *irq = ics->irqs + nr - ics->offset; 524 525 trace_xics_ics_simple_reject(nr, nr - ics->offset); 526 if (irq->flags & XICS_FLAGS_IRQ_MSI) { 527 irq->status |= XICS_STATUS_REJECTED; 528 } else if (irq->flags & XICS_FLAGS_IRQ_LSI) { 529 irq->status &= ~XICS_STATUS_SENT; 530 } 531 } 532 533 static void ics_simple_resend(ICSState *ics) 534 { 535 int i; 536 537 for (i = 0; i < ics->nr_irqs; i++) { 538 /* FIXME: filter by server#? */ 539 if (ics->irqs[i].flags & XICS_FLAGS_IRQ_LSI) { 540 ics_simple_resend_lsi(ics, i); 541 } else { 542 ics_simple_resend_msi(ics, i); 543 } 544 } 545 } 546 547 static void ics_simple_eoi(ICSState *ics, uint32_t nr) 548 { 549 int srcno = nr - ics->offset; 550 ICSIRQState *irq = ics->irqs + srcno; 551 552 trace_xics_ics_simple_eoi(nr); 553 554 if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) { 555 irq->status &= ~XICS_STATUS_SENT; 556 } 557 } 558 559 static void ics_simple_reset(DeviceState *dev) 560 { 561 ICSStateClass *icsc = ICS_BASE_GET_CLASS(dev); 562 563 icsc->parent_reset(dev); 564 565 if (kvm_irqchip_in_kernel()) { 566 ics_set_kvm_state(ICS_BASE(dev)); 567 } 568 } 569 570 static void ics_simple_reset_handler(void *dev) 571 { 572 ics_simple_reset(dev); 573 } 574 575 static void ics_simple_realize(DeviceState *dev, Error **errp) 576 { 577 ICSState *ics = ICS_SIMPLE(dev); 578 ICSStateClass *icsc = ICS_BASE_GET_CLASS(ics); 579 Error *local_err = NULL; 580 581 icsc->parent_realize(dev, &local_err); 582 if (local_err) { 583 error_propagate(errp, local_err); 584 return; 585 } 586 587 qemu_register_reset(ics_simple_reset_handler, ics); 588 } 589 590 static void ics_simple_class_init(ObjectClass *klass, void *data) 591 { 592 DeviceClass *dc = DEVICE_CLASS(klass); 593 ICSStateClass *isc = ICS_BASE_CLASS(klass); 594 595 device_class_set_parent_realize(dc, ics_simple_realize, 596 &isc->parent_realize); 597 device_class_set_parent_reset(dc, ics_simple_reset, 598 &isc->parent_reset); 599 600 isc->reject = ics_simple_reject; 601 isc->resend = ics_simple_resend; 602 isc->eoi = ics_simple_eoi; 603 } 604 605 static const TypeInfo ics_simple_info = { 606 .name = TYPE_ICS_SIMPLE, 607 .parent = TYPE_ICS_BASE, 608 .instance_size = sizeof(ICSState), 609 .class_init = ics_simple_class_init, 610 .class_size = sizeof(ICSStateClass), 611 }; 612 613 static void ics_reset_irq(ICSIRQState *irq) 614 { 615 irq->priority = 0xff; 616 irq->saved_priority = 0xff; 617 } 618 619 static void ics_base_reset(DeviceState *dev) 620 { 621 ICSState *ics = ICS_BASE(dev); 622 int i; 623 uint8_t flags[ics->nr_irqs]; 624 625 for (i = 0; i < ics->nr_irqs; i++) { 626 flags[i] = ics->irqs[i].flags; 627 } 628 629 memset(ics->irqs, 0, sizeof(ICSIRQState) * ics->nr_irqs); 630 631 for (i = 0; i < ics->nr_irqs; i++) { 632 ics_reset_irq(ics->irqs + i); 633 ics->irqs[i].flags = flags[i]; 634 } 635 } 636 637 static void ics_base_realize(DeviceState *dev, Error **errp) 638 { 639 ICSState *ics = ICS_BASE(dev); 640 Object *obj; 641 Error *err = NULL; 642 643 obj = object_property_get_link(OBJECT(dev), ICS_PROP_XICS, &err); 644 if (!obj) { 645 error_propagate_prepend(errp, err, 646 "required link '" ICS_PROP_XICS 647 "' not found: "); 648 return; 649 } 650 ics->xics = XICS_FABRIC(obj); 651 652 if (!ics->nr_irqs) { 653 error_setg(errp, "Number of interrupts needs to be greater 0"); 654 return; 655 } 656 ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState)); 657 } 658 659 static void ics_base_instance_init(Object *obj) 660 { 661 ICSState *ics = ICS_BASE(obj); 662 663 ics->offset = XICS_IRQ_BASE; 664 } 665 666 static int ics_base_pre_save(void *opaque) 667 { 668 ICSState *ics = opaque; 669 670 if (kvm_irqchip_in_kernel()) { 671 ics_get_kvm_state(ics); 672 } 673 674 return 0; 675 } 676 677 static int ics_base_post_load(void *opaque, int version_id) 678 { 679 ICSState *ics = opaque; 680 681 if (kvm_irqchip_in_kernel()) { 682 return ics_set_kvm_state(ics); 683 } 684 685 return 0; 686 } 687 688 static const VMStateDescription vmstate_ics_base_irq = { 689 .name = "ics/irq", 690 .version_id = 2, 691 .minimum_version_id = 1, 692 .fields = (VMStateField[]) { 693 VMSTATE_UINT32(server, ICSIRQState), 694 VMSTATE_UINT8(priority, ICSIRQState), 695 VMSTATE_UINT8(saved_priority, ICSIRQState), 696 VMSTATE_UINT8(status, ICSIRQState), 697 VMSTATE_UINT8(flags, ICSIRQState), 698 VMSTATE_END_OF_LIST() 699 }, 700 }; 701 702 static const VMStateDescription vmstate_ics_base = { 703 .name = "ics", 704 .version_id = 1, 705 .minimum_version_id = 1, 706 .pre_save = ics_base_pre_save, 707 .post_load = ics_base_post_load, 708 .fields = (VMStateField[]) { 709 /* Sanity check */ 710 VMSTATE_UINT32_EQUAL(nr_irqs, ICSState, NULL), 711 712 VMSTATE_STRUCT_VARRAY_POINTER_UINT32(irqs, ICSState, nr_irqs, 713 vmstate_ics_base_irq, 714 ICSIRQState), 715 VMSTATE_END_OF_LIST() 716 }, 717 }; 718 719 static Property ics_base_properties[] = { 720 DEFINE_PROP_UINT32("nr-irqs", ICSState, nr_irqs, 0), 721 DEFINE_PROP_END_OF_LIST(), 722 }; 723 724 static void ics_base_class_init(ObjectClass *klass, void *data) 725 { 726 DeviceClass *dc = DEVICE_CLASS(klass); 727 728 dc->realize = ics_base_realize; 729 dc->props = ics_base_properties; 730 dc->reset = ics_base_reset; 731 dc->vmsd = &vmstate_ics_base; 732 } 733 734 static const TypeInfo ics_base_info = { 735 .name = TYPE_ICS_BASE, 736 .parent = TYPE_DEVICE, 737 .abstract = true, 738 .instance_size = sizeof(ICSState), 739 .instance_init = ics_base_instance_init, 740 .class_init = ics_base_class_init, 741 .class_size = sizeof(ICSStateClass), 742 }; 743 744 static const TypeInfo xics_fabric_info = { 745 .name = TYPE_XICS_FABRIC, 746 .parent = TYPE_INTERFACE, 747 .class_size = sizeof(XICSFabricClass), 748 }; 749 750 /* 751 * Exported functions 752 */ 753 ICPState *xics_icp_get(XICSFabric *xi, int server) 754 { 755 XICSFabricClass *xic = XICS_FABRIC_GET_CLASS(xi); 756 757 return xic->icp_get(xi, server); 758 } 759 760 void ics_set_irq_type(ICSState *ics, int srcno, bool lsi) 761 { 762 assert(!(ics->irqs[srcno].flags & XICS_FLAGS_IRQ_MASK)); 763 764 ics->irqs[srcno].flags |= 765 lsi ? XICS_FLAGS_IRQ_LSI : XICS_FLAGS_IRQ_MSI; 766 767 if (kvm_irqchip_in_kernel()) { 768 ics_reset_irq(ics->irqs + srcno); 769 ics_set_kvm_state_one(ics, srcno); 770 } 771 } 772 773 static void xics_register_types(void) 774 { 775 type_register_static(&ics_simple_info); 776 type_register_static(&ics_base_info); 777 type_register_static(&icp_info); 778 type_register_static(&xics_fabric_info); 779 } 780 781 type_init(xics_register_types) 782