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:
parent
c6304a4a68
commit
7b56516058
@ -779,6 +779,11 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
|
||||
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 */
|
||||
if (cpu_model == NULL) {
|
||||
cpu_model = kvm_enabled() ? "host" : "POWER7";
|
||||
@ -791,6 +796,8 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
|
||||
}
|
||||
env = &cpu->env;
|
||||
|
||||
xics_cpu_setup(spapr->icp, cpu);
|
||||
|
||||
/* Set time-base frequency to 512 MHz */
|
||||
cpu_ppc_tb_init(env, TIMEBASE_FREQ);
|
||||
|
||||
@ -830,11 +837,6 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
|
||||
}
|
||||
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 */
|
||||
spapr_events_init(spapr);
|
||||
|
||||
|
@ -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 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->nr_servers = max_server_num + 1;
|
||||
icp->nr_servers = nr_servers;
|
||||
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->nr_irqs = nr_irqs;
|
||||
ics->offset = XICS_IRQ_BASE;
|
||||
|
@ -35,6 +35,7 @@ struct icp_state;
|
||||
qemu_irq xics_get_qirq(struct icp_state *icp, int irq);
|
||||
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__ */
|
||||
|
Loading…
Reference in New Issue
Block a user