On 06/07/17 03:13, Cédric Le Goater wrote: > The CAS negotiation process determines the interrupt controller model > to use in the guest but currently, the sPAPR machine make uses of the > controller very early in the initialization sequence. The interrupt > source is used to allocate IRQ numbers and populate the device tree > and the interrupt presenter objects are created along with the CPU. > > One solution would be use a bitmap to allocate these IRQ numbers and > then instantiate the interrupt source object of the correct type with > the bitmap as a constructor parameter. > > As for the interrupt presenter objects, we could allocated them later > in the boot process. May be on demand, when a CPU is first notified. > > Signed-off-by: Cédric Le Goater <c...@kaod.org> > --- > hw/ppc/spapr.c | 62 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 62 insertions(+) > > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c > index ca3a6bc2ea16..623fc776c886 100644 > --- a/hw/ppc/spapr.c > +++ b/hw/ppc/spapr.c > @@ -237,6 +237,38 @@ error: > return NULL; > } > > +static XiveICSState *spapr_xive_ics_create(XIVE *x, int nr_irqs, Error > **errp) > +{ > + Error *local_err = NULL; > + int irq_base; > + Object *obj; > + > + /* > + * TODO: use an XICS_IRQ_BASE alignment to be in sync with XICS > + * irq numbers. we should probably simplify the XIVE model or use > + * a common allocator. a bitmap maybe ? > + */ > + irq_base = xive_alloc_hw_irqs(x, nr_irqs, XICS_IRQ_BASE); > + if (irq_base < 0) { > + error_setg(errp, "Failed to allocate %d irqs", nr_irqs); > + return NULL; > + } > + > + obj = object_new(TYPE_ICS_XIVE); > + object_property_add_child(OBJECT(x), "hw", obj, NULL); > + > + xive_ics_create(ICS_XIVE(obj), x, irq_base, nr_irqs, 16 /* 64KB page */, > + XIVE_SRC_TRIGGER, &local_err); > + if (local_err) { > + goto error; > + } > + return ICS_XIVE(obj); > + > +error: > + error_propagate(errp, local_err); > + return NULL; > +} > + > static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu, > int smt_threads) > { > @@ -814,6 +846,11 @@ static int spapr_dt_cas_updates(sPAPRMachineState > *spapr, void *fdt, > /* /interrupt controller */ > if (!spapr_ovec_test(ov5_updates, OV5_XIVE_EXPLOIT)) { > spapr_dt_xics(xics_max_server_number(), fdt, PHANDLE_XICP); > + } else { > + xive_spapr_populate(spapr->xive, fdt); > + > + /* Install XIVE MMIOs */ > + xive_mmio_map(spapr->xive);
xive_mmio_map() could be called where sysbus_init_mmio() is called as once these are mmap'ed, they are never unmapped and tm_base/vc_base never change. And XIVE is always created on P9 anyway. > } > > offset = fdt_path_offset(fdt, "/chosen"); > @@ -963,6 +1000,13 @@ static void spapr_dt_ov5_platform_support(void *fdt, > int chosen) > } else { > val[3] = 0x00; /* Hash */ > } > + > + /* TODO: introduce a kvmppc_has_cap_xive() ? Works with Yes. > + * irqchip=off for now > + */ > + if (first_ppc_cpu->env.excp_model & POWERPC_EXCP_POWER9) { > + val[1] = 0x01; > + } > } else { > if (first_ppc_cpu->env.mmu_model & POWERPC_MMU_V3) { > /* V3 MMU supports both hash and radix (with dynamic switching) > */ > @@ -971,6 +1015,9 @@ static void spapr_dt_ov5_platform_support(void *fdt, int > chosen) > /* Otherwise we can only do hash */ > val[3] = 0x00; > } > + if (first_ppc_cpu->env.excp_model & POWERPC_EXCP_POWER9) { > + val[1] = 0x01; > + } > } > _FDT(fdt_setprop(fdt, chosen, "ibm,arch-vec-5-platform-support", > val, sizeof(val))); > @@ -2237,6 +2284,21 @@ static void ppc_spapr_init(MachineState *machine) > spapr->ov5 = spapr_ovec_new(); > spapr->ov5_cas = spapr_ovec_new(); > > + /* TODO: force XIVE mode by default on POWER9. > + * > + * Switching from XICS to XIVE is badly broken. The ICP type is > + * incorrect and the ICS is needed before the CAS negotiation to > + * allocate irq numbers ... > + */ > + if (strstr(machine->cpu_model, "POWER9") || > + !strcmp(machine->cpu_model, "host")) { > + spapr_ovec_set(spapr->ov5, OV5_XIVE_EXPLOIT); > + > + spapr->icp_type = TYPE_XIVE_ICP; > + spapr->ics = ICS_BASE( > + spapr_xive_ics_create(spapr->xive, XICS_IRQS_SPAPR, > &error_fatal)); > + } > + > if (smc->dr_lmb_enabled) { > spapr_ovec_set(spapr->ov5, OV5_DRCONF_MEMORY); > spapr_validate_node_memory(machine, &error_fatal); > -- Alexey