182cffa2eSCédric Le Goater /* 282cffa2eSCédric Le Goater * QEMU PowerPC sPAPR IRQ interface 382cffa2eSCédric Le Goater * 482cffa2eSCédric Le Goater * Copyright (c) 2018, IBM Corporation. 582cffa2eSCédric Le Goater * 682cffa2eSCédric Le Goater * This code is licensed under the GPL version 2 or later. See the 782cffa2eSCédric Le Goater * COPYING file in the top-level directory. 882cffa2eSCédric Le Goater */ 982cffa2eSCédric Le Goater 1082cffa2eSCédric Le Goater #include "qemu/osdep.h" 1182cffa2eSCédric Le Goater #include "qemu/log.h" 1282cffa2eSCédric Le Goater #include "qemu/error-report.h" 1382cffa2eSCédric Le Goater #include "qapi/error.h" 1464552b6bSMarkus Armbruster #include "hw/irq.h" 1582cffa2eSCédric Le Goater #include "hw/ppc/spapr.h" 16a28b9a5aSCédric Le Goater #include "hw/ppc/spapr_cpu_core.h" 17dcc345b6SCédric Le Goater #include "hw/ppc/spapr_xive.h" 1882cffa2eSCédric Le Goater #include "hw/ppc/xics.h" 19a51d5afcSThomas Huth #include "hw/ppc/xics_spapr.h" 20a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 21273fef83SCédric Le Goater #include "cpu-models.h" 22ef01ed9dSCédric Le Goater #include "sysemu/kvm.h" 23ef01ed9dSCédric Le Goater 24ef01ed9dSCédric Le Goater #include "trace.h" 2582cffa2eSCédric Le Goater 26150e25f8SDavid Gibson static const TypeInfo spapr_intc_info = { 27150e25f8SDavid Gibson .name = TYPE_SPAPR_INTC, 28150e25f8SDavid Gibson .parent = TYPE_INTERFACE, 29150e25f8SDavid Gibson .class_size = sizeof(SpaprInterruptControllerClass), 30150e25f8SDavid Gibson }; 31150e25f8SDavid Gibson 32ce2918cbSDavid Gibson void spapr_irq_msi_init(SpaprMachineState *spapr, uint32_t nr_msis) 3382cffa2eSCédric Le Goater { 3482cffa2eSCédric Le Goater spapr->irq_map_nr = nr_msis; 3582cffa2eSCédric Le Goater spapr->irq_map = bitmap_new(spapr->irq_map_nr); 3682cffa2eSCédric Le Goater } 3782cffa2eSCédric Le Goater 38ce2918cbSDavid Gibson int spapr_irq_msi_alloc(SpaprMachineState *spapr, uint32_t num, bool align, 3982cffa2eSCédric Le Goater Error **errp) 4082cffa2eSCédric Le Goater { 4182cffa2eSCédric Le Goater int irq; 4282cffa2eSCédric Le Goater 4382cffa2eSCédric Le Goater /* 4482cffa2eSCédric Le Goater * The 'align_mask' parameter of bitmap_find_next_zero_area() 4582cffa2eSCédric Le Goater * should be one less than a power of 2; 0 means no 4682cffa2eSCédric Le Goater * alignment. Adapt the 'align' value of the former allocator 4782cffa2eSCédric Le Goater * to fit the requirements of bitmap_find_next_zero_area() 4882cffa2eSCédric Le Goater */ 4982cffa2eSCédric Le Goater align -= 1; 5082cffa2eSCédric Le Goater 5182cffa2eSCédric Le Goater irq = bitmap_find_next_zero_area(spapr->irq_map, spapr->irq_map_nr, 0, num, 5282cffa2eSCédric Le Goater align); 5382cffa2eSCédric Le Goater if (irq == spapr->irq_map_nr) { 5482cffa2eSCédric Le Goater error_setg(errp, "can't find a free %d-IRQ block", num); 5582cffa2eSCédric Le Goater return -1; 5682cffa2eSCédric Le Goater } 5782cffa2eSCédric Le Goater 5882cffa2eSCédric Le Goater bitmap_set(spapr->irq_map, irq, num); 5982cffa2eSCédric Le Goater 6082cffa2eSCédric Le Goater return irq + SPAPR_IRQ_MSI; 6182cffa2eSCédric Le Goater } 6282cffa2eSCédric Le Goater 63ce2918cbSDavid Gibson void spapr_irq_msi_free(SpaprMachineState *spapr, int irq, uint32_t num) 6482cffa2eSCédric Le Goater { 6582cffa2eSCédric Le Goater bitmap_clear(spapr->irq_map, irq - SPAPR_IRQ_MSI, num); 6682cffa2eSCédric Le Goater } 6782cffa2eSCédric Le Goater 68d0e9bc04SCédric Le Goater static void spapr_irq_init_kvm(SpaprMachineState *spapr, 69ae805ea9SCédric Le Goater SpaprIrq *irq, Error **errp) 70ae805ea9SCédric Le Goater { 71ae805ea9SCédric Le Goater MachineState *machine = MACHINE(spapr); 72ae805ea9SCédric Le Goater Error *local_err = NULL; 73ae805ea9SCédric Le Goater 74ae805ea9SCédric Le Goater if (kvm_enabled() && machine_kernel_irqchip_allowed(machine)) { 75ae805ea9SCédric Le Goater irq->init_kvm(spapr, &local_err); 76ae805ea9SCédric Le Goater if (local_err && machine_kernel_irqchip_required(machine)) { 77ae805ea9SCédric Le Goater error_prepend(&local_err, 78ae805ea9SCédric Le Goater "kernel_irqchip requested but unavailable: "); 79ae805ea9SCédric Le Goater error_propagate(errp, local_err); 80ae805ea9SCédric Le Goater return; 81ae805ea9SCédric Le Goater } 82ae805ea9SCédric Le Goater 83ae805ea9SCédric Le Goater if (!local_err) { 84ae805ea9SCédric Le Goater return; 85ae805ea9SCédric Le Goater } 86ae805ea9SCédric Le Goater 87ae805ea9SCédric Le Goater /* 88ae805ea9SCédric Le Goater * We failed to initialize the KVM device, fallback to 89ae805ea9SCédric Le Goater * emulated mode 90ae805ea9SCédric Le Goater */ 91ae805ea9SCédric Le Goater error_prepend(&local_err, "kernel_irqchip allowed but unavailable: "); 92f5bda010SGreg Kurz error_append_hint(&local_err, "Falling back to kernel-irqchip=off\n"); 93ae805ea9SCédric Le Goater warn_report_err(local_err); 94ae805ea9SCédric Le Goater } 95ae805ea9SCédric Le Goater } 96ef01ed9dSCédric Le Goater 97ef01ed9dSCédric Le Goater /* 98ef01ed9dSCédric Le Goater * XICS IRQ backend. 99ef01ed9dSCédric Le Goater */ 100ef01ed9dSCédric Le Goater 101ce2918cbSDavid Gibson static int spapr_irq_claim_xics(SpaprMachineState *spapr, int irq, bool lsi, 102ef01ed9dSCédric Le Goater Error **errp) 103ef01ed9dSCédric Le Goater { 104ef01ed9dSCédric Le Goater ICSState *ics = spapr->ics; 105ef01ed9dSCédric Le Goater 106ef01ed9dSCédric Le Goater assert(ics); 107580dde5eSDavid Gibson assert(ics_valid_irq(ics, irq)); 108ef01ed9dSCédric Le Goater 1094a99d405SCédric Le Goater if (!ics_irq_free(ics, irq - ics->offset)) { 110ef01ed9dSCédric Le Goater error_setg(errp, "IRQ %d is not free", irq); 111ef01ed9dSCédric Le Goater return -1; 112ef01ed9dSCédric Le Goater } 113ef01ed9dSCédric Le Goater 114ef01ed9dSCédric Le Goater ics_set_irq_type(ics, irq - ics->offset, lsi); 115ef01ed9dSCédric Le Goater return 0; 116ef01ed9dSCédric Le Goater } 117ef01ed9dSCédric Le Goater 118f233cee9SDavid Gibson static void spapr_irq_free_xics(SpaprMachineState *spapr, int irq) 119ef01ed9dSCédric Le Goater { 120ef01ed9dSCédric Le Goater ICSState *ics = spapr->ics; 121ef01ed9dSCédric Le Goater uint32_t srcno = irq - ics->offset; 122ef01ed9dSCédric Le Goater 123580dde5eSDavid Gibson assert(ics_valid_irq(ics, irq)); 124580dde5eSDavid Gibson 125f233cee9SDavid Gibson memset(&ics->irqs[srcno], 0, sizeof(ICSIRQState)); 126ef01ed9dSCédric Le Goater } 127ef01ed9dSCédric Le Goater 128ce2918cbSDavid Gibson static void spapr_irq_print_info_xics(SpaprMachineState *spapr, Monitor *mon) 129ef01ed9dSCédric Le Goater { 130ef01ed9dSCédric Le Goater CPUState *cs; 131ef01ed9dSCédric Le Goater 132ef01ed9dSCédric Le Goater CPU_FOREACH(cs) { 133ef01ed9dSCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 134ef01ed9dSCédric Le Goater 135a28b9a5aSCédric Le Goater icp_pic_print_info(spapr_cpu_state(cpu)->icp, mon); 136ef01ed9dSCédric Le Goater } 137ef01ed9dSCédric Le Goater 138ef01ed9dSCédric Le Goater ics_pic_print_info(spapr->ics, mon); 139ef01ed9dSCédric Le Goater } 140ef01ed9dSCédric Le Goater 141ce2918cbSDavid Gibson static int spapr_irq_post_load_xics(SpaprMachineState *spapr, int version_id) 1421c53b06cSCédric Le Goater { 1433272752aSGreg Kurz if (!kvm_irqchip_in_kernel()) { 1441c53b06cSCédric Le Goater CPUState *cs; 1451c53b06cSCédric Le Goater CPU_FOREACH(cs) { 1461c53b06cSCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 147a28b9a5aSCédric Le Goater icp_resend(spapr_cpu_state(cpu)->icp); 1481c53b06cSCédric Le Goater } 1491c53b06cSCédric Le Goater } 1501c53b06cSCédric Le Goater return 0; 1511c53b06cSCédric Le Goater } 1521c53b06cSCédric Le Goater 1539f53c0dbSDavid Gibson static void spapr_irq_set_irq_xics(void *opaque, int irq, int val) 154872ff3deSCédric Le Goater { 155ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 1569f53c0dbSDavid Gibson uint32_t srcno = irq - spapr->ics->offset; 157872ff3deSCédric Le Goater 15828976c99SDavid Gibson ics_set_irq(spapr->ics, srcno, val); 159872ff3deSCédric Le Goater } 160872ff3deSCédric Le Goater 161ce2918cbSDavid Gibson static void spapr_irq_reset_xics(SpaprMachineState *spapr, Error **errp) 16213db0cd9SCédric Le Goater { 1633f777abcSCédric Le Goater Error *local_err = NULL; 1643f777abcSCédric Le Goater 165d0e9bc04SCédric Le Goater spapr_irq_init_kvm(spapr, &spapr_irq_xics, &local_err); 1663f777abcSCédric Le Goater if (local_err) { 1673f777abcSCédric Le Goater error_propagate(errp, local_err); 1683f777abcSCédric Le Goater return; 1693f777abcSCédric Le Goater } 17013db0cd9SCédric Le Goater } 17113db0cd9SCédric Le Goater 172ae805ea9SCédric Le Goater static void spapr_irq_init_kvm_xics(SpaprMachineState *spapr, Error **errp) 173ae805ea9SCédric Le Goater { 174ae805ea9SCédric Le Goater if (kvm_enabled()) { 175eab9f191SGreg Kurz xics_kvm_connect(spapr, errp); 176ae805ea9SCédric Le Goater } 177ae805ea9SCédric Le Goater } 178ae805ea9SCédric Le Goater 179ce2918cbSDavid Gibson SpaprIrq spapr_irq_xics = { 180ad8de986SDavid Gibson .nr_xirqs = SPAPR_NR_XIRQS, 181ad8de986SDavid Gibson .nr_msis = SPAPR_NR_MSIS, 182ca62823bSDavid Gibson .xics = true, 183ca62823bSDavid Gibson .xive = false, 184ef01ed9dSCédric Le Goater 185ef01ed9dSCédric Le Goater .claim = spapr_irq_claim_xics, 186ef01ed9dSCédric Le Goater .free = spapr_irq_free_xics, 187ef01ed9dSCédric Le Goater .print_info = spapr_irq_print_info_xics, 1886e21de4aSCédric Le Goater .dt_populate = spapr_dt_xics, 1891c53b06cSCédric Le Goater .post_load = spapr_irq_post_load_xics, 19013db0cd9SCédric Le Goater .reset = spapr_irq_reset_xics, 191872ff3deSCédric Le Goater .set_irq = spapr_irq_set_irq_xics, 192ae805ea9SCédric Le Goater .init_kvm = spapr_irq_init_kvm_xics, 193ef01ed9dSCédric Le Goater }; 194ef01ed9dSCédric Le Goater 195ef01ed9dSCédric Le Goater /* 196dcc345b6SCédric Le Goater * XIVE IRQ backend. 197dcc345b6SCédric Le Goater */ 198dcc345b6SCédric Le Goater 199ce2918cbSDavid Gibson static int spapr_irq_claim_xive(SpaprMachineState *spapr, int irq, bool lsi, 200dcc345b6SCédric Le Goater Error **errp) 201dcc345b6SCédric Le Goater { 202e594c2adSDavid Gibson return spapr_xive_irq_claim(spapr->xive, irq, lsi, errp); 203dcc345b6SCédric Le Goater } 204dcc345b6SCédric Le Goater 205f233cee9SDavid Gibson static void spapr_irq_free_xive(SpaprMachineState *spapr, int irq) 206dcc345b6SCédric Le Goater { 207f233cee9SDavid Gibson spapr_xive_irq_free(spapr->xive, irq); 208dcc345b6SCédric Le Goater } 209dcc345b6SCédric Le Goater 210ce2918cbSDavid Gibson static void spapr_irq_print_info_xive(SpaprMachineState *spapr, 211dcc345b6SCédric Le Goater Monitor *mon) 212dcc345b6SCédric Le Goater { 213dcc345b6SCédric Le Goater CPUState *cs; 214dcc345b6SCédric Le Goater 215dcc345b6SCédric Le Goater CPU_FOREACH(cs) { 216dcc345b6SCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 217dcc345b6SCédric Le Goater 218a28b9a5aSCédric Le Goater xive_tctx_pic_print_info(spapr_cpu_state(cpu)->tctx, mon); 219dcc345b6SCédric Le Goater } 220dcc345b6SCédric Le Goater 221dcc345b6SCédric Le Goater spapr_xive_pic_print_info(spapr->xive, mon); 222dcc345b6SCédric Le Goater } 223dcc345b6SCédric Le Goater 224ce2918cbSDavid Gibson static int spapr_irq_post_load_xive(SpaprMachineState *spapr, int version_id) 2251c53b06cSCédric Le Goater { 226277dd3d7SCédric Le Goater return spapr_xive_post_load(spapr->xive, version_id); 2271c53b06cSCédric Le Goater } 2281c53b06cSCédric Le Goater 229ce2918cbSDavid Gibson static void spapr_irq_reset_xive(SpaprMachineState *spapr, Error **errp) 230b2e22477SCédric Le Goater { 231b2e22477SCédric Le Goater CPUState *cs; 2323f777abcSCédric Le Goater Error *local_err = NULL; 233b2e22477SCédric Le Goater 234b2e22477SCédric Le Goater CPU_FOREACH(cs) { 235b2e22477SCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 236b2e22477SCédric Le Goater 237b2e22477SCédric Le Goater /* (TCG) Set the OS CAM line of the thread interrupt context. */ 238a28b9a5aSCédric Le Goater spapr_xive_set_tctx_os_cam(spapr_cpu_state(cpu)->tctx); 239b2e22477SCédric Le Goater } 2403a8eb78eSCédric Le Goater 241d0e9bc04SCédric Le Goater spapr_irq_init_kvm(spapr, &spapr_irq_xive, &local_err); 2423f777abcSCédric Le Goater if (local_err) { 2433f777abcSCédric Le Goater error_propagate(errp, local_err); 2443f777abcSCédric Le Goater return; 2453f777abcSCédric Le Goater } 2463f777abcSCédric Le Goater 2473a8eb78eSCédric Le Goater /* Activate the XIVE MMIOs */ 2483a8eb78eSCédric Le Goater spapr_xive_mmio_set_enabled(spapr->xive, true); 249b2e22477SCédric Le Goater } 250b2e22477SCédric Le Goater 2519f53c0dbSDavid Gibson static void spapr_irq_set_irq_xive(void *opaque, int irq, int val) 252872ff3deSCédric Le Goater { 253ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 254872ff3deSCédric Le Goater 25538afd772SCédric Le Goater if (kvm_irqchip_in_kernel()) { 2569f53c0dbSDavid Gibson kvmppc_xive_source_set_irq(&spapr->xive->source, irq, val); 25738afd772SCédric Le Goater } else { 2589f53c0dbSDavid Gibson xive_source_set_irq(&spapr->xive->source, irq, val); 259872ff3deSCédric Le Goater } 26038afd772SCédric Le Goater } 261872ff3deSCédric Le Goater 262ae805ea9SCédric Le Goater static void spapr_irq_init_kvm_xive(SpaprMachineState *spapr, Error **errp) 263ae805ea9SCédric Le Goater { 264ae805ea9SCédric Le Goater if (kvm_enabled()) { 265ae805ea9SCédric Le Goater kvmppc_xive_connect(spapr->xive, errp); 266ae805ea9SCédric Le Goater } 267ae805ea9SCédric Le Goater } 268ae805ea9SCédric Le Goater 269ce2918cbSDavid Gibson SpaprIrq spapr_irq_xive = { 270ad8de986SDavid Gibson .nr_xirqs = SPAPR_NR_XIRQS, 271ad8de986SDavid Gibson .nr_msis = SPAPR_NR_MSIS, 272ca62823bSDavid Gibson .xics = false, 273ca62823bSDavid Gibson .xive = true, 274dcc345b6SCédric Le Goater 275dcc345b6SCédric Le Goater .claim = spapr_irq_claim_xive, 276dcc345b6SCédric Le Goater .free = spapr_irq_free_xive, 277dcc345b6SCédric Le Goater .print_info = spapr_irq_print_info_xive, 2786e21de4aSCédric Le Goater .dt_populate = spapr_dt_xive, 2791c53b06cSCédric Le Goater .post_load = spapr_irq_post_load_xive, 280b2e22477SCédric Le Goater .reset = spapr_irq_reset_xive, 281872ff3deSCédric Le Goater .set_irq = spapr_irq_set_irq_xive, 282ae805ea9SCédric Le Goater .init_kvm = spapr_irq_init_kvm_xive, 283dcc345b6SCédric Le Goater }; 284dcc345b6SCédric Le Goater 285dcc345b6SCédric Le Goater /* 28613db0cd9SCédric Le Goater * Dual XIVE and XICS IRQ backend. 28713db0cd9SCédric Le Goater * 28813db0cd9SCédric Le Goater * Both interrupt mode, XIVE and XICS, objects are created but the 28913db0cd9SCédric Le Goater * machine starts in legacy interrupt mode (XICS). It can be changed 29013db0cd9SCédric Le Goater * by the CAS negotiation process and, in that case, the new mode is 29113db0cd9SCédric Le Goater * activated after an extra machine reset. 29213db0cd9SCédric Le Goater */ 29313db0cd9SCédric Le Goater 29413db0cd9SCédric Le Goater /* 29513db0cd9SCédric Le Goater * Returns the sPAPR IRQ backend negotiated by CAS. XICS is the 29613db0cd9SCédric Le Goater * default. 29713db0cd9SCédric Le Goater */ 298ce2918cbSDavid Gibson static SpaprIrq *spapr_irq_current(SpaprMachineState *spapr) 29913db0cd9SCédric Le Goater { 30013db0cd9SCédric Le Goater return spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT) ? 30113db0cd9SCédric Le Goater &spapr_irq_xive : &spapr_irq_xics; 30213db0cd9SCédric Le Goater } 30313db0cd9SCédric Le Goater 304ce2918cbSDavid Gibson static int spapr_irq_claim_dual(SpaprMachineState *spapr, int irq, bool lsi, 30513db0cd9SCédric Le Goater Error **errp) 30613db0cd9SCédric Le Goater { 30713db0cd9SCédric Le Goater Error *local_err = NULL; 30813db0cd9SCédric Le Goater int ret; 30913db0cd9SCédric Le Goater 31013db0cd9SCédric Le Goater ret = spapr_irq_xics.claim(spapr, irq, lsi, &local_err); 31113db0cd9SCédric Le Goater if (local_err) { 31213db0cd9SCédric Le Goater error_propagate(errp, local_err); 31313db0cd9SCédric Le Goater return ret; 31413db0cd9SCédric Le Goater } 31513db0cd9SCédric Le Goater 31613db0cd9SCédric Le Goater ret = spapr_irq_xive.claim(spapr, irq, lsi, &local_err); 31713db0cd9SCédric Le Goater if (local_err) { 31813db0cd9SCédric Le Goater error_propagate(errp, local_err); 31913db0cd9SCédric Le Goater return ret; 32013db0cd9SCédric Le Goater } 32113db0cd9SCédric Le Goater 32213db0cd9SCédric Le Goater return ret; 32313db0cd9SCédric Le Goater } 32413db0cd9SCédric Le Goater 325f233cee9SDavid Gibson static void spapr_irq_free_dual(SpaprMachineState *spapr, int irq) 32613db0cd9SCédric Le Goater { 327f233cee9SDavid Gibson spapr_irq_xics.free(spapr, irq); 328f233cee9SDavid Gibson spapr_irq_xive.free(spapr, irq); 32913db0cd9SCédric Le Goater } 33013db0cd9SCédric Le Goater 331ce2918cbSDavid Gibson static void spapr_irq_print_info_dual(SpaprMachineState *spapr, Monitor *mon) 33213db0cd9SCédric Le Goater { 33313db0cd9SCédric Le Goater spapr_irq_current(spapr)->print_info(spapr, mon); 33413db0cd9SCédric Le Goater } 33513db0cd9SCédric Le Goater 336ce2918cbSDavid Gibson static void spapr_irq_dt_populate_dual(SpaprMachineState *spapr, 33713db0cd9SCédric Le Goater uint32_t nr_servers, void *fdt, 33813db0cd9SCédric Le Goater uint32_t phandle) 33913db0cd9SCédric Le Goater { 34013db0cd9SCédric Le Goater spapr_irq_current(spapr)->dt_populate(spapr, nr_servers, fdt, phandle); 34113db0cd9SCédric Le Goater } 34213db0cd9SCédric Le Goater 343ce2918cbSDavid Gibson static int spapr_irq_post_load_dual(SpaprMachineState *spapr, int version_id) 34413db0cd9SCédric Le Goater { 34513db0cd9SCédric Le Goater /* 34613db0cd9SCédric Le Goater * Force a reset of the XIVE backend after migration. The machine 34713db0cd9SCédric Le Goater * defaults to XICS at startup. 34813db0cd9SCédric Le Goater */ 34913db0cd9SCédric Le Goater if (spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) { 3503f777abcSCédric Le Goater if (kvm_irqchip_in_kernel()) { 3513f777abcSCédric Le Goater xics_kvm_disconnect(spapr, &error_fatal); 3523f777abcSCédric Le Goater } 35313db0cd9SCédric Le Goater spapr_irq_xive.reset(spapr, &error_fatal); 35413db0cd9SCédric Le Goater } 35513db0cd9SCédric Le Goater 35613db0cd9SCédric Le Goater return spapr_irq_current(spapr)->post_load(spapr, version_id); 35713db0cd9SCédric Le Goater } 35813db0cd9SCédric Le Goater 359ce2918cbSDavid Gibson static void spapr_irq_reset_dual(SpaprMachineState *spapr, Error **errp) 36013db0cd9SCédric Le Goater { 3613f777abcSCédric Le Goater Error *local_err = NULL; 3623f777abcSCédric Le Goater 3633a8eb78eSCédric Le Goater /* 3643a8eb78eSCédric Le Goater * Deactivate the XIVE MMIOs. The XIVE backend will reenable them 3653a8eb78eSCédric Le Goater * if selected. 3663a8eb78eSCédric Le Goater */ 3673a8eb78eSCédric Le Goater spapr_xive_mmio_set_enabled(spapr->xive, false); 3683a8eb78eSCédric Le Goater 3693f777abcSCédric Le Goater /* Destroy all KVM devices */ 3703f777abcSCédric Le Goater if (kvm_irqchip_in_kernel()) { 3713f777abcSCédric Le Goater xics_kvm_disconnect(spapr, &local_err); 3723f777abcSCédric Le Goater if (local_err) { 3733f777abcSCédric Le Goater error_propagate(errp, local_err); 3743f777abcSCédric Le Goater error_prepend(errp, "KVM XICS disconnect failed: "); 3753f777abcSCédric Le Goater return; 3763f777abcSCédric Le Goater } 3773f777abcSCédric Le Goater kvmppc_xive_disconnect(spapr->xive, &local_err); 3783f777abcSCédric Le Goater if (local_err) { 3793f777abcSCédric Le Goater error_propagate(errp, local_err); 3803f777abcSCédric Le Goater error_prepend(errp, "KVM XIVE disconnect failed: "); 3813f777abcSCédric Le Goater return; 3823f777abcSCédric Le Goater } 3833f777abcSCédric Le Goater } 3843f777abcSCédric Le Goater 38513db0cd9SCédric Le Goater spapr_irq_current(spapr)->reset(spapr, errp); 38613db0cd9SCédric Le Goater } 38713db0cd9SCédric Le Goater 3889f53c0dbSDavid Gibson static void spapr_irq_set_irq_dual(void *opaque, int irq, int val) 38913db0cd9SCédric Le Goater { 390ce2918cbSDavid Gibson SpaprMachineState *spapr = opaque; 39113db0cd9SCédric Le Goater 3929f53c0dbSDavid Gibson spapr_irq_current(spapr)->set_irq(spapr, irq, val); 39313db0cd9SCédric Le Goater } 39413db0cd9SCédric Le Goater 39513db0cd9SCédric Le Goater /* 39613db0cd9SCédric Le Goater * Define values in sync with the XIVE and XICS backend 39713db0cd9SCédric Le Goater */ 398ce2918cbSDavid Gibson SpaprIrq spapr_irq_dual = { 399ad8de986SDavid Gibson .nr_xirqs = SPAPR_NR_XIRQS, 400ad8de986SDavid Gibson .nr_msis = SPAPR_NR_MSIS, 401ca62823bSDavid Gibson .xics = true, 402ca62823bSDavid Gibson .xive = true, 40313db0cd9SCédric Le Goater 40413db0cd9SCédric Le Goater .claim = spapr_irq_claim_dual, 40513db0cd9SCédric Le Goater .free = spapr_irq_free_dual, 40613db0cd9SCédric Le Goater .print_info = spapr_irq_print_info_dual, 40713db0cd9SCédric Le Goater .dt_populate = spapr_irq_dt_populate_dual, 40813db0cd9SCédric Le Goater .post_load = spapr_irq_post_load_dual, 40913db0cd9SCédric Le Goater .reset = spapr_irq_reset_dual, 410743ed566SGreg Kurz .set_irq = spapr_irq_set_irq_dual, 411ae805ea9SCédric Le Goater .init_kvm = NULL, /* should not be used */ 41213db0cd9SCédric Le Goater }; 41313db0cd9SCédric Le Goater 414273fef83SCédric Le Goater 4150a3fd3dfSDavid Gibson static int spapr_irq_check(SpaprMachineState *spapr, Error **errp) 416273fef83SCédric Le Goater { 417273fef83SCédric Le Goater MachineState *machine = MACHINE(spapr); 418273fef83SCédric Le Goater 419273fef83SCédric Le Goater /* 420273fef83SCédric Le Goater * Sanity checks on non-P9 machines. On these, XIVE is not 421273fef83SCédric Le Goater * advertised, see spapr_dt_ov5_platform_support() 422273fef83SCédric Le Goater */ 423273fef83SCédric Le Goater if (!ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, 424273fef83SCédric Le Goater 0, spapr->max_compat_pvr)) { 425273fef83SCédric Le Goater /* 426273fef83SCédric Le Goater * If the 'dual' interrupt mode is selected, force XICS as CAS 427273fef83SCédric Le Goater * negotiation is useless. 428273fef83SCédric Le Goater */ 429273fef83SCédric Le Goater if (spapr->irq == &spapr_irq_dual) { 430273fef83SCédric Le Goater spapr->irq = &spapr_irq_xics; 4310a3fd3dfSDavid Gibson return 0; 432273fef83SCédric Le Goater } 433273fef83SCédric Le Goater 434273fef83SCédric Le Goater /* 435273fef83SCédric Le Goater * Non-P9 machines using only XIVE is a bogus setup. We have two 436273fef83SCédric Le Goater * scenarios to take into account because of the compat mode: 437273fef83SCédric Le Goater * 438273fef83SCédric Le Goater * 1. POWER7/8 machines should fail to init later on when creating 439273fef83SCédric Le Goater * the XIVE interrupt presenters because a POWER9 exception 440273fef83SCédric Le Goater * model is required. 441273fef83SCédric Le Goater 442273fef83SCédric Le Goater * 2. POWER9 machines using the POWER8 compat mode won't fail and 443273fef83SCédric Le Goater * will let the OS boot with a partial XIVE setup : DT 444273fef83SCédric Le Goater * properties but no hcalls. 445273fef83SCédric Le Goater * 446273fef83SCédric Le Goater * To cover both and not confuse the OS, add an early failure in 447273fef83SCédric Le Goater * QEMU. 448273fef83SCédric Le Goater */ 449273fef83SCédric Le Goater if (spapr->irq == &spapr_irq_xive) { 450273fef83SCédric Le Goater error_setg(errp, "XIVE-only machines require a POWER9 CPU"); 4510a3fd3dfSDavid Gibson return -1; 452273fef83SCédric Le Goater } 453273fef83SCédric Le Goater } 4547abc0c6dSGreg Kurz 4557abc0c6dSGreg Kurz /* 4567abc0c6dSGreg Kurz * On a POWER9 host, some older KVM XICS devices cannot be destroyed and 4577abc0c6dSGreg Kurz * re-created. Detect that early to avoid QEMU to exit later when the 4587abc0c6dSGreg Kurz * guest reboots. 4597abc0c6dSGreg Kurz */ 4607abc0c6dSGreg Kurz if (kvm_enabled() && 4617abc0c6dSGreg Kurz spapr->irq == &spapr_irq_dual && 4627abc0c6dSGreg Kurz machine_kernel_irqchip_required(machine) && 4637abc0c6dSGreg Kurz xics_kvm_has_broken_disconnect(spapr)) { 4647abc0c6dSGreg Kurz error_setg(errp, "KVM is too old to support ic-mode=dual,kernel-irqchip=on"); 4650a3fd3dfSDavid Gibson return -1; 4667abc0c6dSGreg Kurz } 4670a3fd3dfSDavid Gibson 4680a3fd3dfSDavid Gibson return 0; 469273fef83SCédric Le Goater } 470273fef83SCédric Le Goater 47113db0cd9SCédric Le Goater /* 472ef01ed9dSCédric Le Goater * sPAPR IRQ frontend routines for devices 473ef01ed9dSCédric Le Goater */ 474*ebd6be08SDavid Gibson #define ALL_INTCS(spapr_) \ 475*ebd6be08SDavid Gibson { SPAPR_INTC((spapr_)->ics), SPAPR_INTC((spapr_)->xive), } 476*ebd6be08SDavid Gibson 477*ebd6be08SDavid Gibson int spapr_irq_cpu_intc_create(SpaprMachineState *spapr, 478*ebd6be08SDavid Gibson PowerPCCPU *cpu, Error **errp) 479*ebd6be08SDavid Gibson { 480*ebd6be08SDavid Gibson SpaprInterruptController *intcs[] = ALL_INTCS(spapr); 481*ebd6be08SDavid Gibson int i; 482*ebd6be08SDavid Gibson int rc; 483*ebd6be08SDavid Gibson 484*ebd6be08SDavid Gibson for (i = 0; i < ARRAY_SIZE(intcs); i++) { 485*ebd6be08SDavid Gibson SpaprInterruptController *intc = intcs[i]; 486*ebd6be08SDavid Gibson if (intc) { 487*ebd6be08SDavid Gibson SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc); 488*ebd6be08SDavid Gibson rc = sicc->cpu_intc_create(intc, cpu, errp); 489*ebd6be08SDavid Gibson if (rc < 0) { 490*ebd6be08SDavid Gibson return rc; 491*ebd6be08SDavid Gibson } 492*ebd6be08SDavid Gibson } 493*ebd6be08SDavid Gibson } 494*ebd6be08SDavid Gibson 495*ebd6be08SDavid Gibson return 0; 496*ebd6be08SDavid Gibson } 497*ebd6be08SDavid Gibson 498ce2918cbSDavid Gibson void spapr_irq_init(SpaprMachineState *spapr, Error **errp) 499fab397d8SCédric Le Goater { 5001a511340SGreg Kurz MachineState *machine = MACHINE(spapr); 5011a511340SGreg Kurz 5021a511340SGreg Kurz if (machine_kernel_irqchip_split(machine)) { 5031a511340SGreg Kurz error_setg(errp, "kernel_irqchip split mode not supported on pseries"); 5041a511340SGreg Kurz return; 5051a511340SGreg Kurz } 5061a511340SGreg Kurz 5071a511340SGreg Kurz if (!kvm_enabled() && machine_kernel_irqchip_required(machine)) { 5081a511340SGreg Kurz error_setg(errp, 5091a511340SGreg Kurz "kernel_irqchip requested but only available with KVM"); 5101a511340SGreg Kurz return; 5111a511340SGreg Kurz } 5121a511340SGreg Kurz 5130a3fd3dfSDavid Gibson if (spapr_irq_check(spapr, errp) < 0) { 514273fef83SCédric Le Goater return; 515273fef83SCédric Le Goater } 516273fef83SCédric Le Goater 517fab397d8SCédric Le Goater /* Initialize the MSI IRQ allocator. */ 518fab397d8SCédric Le Goater if (!SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) { 5193ba3d0bcSCédric Le Goater spapr_irq_msi_init(spapr, spapr->irq->nr_msis); 520fab397d8SCédric Le Goater } 521fab397d8SCédric Le Goater 522f478d9afSDavid Gibson if (spapr->irq->xics) { 523f478d9afSDavid Gibson Error *local_err = NULL; 524f478d9afSDavid Gibson Object *obj; 525f478d9afSDavid Gibson 526f478d9afSDavid Gibson obj = object_new(TYPE_ICS_SPAPR); 527f478d9afSDavid Gibson object_property_add_child(OBJECT(spapr), "ics", obj, &local_err); 528f478d9afSDavid Gibson if (local_err) { 529f478d9afSDavid Gibson error_propagate(errp, local_err); 530f478d9afSDavid Gibson return; 531f478d9afSDavid Gibson } 532f478d9afSDavid Gibson 533f478d9afSDavid Gibson object_property_add_const_link(obj, ICS_PROP_XICS, OBJECT(spapr), 534f478d9afSDavid Gibson &local_err); 535f478d9afSDavid Gibson if (local_err) { 536f478d9afSDavid Gibson error_propagate(errp, local_err); 537f478d9afSDavid Gibson return; 538f478d9afSDavid Gibson } 539f478d9afSDavid Gibson 540f478d9afSDavid Gibson object_property_set_int(obj, spapr->irq->nr_xirqs, "nr-irqs", 541f478d9afSDavid Gibson &local_err); 542f478d9afSDavid Gibson if (local_err) { 543f478d9afSDavid Gibson error_propagate(errp, local_err); 544f478d9afSDavid Gibson return; 545f478d9afSDavid Gibson } 546f478d9afSDavid Gibson 547f478d9afSDavid Gibson object_property_set_bool(obj, true, "realized", &local_err); 548f478d9afSDavid Gibson if (local_err) { 549f478d9afSDavid Gibson error_propagate(errp, local_err); 550f478d9afSDavid Gibson return; 551f478d9afSDavid Gibson } 552f478d9afSDavid Gibson 553f478d9afSDavid Gibson spapr->ics = ICS_SPAPR(obj); 554f478d9afSDavid Gibson } 555f478d9afSDavid Gibson 556f478d9afSDavid Gibson if (spapr->irq->xive) { 557f478d9afSDavid Gibson uint32_t nr_servers = spapr_max_server_number(spapr); 558f478d9afSDavid Gibson DeviceState *dev; 559f478d9afSDavid Gibson int i; 560f478d9afSDavid Gibson 561f478d9afSDavid Gibson dev = qdev_create(NULL, TYPE_SPAPR_XIVE); 562f478d9afSDavid Gibson qdev_prop_set_uint32(dev, "nr-irqs", 563f478d9afSDavid Gibson spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE); 564f478d9afSDavid Gibson /* 565f478d9afSDavid Gibson * 8 XIVE END structures per CPU. One for each available 566f478d9afSDavid Gibson * priority 567f478d9afSDavid Gibson */ 568f478d9afSDavid Gibson qdev_prop_set_uint32(dev, "nr-ends", nr_servers << 3); 569f478d9afSDavid Gibson qdev_init_nofail(dev); 570f478d9afSDavid Gibson 571f478d9afSDavid Gibson spapr->xive = SPAPR_XIVE(dev); 572f478d9afSDavid Gibson 573f478d9afSDavid Gibson /* Enable the CPU IPIs */ 574f478d9afSDavid Gibson for (i = 0; i < nr_servers; ++i) { 575f478d9afSDavid Gibson if (spapr_xive_irq_claim(spapr->xive, SPAPR_IRQ_IPI + i, 576f478d9afSDavid Gibson false, errp) < 0) { 577f478d9afSDavid Gibson return; 578f478d9afSDavid Gibson } 579f478d9afSDavid Gibson } 580f478d9afSDavid Gibson 581f478d9afSDavid Gibson spapr_xive_hcall_init(spapr); 582f478d9afSDavid Gibson } 583872ff3deSCédric Le Goater 584872ff3deSCédric Le Goater spapr->qirqs = qemu_allocate_irqs(spapr->irq->set_irq, spapr, 585ad8de986SDavid Gibson spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE); 586fab397d8SCédric Le Goater } 587ef01ed9dSCédric Le Goater 588ce2918cbSDavid Gibson int spapr_irq_claim(SpaprMachineState *spapr, int irq, bool lsi, Error **errp) 589ef01ed9dSCédric Le Goater { 590580dde5eSDavid Gibson assert(irq >= SPAPR_XIRQ_BASE); 591580dde5eSDavid Gibson assert(irq < (spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE)); 592580dde5eSDavid Gibson 5933ba3d0bcSCédric Le Goater return spapr->irq->claim(spapr, irq, lsi, errp); 594ef01ed9dSCédric Le Goater } 595ef01ed9dSCédric Le Goater 596ce2918cbSDavid Gibson void spapr_irq_free(SpaprMachineState *spapr, int irq, int num) 597ef01ed9dSCédric Le Goater { 598f233cee9SDavid Gibson int i; 599f233cee9SDavid Gibson 600580dde5eSDavid Gibson assert(irq >= SPAPR_XIRQ_BASE); 601580dde5eSDavid Gibson assert((irq + num) <= (spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE)); 602580dde5eSDavid Gibson 603f233cee9SDavid Gibson for (i = irq; i < (irq + num); i++) { 604f233cee9SDavid Gibson spapr->irq->free(spapr, i); 605f233cee9SDavid Gibson } 606ef01ed9dSCédric Le Goater } 607ef01ed9dSCédric Le Goater 608ce2918cbSDavid Gibson qemu_irq spapr_qirq(SpaprMachineState *spapr, int irq) 609ef01ed9dSCédric Le Goater { 610af186151SDavid Gibson /* 611af186151SDavid Gibson * This interface is basically for VIO and PHB devices to find the 612af186151SDavid Gibson * right qemu_irq to manipulate, so we only allow access to the 613af186151SDavid Gibson * external irqs for now. Currently anything which needs to 614af186151SDavid Gibson * access the IPIs most naturally gets there via the guest side 615af186151SDavid Gibson * interfaces, we can change this if we need to in future. 616af186151SDavid Gibson */ 617af186151SDavid Gibson assert(irq >= SPAPR_XIRQ_BASE); 618af186151SDavid Gibson assert(irq < (spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE)); 619af186151SDavid Gibson 620af186151SDavid Gibson if (spapr->ics) { 621af186151SDavid Gibson assert(ics_valid_irq(spapr->ics, irq)); 622af186151SDavid Gibson } 623af186151SDavid Gibson if (spapr->xive) { 624af186151SDavid Gibson assert(irq < spapr->xive->nr_irqs); 625af186151SDavid Gibson assert(xive_eas_is_valid(&spapr->xive->eat[irq])); 626af186151SDavid Gibson } 627af186151SDavid Gibson 628af186151SDavid Gibson return spapr->qirqs[irq]; 629ef01ed9dSCédric Le Goater } 630ef01ed9dSCédric Le Goater 631ce2918cbSDavid Gibson int spapr_irq_post_load(SpaprMachineState *spapr, int version_id) 6321c53b06cSCédric Le Goater { 6333ba3d0bcSCédric Le Goater return spapr->irq->post_load(spapr, version_id); 6341c53b06cSCédric Le Goater } 6351c53b06cSCédric Le Goater 636ce2918cbSDavid Gibson void spapr_irq_reset(SpaprMachineState *spapr, Error **errp) 637b2e22477SCédric Le Goater { 638e1588bcdSGreg Kurz assert(!spapr->irq_map || bitmap_empty(spapr->irq_map, spapr->irq_map_nr)); 639e1588bcdSGreg Kurz 6403ba3d0bcSCédric Le Goater if (spapr->irq->reset) { 6413ba3d0bcSCédric Le Goater spapr->irq->reset(spapr, errp); 642b2e22477SCédric Le Goater } 643b2e22477SCédric Le Goater } 644b2e22477SCédric Le Goater 645ce2918cbSDavid Gibson int spapr_irq_get_phandle(SpaprMachineState *spapr, void *fdt, Error **errp) 646ad62bff6SGreg Kurz { 64714789694SDavid Gibson const char *nodename = "interrupt-controller"; 648ad62bff6SGreg Kurz int offset, phandle; 649ad62bff6SGreg Kurz 650ad62bff6SGreg Kurz offset = fdt_subnode_offset(fdt, 0, nodename); 651ad62bff6SGreg Kurz if (offset < 0) { 65214789694SDavid Gibson error_setg(errp, "Can't find node \"%s\": %s", 65314789694SDavid Gibson nodename, fdt_strerror(offset)); 654ad62bff6SGreg Kurz return -1; 655ad62bff6SGreg Kurz } 656ad62bff6SGreg Kurz 657ad62bff6SGreg Kurz phandle = fdt_get_phandle(fdt, offset); 658ad62bff6SGreg Kurz if (!phandle) { 659ad62bff6SGreg Kurz error_setg(errp, "Can't get phandle of node \"%s\"", nodename); 660ad62bff6SGreg Kurz return -1; 661ad62bff6SGreg Kurz } 662ad62bff6SGreg Kurz 663ad62bff6SGreg Kurz return phandle; 664ad62bff6SGreg Kurz } 665ad62bff6SGreg Kurz 666ef01ed9dSCédric Le Goater /* 667ef01ed9dSCédric Le Goater * XICS legacy routines - to deprecate one day 668ef01ed9dSCédric Le Goater */ 669ef01ed9dSCédric Le Goater 670ef01ed9dSCédric Le Goater static int ics_find_free_block(ICSState *ics, int num, int alignnum) 671ef01ed9dSCédric Le Goater { 672ef01ed9dSCédric Le Goater int first, i; 673ef01ed9dSCédric Le Goater 674ef01ed9dSCédric Le Goater for (first = 0; first < ics->nr_irqs; first += alignnum) { 675ef01ed9dSCédric Le Goater if (num > (ics->nr_irqs - first)) { 676ef01ed9dSCédric Le Goater return -1; 677ef01ed9dSCédric Le Goater } 678ef01ed9dSCédric Le Goater for (i = first; i < first + num; ++i) { 6794a99d405SCédric Le Goater if (!ics_irq_free(ics, i)) { 680ef01ed9dSCédric Le Goater break; 681ef01ed9dSCédric Le Goater } 682ef01ed9dSCédric Le Goater } 683ef01ed9dSCédric Le Goater if (i == (first + num)) { 684ef01ed9dSCédric Le Goater return first; 685ef01ed9dSCédric Le Goater } 686ef01ed9dSCédric Le Goater } 687ef01ed9dSCédric Le Goater 688ef01ed9dSCédric Le Goater return -1; 689ef01ed9dSCédric Le Goater } 690ef01ed9dSCédric Le Goater 691ce2918cbSDavid Gibson int spapr_irq_find(SpaprMachineState *spapr, int num, bool align, Error **errp) 692ef01ed9dSCédric Le Goater { 693ef01ed9dSCédric Le Goater ICSState *ics = spapr->ics; 694ef01ed9dSCédric Le Goater int first = -1; 695ef01ed9dSCédric Le Goater 696ef01ed9dSCédric Le Goater assert(ics); 697ef01ed9dSCédric Le Goater 698ef01ed9dSCédric Le Goater /* 699ef01ed9dSCédric Le Goater * MSIMesage::data is used for storing VIRQ so 700ef01ed9dSCédric Le Goater * it has to be aligned to num to support multiple 701ef01ed9dSCédric Le Goater * MSI vectors. MSI-X is not affected by this. 702ef01ed9dSCédric Le Goater * The hint is used for the first IRQ, the rest should 703ef01ed9dSCédric Le Goater * be allocated continuously. 704ef01ed9dSCédric Le Goater */ 705ef01ed9dSCédric Le Goater if (align) { 706ef01ed9dSCédric Le Goater assert((num == 1) || (num == 2) || (num == 4) || 707ef01ed9dSCédric Le Goater (num == 8) || (num == 16) || (num == 32)); 708ef01ed9dSCédric Le Goater first = ics_find_free_block(ics, num, num); 709ef01ed9dSCédric Le Goater } else { 710ef01ed9dSCédric Le Goater first = ics_find_free_block(ics, num, 1); 711ef01ed9dSCédric Le Goater } 712ef01ed9dSCédric Le Goater 713ef01ed9dSCédric Le Goater if (first < 0) { 714ef01ed9dSCédric Le Goater error_setg(errp, "can't find a free %d-IRQ block", num); 715ef01ed9dSCédric Le Goater return -1; 716ef01ed9dSCédric Le Goater } 717ef01ed9dSCédric Le Goater 718ef01ed9dSCédric Le Goater return first + ics->offset; 719ef01ed9dSCédric Le Goater } 720ae837402SCédric Le Goater 721ad8de986SDavid Gibson #define SPAPR_IRQ_XICS_LEGACY_NR_XIRQS 0x400 722ae837402SCédric Le Goater 723ce2918cbSDavid Gibson SpaprIrq spapr_irq_xics_legacy = { 724ad8de986SDavid Gibson .nr_xirqs = SPAPR_IRQ_XICS_LEGACY_NR_XIRQS, 725ad8de986SDavid Gibson .nr_msis = SPAPR_IRQ_XICS_LEGACY_NR_XIRQS, 726ca62823bSDavid Gibson .xics = true, 727ca62823bSDavid Gibson .xive = false, 728ae837402SCédric Le Goater 729ae837402SCédric Le Goater .claim = spapr_irq_claim_xics, 730ae837402SCédric Le Goater .free = spapr_irq_free_xics, 731ae837402SCédric Le Goater .print_info = spapr_irq_print_info_xics, 7326e21de4aSCédric Le Goater .dt_populate = spapr_dt_xics, 7331c53b06cSCédric Le Goater .post_load = spapr_irq_post_load_xics, 7343f777abcSCédric Le Goater .reset = spapr_irq_reset_xics, 735872ff3deSCédric Le Goater .set_irq = spapr_irq_set_irq_xics, 7363f777abcSCédric Le Goater .init_kvm = spapr_irq_init_kvm_xics, 737ae837402SCédric Le Goater }; 738150e25f8SDavid Gibson 739150e25f8SDavid Gibson static void spapr_irq_register_types(void) 740150e25f8SDavid Gibson { 741150e25f8SDavid Gibson type_register_static(&spapr_intc_info); 742150e25f8SDavid Gibson } 743150e25f8SDavid Gibson 744150e25f8SDavid Gibson type_init(spapr_irq_register_types) 745