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 41 int xics_get_cpu_index_by_dt_id(int cpu_dt_id) 42 { 43 PowerPCCPU *cpu = ppc_get_vcpu_by_dt_id(cpu_dt_id); 44 45 if (cpu) { 46 return cpu->parent_obj.cpu_index; 47 } 48 49 return -1; 50 } 51 52 void xics_cpu_destroy(XICSState *xics, PowerPCCPU *cpu) 53 { 54 CPUState *cs = CPU(cpu); 55 ICPState *ss = &xics->ss[cs->cpu_index]; 56 57 assert(cs->cpu_index < xics->nr_servers); 58 assert(cs == ss->cs); 59 60 ss->output = NULL; 61 ss->cs = NULL; 62 } 63 64 void xics_cpu_setup(XICSState *xics, PowerPCCPU *cpu) 65 { 66 CPUState *cs = CPU(cpu); 67 CPUPPCState *env = &cpu->env; 68 ICPState *ss = &xics->ss[cs->cpu_index]; 69 XICSStateClass *info = XICS_COMMON_GET_CLASS(xics); 70 71 assert(cs->cpu_index < xics->nr_servers); 72 73 ss->cs = cs; 74 75 if (info->cpu_setup) { 76 info->cpu_setup(xics, cpu); 77 } 78 79 switch (PPC_INPUT(env)) { 80 case PPC_FLAGS_INPUT_POWER7: 81 ss->output = env->irq_inputs[POWER7_INPUT_INT]; 82 break; 83 84 case PPC_FLAGS_INPUT_970: 85 ss->output = env->irq_inputs[PPC970_INPUT_INT]; 86 break; 87 88 default: 89 error_report("XICS interrupt controller does not support this CPU " 90 "bus model"); 91 abort(); 92 } 93 } 94 95 static void xics_common_pic_print_info(InterruptStatsProvider *obj, 96 Monitor *mon) 97 { 98 XICSState *xics = XICS_COMMON(obj); 99 ICSState *ics; 100 uint32_t i; 101 102 for (i = 0; i < xics->nr_servers; i++) { 103 ICPState *icp = &xics->ss[i]; 104 105 if (!icp->output) { 106 continue; 107 } 108 monitor_printf(mon, "CPU %d XIRR=%08x (%p) PP=%02x MFRR=%02x\n", 109 i, icp->xirr, icp->xirr_owner, 110 icp->pending_priority, icp->mfrr); 111 } 112 113 QLIST_FOREACH(ics, &xics->ics, list) { 114 monitor_printf(mon, "ICS %4x..%4x %p\n", 115 ics->offset, ics->offset + ics->nr_irqs - 1, ics); 116 117 if (!ics->irqs) { 118 continue; 119 } 120 121 for (i = 0; i < ics->nr_irqs; i++) { 122 ICSIRQState *irq = ics->irqs + i; 123 124 if (!(irq->flags & XICS_FLAGS_IRQ_MASK)) { 125 continue; 126 } 127 monitor_printf(mon, " %4x %s %02x %02x\n", 128 ics->offset + i, 129 (irq->flags & XICS_FLAGS_IRQ_LSI) ? 130 "LSI" : "MSI", 131 irq->priority, irq->status); 132 } 133 } 134 } 135 136 /* 137 * XICS Common class - parent for emulated XICS and KVM-XICS 138 */ 139 static void xics_common_reset(DeviceState *d) 140 { 141 XICSState *xics = XICS_COMMON(d); 142 ICSState *ics; 143 int i; 144 145 for (i = 0; i < xics->nr_servers; i++) { 146 device_reset(DEVICE(&xics->ss[i])); 147 } 148 149 QLIST_FOREACH(ics, &xics->ics, list) { 150 device_reset(DEVICE(ics)); 151 } 152 } 153 154 static void xics_prop_get_nr_irqs(Object *obj, Visitor *v, const char *name, 155 void *opaque, Error **errp) 156 { 157 XICSState *xics = XICS_COMMON(obj); 158 int64_t value = xics->nr_irqs; 159 160 visit_type_int(v, name, &value, errp); 161 } 162 163 static void xics_prop_set_nr_irqs(Object *obj, Visitor *v, const char *name, 164 void *opaque, Error **errp) 165 { 166 XICSState *xics = XICS_COMMON(obj); 167 XICSStateClass *info = XICS_COMMON_GET_CLASS(xics); 168 Error *error = NULL; 169 int64_t value; 170 171 visit_type_int(v, name, &value, &error); 172 if (error) { 173 error_propagate(errp, error); 174 return; 175 } 176 if (xics->nr_irqs) { 177 error_setg(errp, "Number of interrupts is already set to %u", 178 xics->nr_irqs); 179 return; 180 } 181 182 assert(info->set_nr_irqs); 183 info->set_nr_irqs(xics, value, errp); 184 } 185 186 void xics_set_nr_servers(XICSState *xics, uint32_t nr_servers, 187 const char *typename, Error **errp) 188 { 189 int i; 190 191 xics->nr_servers = nr_servers; 192 193 xics->ss = g_malloc0(xics->nr_servers * sizeof(ICPState)); 194 for (i = 0; i < xics->nr_servers; i++) { 195 char name[32]; 196 ICPState *icp = &xics->ss[i]; 197 198 object_initialize(icp, sizeof(*icp), typename); 199 snprintf(name, sizeof(name), "icp[%d]", i); 200 object_property_add_child(OBJECT(xics), name, OBJECT(icp), errp); 201 icp->xics = xics; 202 } 203 } 204 205 static void xics_prop_get_nr_servers(Object *obj, Visitor *v, 206 const char *name, void *opaque, 207 Error **errp) 208 { 209 XICSState *xics = XICS_COMMON(obj); 210 int64_t value = xics->nr_servers; 211 212 visit_type_int(v, name, &value, errp); 213 } 214 215 static void xics_prop_set_nr_servers(Object *obj, Visitor *v, 216 const char *name, void *opaque, 217 Error **errp) 218 { 219 XICSState *xics = XICS_COMMON(obj); 220 XICSStateClass *xsc = XICS_COMMON_GET_CLASS(xics); 221 Error *error = NULL; 222 int64_t value; 223 224 visit_type_int(v, name, &value, &error); 225 if (error) { 226 error_propagate(errp, error); 227 return; 228 } 229 if (xics->nr_servers) { 230 error_setg(errp, "Number of servers is already set to %u", 231 xics->nr_servers); 232 return; 233 } 234 235 assert(xsc->set_nr_servers); 236 xsc->set_nr_servers(xics, value, errp); 237 } 238 239 static void xics_common_initfn(Object *obj) 240 { 241 XICSState *xics = XICS_COMMON(obj); 242 243 QLIST_INIT(&xics->ics); 244 object_property_add(obj, "nr_irqs", "int", 245 xics_prop_get_nr_irqs, xics_prop_set_nr_irqs, 246 NULL, NULL, NULL); 247 object_property_add(obj, "nr_servers", "int", 248 xics_prop_get_nr_servers, xics_prop_set_nr_servers, 249 NULL, NULL, NULL); 250 } 251 252 static void xics_common_class_init(ObjectClass *oc, void *data) 253 { 254 DeviceClass *dc = DEVICE_CLASS(oc); 255 InterruptStatsProviderClass *ic = INTERRUPT_STATS_PROVIDER_CLASS(oc); 256 257 dc->reset = xics_common_reset; 258 ic->print_info = xics_common_pic_print_info; 259 } 260 261 static const TypeInfo xics_common_info = { 262 .name = TYPE_XICS_COMMON, 263 .parent = TYPE_SYS_BUS_DEVICE, 264 .instance_size = sizeof(XICSState), 265 .class_size = sizeof(XICSStateClass), 266 .instance_init = xics_common_initfn, 267 .class_init = xics_common_class_init, 268 .interfaces = (InterfaceInfo[]) { 269 { TYPE_INTERRUPT_STATS_PROVIDER }, 270 { } 271 }, 272 }; 273 274 /* 275 * ICP: Presentation layer 276 */ 277 278 #define XISR_MASK 0x00ffffff 279 #define CPPR_MASK 0xff000000 280 281 #define XISR(ss) (((ss)->xirr) & XISR_MASK) 282 #define CPPR(ss) (((ss)->xirr) >> 24) 283 284 static void ics_reject(ICSState *ics, uint32_t nr) 285 { 286 ICSStateClass *k = ICS_BASE_GET_CLASS(ics); 287 288 if (k->reject) { 289 k->reject(ics, nr); 290 } 291 } 292 293 static void ics_resend(ICSState *ics) 294 { 295 ICSStateClass *k = ICS_BASE_GET_CLASS(ics); 296 297 if (k->resend) { 298 k->resend(ics); 299 } 300 } 301 302 static void ics_eoi(ICSState *ics, int nr) 303 { 304 ICSStateClass *k = ICS_BASE_GET_CLASS(ics); 305 306 if (k->eoi) { 307 k->eoi(ics, nr); 308 } 309 } 310 311 static void icp_check_ipi(ICPState *ss) 312 { 313 if (XISR(ss) && (ss->pending_priority <= ss->mfrr)) { 314 return; 315 } 316 317 trace_xics_icp_check_ipi(ss->cs->cpu_index, ss->mfrr); 318 319 if (XISR(ss) && ss->xirr_owner) { 320 ics_reject(ss->xirr_owner, XISR(ss)); 321 } 322 323 ss->xirr = (ss->xirr & ~XISR_MASK) | XICS_IPI; 324 ss->pending_priority = ss->mfrr; 325 ss->xirr_owner = NULL; 326 qemu_irq_raise(ss->output); 327 } 328 329 static void icp_resend(ICPState *ss) 330 { 331 ICSState *ics; 332 333 if (ss->mfrr < CPPR(ss)) { 334 icp_check_ipi(ss); 335 } 336 QLIST_FOREACH(ics, &ss->xics->ics, list) { 337 ics_resend(ics); 338 } 339 } 340 341 void icp_set_cppr(ICPState *ss, uint8_t cppr) 342 { 343 uint8_t old_cppr; 344 uint32_t old_xisr; 345 346 old_cppr = CPPR(ss); 347 ss->xirr = (ss->xirr & ~CPPR_MASK) | (cppr << 24); 348 349 if (cppr < old_cppr) { 350 if (XISR(ss) && (cppr <= ss->pending_priority)) { 351 old_xisr = XISR(ss); 352 ss->xirr &= ~XISR_MASK; /* Clear XISR */ 353 ss->pending_priority = 0xff; 354 qemu_irq_lower(ss->output); 355 if (ss->xirr_owner) { 356 ics_reject(ss->xirr_owner, old_xisr); 357 ss->xirr_owner = NULL; 358 } 359 } 360 } else { 361 if (!XISR(ss)) { 362 icp_resend(ss); 363 } 364 } 365 } 366 367 void icp_set_mfrr(ICPState *ss, uint8_t mfrr) 368 { 369 ss->mfrr = mfrr; 370 if (mfrr < CPPR(ss)) { 371 icp_check_ipi(ss); 372 } 373 } 374 375 uint32_t icp_accept(ICPState *ss) 376 { 377 uint32_t xirr = ss->xirr; 378 379 qemu_irq_lower(ss->output); 380 ss->xirr = ss->pending_priority << 24; 381 ss->pending_priority = 0xff; 382 ss->xirr_owner = NULL; 383 384 trace_xics_icp_accept(xirr, ss->xirr); 385 386 return xirr; 387 } 388 389 uint32_t icp_ipoll(ICPState *ss, uint32_t *mfrr) 390 { 391 if (mfrr) { 392 *mfrr = ss->mfrr; 393 } 394 return ss->xirr; 395 } 396 397 void icp_eoi(ICPState *ss, uint32_t xirr) 398 { 399 ICSState *ics; 400 uint32_t irq; 401 402 /* Send EOI -> ICS */ 403 ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK); 404 trace_xics_icp_eoi(ss->cs->cpu_index, xirr, ss->xirr); 405 irq = xirr & XISR_MASK; 406 QLIST_FOREACH(ics, &ss->xics->ics, list) { 407 if (ics_valid_irq(ics, irq)) { 408 ics_eoi(ics, irq); 409 } 410 } 411 if (!XISR(ss)) { 412 icp_resend(ss); 413 } 414 } 415 416 static void icp_irq(ICSState *ics, int server, int nr, uint8_t priority) 417 { 418 XICSState *xics = ics->xics; 419 ICPState *ss = xics->ss + server; 420 421 trace_xics_icp_irq(server, nr, priority); 422 423 if ((priority >= CPPR(ss)) 424 || (XISR(ss) && (ss->pending_priority <= priority))) { 425 ics_reject(ics, nr); 426 } else { 427 if (XISR(ss) && ss->xirr_owner) { 428 ics_reject(ss->xirr_owner, XISR(ss)); 429 ss->xirr_owner = NULL; 430 } 431 ss->xirr = (ss->xirr & ~XISR_MASK) | (nr & XISR_MASK); 432 ss->xirr_owner = ics; 433 ss->pending_priority = priority; 434 trace_xics_icp_raise(ss->xirr, ss->pending_priority); 435 qemu_irq_raise(ss->output); 436 } 437 } 438 439 static void icp_dispatch_pre_save(void *opaque) 440 { 441 ICPState *ss = opaque; 442 ICPStateClass *info = ICP_GET_CLASS(ss); 443 444 if (info->pre_save) { 445 info->pre_save(ss); 446 } 447 } 448 449 static int icp_dispatch_post_load(void *opaque, int version_id) 450 { 451 ICPState *ss = opaque; 452 ICPStateClass *info = ICP_GET_CLASS(ss); 453 454 if (info->post_load) { 455 return info->post_load(ss, version_id); 456 } 457 458 return 0; 459 } 460 461 static const VMStateDescription vmstate_icp_server = { 462 .name = "icp/server", 463 .version_id = 1, 464 .minimum_version_id = 1, 465 .pre_save = icp_dispatch_pre_save, 466 .post_load = icp_dispatch_post_load, 467 .fields = (VMStateField[]) { 468 /* Sanity check */ 469 VMSTATE_UINT32(xirr, ICPState), 470 VMSTATE_UINT8(pending_priority, ICPState), 471 VMSTATE_UINT8(mfrr, ICPState), 472 VMSTATE_END_OF_LIST() 473 }, 474 }; 475 476 static void icp_reset(DeviceState *dev) 477 { 478 ICPState *icp = ICP(dev); 479 480 icp->xirr = 0; 481 icp->pending_priority = 0xff; 482 icp->mfrr = 0xff; 483 484 /* Make all outputs are deasserted */ 485 qemu_set_irq(icp->output, 0); 486 } 487 488 static void icp_class_init(ObjectClass *klass, void *data) 489 { 490 DeviceClass *dc = DEVICE_CLASS(klass); 491 492 dc->reset = icp_reset; 493 dc->vmsd = &vmstate_icp_server; 494 } 495 496 static const TypeInfo icp_info = { 497 .name = TYPE_ICP, 498 .parent = TYPE_DEVICE, 499 .instance_size = sizeof(ICPState), 500 .class_init = icp_class_init, 501 .class_size = sizeof(ICPStateClass), 502 }; 503 504 /* 505 * ICS: Source layer 506 */ 507 static void ics_simple_resend_msi(ICSState *ics, int srcno) 508 { 509 ICSIRQState *irq = ics->irqs + srcno; 510 511 /* FIXME: filter by server#? */ 512 if (irq->status & XICS_STATUS_REJECTED) { 513 irq->status &= ~XICS_STATUS_REJECTED; 514 if (irq->priority != 0xff) { 515 icp_irq(ics, irq->server, srcno + ics->offset, irq->priority); 516 } 517 } 518 } 519 520 static void ics_simple_resend_lsi(ICSState *ics, int srcno) 521 { 522 ICSIRQState *irq = ics->irqs + srcno; 523 524 if ((irq->priority != 0xff) 525 && (irq->status & XICS_STATUS_ASSERTED) 526 && !(irq->status & XICS_STATUS_SENT)) { 527 irq->status |= XICS_STATUS_SENT; 528 icp_irq(ics, irq->server, srcno + ics->offset, irq->priority); 529 } 530 } 531 532 static void ics_simple_set_irq_msi(ICSState *ics, int srcno, int val) 533 { 534 ICSIRQState *irq = ics->irqs + srcno; 535 536 trace_xics_ics_simple_set_irq_msi(srcno, srcno + ics->offset); 537 538 if (val) { 539 if (irq->priority == 0xff) { 540 irq->status |= XICS_STATUS_MASKED_PENDING; 541 trace_xics_masked_pending(); 542 } else { 543 icp_irq(ics, irq->server, srcno + ics->offset, irq->priority); 544 } 545 } 546 } 547 548 static void ics_simple_set_irq_lsi(ICSState *ics, int srcno, int val) 549 { 550 ICSIRQState *irq = ics->irqs + srcno; 551 552 trace_xics_ics_simple_set_irq_lsi(srcno, srcno + ics->offset); 553 if (val) { 554 irq->status |= XICS_STATUS_ASSERTED; 555 } else { 556 irq->status &= ~XICS_STATUS_ASSERTED; 557 } 558 ics_simple_resend_lsi(ics, srcno); 559 } 560 561 static void ics_simple_set_irq(void *opaque, int srcno, int val) 562 { 563 ICSState *ics = (ICSState *)opaque; 564 565 if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) { 566 ics_simple_set_irq_lsi(ics, srcno, val); 567 } else { 568 ics_simple_set_irq_msi(ics, srcno, val); 569 } 570 } 571 572 static void ics_simple_write_xive_msi(ICSState *ics, int srcno) 573 { 574 ICSIRQState *irq = ics->irqs + srcno; 575 576 if (!(irq->status & XICS_STATUS_MASKED_PENDING) 577 || (irq->priority == 0xff)) { 578 return; 579 } 580 581 irq->status &= ~XICS_STATUS_MASKED_PENDING; 582 icp_irq(ics, irq->server, srcno + ics->offset, irq->priority); 583 } 584 585 static void ics_simple_write_xive_lsi(ICSState *ics, int srcno) 586 { 587 ics_simple_resend_lsi(ics, srcno); 588 } 589 590 void ics_simple_write_xive(ICSState *ics, int srcno, int server, 591 uint8_t priority, uint8_t saved_priority) 592 { 593 ICSIRQState *irq = ics->irqs + srcno; 594 595 irq->server = server; 596 irq->priority = priority; 597 irq->saved_priority = saved_priority; 598 599 trace_xics_ics_simple_write_xive(ics->offset + srcno, srcno, server, 600 priority); 601 602 if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) { 603 ics_simple_write_xive_lsi(ics, srcno); 604 } else { 605 ics_simple_write_xive_msi(ics, srcno); 606 } 607 } 608 609 static void ics_simple_reject(ICSState *ics, uint32_t nr) 610 { 611 ICSIRQState *irq = ics->irqs + nr - ics->offset; 612 613 trace_xics_ics_simple_reject(nr, nr - ics->offset); 614 if (irq->flags & XICS_FLAGS_IRQ_MSI) { 615 irq->status |= XICS_STATUS_REJECTED; 616 } else if (irq->flags & XICS_FLAGS_IRQ_LSI) { 617 irq->status &= ~XICS_STATUS_SENT; 618 } 619 } 620 621 static void ics_simple_resend(ICSState *ics) 622 { 623 int i; 624 625 for (i = 0; i < ics->nr_irqs; i++) { 626 /* FIXME: filter by server#? */ 627 if (ics->irqs[i].flags & XICS_FLAGS_IRQ_LSI) { 628 ics_simple_resend_lsi(ics, i); 629 } else { 630 ics_simple_resend_msi(ics, i); 631 } 632 } 633 } 634 635 static void ics_simple_eoi(ICSState *ics, uint32_t nr) 636 { 637 int srcno = nr - ics->offset; 638 ICSIRQState *irq = ics->irqs + srcno; 639 640 trace_xics_ics_simple_eoi(nr); 641 642 if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) { 643 irq->status &= ~XICS_STATUS_SENT; 644 } 645 } 646 647 static void ics_simple_reset(DeviceState *dev) 648 { 649 ICSState *ics = ICS_SIMPLE(dev); 650 int i; 651 uint8_t flags[ics->nr_irqs]; 652 653 for (i = 0; i < ics->nr_irqs; i++) { 654 flags[i] = ics->irqs[i].flags; 655 } 656 657 memset(ics->irqs, 0, sizeof(ICSIRQState) * ics->nr_irqs); 658 659 for (i = 0; i < ics->nr_irqs; i++) { 660 ics->irqs[i].priority = 0xff; 661 ics->irqs[i].saved_priority = 0xff; 662 ics->irqs[i].flags = flags[i]; 663 } 664 } 665 666 static int ics_simple_post_load(ICSState *ics, int version_id) 667 { 668 int i; 669 670 for (i = 0; i < ics->xics->nr_servers; i++) { 671 icp_resend(&ics->xics->ss[i]); 672 } 673 674 return 0; 675 } 676 677 static void ics_simple_dispatch_pre_save(void *opaque) 678 { 679 ICSState *ics = opaque; 680 ICSStateClass *info = ICS_BASE_GET_CLASS(ics); 681 682 if (info->pre_save) { 683 info->pre_save(ics); 684 } 685 } 686 687 static int ics_simple_dispatch_post_load(void *opaque, int version_id) 688 { 689 ICSState *ics = opaque; 690 ICSStateClass *info = ICS_BASE_GET_CLASS(ics); 691 692 if (info->post_load) { 693 return info->post_load(ics, version_id); 694 } 695 696 return 0; 697 } 698 699 static const VMStateDescription vmstate_ics_simple_irq = { 700 .name = "ics/irq", 701 .version_id = 2, 702 .minimum_version_id = 1, 703 .fields = (VMStateField[]) { 704 VMSTATE_UINT32(server, ICSIRQState), 705 VMSTATE_UINT8(priority, ICSIRQState), 706 VMSTATE_UINT8(saved_priority, ICSIRQState), 707 VMSTATE_UINT8(status, ICSIRQState), 708 VMSTATE_UINT8(flags, ICSIRQState), 709 VMSTATE_END_OF_LIST() 710 }, 711 }; 712 713 static const VMStateDescription vmstate_ics_simple = { 714 .name = "ics", 715 .version_id = 1, 716 .minimum_version_id = 1, 717 .pre_save = ics_simple_dispatch_pre_save, 718 .post_load = ics_simple_dispatch_post_load, 719 .fields = (VMStateField[]) { 720 /* Sanity check */ 721 VMSTATE_UINT32_EQUAL(nr_irqs, ICSState), 722 723 VMSTATE_STRUCT_VARRAY_POINTER_UINT32(irqs, ICSState, nr_irqs, 724 vmstate_ics_simple_irq, 725 ICSIRQState), 726 VMSTATE_END_OF_LIST() 727 }, 728 }; 729 730 static void ics_simple_initfn(Object *obj) 731 { 732 ICSState *ics = ICS_SIMPLE(obj); 733 734 ics->offset = XICS_IRQ_BASE; 735 } 736 737 static void ics_simple_realize(DeviceState *dev, Error **errp) 738 { 739 ICSState *ics = ICS_SIMPLE(dev); 740 741 if (!ics->nr_irqs) { 742 error_setg(errp, "Number of interrupts needs to be greater 0"); 743 return; 744 } 745 ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState)); 746 ics->qirqs = qemu_allocate_irqs(ics_simple_set_irq, ics, ics->nr_irqs); 747 } 748 749 static void ics_simple_class_init(ObjectClass *klass, void *data) 750 { 751 DeviceClass *dc = DEVICE_CLASS(klass); 752 ICSStateClass *isc = ICS_BASE_CLASS(klass); 753 754 dc->realize = ics_simple_realize; 755 dc->vmsd = &vmstate_ics_simple; 756 dc->reset = ics_simple_reset; 757 isc->post_load = ics_simple_post_load; 758 isc->reject = ics_simple_reject; 759 isc->resend = ics_simple_resend; 760 isc->eoi = ics_simple_eoi; 761 } 762 763 static const TypeInfo ics_simple_info = { 764 .name = TYPE_ICS_SIMPLE, 765 .parent = TYPE_ICS_BASE, 766 .instance_size = sizeof(ICSState), 767 .class_init = ics_simple_class_init, 768 .class_size = sizeof(ICSStateClass), 769 .instance_init = ics_simple_initfn, 770 }; 771 772 static const TypeInfo ics_base_info = { 773 .name = TYPE_ICS_BASE, 774 .parent = TYPE_DEVICE, 775 .abstract = true, 776 .instance_size = sizeof(ICSState), 777 .class_size = sizeof(ICSStateClass), 778 }; 779 780 /* 781 * Exported functions 782 */ 783 ICSState *xics_find_source(XICSState *xics, int irq) 784 { 785 ICSState *ics; 786 787 QLIST_FOREACH(ics, &xics->ics, list) { 788 if (ics_valid_irq(ics, irq)) { 789 return ics; 790 } 791 } 792 return NULL; 793 } 794 795 qemu_irq xics_get_qirq(XICSState *xics, int irq) 796 { 797 ICSState *ics = xics_find_source(xics, irq); 798 799 if (ics) { 800 return ics->qirqs[irq - ics->offset]; 801 } 802 803 return NULL; 804 } 805 806 void ics_set_irq_type(ICSState *ics, int srcno, bool lsi) 807 { 808 assert(!(ics->irqs[srcno].flags & XICS_FLAGS_IRQ_MASK)); 809 810 ics->irqs[srcno].flags |= 811 lsi ? XICS_FLAGS_IRQ_LSI : XICS_FLAGS_IRQ_MSI; 812 } 813 814 static void xics_register_types(void) 815 { 816 type_register_static(&xics_common_info); 817 type_register_static(&ics_simple_info); 818 type_register_static(&ics_base_info); 819 type_register_static(&icp_info); 820 } 821 822 type_init(xics_register_types) 823