diff options
Diffstat (limited to 'qemu/hw/mips/mips_malta.c')
-rw-r--r-- | qemu/hw/mips/mips_malta.c | 152 |
1 files changed, 92 insertions, 60 deletions
diff --git a/qemu/hw/mips/mips_malta.c b/qemu/hw/mips/mips_malta.c index 3082e7534..fa769e5c0 100644 --- a/qemu/hw/mips/mips_malta.c +++ b/qemu/hw/mips/mips_malta.c @@ -22,6 +22,9 @@ * THE SOFTWARE. */ +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "cpu.h" #include "hw/hw.h" #include "hw/i386/pc.h" #include "hw/char/serial.h" @@ -54,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 @@ -92,6 +96,7 @@ typedef struct { typedef struct { SysBusDevice parent_obj; + MIPSCPSState *cps; qemu_irq *i8259; } MaltaState; @@ -605,8 +610,8 @@ static void network_init(PCIBus *pci_bus) a3 - RAM size in bytes */ -static void write_bootloader (CPUMIPSState *env, uint8_t *base, - int64_t run_addr, int64_t kernel_entry) +static void write_bootloader(uint8_t *base, int64_t run_addr, + int64_t kernel_entry) { uint32_t *p; @@ -795,7 +800,7 @@ static int64_t load_kernel (void) if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL, (uint64_t *)&kernel_entry, NULL, (uint64_t *)&kernel_high, - big_endian, ELF_MACHINE, 1) < 0) { + big_endian, EM_MIPS, 1, 0) < 0) { fprintf(stderr, "qemu: could not load kernel '%s'\n", loaderparams.kernel_filename); exit(1); @@ -901,16 +906,77 @@ static void main_cpu_reset(void *opaque) if (kvm_enabled()) { /* Start running from the bootloader we wrote to end of RAM */ - env->active_tc.PC = 0x40000000 + loaderparams.ram_size; + env->active_tc.PC = 0x40000000 + loaderparams.ram_low_size; } } -static void cpu_request_exit(void *opaque, int irq, int level) +static void create_cpu_without_cps(const char *cpu_model, + qemu_irq *cbus_irq, qemu_irq *i8259_irq) { - CPUState *cpu = current_cpu; + CPUMIPSState *env; + MIPSCPU *cpu; + int i; - if (cpu && level) { - cpu_exit(cpu); + for (i = 0; i < smp_cpus; i++) { + cpu = cpu_mips_init(cpu_model); + if (cpu == NULL) { + fprintf(stderr, "Unable to find CPU definition\n"); + exit(1); + } + env = &cpu->env; + + /* Init internal devices */ + cpu_mips_irq_init_cpu(env); + cpu_mips_clock_init(env); + qemu_register_reset(main_cpu_reset, cpu); + } + + cpu = MIPS_CPU(first_cpu); + env = &cpu->env; + *i8259_irq = env->irq[2]; + *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); } } @@ -919,7 +985,6 @@ void mips_malta_init(MachineState *machine) { ram_addr_t ram_size = machine->ram_size; ram_addr_t ram_low_size; - const char *cpu_model = machine->cpu_model; const char *kernel_filename = machine->kernel_filename; const char *kernel_cmdline = machine->kernel_cmdline; const char *initrd_filename = machine->initrd_filename; @@ -936,10 +1001,8 @@ void mips_malta_init(MachineState *machine) int64_t kernel_entry, bootloader_run_addr; PCIBus *pci_bus; ISABus *isa_bus; - MIPSCPU *cpu; - CPUMIPSState *env; qemu_irq *isa_irq; - qemu_irq *cpu_exit_irq; + qemu_irq cbus_irq, i8259_irq; int piix4_devfn; I2CBus *smbus; int i; @@ -969,30 +1032,8 @@ void mips_malta_init(MachineState *machine) } } - /* init CPUs */ - 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); - if (cpu == NULL) { - fprintf(stderr, "Unable to find CPU definition\n"); - exit(1); - } - env = &cpu->env; - - /* Init internal devices */ - cpu_mips_irq_init_cpu(env); - cpu_mips_clock_init(env); - qemu_register_reset(main_cpu_reset, cpu); - } - cpu = MIPS_CPU(first_cpu); - env = &cpu->env; + /* create CPU */ + create_cpu(s, machine->cpu_model, &cbus_irq, &i8259_irq); /* allocate RAM */ if (ram_size > (2048u << 20)) { @@ -1033,7 +1074,7 @@ void mips_malta_init(MachineState *machine) #endif /* FPGA */ /* The CBUS UART is attached to the MIPS CPU INT2 pin, ie interrupt 4 */ - malta_fpga_init(system_memory, FPGA_ADDRESS, env->irq[4], serial_hds[2]); + malta_fpga_init(system_memory, FPGA_ADDRESS, cbus_irq, serial_hds[2]); /* Load firmware in flash / BIOS. */ dinfo = drive_get(IF_PFLASH, 0, fl_idx); @@ -1070,11 +1111,11 @@ void mips_malta_init(MachineState *machine) loaderparams.initrd_filename = initrd_filename; kernel_entry = load_kernel(); - write_bootloader(env, memory_region_get_ram_ptr(bios), + write_bootloader(memory_region_get_ram_ptr(bios), bootloader_run_addr, kernel_entry); if (kvm_enabled()) { /* Write the bootloader code @ the end of RAM, 1MB reserved */ - write_bootloader(env, memory_region_get_ram_ptr(ram_low_preio) + + write_bootloader(memory_region_get_ram_ptr(ram_low_preio) + ram_low_size, bootloader_run_addr, kernel_entry); } @@ -1130,7 +1171,7 @@ void mips_malta_init(MachineState *machine) * regions are not executable. */ memory_region_init_ram(bios_copy, NULL, "bios.1fc", BIOS_SIZE, - &error_abort); + &error_fatal); if (!rom_copy(memory_region_get_ram_ptr(bios_copy), FLASH_ADDRESS, BIOS_SIZE)) { memcpy(memory_region_get_ram_ptr(bios_copy), @@ -1142,10 +1183,6 @@ void mips_malta_init(MachineState *machine) /* Board ID = 0x420 (Malta Board with CoreLV) */ stl_p(memory_region_get_ram_ptr(bios_copy) + 0x10, 0x00000420); - /* Init internal devices */ - cpu_mips_irq_init_cpu(env); - cpu_mips_clock_init(env); - /* * We have a circular dependency problem: pci_bus depends on isa_irq, * isa_irq is provided by i8259, i8259 depends on ISA, ISA depends @@ -1165,7 +1202,7 @@ 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]); + s->i8259 = i8259_init(isa_bus, i8259_irq); isa_bus_irqs(isa_bus, s->i8259); pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1); @@ -1175,8 +1212,7 @@ void mips_malta_init(MachineState *machine) smbus_eeprom_init(smbus, 8, smbus_eeprom_buf, smbus_eeprom_size); g_free(smbus_eeprom_buf); pit = pit_init(isa_bus, 0x40, 0, NULL); - cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1); - DMA_init(0, cpu_exit_irq); + DMA_init(isa_bus, 0); /* Super I/O */ isa_create_simple(isa_bus, "i8042"); @@ -1216,23 +1252,19 @@ static const TypeInfo mips_malta_device = { .class_init = mips_malta_class_init, }; -static QEMUMachine mips_malta_machine = { - .name = "malta", - .desc = "MIPS Malta Core LV", - .init = mips_malta_init, - .max_cpus = 16, - .is_default = 1, -}; - -static void mips_malta_register_types(void) +static void mips_malta_machine_init(MachineClass *mc) { - type_register_static(&mips_malta_device); + mc->desc = "MIPS Malta Core LV"; + mc->init = mips_malta_init; + mc->max_cpus = 16; + mc->is_default = 1; } -static void mips_malta_machine_init(void) +DEFINE_MACHINE("malta", mips_malta_machine_init) + +static void mips_malta_register_types(void) { - qemu_register_machine(&mips_malta_machine); + type_register_static(&mips_malta_device); } type_init(mips_malta_register_types) -machine_init(mips_malta_machine_init); |