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++;
|
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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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__ */
|
||||||
|
Loading…
Reference in New Issue
Block a user