aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/mips/mips_malta.c60
-rw-r--r--target-mips/cpu.h1
-rw-r--r--target-mips/translate.c10
3 files changed, 60 insertions, 11 deletions
diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index cc32a44429..fa769e5c00 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -57,6 +57,7 @@
#include "hw/empty_slot.h"
#include "sysemu/kvm.h"
#include "exec/semihost.h"
+#include "hw/mips/cps.h"
//#define DEBUG_BOARD_INIT
@@ -95,6 +96,7 @@ typedef struct {
typedef struct {
SysBusDevice parent_obj;
+ MIPSCPSState *cps;
qemu_irq *i8259;
} MaltaState;
@@ -908,19 +910,12 @@ static void main_cpu_reset(void *opaque)
}
}
-static void create_cpu(const char *cpu_model,
- qemu_irq *cbus_irq, qemu_irq *i8259_irq)
+static void create_cpu_without_cps(const char *cpu_model,
+ qemu_irq *cbus_irq, qemu_irq *i8259_irq)
{
CPUMIPSState *env;
MIPSCPU *cpu;
int i;
- if (cpu_model == NULL) {
-#ifdef TARGET_MIPS64
- cpu_model = "20Kc";
-#else
- cpu_model = "24Kf";
-#endif
- }
for (i = 0; i < smp_cpus; i++) {
cpu = cpu_mips_init(cpu_model);
@@ -942,6 +937,49 @@ static void create_cpu(const char *cpu_model,
*cbus_irq = env->irq[4];
}
+static void create_cps(MaltaState *s, const char *cpu_model,
+ qemu_irq *cbus_irq, qemu_irq *i8259_irq)
+{
+ Error *err = NULL;
+ s->cps = g_new0(MIPSCPSState, 1);
+
+ object_initialize(s->cps, sizeof(MIPSCPSState), TYPE_MIPS_CPS);
+ qdev_set_parent_bus(DEVICE(s->cps), sysbus_get_default());
+
+ object_property_set_str(OBJECT(s->cps), cpu_model, "cpu-model", &err);
+ object_property_set_int(OBJECT(s->cps), smp_cpus, "num-vp", &err);
+ object_property_set_bool(OBJECT(s->cps), true, "realized", &err);
+ if (err != NULL) {
+ error_report("%s", error_get_pretty(err));
+ exit(1);
+ }
+
+ sysbus_mmio_map_overlap(SYS_BUS_DEVICE(s->cps), 0, 0, 1);
+
+ /* FIXME: When GIC is present then we should use GIC's IRQ 3.
+ Until then CPS exposes CPU's IRQs thus use the default IRQ 2. */
+ *i8259_irq = get_cps_irq(s->cps, 2);
+ *cbus_irq = NULL;
+}
+
+static void create_cpu(MaltaState *s, const char *cpu_model,
+ qemu_irq *cbus_irq, qemu_irq *i8259_irq)
+{
+ if (cpu_model == NULL) {
+#ifdef TARGET_MIPS64
+ cpu_model = "20Kc";
+#else
+ cpu_model = "24Kf";
+#endif
+ }
+
+ if ((smp_cpus > 1) && cpu_supports_cps_smp(cpu_model)) {
+ create_cps(s, cpu_model, cbus_irq, i8259_irq);
+ } else {
+ create_cpu_without_cps(cpu_model, cbus_irq, i8259_irq);
+ }
+}
+
static
void mips_malta_init(MachineState *machine)
{
@@ -994,8 +1032,8 @@ void mips_malta_init(MachineState *machine)
}
}
- /* create CPUs */
- create_cpu(machine->cpu_model, &cbus_irq, &i8259_irq);
+ /* create CPU */
+ create_cpu(s, machine->cpu_model, &cbus_irq, &i8259_irq);
/* allocate RAM */
if (ram_size > (2048u << 20)) {
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 55d3224291..63fea676a0 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -760,6 +760,7 @@ MIPSCPU *cpu_mips_init(const char *cpu_model);
int cpu_mips_signal_handler(int host_signum, void *pinfo, void *puc);
#define cpu_init(cpu_model) CPU(cpu_mips_init(cpu_model))
+bool cpu_supports_cps_smp(const char *cpu_model);
/* TODO QOM'ify CPU reset and remove */
void cpu_state_reset(CPUMIPSState *s);
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 8191b9241f..a5b8805f77 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -19977,6 +19977,16 @@ MIPSCPU *cpu_mips_init(const char *cpu_model)
return cpu;
}
+bool cpu_supports_cps_smp(const char *cpu_model)
+{
+ const mips_def_t *def = cpu_mips_find_by_name(cpu_model);
+ if (!def) {
+ return false;
+ }
+
+ return (def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
+}
+
void cpu_state_reset(CPUMIPSState *env)
{
MIPSCPU *cpu = mips_env_get_cpu(env);