diff options
author | Cédric Le Goater <clg@kaod.org> | 2018-07-30 16:11:33 +0200 |
---|---|---|
committer | David Gibson <david@gibson.dropbear.id.au> | 2018-08-21 14:28:45 +1000 |
commit | ef01ed9d19ffffbb5d5517ecb424c543cde373a1 (patch) | |
tree | 12e371305e8b3344b67623049ccfad142d25f663 /hw/ppc/spapr.c | |
parent | 69bd18f84347b1b342443601f10a55da4c87bc9d (diff) |
spapr: introduce a IRQ controller backend to the machine
This proposal moves all the related IRQ routines of the sPAPR machine
behind a sPAPR IRQ backend interface 'spapr_irq' to prepare for future
changes. First of which will be to increase the size of the IRQ number
space, then, will follow a new backend for the POWER9 XIVE IRQ controller.
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: Greg Kurz <groug@kaod.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'hw/ppc/spapr.c')
-rw-r--r-- | hw/ppc/spapr.c | 180 |
1 files changed, 4 insertions, 176 deletions
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 6a78ceb708..ddd4478a34 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -54,7 +54,6 @@ #include "hw/ppc/spapr.h" #include "hw/ppc/spapr_vio.h" #include "hw/pci-host/spapr.h" -#include "hw/ppc/xics.h" #include "hw/pci/msi.h" #include "hw/pci/pci.h" @@ -117,33 +116,6 @@ static bool spapr_is_thread0_in_vcore(sPAPRMachineState *spapr, return spapr_get_vcpu_id(cpu) % spapr->vsmt == 0; } -static ICSState *spapr_ics_create(sPAPRMachineState *spapr, - const char *type_ics, - int nr_irqs, Error **errp) -{ - Error *local_err = NULL; - Object *obj; - - obj = object_new(type_ics); - object_property_add_child(OBJECT(spapr), "ics", obj, &error_abort); - object_property_add_const_link(obj, ICS_PROP_XICS, OBJECT(spapr), - &error_abort); - object_property_set_int(obj, nr_irqs, "nr-irqs", &local_err); - if (local_err) { - goto error; - } - object_property_set_bool(obj, true, "realized", &local_err); - if (local_err) { - goto error; - } - - return ICS_BASE(obj); - -error: - error_propagate(errp, local_err); - return NULL; -} - static bool pre_2_10_vmstate_dummy_icp_needed(void *opaque) { /* Dummy entries correspond to unused ICPState objects in older QEMUs, @@ -184,43 +156,6 @@ static int xics_max_server_number(sPAPRMachineState *spapr) return DIV_ROUND_UP(max_cpus * spapr->vsmt, smp_threads); } -static void xics_system_init(MachineState *machine, int nr_irqs, Error **errp) -{ - sPAPRMachineState *spapr = SPAPR_MACHINE(machine); - Error *local_err = NULL; - - /* Initialize the MSI IRQ allocator. */ - if (!SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) { - spapr_irq_msi_init(spapr, XICS_IRQ_BASE + nr_irqs - SPAPR_IRQ_MSI); - } - - if (kvm_enabled()) { - if (machine_kernel_irqchip_allowed(machine) && - !xics_kvm_init(spapr, &local_err)) { - spapr->icp_type = TYPE_KVM_ICP; - spapr->ics = spapr_ics_create(spapr, TYPE_ICS_KVM, nr_irqs, - &local_err); - } - if (machine_kernel_irqchip_required(machine) && !spapr->ics) { - error_prepend(&local_err, - "kernel_irqchip requested but unavailable: "); - goto error; - } - error_free(local_err); - local_err = NULL; - } - - if (!spapr->ics) { - xics_spapr_init(spapr); - spapr->icp_type = TYPE_ICP; - spapr->ics = spapr_ics_create(spapr, TYPE_ICS_SIMPLE, nr_irqs, - &local_err); - } - -error: - error_propagate(errp, local_err); -} - static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu, int smt_threads) { @@ -2618,7 +2553,7 @@ static void spapr_machine_init(MachineState *machine) load_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FW_OVERHEAD; /* Set up Interrupt Controller before we create the VCPUs */ - xics_system_init(machine, XICS_IRQS_SPAPR, &error_fatal); + smc->irq->init(spapr, &error_fatal); /* Set up containers for ibm,client-architecture-support negotiated options */ @@ -3810,121 +3745,13 @@ static ICPState *spapr_icp_get(XICSFabric *xi, int vcpu_id) return cpu ? ICP(cpu->intc) : NULL; } -#define ICS_IRQ_FREE(ics, srcno) \ - (!((ics)->irqs[(srcno)].flags & (XICS_FLAGS_IRQ_MASK))) - -static int ics_find_free_block(ICSState *ics, int num, int alignnum) -{ - int first, i; - - for (first = 0; first < ics->nr_irqs; first += alignnum) { - if (num > (ics->nr_irqs - first)) { - return -1; - } - for (i = first; i < first + num; ++i) { - if (!ICS_IRQ_FREE(ics, i)) { - break; - } - } - if (i == (first + num)) { - return first; - } - } - - return -1; -} - -int spapr_irq_find(sPAPRMachineState *spapr, int num, bool align, Error **errp) -{ - ICSState *ics = spapr->ics; - int first = -1; - - assert(ics); - - /* - * MSIMesage::data is used for storing VIRQ so - * it has to be aligned to num to support multiple - * MSI vectors. MSI-X is not affected by this. - * The hint is used for the first IRQ, the rest should - * be allocated continuously. - */ - if (align) { - assert((num == 1) || (num == 2) || (num == 4) || - (num == 8) || (num == 16) || (num == 32)); - first = ics_find_free_block(ics, num, num); - } else { - first = ics_find_free_block(ics, num, 1); - } - - if (first < 0) { - error_setg(errp, "can't find a free %d-IRQ block", num); - return -1; - } - - return first + ics->offset; -} - -int spapr_irq_claim(sPAPRMachineState *spapr, int irq, bool lsi, Error **errp) -{ - ICSState *ics = spapr->ics; - - assert(ics); - - if (!ics_valid_irq(ics, irq)) { - error_setg(errp, "IRQ %d is invalid", irq); - return -1; - } - - if (!ICS_IRQ_FREE(ics, irq - ics->offset)) { - error_setg(errp, "IRQ %d is not free", irq); - return -1; - } - - ics_set_irq_type(ics, irq - ics->offset, lsi); - return 0; -} - -void spapr_irq_free(sPAPRMachineState *spapr, int irq, int num) -{ - ICSState *ics = spapr->ics; - int srcno = irq - ics->offset; - int i; - - if (ics_valid_irq(ics, irq)) { - trace_spapr_irq_free(0, irq, num); - for (i = srcno; i < srcno + num; ++i) { - if (ICS_IRQ_FREE(ics, i)) { - trace_spapr_irq_free_warn(0, i + ics->offset); - } - memset(&ics->irqs[i], 0, sizeof(ICSIRQState)); - } - } -} - -qemu_irq spapr_qirq(sPAPRMachineState *spapr, int irq) -{ - ICSState *ics = spapr->ics; - - if (ics_valid_irq(ics, irq)) { - return ics->qirqs[irq - ics->offset]; - } - - return NULL; -} - static void spapr_pic_print_info(InterruptStatsProvider *obj, Monitor *mon) { sPAPRMachineState *spapr = SPAPR_MACHINE(obj); - CPUState *cs; - - CPU_FOREACH(cs) { - PowerPCCPU *cpu = POWERPC_CPU(cs); - - icp_pic_print_info(ICP(cpu->intc), mon); - } + sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); - ics_pic_print_info(spapr->ics, mon); + smc->irq->print_info(spapr, mon); } int spapr_get_vcpu_id(PowerPCCPU *cpu) @@ -4037,6 +3864,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN; smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 16; /* 64kiB */ spapr_caps_add_properties(smc, &error_abort); + smc->irq = &spapr_irq_xics; } static const TypeInfo spapr_machine_info = { |