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 void spapr_irq_print_info_xics(SpaprMachineState *spapr, Monitor *mon) 102ef01ed9dSCédric Le Goater { 103ef01ed9dSCédric Le Goater CPUState *cs; 104ef01ed9dSCédric Le Goater 105ef01ed9dSCédric Le Goater CPU_FOREACH(cs) { 106ef01ed9dSCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 107ef01ed9dSCédric Le Goater 108a28b9a5aSCédric Le Goater icp_pic_print_info(spapr_cpu_state(cpu)->icp, mon); 109ef01ed9dSCédric Le Goater } 110ef01ed9dSCédric Le Goater 111ef01ed9dSCédric Le Goater ics_pic_print_info(spapr->ics, mon); 112ef01ed9dSCédric Le Goater } 113ef01ed9dSCédric Le Goater 114ce2918cbSDavid Gibson static int spapr_irq_post_load_xics(SpaprMachineState *spapr, int version_id) 1151c53b06cSCédric Le Goater { 1163272752aSGreg Kurz if (!kvm_irqchip_in_kernel()) { 1171c53b06cSCédric Le Goater CPUState *cs; 1181c53b06cSCédric Le Goater CPU_FOREACH(cs) { 1191c53b06cSCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 120a28b9a5aSCédric Le Goater icp_resend(spapr_cpu_state(cpu)->icp); 1211c53b06cSCédric Le Goater } 1221c53b06cSCédric Le Goater } 1231c53b06cSCédric Le Goater return 0; 1241c53b06cSCédric Le Goater } 1251c53b06cSCédric Le Goater 126ce2918cbSDavid Gibson static void spapr_irq_reset_xics(SpaprMachineState *spapr, Error **errp) 12713db0cd9SCédric Le Goater { 1283f777abcSCédric Le Goater Error *local_err = NULL; 1293f777abcSCédric Le Goater 130d0e9bc04SCédric Le Goater spapr_irq_init_kvm(spapr, &spapr_irq_xics, &local_err); 1313f777abcSCédric Le Goater if (local_err) { 1323f777abcSCédric Le Goater error_propagate(errp, local_err); 1333f777abcSCédric Le Goater return; 1343f777abcSCédric Le Goater } 13513db0cd9SCédric Le Goater } 13613db0cd9SCédric Le Goater 137ae805ea9SCédric Le Goater static void spapr_irq_init_kvm_xics(SpaprMachineState *spapr, Error **errp) 138ae805ea9SCédric Le Goater { 139ae805ea9SCédric Le Goater if (kvm_enabled()) { 140eab9f191SGreg Kurz xics_kvm_connect(spapr, errp); 141ae805ea9SCédric Le Goater } 142ae805ea9SCédric Le Goater } 143ae805ea9SCédric Le Goater 144ce2918cbSDavid Gibson SpaprIrq spapr_irq_xics = { 145ad8de986SDavid Gibson .nr_xirqs = SPAPR_NR_XIRQS, 146ad8de986SDavid Gibson .nr_msis = SPAPR_NR_MSIS, 147ca62823bSDavid Gibson .xics = true, 148ca62823bSDavid Gibson .xive = false, 149ef01ed9dSCédric Le Goater 150ef01ed9dSCédric Le Goater .print_info = spapr_irq_print_info_xics, 1516e21de4aSCédric Le Goater .dt_populate = spapr_dt_xics, 1521c53b06cSCédric Le Goater .post_load = spapr_irq_post_load_xics, 15313db0cd9SCédric Le Goater .reset = spapr_irq_reset_xics, 154ae805ea9SCédric Le Goater .init_kvm = spapr_irq_init_kvm_xics, 155ef01ed9dSCédric Le Goater }; 156ef01ed9dSCédric Le Goater 157ef01ed9dSCédric Le Goater /* 158dcc345b6SCédric Le Goater * XIVE IRQ backend. 159dcc345b6SCédric Le Goater */ 160dcc345b6SCédric Le Goater 161ce2918cbSDavid Gibson static void spapr_irq_print_info_xive(SpaprMachineState *spapr, 162dcc345b6SCédric Le Goater Monitor *mon) 163dcc345b6SCédric Le Goater { 164dcc345b6SCédric Le Goater CPUState *cs; 165dcc345b6SCédric Le Goater 166dcc345b6SCédric Le Goater CPU_FOREACH(cs) { 167dcc345b6SCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 168dcc345b6SCédric Le Goater 169a28b9a5aSCédric Le Goater xive_tctx_pic_print_info(spapr_cpu_state(cpu)->tctx, mon); 170dcc345b6SCédric Le Goater } 171dcc345b6SCédric Le Goater 172dcc345b6SCédric Le Goater spapr_xive_pic_print_info(spapr->xive, mon); 173dcc345b6SCédric Le Goater } 174dcc345b6SCédric Le Goater 175ce2918cbSDavid Gibson static int spapr_irq_post_load_xive(SpaprMachineState *spapr, int version_id) 1761c53b06cSCédric Le Goater { 177277dd3d7SCédric Le Goater return spapr_xive_post_load(spapr->xive, version_id); 1781c53b06cSCédric Le Goater } 1791c53b06cSCédric Le Goater 180ce2918cbSDavid Gibson static void spapr_irq_reset_xive(SpaprMachineState *spapr, Error **errp) 181b2e22477SCédric Le Goater { 182b2e22477SCédric Le Goater CPUState *cs; 1833f777abcSCédric Le Goater Error *local_err = NULL; 184b2e22477SCédric Le Goater 185b2e22477SCédric Le Goater CPU_FOREACH(cs) { 186b2e22477SCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 187b2e22477SCédric Le Goater 188b2e22477SCédric Le Goater /* (TCG) Set the OS CAM line of the thread interrupt context. */ 189a28b9a5aSCédric Le Goater spapr_xive_set_tctx_os_cam(spapr_cpu_state(cpu)->tctx); 190b2e22477SCédric Le Goater } 1913a8eb78eSCédric Le Goater 192d0e9bc04SCédric Le Goater spapr_irq_init_kvm(spapr, &spapr_irq_xive, &local_err); 1933f777abcSCédric Le Goater if (local_err) { 1943f777abcSCédric Le Goater error_propagate(errp, local_err); 1953f777abcSCédric Le Goater return; 1963f777abcSCédric Le Goater } 1973f777abcSCédric Le Goater 1983a8eb78eSCédric Le Goater /* Activate the XIVE MMIOs */ 1993a8eb78eSCédric Le Goater spapr_xive_mmio_set_enabled(spapr->xive, true); 200b2e22477SCédric Le Goater } 201b2e22477SCédric Le Goater 202ae805ea9SCédric Le Goater static void spapr_irq_init_kvm_xive(SpaprMachineState *spapr, Error **errp) 203ae805ea9SCédric Le Goater { 204ae805ea9SCédric Le Goater if (kvm_enabled()) { 205ae805ea9SCédric Le Goater kvmppc_xive_connect(spapr->xive, errp); 206ae805ea9SCédric Le Goater } 207ae805ea9SCédric Le Goater } 208ae805ea9SCédric Le Goater 209ce2918cbSDavid Gibson SpaprIrq spapr_irq_xive = { 210ad8de986SDavid Gibson .nr_xirqs = SPAPR_NR_XIRQS, 211ad8de986SDavid Gibson .nr_msis = SPAPR_NR_MSIS, 212ca62823bSDavid Gibson .xics = false, 213ca62823bSDavid Gibson .xive = true, 214dcc345b6SCédric Le Goater 215dcc345b6SCédric Le Goater .print_info = spapr_irq_print_info_xive, 2166e21de4aSCédric Le Goater .dt_populate = spapr_dt_xive, 2171c53b06cSCédric Le Goater .post_load = spapr_irq_post_load_xive, 218b2e22477SCédric Le Goater .reset = spapr_irq_reset_xive, 219ae805ea9SCédric Le Goater .init_kvm = spapr_irq_init_kvm_xive, 220dcc345b6SCédric Le Goater }; 221dcc345b6SCédric Le Goater 222dcc345b6SCédric Le Goater /* 22313db0cd9SCédric Le Goater * Dual XIVE and XICS IRQ backend. 22413db0cd9SCédric Le Goater * 22513db0cd9SCédric Le Goater * Both interrupt mode, XIVE and XICS, objects are created but the 22613db0cd9SCédric Le Goater * machine starts in legacy interrupt mode (XICS). It can be changed 22713db0cd9SCédric Le Goater * by the CAS negotiation process and, in that case, the new mode is 22813db0cd9SCédric Le Goater * activated after an extra machine reset. 22913db0cd9SCédric Le Goater */ 23013db0cd9SCédric Le Goater 23113db0cd9SCédric Le Goater /* 23213db0cd9SCédric Le Goater * Returns the sPAPR IRQ backend negotiated by CAS. XICS is the 23313db0cd9SCédric Le Goater * default. 23413db0cd9SCédric Le Goater */ 235ce2918cbSDavid Gibson static SpaprIrq *spapr_irq_current(SpaprMachineState *spapr) 23613db0cd9SCédric Le Goater { 23713db0cd9SCédric Le Goater return spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT) ? 23813db0cd9SCédric Le Goater &spapr_irq_xive : &spapr_irq_xics; 23913db0cd9SCédric Le Goater } 24013db0cd9SCédric Le Goater 241ce2918cbSDavid Gibson static void spapr_irq_print_info_dual(SpaprMachineState *spapr, Monitor *mon) 24213db0cd9SCédric Le Goater { 24313db0cd9SCédric Le Goater spapr_irq_current(spapr)->print_info(spapr, mon); 24413db0cd9SCédric Le Goater } 24513db0cd9SCédric Le Goater 246ce2918cbSDavid Gibson static void spapr_irq_dt_populate_dual(SpaprMachineState *spapr, 24713db0cd9SCédric Le Goater uint32_t nr_servers, void *fdt, 24813db0cd9SCédric Le Goater uint32_t phandle) 24913db0cd9SCédric Le Goater { 25013db0cd9SCédric Le Goater spapr_irq_current(spapr)->dt_populate(spapr, nr_servers, fdt, phandle); 25113db0cd9SCédric Le Goater } 25213db0cd9SCédric Le Goater 253ce2918cbSDavid Gibson static int spapr_irq_post_load_dual(SpaprMachineState *spapr, int version_id) 25413db0cd9SCédric Le Goater { 25513db0cd9SCédric Le Goater /* 25613db0cd9SCédric Le Goater * Force a reset of the XIVE backend after migration. The machine 25713db0cd9SCédric Le Goater * defaults to XICS at startup. 25813db0cd9SCédric Le Goater */ 25913db0cd9SCédric Le Goater if (spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) { 2603f777abcSCédric Le Goater if (kvm_irqchip_in_kernel()) { 2613f777abcSCédric Le Goater xics_kvm_disconnect(spapr, &error_fatal); 2623f777abcSCédric Le Goater } 26313db0cd9SCédric Le Goater spapr_irq_xive.reset(spapr, &error_fatal); 26413db0cd9SCédric Le Goater } 26513db0cd9SCédric Le Goater 26613db0cd9SCédric Le Goater return spapr_irq_current(spapr)->post_load(spapr, version_id); 26713db0cd9SCédric Le Goater } 26813db0cd9SCédric Le Goater 269ce2918cbSDavid Gibson static void spapr_irq_reset_dual(SpaprMachineState *spapr, Error **errp) 27013db0cd9SCédric Le Goater { 2713f777abcSCédric Le Goater Error *local_err = NULL; 2723f777abcSCédric Le Goater 2733a8eb78eSCédric Le Goater /* 2743a8eb78eSCédric Le Goater * Deactivate the XIVE MMIOs. The XIVE backend will reenable them 2753a8eb78eSCédric Le Goater * if selected. 2763a8eb78eSCédric Le Goater */ 2773a8eb78eSCédric Le Goater spapr_xive_mmio_set_enabled(spapr->xive, false); 2783a8eb78eSCédric Le Goater 2793f777abcSCédric Le Goater /* Destroy all KVM devices */ 2803f777abcSCédric Le Goater if (kvm_irqchip_in_kernel()) { 2813f777abcSCédric Le Goater xics_kvm_disconnect(spapr, &local_err); 2823f777abcSCédric Le Goater if (local_err) { 2833f777abcSCédric Le Goater error_propagate(errp, local_err); 2843f777abcSCédric Le Goater error_prepend(errp, "KVM XICS disconnect failed: "); 2853f777abcSCédric Le Goater return; 2863f777abcSCédric Le Goater } 2873f777abcSCédric Le Goater kvmppc_xive_disconnect(spapr->xive, &local_err); 2883f777abcSCédric Le Goater if (local_err) { 2893f777abcSCédric Le Goater error_propagate(errp, local_err); 2903f777abcSCédric Le Goater error_prepend(errp, "KVM XIVE disconnect failed: "); 2913f777abcSCédric Le Goater return; 2923f777abcSCédric Le Goater } 2933f777abcSCédric Le Goater } 2943f777abcSCédric Le Goater 29513db0cd9SCédric Le Goater spapr_irq_current(spapr)->reset(spapr, errp); 29613db0cd9SCédric Le Goater } 29713db0cd9SCédric Le Goater 29813db0cd9SCédric Le Goater /* 29913db0cd9SCédric Le Goater * Define values in sync with the XIVE and XICS backend 30013db0cd9SCédric Le Goater */ 301ce2918cbSDavid Gibson SpaprIrq spapr_irq_dual = { 302ad8de986SDavid Gibson .nr_xirqs = SPAPR_NR_XIRQS, 303ad8de986SDavid Gibson .nr_msis = SPAPR_NR_MSIS, 304ca62823bSDavid Gibson .xics = true, 305ca62823bSDavid Gibson .xive = true, 30613db0cd9SCédric Le Goater 30713db0cd9SCédric Le Goater .print_info = spapr_irq_print_info_dual, 30813db0cd9SCédric Le Goater .dt_populate = spapr_irq_dt_populate_dual, 30913db0cd9SCédric Le Goater .post_load = spapr_irq_post_load_dual, 31013db0cd9SCédric Le Goater .reset = spapr_irq_reset_dual, 311ae805ea9SCédric Le Goater .init_kvm = NULL, /* should not be used */ 31213db0cd9SCédric Le Goater }; 31313db0cd9SCédric Le Goater 314273fef83SCédric Le Goater 3150a3fd3dfSDavid Gibson static int spapr_irq_check(SpaprMachineState *spapr, Error **errp) 316273fef83SCédric Le Goater { 317273fef83SCédric Le Goater MachineState *machine = MACHINE(spapr); 318273fef83SCédric Le Goater 319273fef83SCédric Le Goater /* 320273fef83SCédric Le Goater * Sanity checks on non-P9 machines. On these, XIVE is not 321273fef83SCédric Le Goater * advertised, see spapr_dt_ov5_platform_support() 322273fef83SCédric Le Goater */ 323273fef83SCédric Le Goater if (!ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, 324273fef83SCédric Le Goater 0, spapr->max_compat_pvr)) { 325273fef83SCédric Le Goater /* 326273fef83SCédric Le Goater * If the 'dual' interrupt mode is selected, force XICS as CAS 327273fef83SCédric Le Goater * negotiation is useless. 328273fef83SCédric Le Goater */ 329273fef83SCédric Le Goater if (spapr->irq == &spapr_irq_dual) { 330273fef83SCédric Le Goater spapr->irq = &spapr_irq_xics; 3310a3fd3dfSDavid Gibson return 0; 332273fef83SCédric Le Goater } 333273fef83SCédric Le Goater 334273fef83SCédric Le Goater /* 335273fef83SCédric Le Goater * Non-P9 machines using only XIVE is a bogus setup. We have two 336273fef83SCédric Le Goater * scenarios to take into account because of the compat mode: 337273fef83SCédric Le Goater * 338273fef83SCédric Le Goater * 1. POWER7/8 machines should fail to init later on when creating 339273fef83SCédric Le Goater * the XIVE interrupt presenters because a POWER9 exception 340273fef83SCédric Le Goater * model is required. 341273fef83SCédric Le Goater 342273fef83SCédric Le Goater * 2. POWER9 machines using the POWER8 compat mode won't fail and 343273fef83SCédric Le Goater * will let the OS boot with a partial XIVE setup : DT 344273fef83SCédric Le Goater * properties but no hcalls. 345273fef83SCédric Le Goater * 346273fef83SCédric Le Goater * To cover both and not confuse the OS, add an early failure in 347273fef83SCédric Le Goater * QEMU. 348273fef83SCédric Le Goater */ 349273fef83SCédric Le Goater if (spapr->irq == &spapr_irq_xive) { 350273fef83SCédric Le Goater error_setg(errp, "XIVE-only machines require a POWER9 CPU"); 3510a3fd3dfSDavid Gibson return -1; 352273fef83SCédric Le Goater } 353273fef83SCédric Le Goater } 3547abc0c6dSGreg Kurz 3557abc0c6dSGreg Kurz /* 3567abc0c6dSGreg Kurz * On a POWER9 host, some older KVM XICS devices cannot be destroyed and 3577abc0c6dSGreg Kurz * re-created. Detect that early to avoid QEMU to exit later when the 3587abc0c6dSGreg Kurz * guest reboots. 3597abc0c6dSGreg Kurz */ 3607abc0c6dSGreg Kurz if (kvm_enabled() && 3617abc0c6dSGreg Kurz spapr->irq == &spapr_irq_dual && 3627abc0c6dSGreg Kurz machine_kernel_irqchip_required(machine) && 3637abc0c6dSGreg Kurz xics_kvm_has_broken_disconnect(spapr)) { 3647abc0c6dSGreg Kurz error_setg(errp, "KVM is too old to support ic-mode=dual,kernel-irqchip=on"); 3650a3fd3dfSDavid Gibson return -1; 3667abc0c6dSGreg Kurz } 3670a3fd3dfSDavid Gibson 3680a3fd3dfSDavid Gibson return 0; 369273fef83SCédric Le Goater } 370273fef83SCédric Le Goater 37113db0cd9SCédric Le Goater /* 372ef01ed9dSCédric Le Goater * sPAPR IRQ frontend routines for devices 373ef01ed9dSCédric Le Goater */ 374ebd6be08SDavid Gibson #define ALL_INTCS(spapr_) \ 375ebd6be08SDavid Gibson { SPAPR_INTC((spapr_)->ics), SPAPR_INTC((spapr_)->xive), } 376ebd6be08SDavid Gibson 377ebd6be08SDavid Gibson int spapr_irq_cpu_intc_create(SpaprMachineState *spapr, 378ebd6be08SDavid Gibson PowerPCCPU *cpu, Error **errp) 379ebd6be08SDavid Gibson { 380ebd6be08SDavid Gibson SpaprInterruptController *intcs[] = ALL_INTCS(spapr); 381ebd6be08SDavid Gibson int i; 382ebd6be08SDavid Gibson int rc; 383ebd6be08SDavid Gibson 384ebd6be08SDavid Gibson for (i = 0; i < ARRAY_SIZE(intcs); i++) { 385ebd6be08SDavid Gibson SpaprInterruptController *intc = intcs[i]; 386ebd6be08SDavid Gibson if (intc) { 387ebd6be08SDavid Gibson SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc); 388ebd6be08SDavid Gibson rc = sicc->cpu_intc_create(intc, cpu, errp); 389ebd6be08SDavid Gibson if (rc < 0) { 390ebd6be08SDavid Gibson return rc; 391ebd6be08SDavid Gibson } 392ebd6be08SDavid Gibson } 393ebd6be08SDavid Gibson } 394ebd6be08SDavid Gibson 395ebd6be08SDavid Gibson return 0; 396ebd6be08SDavid Gibson } 397ebd6be08SDavid Gibson 398*7bcdbccaSDavid Gibson static void spapr_set_irq(void *opaque, int irq, int level) 399*7bcdbccaSDavid Gibson { 400*7bcdbccaSDavid Gibson SpaprMachineState *spapr = SPAPR_MACHINE(opaque); 401*7bcdbccaSDavid Gibson SpaprInterruptControllerClass *sicc 402*7bcdbccaSDavid Gibson = SPAPR_INTC_GET_CLASS(spapr->active_intc); 403*7bcdbccaSDavid Gibson 404*7bcdbccaSDavid Gibson sicc->set_irq(spapr->active_intc, irq, level); 405*7bcdbccaSDavid Gibson } 406*7bcdbccaSDavid Gibson 407ce2918cbSDavid Gibson void spapr_irq_init(SpaprMachineState *spapr, Error **errp) 408fab397d8SCédric Le Goater { 4091a511340SGreg Kurz MachineState *machine = MACHINE(spapr); 4101a511340SGreg Kurz 4111a511340SGreg Kurz if (machine_kernel_irqchip_split(machine)) { 4121a511340SGreg Kurz error_setg(errp, "kernel_irqchip split mode not supported on pseries"); 4131a511340SGreg Kurz return; 4141a511340SGreg Kurz } 4151a511340SGreg Kurz 4161a511340SGreg Kurz if (!kvm_enabled() && machine_kernel_irqchip_required(machine)) { 4171a511340SGreg Kurz error_setg(errp, 4181a511340SGreg Kurz "kernel_irqchip requested but only available with KVM"); 4191a511340SGreg Kurz return; 4201a511340SGreg Kurz } 4211a511340SGreg Kurz 4220a3fd3dfSDavid Gibson if (spapr_irq_check(spapr, errp) < 0) { 423273fef83SCédric Le Goater return; 424273fef83SCédric Le Goater } 425273fef83SCédric Le Goater 426fab397d8SCédric Le Goater /* Initialize the MSI IRQ allocator. */ 427fab397d8SCédric Le Goater if (!SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) { 4283ba3d0bcSCédric Le Goater spapr_irq_msi_init(spapr, spapr->irq->nr_msis); 429fab397d8SCédric Le Goater } 430fab397d8SCédric Le Goater 431f478d9afSDavid Gibson if (spapr->irq->xics) { 432f478d9afSDavid Gibson Error *local_err = NULL; 433f478d9afSDavid Gibson Object *obj; 434f478d9afSDavid Gibson 435f478d9afSDavid Gibson obj = object_new(TYPE_ICS_SPAPR); 436f478d9afSDavid Gibson object_property_add_child(OBJECT(spapr), "ics", obj, &local_err); 437f478d9afSDavid Gibson if (local_err) { 438f478d9afSDavid Gibson error_propagate(errp, local_err); 439f478d9afSDavid Gibson return; 440f478d9afSDavid Gibson } 441f478d9afSDavid Gibson 442f478d9afSDavid Gibson object_property_add_const_link(obj, ICS_PROP_XICS, OBJECT(spapr), 443f478d9afSDavid Gibson &local_err); 444f478d9afSDavid Gibson if (local_err) { 445f478d9afSDavid Gibson error_propagate(errp, local_err); 446f478d9afSDavid Gibson return; 447f478d9afSDavid Gibson } 448f478d9afSDavid Gibson 449f478d9afSDavid Gibson object_property_set_int(obj, spapr->irq->nr_xirqs, "nr-irqs", 450f478d9afSDavid Gibson &local_err); 451f478d9afSDavid Gibson if (local_err) { 452f478d9afSDavid Gibson error_propagate(errp, local_err); 453f478d9afSDavid Gibson return; 454f478d9afSDavid Gibson } 455f478d9afSDavid Gibson 456f478d9afSDavid Gibson object_property_set_bool(obj, true, "realized", &local_err); 457f478d9afSDavid Gibson if (local_err) { 458f478d9afSDavid Gibson error_propagate(errp, local_err); 459f478d9afSDavid Gibson return; 460f478d9afSDavid Gibson } 461f478d9afSDavid Gibson 462f478d9afSDavid Gibson spapr->ics = ICS_SPAPR(obj); 463f478d9afSDavid Gibson } 464f478d9afSDavid Gibson 465f478d9afSDavid Gibson if (spapr->irq->xive) { 466f478d9afSDavid Gibson uint32_t nr_servers = spapr_max_server_number(spapr); 467f478d9afSDavid Gibson DeviceState *dev; 468f478d9afSDavid Gibson int i; 469f478d9afSDavid Gibson 470f478d9afSDavid Gibson dev = qdev_create(NULL, TYPE_SPAPR_XIVE); 471f478d9afSDavid Gibson qdev_prop_set_uint32(dev, "nr-irqs", 472f478d9afSDavid Gibson spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE); 473f478d9afSDavid Gibson /* 474f478d9afSDavid Gibson * 8 XIVE END structures per CPU. One for each available 475f478d9afSDavid Gibson * priority 476f478d9afSDavid Gibson */ 477f478d9afSDavid Gibson qdev_prop_set_uint32(dev, "nr-ends", nr_servers << 3); 478f478d9afSDavid Gibson qdev_init_nofail(dev); 479f478d9afSDavid Gibson 480f478d9afSDavid Gibson spapr->xive = SPAPR_XIVE(dev); 481f478d9afSDavid Gibson 482f478d9afSDavid Gibson /* Enable the CPU IPIs */ 483f478d9afSDavid Gibson for (i = 0; i < nr_servers; ++i) { 4840b0e52b1SDavid Gibson SpaprInterruptControllerClass *sicc 4850b0e52b1SDavid Gibson = SPAPR_INTC_GET_CLASS(spapr->xive); 4860b0e52b1SDavid Gibson 4870b0e52b1SDavid Gibson if (sicc->claim_irq(SPAPR_INTC(spapr->xive), SPAPR_IRQ_IPI + i, 488f478d9afSDavid Gibson false, errp) < 0) { 489f478d9afSDavid Gibson return; 490f478d9afSDavid Gibson } 491f478d9afSDavid Gibson } 492f478d9afSDavid Gibson 493f478d9afSDavid Gibson spapr_xive_hcall_init(spapr); 494f478d9afSDavid Gibson } 495872ff3deSCédric Le Goater 496*7bcdbccaSDavid Gibson spapr->qirqs = qemu_allocate_irqs(spapr_set_irq, spapr, 497ad8de986SDavid Gibson spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE); 498fab397d8SCédric Le Goater } 499ef01ed9dSCédric Le Goater 500ce2918cbSDavid Gibson int spapr_irq_claim(SpaprMachineState *spapr, int irq, bool lsi, Error **errp) 501ef01ed9dSCédric Le Goater { 5020b0e52b1SDavid Gibson SpaprInterruptController *intcs[] = ALL_INTCS(spapr); 5030b0e52b1SDavid Gibson int i; 5040b0e52b1SDavid Gibson int rc; 5050b0e52b1SDavid Gibson 506580dde5eSDavid Gibson assert(irq >= SPAPR_XIRQ_BASE); 507580dde5eSDavid Gibson assert(irq < (spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE)); 508580dde5eSDavid Gibson 5090b0e52b1SDavid Gibson for (i = 0; i < ARRAY_SIZE(intcs); i++) { 5100b0e52b1SDavid Gibson SpaprInterruptController *intc = intcs[i]; 5110b0e52b1SDavid Gibson if (intc) { 5120b0e52b1SDavid Gibson SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc); 5130b0e52b1SDavid Gibson rc = sicc->claim_irq(intc, irq, lsi, errp); 5140b0e52b1SDavid Gibson if (rc < 0) { 5150b0e52b1SDavid Gibson return rc; 5160b0e52b1SDavid Gibson } 5170b0e52b1SDavid Gibson } 5180b0e52b1SDavid Gibson } 5190b0e52b1SDavid Gibson 5200b0e52b1SDavid Gibson return 0; 521ef01ed9dSCédric Le Goater } 522ef01ed9dSCédric Le Goater 523ce2918cbSDavid Gibson void spapr_irq_free(SpaprMachineState *spapr, int irq, int num) 524ef01ed9dSCédric Le Goater { 5250b0e52b1SDavid Gibson SpaprInterruptController *intcs[] = ALL_INTCS(spapr); 5260b0e52b1SDavid Gibson int i, j; 527f233cee9SDavid Gibson 528580dde5eSDavid Gibson assert(irq >= SPAPR_XIRQ_BASE); 529580dde5eSDavid Gibson assert((irq + num) <= (spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE)); 530580dde5eSDavid Gibson 531f233cee9SDavid Gibson for (i = irq; i < (irq + num); i++) { 5320b0e52b1SDavid Gibson for (j = 0; j < ARRAY_SIZE(intcs); j++) { 5330b0e52b1SDavid Gibson SpaprInterruptController *intc = intcs[j]; 5340b0e52b1SDavid Gibson 5350b0e52b1SDavid Gibson if (intc) { 5360b0e52b1SDavid Gibson SpaprInterruptControllerClass *sicc 5370b0e52b1SDavid Gibson = SPAPR_INTC_GET_CLASS(intc); 5380b0e52b1SDavid Gibson sicc->free_irq(intc, i); 5390b0e52b1SDavid Gibson } 5400b0e52b1SDavid Gibson } 541f233cee9SDavid Gibson } 542ef01ed9dSCédric Le Goater } 543ef01ed9dSCédric Le Goater 544ce2918cbSDavid Gibson qemu_irq spapr_qirq(SpaprMachineState *spapr, int irq) 545ef01ed9dSCédric Le Goater { 546af186151SDavid Gibson /* 547af186151SDavid Gibson * This interface is basically for VIO and PHB devices to find the 548af186151SDavid Gibson * right qemu_irq to manipulate, so we only allow access to the 549af186151SDavid Gibson * external irqs for now. Currently anything which needs to 550af186151SDavid Gibson * access the IPIs most naturally gets there via the guest side 551af186151SDavid Gibson * interfaces, we can change this if we need to in future. 552af186151SDavid Gibson */ 553af186151SDavid Gibson assert(irq >= SPAPR_XIRQ_BASE); 554af186151SDavid Gibson assert(irq < (spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE)); 555af186151SDavid Gibson 556af186151SDavid Gibson if (spapr->ics) { 557af186151SDavid Gibson assert(ics_valid_irq(spapr->ics, irq)); 558af186151SDavid Gibson } 559af186151SDavid Gibson if (spapr->xive) { 560af186151SDavid Gibson assert(irq < spapr->xive->nr_irqs); 561af186151SDavid Gibson assert(xive_eas_is_valid(&spapr->xive->eat[irq])); 562af186151SDavid Gibson } 563af186151SDavid Gibson 564af186151SDavid Gibson return spapr->qirqs[irq]; 565ef01ed9dSCédric Le Goater } 566ef01ed9dSCédric Le Goater 567ce2918cbSDavid Gibson int spapr_irq_post_load(SpaprMachineState *spapr, int version_id) 5681c53b06cSCédric Le Goater { 56981106dddSDavid Gibson spapr_irq_update_active_intc(spapr); 5703ba3d0bcSCédric Le Goater return spapr->irq->post_load(spapr, version_id); 5711c53b06cSCédric Le Goater } 5721c53b06cSCédric Le Goater 573ce2918cbSDavid Gibson void spapr_irq_reset(SpaprMachineState *spapr, Error **errp) 574b2e22477SCédric Le Goater { 575e1588bcdSGreg Kurz assert(!spapr->irq_map || bitmap_empty(spapr->irq_map, spapr->irq_map_nr)); 576e1588bcdSGreg Kurz 57781106dddSDavid Gibson spapr_irq_update_active_intc(spapr); 57881106dddSDavid Gibson 5793ba3d0bcSCédric Le Goater if (spapr->irq->reset) { 5803ba3d0bcSCédric Le Goater spapr->irq->reset(spapr, errp); 581b2e22477SCédric Le Goater } 582b2e22477SCédric Le Goater } 583b2e22477SCédric Le Goater 584ce2918cbSDavid Gibson int spapr_irq_get_phandle(SpaprMachineState *spapr, void *fdt, Error **errp) 585ad62bff6SGreg Kurz { 58614789694SDavid Gibson const char *nodename = "interrupt-controller"; 587ad62bff6SGreg Kurz int offset, phandle; 588ad62bff6SGreg Kurz 589ad62bff6SGreg Kurz offset = fdt_subnode_offset(fdt, 0, nodename); 590ad62bff6SGreg Kurz if (offset < 0) { 59114789694SDavid Gibson error_setg(errp, "Can't find node \"%s\": %s", 59214789694SDavid Gibson nodename, fdt_strerror(offset)); 593ad62bff6SGreg Kurz return -1; 594ad62bff6SGreg Kurz } 595ad62bff6SGreg Kurz 596ad62bff6SGreg Kurz phandle = fdt_get_phandle(fdt, offset); 597ad62bff6SGreg Kurz if (!phandle) { 598ad62bff6SGreg Kurz error_setg(errp, "Can't get phandle of node \"%s\"", nodename); 599ad62bff6SGreg Kurz return -1; 600ad62bff6SGreg Kurz } 601ad62bff6SGreg Kurz 602ad62bff6SGreg Kurz return phandle; 603ad62bff6SGreg Kurz } 604ad62bff6SGreg Kurz 60581106dddSDavid Gibson static void set_active_intc(SpaprMachineState *spapr, 60681106dddSDavid Gibson SpaprInterruptController *new_intc) 60781106dddSDavid Gibson { 60881106dddSDavid Gibson SpaprInterruptControllerClass *sicc; 60981106dddSDavid Gibson 61081106dddSDavid Gibson assert(new_intc); 61181106dddSDavid Gibson 61281106dddSDavid Gibson if (new_intc == spapr->active_intc) { 61381106dddSDavid Gibson /* Nothing to do */ 61481106dddSDavid Gibson return; 61581106dddSDavid Gibson } 61681106dddSDavid Gibson 61781106dddSDavid Gibson if (spapr->active_intc) { 61881106dddSDavid Gibson sicc = SPAPR_INTC_GET_CLASS(spapr->active_intc); 61981106dddSDavid Gibson if (sicc->deactivate) { 62081106dddSDavid Gibson sicc->deactivate(spapr->active_intc); 62181106dddSDavid Gibson } 62281106dddSDavid Gibson } 62381106dddSDavid Gibson 62481106dddSDavid Gibson sicc = SPAPR_INTC_GET_CLASS(new_intc); 62581106dddSDavid Gibson if (sicc->activate) { 62681106dddSDavid Gibson sicc->activate(new_intc, &error_fatal); 62781106dddSDavid Gibson } 62881106dddSDavid Gibson 62981106dddSDavid Gibson spapr->active_intc = new_intc; 63081106dddSDavid Gibson } 63181106dddSDavid Gibson 63281106dddSDavid Gibson void spapr_irq_update_active_intc(SpaprMachineState *spapr) 63381106dddSDavid Gibson { 63481106dddSDavid Gibson SpaprInterruptController *new_intc; 63581106dddSDavid Gibson 63681106dddSDavid Gibson if (!spapr->ics) { 63781106dddSDavid Gibson /* 63881106dddSDavid Gibson * XXX before we run CAS, ov5_cas is initialized empty, which 63981106dddSDavid Gibson * indicates XICS, even if we have ic-mode=xive. TODO: clean 64081106dddSDavid Gibson * up the CAS path so that we have a clearer way of handling 64181106dddSDavid Gibson * this. 64281106dddSDavid Gibson */ 64381106dddSDavid Gibson new_intc = SPAPR_INTC(spapr->xive); 64481106dddSDavid Gibson } else if (spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) { 64581106dddSDavid Gibson new_intc = SPAPR_INTC(spapr->xive); 64681106dddSDavid Gibson } else { 64781106dddSDavid Gibson new_intc = SPAPR_INTC(spapr->ics); 64881106dddSDavid Gibson } 64981106dddSDavid Gibson 65081106dddSDavid Gibson set_active_intc(spapr, new_intc); 65181106dddSDavid Gibson } 65281106dddSDavid Gibson 653ef01ed9dSCédric Le Goater /* 654ef01ed9dSCédric Le Goater * XICS legacy routines - to deprecate one day 655ef01ed9dSCédric Le Goater */ 656ef01ed9dSCédric Le Goater 657ef01ed9dSCédric Le Goater static int ics_find_free_block(ICSState *ics, int num, int alignnum) 658ef01ed9dSCédric Le Goater { 659ef01ed9dSCédric Le Goater int first, i; 660ef01ed9dSCédric Le Goater 661ef01ed9dSCédric Le Goater for (first = 0; first < ics->nr_irqs; first += alignnum) { 662ef01ed9dSCédric Le Goater if (num > (ics->nr_irqs - first)) { 663ef01ed9dSCédric Le Goater return -1; 664ef01ed9dSCédric Le Goater } 665ef01ed9dSCédric Le Goater for (i = first; i < first + num; ++i) { 6664a99d405SCédric Le Goater if (!ics_irq_free(ics, i)) { 667ef01ed9dSCédric Le Goater break; 668ef01ed9dSCédric Le Goater } 669ef01ed9dSCédric Le Goater } 670ef01ed9dSCédric Le Goater if (i == (first + num)) { 671ef01ed9dSCédric Le Goater return first; 672ef01ed9dSCédric Le Goater } 673ef01ed9dSCédric Le Goater } 674ef01ed9dSCédric Le Goater 675ef01ed9dSCédric Le Goater return -1; 676ef01ed9dSCédric Le Goater } 677ef01ed9dSCédric Le Goater 678ce2918cbSDavid Gibson int spapr_irq_find(SpaprMachineState *spapr, int num, bool align, Error **errp) 679ef01ed9dSCédric Le Goater { 680ef01ed9dSCédric Le Goater ICSState *ics = spapr->ics; 681ef01ed9dSCédric Le Goater int first = -1; 682ef01ed9dSCédric Le Goater 683ef01ed9dSCédric Le Goater assert(ics); 684ef01ed9dSCédric Le Goater 685ef01ed9dSCédric Le Goater /* 686ef01ed9dSCédric Le Goater * MSIMesage::data is used for storing VIRQ so 687ef01ed9dSCédric Le Goater * it has to be aligned to num to support multiple 688ef01ed9dSCédric Le Goater * MSI vectors. MSI-X is not affected by this. 689ef01ed9dSCédric Le Goater * The hint is used for the first IRQ, the rest should 690ef01ed9dSCédric Le Goater * be allocated continuously. 691ef01ed9dSCédric Le Goater */ 692ef01ed9dSCédric Le Goater if (align) { 693ef01ed9dSCédric Le Goater assert((num == 1) || (num == 2) || (num == 4) || 694ef01ed9dSCédric Le Goater (num == 8) || (num == 16) || (num == 32)); 695ef01ed9dSCédric Le Goater first = ics_find_free_block(ics, num, num); 696ef01ed9dSCédric Le Goater } else { 697ef01ed9dSCédric Le Goater first = ics_find_free_block(ics, num, 1); 698ef01ed9dSCédric Le Goater } 699ef01ed9dSCédric Le Goater 700ef01ed9dSCédric Le Goater if (first < 0) { 701ef01ed9dSCédric Le Goater error_setg(errp, "can't find a free %d-IRQ block", num); 702ef01ed9dSCédric Le Goater return -1; 703ef01ed9dSCédric Le Goater } 704ef01ed9dSCédric Le Goater 705ef01ed9dSCédric Le Goater return first + ics->offset; 706ef01ed9dSCédric Le Goater } 707ae837402SCédric Le Goater 708ad8de986SDavid Gibson #define SPAPR_IRQ_XICS_LEGACY_NR_XIRQS 0x400 709ae837402SCédric Le Goater 710ce2918cbSDavid Gibson SpaprIrq spapr_irq_xics_legacy = { 711ad8de986SDavid Gibson .nr_xirqs = SPAPR_IRQ_XICS_LEGACY_NR_XIRQS, 712ad8de986SDavid Gibson .nr_msis = SPAPR_IRQ_XICS_LEGACY_NR_XIRQS, 713ca62823bSDavid Gibson .xics = true, 714ca62823bSDavid Gibson .xive = false, 715ae837402SCédric Le Goater 716ae837402SCédric Le Goater .print_info = spapr_irq_print_info_xics, 7176e21de4aSCédric Le Goater .dt_populate = spapr_dt_xics, 7181c53b06cSCédric Le Goater .post_load = spapr_irq_post_load_xics, 7193f777abcSCédric Le Goater .reset = spapr_irq_reset_xics, 7203f777abcSCédric Le Goater .init_kvm = spapr_irq_init_kvm_xics, 721ae837402SCédric Le Goater }; 722150e25f8SDavid Gibson 723150e25f8SDavid Gibson static void spapr_irq_register_types(void) 724150e25f8SDavid Gibson { 725150e25f8SDavid Gibson type_register_static(&spapr_intc_info); 726150e25f8SDavid Gibson } 727150e25f8SDavid Gibson 728150e25f8SDavid Gibson type_init(spapr_irq_register_types) 729