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 Error *local_err = NULL; 271 int ret; 272 273 ret = icp_set_kvm_state(icp, &local_err); 274 if (ret < 0) { 275 error_report_err(local_err); 276 return ret; 277 } 278 } 279 280 return 0; 281 } 282 283 static const VMStateDescription vmstate_icp_server = { 284 .name = "icp/server", 285 .version_id = 1, 286 .minimum_version_id = 1, 287 .pre_save = icp_pre_save, 288 .post_load = icp_post_load, 289 .fields = (VMStateField[]) { 290 /* Sanity check */ 291 VMSTATE_UINT32(xirr, ICPState), 292 VMSTATE_UINT8(pending_priority, ICPState), 293 VMSTATE_UINT8(mfrr, ICPState), 294 VMSTATE_END_OF_LIST() 295 }, 296 }; 297 298 static void icp_reset_handler(void *dev) 299 { 300 ICPState *icp = ICP(dev); 301 302 icp->xirr = 0; 303 icp->pending_priority = 0xff; 304 icp->mfrr = 0xff; 305 306 /* Make all outputs are deasserted */ 307 qemu_set_irq(icp->output, 0); 308 309 if (kvm_irqchip_in_kernel()) { 310 Error *local_err = NULL; 311 312 icp_set_kvm_state(ICP(dev), &local_err); 313 if (local_err) { 314 error_report_err(local_err); 315 } 316 } 317 } 318 319 static void icp_realize(DeviceState *dev, Error **errp) 320 { 321 ICPState *icp = ICP(dev); 322 PowerPCCPU *cpu; 323 CPUPPCState *env; 324 Object *obj; 325 Error *err = NULL; 326 327 obj = object_property_get_link(OBJECT(dev), ICP_PROP_XICS, &err); 328 if (!obj) { 329 error_propagate_prepend(errp, err, 330 "required link '" ICP_PROP_XICS 331 "' not found: "); 332 return; 333 } 334 335 icp->xics = XICS_FABRIC(obj); 336 337 obj = object_property_get_link(OBJECT(dev), ICP_PROP_CPU, &err); 338 if (!obj) { 339 error_propagate_prepend(errp, err, 340 "required link '" ICP_PROP_CPU 341 "' not found: "); 342 return; 343 } 344 345 cpu = POWERPC_CPU(obj); 346 icp->cs = CPU(obj); 347 348 env = &cpu->env; 349 switch (PPC_INPUT(env)) { 350 case PPC_FLAGS_INPUT_POWER7: 351 icp->output = env->irq_inputs[POWER7_INPUT_INT]; 352 break; 353 case PPC_FLAGS_INPUT_POWER9: /* For SPAPR xics emulation */ 354 icp->output = env->irq_inputs[POWER9_INPUT_INT]; 355 break; 356 357 case PPC_FLAGS_INPUT_970: 358 icp->output = env->irq_inputs[PPC970_INPUT_INT]; 359 break; 360 361 default: 362 error_setg(errp, "XICS interrupt controller does not support this CPU bus model"); 363 return; 364 } 365 366 /* Connect the presenter to the VCPU (required for CPU hotplug) */ 367 if (kvm_irqchip_in_kernel()) { 368 icp_kvm_realize(dev, &err); 369 if (err) { 370 error_propagate(errp, err); 371 return; 372 } 373 } 374 375 qemu_register_reset(icp_reset_handler, dev); 376 vmstate_register(NULL, icp->cs->cpu_index, &vmstate_icp_server, icp); 377 } 378 379 static void icp_unrealize(DeviceState *dev, Error **errp) 380 { 381 ICPState *icp = ICP(dev); 382 383 vmstate_unregister(NULL, &vmstate_icp_server, icp); 384 qemu_unregister_reset(icp_reset_handler, dev); 385 } 386 387 static void icp_class_init(ObjectClass *klass, void *data) 388 { 389 DeviceClass *dc = DEVICE_CLASS(klass); 390 391 dc->realize = icp_realize; 392 dc->unrealize = icp_unrealize; 393 } 394 395 static const TypeInfo icp_info = { 396 .name = TYPE_ICP, 397 .parent = TYPE_DEVICE, 398 .instance_size = sizeof(ICPState), 399 .class_init = icp_class_init, 400 .class_size = sizeof(ICPStateClass), 401 }; 402 403 Object *icp_create(Object *cpu, const char *type, XICSFabric *xi, Error **errp) 404 { 405 Error *local_err = NULL; 406 Object *obj; 407 408 obj = object_new(type); 409 object_property_add_child(cpu, type, obj, &error_abort); 410 object_unref(obj); 411 object_property_add_const_link(obj, ICP_PROP_XICS, OBJECT(xi), 412 &error_abort); 413 object_property_add_const_link(obj, ICP_PROP_CPU, cpu, &error_abort); 414 object_property_set_bool(obj, true, "realized", &local_err); 415 if (local_err) { 416 object_unparent(obj); 417 error_propagate(errp, local_err); 418 obj = NULL; 419 } 420 421 return obj; 422 } 423 424 /* 425 * ICS: Source layer 426 */ 427 static void ics_simple_resend_msi(ICSState *ics, int srcno) 428 { 429 ICSIRQState *irq = ics->irqs + srcno; 430 431 /* FIXME: filter by server#? */ 432 if (irq->status & XICS_STATUS_REJECTED) { 433 irq->status &= ~XICS_STATUS_REJECTED; 434 if (irq->priority != 0xff) { 435 icp_irq(ics, irq->server, srcno + ics->offset, irq->priority); 436 } 437 } 438 } 439 440 static void ics_simple_resend_lsi(ICSState *ics, int srcno) 441 { 442 ICSIRQState *irq = ics->irqs + srcno; 443 444 if ((irq->priority != 0xff) 445 && (irq->status & XICS_STATUS_ASSERTED) 446 && !(irq->status & XICS_STATUS_SENT)) { 447 irq->status |= XICS_STATUS_SENT; 448 icp_irq(ics, irq->server, srcno + ics->offset, irq->priority); 449 } 450 } 451 452 static void ics_simple_set_irq_msi(ICSState *ics, int srcno, int val) 453 { 454 ICSIRQState *irq = ics->irqs + srcno; 455 456 trace_xics_ics_simple_set_irq_msi(srcno, srcno + ics->offset); 457 458 if (val) { 459 if (irq->priority == 0xff) { 460 irq->status |= XICS_STATUS_MASKED_PENDING; 461 trace_xics_masked_pending(); 462 } else { 463 icp_irq(ics, irq->server, srcno + ics->offset, irq->priority); 464 } 465 } 466 } 467 468 static void ics_simple_set_irq_lsi(ICSState *ics, int srcno, int val) 469 { 470 ICSIRQState *irq = ics->irqs + srcno; 471 472 trace_xics_ics_simple_set_irq_lsi(srcno, srcno + ics->offset); 473 if (val) { 474 irq->status |= XICS_STATUS_ASSERTED; 475 } else { 476 irq->status &= ~XICS_STATUS_ASSERTED; 477 } 478 ics_simple_resend_lsi(ics, srcno); 479 } 480 481 void ics_simple_set_irq(void *opaque, int srcno, int val) 482 { 483 ICSState *ics = (ICSState *)opaque; 484 485 if (kvm_irqchip_in_kernel()) { 486 ics_kvm_set_irq(ics, srcno, val); 487 return; 488 } 489 490 if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) { 491 ics_simple_set_irq_lsi(ics, srcno, val); 492 } else { 493 ics_simple_set_irq_msi(ics, srcno, val); 494 } 495 } 496 497 static void ics_simple_write_xive_msi(ICSState *ics, int srcno) 498 { 499 ICSIRQState *irq = ics->irqs + srcno; 500 501 if (!(irq->status & XICS_STATUS_MASKED_PENDING) 502 || (irq->priority == 0xff)) { 503 return; 504 } 505 506 irq->status &= ~XICS_STATUS_MASKED_PENDING; 507 icp_irq(ics, irq->server, srcno + ics->offset, irq->priority); 508 } 509 510 static void ics_simple_write_xive_lsi(ICSState *ics, int srcno) 511 { 512 ics_simple_resend_lsi(ics, srcno); 513 } 514 515 void ics_simple_write_xive(ICSState *ics, int srcno, int server, 516 uint8_t priority, uint8_t saved_priority) 517 { 518 ICSIRQState *irq = ics->irqs + srcno; 519 520 irq->server = server; 521 irq->priority = priority; 522 irq->saved_priority = saved_priority; 523 524 trace_xics_ics_simple_write_xive(ics->offset + srcno, srcno, server, 525 priority); 526 527 if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) { 528 ics_simple_write_xive_lsi(ics, srcno); 529 } else { 530 ics_simple_write_xive_msi(ics, srcno); 531 } 532 } 533 534 static void ics_simple_reject(ICSState *ics, uint32_t nr) 535 { 536 ICSIRQState *irq = ics->irqs + nr - ics->offset; 537 538 trace_xics_ics_simple_reject(nr, nr - ics->offset); 539 if (irq->flags & XICS_FLAGS_IRQ_MSI) { 540 irq->status |= XICS_STATUS_REJECTED; 541 } else if (irq->flags & XICS_FLAGS_IRQ_LSI) { 542 irq->status &= ~XICS_STATUS_SENT; 543 } 544 } 545 546 static void ics_simple_resend(ICSState *ics) 547 { 548 int i; 549 550 for (i = 0; i < ics->nr_irqs; i++) { 551 /* FIXME: filter by server#? */ 552 if (ics->irqs[i].flags & XICS_FLAGS_IRQ_LSI) { 553 ics_simple_resend_lsi(ics, i); 554 } else { 555 ics_simple_resend_msi(ics, i); 556 } 557 } 558 } 559 560 static void ics_simple_eoi(ICSState *ics, uint32_t nr) 561 { 562 int srcno = nr - ics->offset; 563 ICSIRQState *irq = ics->irqs + srcno; 564 565 trace_xics_ics_simple_eoi(nr); 566 567 if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) { 568 irq->status &= ~XICS_STATUS_SENT; 569 } 570 } 571 572 static void ics_simple_reset(DeviceState *dev) 573 { 574 ICSStateClass *icsc = ICS_BASE_GET_CLASS(dev); 575 576 icsc->parent_reset(dev); 577 578 if (kvm_irqchip_in_kernel()) { 579 Error *local_err = NULL; 580 581 ics_set_kvm_state(ICS_BASE(dev), &local_err); 582 if (local_err) { 583 error_report_err(local_err); 584 } 585 } 586 } 587 588 static void ics_simple_reset_handler(void *dev) 589 { 590 ics_simple_reset(dev); 591 } 592 593 static void ics_simple_realize(DeviceState *dev, Error **errp) 594 { 595 ICSState *ics = ICS_SIMPLE(dev); 596 ICSStateClass *icsc = ICS_BASE_GET_CLASS(ics); 597 Error *local_err = NULL; 598 599 icsc->parent_realize(dev, &local_err); 600 if (local_err) { 601 error_propagate(errp, local_err); 602 return; 603 } 604 605 qemu_register_reset(ics_simple_reset_handler, ics); 606 } 607 608 static void ics_simple_class_init(ObjectClass *klass, void *data) 609 { 610 DeviceClass *dc = DEVICE_CLASS(klass); 611 ICSStateClass *isc = ICS_BASE_CLASS(klass); 612 613 device_class_set_parent_realize(dc, ics_simple_realize, 614 &isc->parent_realize); 615 device_class_set_parent_reset(dc, ics_simple_reset, 616 &isc->parent_reset); 617 618 isc->reject = ics_simple_reject; 619 isc->resend = ics_simple_resend; 620 isc->eoi = ics_simple_eoi; 621 } 622 623 static const TypeInfo ics_simple_info = { 624 .name = TYPE_ICS_SIMPLE, 625 .parent = TYPE_ICS_BASE, 626 .instance_size = sizeof(ICSState), 627 .class_init = ics_simple_class_init, 628 .class_size = sizeof(ICSStateClass), 629 }; 630 631 static void ics_reset_irq(ICSIRQState *irq) 632 { 633 irq->priority = 0xff; 634 irq->saved_priority = 0xff; 635 } 636 637 static void ics_base_reset(DeviceState *dev) 638 { 639 ICSState *ics = ICS_BASE(dev); 640 int i; 641 uint8_t flags[ics->nr_irqs]; 642 643 for (i = 0; i < ics->nr_irqs; i++) { 644 flags[i] = ics->irqs[i].flags; 645 } 646 647 memset(ics->irqs, 0, sizeof(ICSIRQState) * ics->nr_irqs); 648 649 for (i = 0; i < ics->nr_irqs; i++) { 650 ics_reset_irq(ics->irqs + i); 651 ics->irqs[i].flags = flags[i]; 652 } 653 } 654 655 static void ics_base_realize(DeviceState *dev, Error **errp) 656 { 657 ICSState *ics = ICS_BASE(dev); 658 Object *obj; 659 Error *err = NULL; 660 661 obj = object_property_get_link(OBJECT(dev), ICS_PROP_XICS, &err); 662 if (!obj) { 663 error_propagate_prepend(errp, err, 664 "required link '" ICS_PROP_XICS 665 "' not found: "); 666 return; 667 } 668 ics->xics = XICS_FABRIC(obj); 669 670 if (!ics->nr_irqs) { 671 error_setg(errp, "Number of interrupts needs to be greater 0"); 672 return; 673 } 674 ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState)); 675 } 676 677 static void ics_base_instance_init(Object *obj) 678 { 679 ICSState *ics = ICS_BASE(obj); 680 681 ics->offset = XICS_IRQ_BASE; 682 } 683 684 static int ics_base_pre_save(void *opaque) 685 { 686 ICSState *ics = opaque; 687 688 if (kvm_irqchip_in_kernel()) { 689 ics_get_kvm_state(ics); 690 } 691 692 return 0; 693 } 694 695 static int ics_base_post_load(void *opaque, int version_id) 696 { 697 ICSState *ics = opaque; 698 699 if (kvm_irqchip_in_kernel()) { 700 Error *local_err = NULL; 701 int ret; 702 703 ret = ics_set_kvm_state(ics, &local_err); 704 if (ret < 0) { 705 error_report_err(local_err); 706 return ret; 707 } 708 } 709 710 return 0; 711 } 712 713 static const VMStateDescription vmstate_ics_base_irq = { 714 .name = "ics/irq", 715 .version_id = 2, 716 .minimum_version_id = 1, 717 .fields = (VMStateField[]) { 718 VMSTATE_UINT32(server, ICSIRQState), 719 VMSTATE_UINT8(priority, ICSIRQState), 720 VMSTATE_UINT8(saved_priority, ICSIRQState), 721 VMSTATE_UINT8(status, ICSIRQState), 722 VMSTATE_UINT8(flags, ICSIRQState), 723 VMSTATE_END_OF_LIST() 724 }, 725 }; 726 727 static const VMStateDescription vmstate_ics_base = { 728 .name = "ics", 729 .version_id = 1, 730 .minimum_version_id = 1, 731 .pre_save = ics_base_pre_save, 732 .post_load = ics_base_post_load, 733 .fields = (VMStateField[]) { 734 /* Sanity check */ 735 VMSTATE_UINT32_EQUAL(nr_irqs, ICSState, NULL), 736 737 VMSTATE_STRUCT_VARRAY_POINTER_UINT32(irqs, ICSState, nr_irqs, 738 vmstate_ics_base_irq, 739 ICSIRQState), 740 VMSTATE_END_OF_LIST() 741 }, 742 }; 743 744 static Property ics_base_properties[] = { 745 DEFINE_PROP_UINT32("nr-irqs", ICSState, nr_irqs, 0), 746 DEFINE_PROP_END_OF_LIST(), 747 }; 748 749 static void ics_base_class_init(ObjectClass *klass, void *data) 750 { 751 DeviceClass *dc = DEVICE_CLASS(klass); 752 753 dc->realize = ics_base_realize; 754 dc->props = ics_base_properties; 755 dc->reset = ics_base_reset; 756 dc->vmsd = &vmstate_ics_base; 757 } 758 759 static const TypeInfo ics_base_info = { 760 .name = TYPE_ICS_BASE, 761 .parent = TYPE_DEVICE, 762 .abstract = true, 763 .instance_size = sizeof(ICSState), 764 .instance_init = ics_base_instance_init, 765 .class_init = ics_base_class_init, 766 .class_size = sizeof(ICSStateClass), 767 }; 768 769 static const TypeInfo xics_fabric_info = { 770 .name = TYPE_XICS_FABRIC, 771 .parent = TYPE_INTERFACE, 772 .class_size = sizeof(XICSFabricClass), 773 }; 774 775 /* 776 * Exported functions 777 */ 778 ICPState *xics_icp_get(XICSFabric *xi, int server) 779 { 780 XICSFabricClass *xic = XICS_FABRIC_GET_CLASS(xi); 781 782 return xic->icp_get(xi, server); 783 } 784 785 void ics_set_irq_type(ICSState *ics, int srcno, bool lsi) 786 { 787 assert(!(ics->irqs[srcno].flags & XICS_FLAGS_IRQ_MASK)); 788 789 ics->irqs[srcno].flags |= 790 lsi ? XICS_FLAGS_IRQ_LSI : XICS_FLAGS_IRQ_MSI; 791 792 if (kvm_irqchip_in_kernel()) { 793 Error *local_err = NULL; 794 795 ics_reset_irq(ics->irqs + srcno); 796 ics_set_kvm_state_one(ics, srcno, &local_err); 797 if (local_err) { 798 error_report_err(local_err); 799 } 800 } 801 } 802 803 static void xics_register_types(void) 804 { 805 type_register_static(&ics_simple_info); 806 type_register_static(&ics_base_info); 807 type_register_static(&icp_info); 808 type_register_static(&xics_fabric_info); 809 } 810 811 type_init(xics_register_types) 812