Add Global Interrupt Controller support to Malta board. The I8259 is connected to pin 3 of the GIC. Increase number of CPUs supported to 32.
Signed-off-by: Yongbok Kim <yongbok....@imgtec.com> --- hw/mips/mips_malta.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++- target-mips/cpu.h | 1 + 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index c1f570a..d2611f0 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -54,6 +54,8 @@ #include "hw/empty_slot.h" #include "sysemu/kvm.h" #include "exec/semihost.h" +#include "hw/mips/mips_gcr.h" +#include "hw/mips/mips_gic.h" //#define DEBUG_BOARD_INIT @@ -92,6 +94,8 @@ typedef struct { typedef struct { SysBusDevice parent_obj; + MIPSGCRState gcr; + MIPSGICState gic; qemu_irq *i8259; } MaltaState; @@ -566,6 +570,50 @@ static MaltaFPGAState *malta_fpga_init(MemoryRegion *address_space, return s; } +static void gcr_init(MaltaState *s, Error **err) +{ + SysBusDevice *gcrbusdev; + DeviceState *gcrdev; + + object_initialize(&s->gcr, sizeof(s->gcr), TYPE_MIPS_GCR); + qdev_set_parent_bus(DEVICE(&s->gcr), sysbus_get_default()); + + gcrdev = DEVICE(&s->gcr); + + object_property_set_int(OBJECT(&s->gcr), smp_cpus, "num-cpu", err); + object_property_set_int(OBJECT(&s->gcr), 0x800, "gcr-rev", err); + object_property_set_bool(OBJECT(&s->gcr), true, "realized", err); + if (*err != NULL) { + return; + } + + gcrbusdev = SYS_BUS_DEVICE(gcrdev); + sysbus_mmio_map(gcrbusdev, 0, GCR_BASE_ADDR); +} + +static void *gic_init(MaltaState *s, Error **err) +{ + SysBusDevice *gicbusdev; + DeviceState *gicdev; + + object_initialize(&s->gic, sizeof(s->gic), TYPE_MIPS_GIC); + qdev_set_parent_bus(DEVICE(&s->gic), sysbus_get_default()); + + gicdev = DEVICE(&s->gic); + + object_property_set_int(OBJECT(&s->gic), smp_cpus, "num-cpu", err); + object_property_set_int(OBJECT(&s->gic), 256, "num-irq", err); + object_property_set_bool(OBJECT(&s->gic), true, "realized", err); + if (*err != NULL) { + return NULL; + } + + gicbusdev = SYS_BUS_DEVICE(gicdev); + sysbus_mmio_map(gicbusdev, 0, GIC_BASE_ADDR); + + return (void *) s->gic.irqs; +} + /* Network support */ static void network_init(PCIBus *pci_bus) { @@ -1136,6 +1184,21 @@ void mips_malta_init(MachineState *machine) cpu_mips_irq_init_cpu(env); cpu_mips_clock_init(env); + /* GCR/GIC */ + if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) { + Error *err = NULL; + gcr_init(s, &err); + if (err != NULL) { + error_report("%s", error_get_pretty(err)); + exit(1); + } + env->gic_irqs = gic_init(s, &err); + if (err != NULL) { + error_report("%s", error_get_pretty(err)); + exit(1); + } + } + /* * We have a circular dependency problem: pci_bus depends on isa_irq, * isa_irq is provided by i8259, i8259 depends on ISA, ISA depends @@ -1155,7 +1218,11 @@ void mips_malta_init(MachineState *machine) /* Interrupt controller */ /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */ - s->i8259 = i8259_init(isa_bus, env->irq[2]); + if (env->gic_irqs) { + s->i8259 = i8259_init(isa_bus, env->gic_irqs[3]); + } else { + s->i8259 = i8259_init(isa_bus, env->irq[2]); + } isa_bus_irqs(isa_bus, s->i8259); pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1); @@ -1209,7 +1276,7 @@ static void mips_malta_machine_init(MachineClass *mc) { mc->desc = "MIPS Malta Core LV"; mc->init = mips_malta_init; - mc->max_cpus = 16; + mc->max_cpus = 32; mc->is_default = 1; } diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 639ef37..fdd5643 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -594,6 +594,7 @@ struct CPUMIPSState { const mips_def_t *cpu_model; void *irq[8]; + void **gic_irqs; QEMUTimer *timer; /* Internal timer */ }; -- 1.7.1