diff options
Diffstat (limited to 'hw/ppc/spapr.c')
| -rw-r--r-- | hw/ppc/spapr.c | 225 |
1 files changed, 52 insertions, 173 deletions
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index e5d825374e..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,38 +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; - - 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) { @@ -1636,6 +1576,10 @@ static void spapr_machine_reset(void) ppc_set_compat(first_ppc_cpu, spapr->max_compat_pvr, &error_fatal); } + if (!SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) { + spapr_irq_msi_reset(spapr); + } + qemu_devices_reset(); /* DRC reset may cause a device to be unplugged. This will cause troubles @@ -1910,6 +1854,24 @@ static const VMStateDescription vmstate_spapr_patb_entry = { }, }; +static bool spapr_irq_map_needed(void *opaque) +{ + sPAPRMachineState *spapr = opaque; + + return spapr->irq_map && !bitmap_empty(spapr->irq_map, spapr->irq_map_nr); +} + +static const VMStateDescription vmstate_spapr_irq_map = { + .name = "spapr_irq_map", + .version_id = 1, + .minimum_version_id = 1, + .needed = spapr_irq_map_needed, + .fields = (VMStateField[]) { + VMSTATE_BITMAP(irq_map, sPAPRMachineState, 0, irq_map_nr), + VMSTATE_END_OF_LIST() + }, +}; + static const VMStateDescription vmstate_spapr = { .name = "spapr", .version_id = 3, @@ -1937,6 +1899,7 @@ static const VMStateDescription vmstate_spapr = { &vmstate_spapr_cap_cfpc, &vmstate_spapr_cap_sbbc, &vmstate_spapr_cap_ibs, + &vmstate_spapr_irq_map, NULL } }; @@ -2590,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 */ @@ -3782,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) @@ -4009,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 = { @@ -4059,19 +3915,42 @@ static const TypeInfo spapr_machine_info = { } \ type_init(spapr_machine_register_##suffix) + /* + * pseries-3.1 + */ +static void spapr_machine_3_1_instance_options(MachineState *machine) +{ +} + +static void spapr_machine_3_1_class_options(MachineClass *mc) +{ + /* Defaults for the latest behaviour inherited from the base class */ +} + +DEFINE_SPAPR_MACHINE(3_1, "3.1", true); + /* * pseries-3.0 */ +#define SPAPR_COMPAT_3_0 \ + HW_COMPAT_3_0 + static void spapr_machine_3_0_instance_options(MachineState *machine) { + spapr_machine_3_1_instance_options(machine); } static void spapr_machine_3_0_class_options(MachineClass *mc) { - /* Defaults for the latest behaviour inherited from the base class */ + sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); + + spapr_machine_3_1_class_options(mc); + SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_3_0); + + smc->legacy_irq_allocation = true; } -DEFINE_SPAPR_MACHINE(3_0, "3.0", true); +DEFINE_SPAPR_MACHINE(3_0, "3.0", false); /* * pseries-2.12 |