pseries: Move XICS initialization before cpu initialization

Currently, the pseries machine initializes the cpus, then the XICS
interrupt controller.  However, to support the upcoming in-kernel XICS
implementation we will need to initialize the irq controller before the
vcpus.  This patch makes the necesssary rearrangement.  This means the
xics init code can no longer auto-detect the number of cpus ("interrupt
servers" in XICS terminology) and so we must pass that in explicitly from
the platform code.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Ben Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
David Gibson 2013-03-13 15:53:28 +00:00 committed by Alexander Graf
parent c6304a4a68
commit 7b56516058
3 changed files with 35 additions and 39 deletions

View File

@ -779,6 +779,11 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
spapr->htab_shift++; spapr->htab_shift++;
} }
/* Set up Interrupt Controller before we create the VCPUs */
spapr->icp = xics_system_init(smp_cpus * kvmppc_smt_threads() / smp_threads,
XICS_IRQS);
spapr->next_irq = XICS_IRQ_BASE;
/* init CPUs */ /* init CPUs */
if (cpu_model == NULL) { if (cpu_model == NULL) {
cpu_model = kvm_enabled() ? "host" : "POWER7"; cpu_model = kvm_enabled() ? "host" : "POWER7";
@ -791,6 +796,8 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
} }
env = &cpu->env; env = &cpu->env;
xics_cpu_setup(spapr->icp, cpu);
/* Set time-base frequency to 512 MHz */ /* Set time-base frequency to 512 MHz */
cpu_ppc_tb_init(env, TIMEBASE_FREQ); cpu_ppc_tb_init(env, TIMEBASE_FREQ);
@ -830,11 +837,6 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
} }
g_free(filename); g_free(filename);
/* Set up Interrupt Controller */
spapr->icp = xics_system_init(XICS_IRQS);
spapr->next_irq = XICS_IRQ_BASE;
/* Set up EPOW events infrastructure */ /* Set up EPOW events infrastructure */
spapr_events_init(spapr); spapr_events_init(spapr);

View File

@ -521,46 +521,39 @@ static void xics_reset(void *opaque)
} }
} }
struct icp_state *xics_system_init(int nr_irqs) void xics_cpu_setup(struct icp_state *icp, PowerPCCPU *cpu)
{
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
struct icp_server_state *ss = &icp->ss[cs->cpu_index];
assert(cs->cpu_index < icp->nr_servers);
switch (PPC_INPUT(env)) {
case PPC_FLAGS_INPUT_POWER7:
ss->output = env->irq_inputs[POWER7_INPUT_INT];
break;
case PPC_FLAGS_INPUT_970:
ss->output = env->irq_inputs[PPC970_INPUT_INT];
break;
default:
fprintf(stderr, "XICS interrupt controller does not support this CPU "
"bus model\n");
abort();
}
}
struct icp_state *xics_system_init(int nr_servers, int nr_irqs)
{ {
CPUPPCState *env;
CPUState *cpu;
int max_server_num;
struct icp_state *icp; struct icp_state *icp;
struct ics_state *ics; struct ics_state *ics;
max_server_num = -1;
for (env = first_cpu; env != NULL; env = env->next_cpu) {
cpu = CPU(ppc_env_get_cpu(env));
if (cpu->cpu_index > max_server_num) {
max_server_num = cpu->cpu_index;
}
}
icp = g_malloc0(sizeof(*icp)); icp = g_malloc0(sizeof(*icp));
icp->nr_servers = max_server_num + 1; icp->nr_servers = nr_servers;
icp->ss = g_malloc0(icp->nr_servers*sizeof(struct icp_server_state)); icp->ss = g_malloc0(icp->nr_servers*sizeof(struct icp_server_state));
for (env = first_cpu; env != NULL; env = env->next_cpu) {
cpu = CPU(ppc_env_get_cpu(env));
struct icp_server_state *ss = &icp->ss[cpu->cpu_index];
switch (PPC_INPUT(env)) {
case PPC_FLAGS_INPUT_POWER7:
ss->output = env->irq_inputs[POWER7_INPUT_INT];
break;
case PPC_FLAGS_INPUT_970:
ss->output = env->irq_inputs[PPC970_INPUT_INT];
break;
default:
hw_error("XICS interrupt model does not support this CPU bus "
"model\n");
exit(1);
}
}
ics = g_malloc0(sizeof(*ics)); ics = g_malloc0(sizeof(*ics));
ics->nr_irqs = nr_irqs; ics->nr_irqs = nr_irqs;
ics->offset = XICS_IRQ_BASE; ics->offset = XICS_IRQ_BASE;

View File

@ -35,6 +35,7 @@ struct icp_state;
qemu_irq xics_get_qirq(struct icp_state *icp, int irq); qemu_irq xics_get_qirq(struct icp_state *icp, int irq);
void xics_set_irq_type(struct icp_state *icp, int irq, bool lsi); void xics_set_irq_type(struct icp_state *icp, int irq, bool lsi);
struct icp_state *xics_system_init(int nr_irqs); struct icp_state *xics_system_init(int nr_servers, int nr_irqs);
void xics_cpu_setup(struct icp_state *icp, PowerPCCPU *cpu);
#endif /* __XICS_H__ */ #endif /* __XICS_H__ */