On Malta, after reset, only VP0 on Core0 starts the execution. Other VPs are halted until VP0 powers them up using Cluster Power Controller.
Signed-off-by: Leon Alrae <leon.al...@imgtec.com> --- hw/mips/mips_malta.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index 1fb17fb..34cc4cb 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -57,6 +57,7 @@ #include "exec/semihost.h" #include "hw/misc/mips_gcr.h" #include "hw/intc/mips_gic.h" +#include "hw/misc/mips_cpc.h" //#define DEBUG_BOARD_INIT @@ -97,6 +98,7 @@ typedef struct { MIPSGCRState gcr; MIPSGICState gic; + MIPSCPCState cpc; qemu_irq *i8259; } MaltaState; @@ -617,6 +619,19 @@ static void gic_init(MaltaState *s, Error **err) sysbus_mmio_map(gicbusdev, 0, gicbase); } +static void cpc_init(MaltaState *s, Error **err) +{ + object_initialize(&s->cpc, sizeof(s->cpc), TYPE_MIPS_CPC); + qdev_set_parent_bus(DEVICE(&s->cpc), sysbus_get_default()); + + object_property_set_bool(OBJECT(&s->cpc), true, "realized", err); + if (*err != NULL) { + return; + } + + sysbus_mmio_map(SYS_BUS_DEVICE(&s->cpc), 0, CPC_BASE_ADDR); +} + /* Network support */ static void network_init(PCIBus *pci_bus) { @@ -937,6 +952,7 @@ static void malta_mips_config(MIPSCPU *cpu) static void main_cpu_reset(void *opaque) { MIPSCPU *cpu = opaque; + CPUState *cs = CPU(cpu); CPUMIPSState *env = &cpu->env; cpu_reset(CPU(cpu)); @@ -954,6 +970,15 @@ static void main_cpu_reset(void *opaque) /* Start running from the bootloader we wrote to end of RAM */ env->active_tc.PC = 0x40000000 + loaderparams.ram_low_size; } + + /* At reset only VP0 on Core0 will start executing the code, other + VPs are halted until VP0 powers them up through Cluster Power + Controller. */ + if ((env->CP0_Config5 & (1 << CP0C5_VP)) && + (env->CP0_Config3 & (1 << CP0C3_CMGCR)) && + (cs->cpu_index != 0)) { + cs->halted = 1; + } } static @@ -1200,6 +1225,11 @@ void mips_malta_init(MachineState *machine) error_report("%s", error_get_pretty(err)); exit(1); } + cpc_init(s, &err); + if (err != NULL) { + error_report("%s", error_get_pretty(err)); + exit(1); + } } /* -- 2.1.0