diff options
Diffstat (limited to 'qemu/hw/mips')
-rw-r--r-- | qemu/hw/mips/Makefile.objs | 1 | ||||
-rw-r--r-- | qemu/hw/mips/addr.c | 1 | ||||
-rw-r--r-- | qemu/hw/mips/cps.c | 180 | ||||
-rw-r--r-- | qemu/hw/mips/cputimer.c | 34 | ||||
-rw-r--r-- | qemu/hw/mips/gt64xxx_pci.c | 10 | ||||
-rw-r--r-- | qemu/hw/mips/mips_fulong2e.c | 32 | ||||
-rw-r--r-- | qemu/hw/mips/mips_int.c | 1 | ||||
-rw-r--r-- | qemu/hw/mips/mips_jazz.c | 66 | ||||
-rw-r--r-- | qemu/hw/mips/mips_malta.c | 152 | ||||
-rw-r--r-- | qemu/hw/mips/mips_mipssim.c | 21 | ||||
-rw-r--r-- | qemu/hw/mips/mips_r4k.c | 27 |
11 files changed, 368 insertions, 157 deletions
diff --git a/qemu/hw/mips/Makefile.objs b/qemu/hw/mips/Makefile.objs index 9633f3a57..9352a1c06 100644 --- a/qemu/hw/mips/Makefile.objs +++ b/qemu/hw/mips/Makefile.objs @@ -3,3 +3,4 @@ obj-y += addr.o cputimer.o mips_int.o obj-$(CONFIG_JAZZ) += mips_jazz.o obj-$(CONFIG_FULONG) += mips_fulong2e.o obj-y += gt64xxx_pci.o +obj-$(CONFIG_MIPS_CPS) += cps.o diff --git a/qemu/hw/mips/addr.c b/qemu/hw/mips/addr.c index ff3b95260..e4e86b4a7 100644 --- a/qemu/hw/mips/addr.c +++ b/qemu/hw/mips/addr.c @@ -20,6 +20,7 @@ * THE SOFTWARE. */ +#include "qemu/osdep.h" #include "hw/hw.h" #include "hw/mips/cpudevs.h" diff --git a/qemu/hw/mips/cps.c b/qemu/hw/mips/cps.c new file mode 100644 index 000000000..1bafbbb27 --- /dev/null +++ b/qemu/hw/mips/cps.c @@ -0,0 +1,180 @@ +/* + * Coherent Processing System emulation. + * + * Copyright (c) 2016 Imagination Technologies + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "hw/mips/cps.h" +#include "hw/mips/mips.h" +#include "hw/mips/cpudevs.h" +#include "sysemu/kvm.h" + +qemu_irq get_cps_irq(MIPSCPSState *s, int pin_number) +{ + MIPSCPU *cpu = MIPS_CPU(first_cpu); + CPUMIPSState *env = &cpu->env; + + assert(pin_number < s->num_irq); + + /* TODO: return GIC pins once implemented */ + return env->irq[pin_number]; +} + +static void mips_cps_init(Object *obj) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + MIPSCPSState *s = MIPS_CPS(obj); + + /* Cover entire address space as there do not seem to be any + * constraints for the base address of CPC and GIC. */ + memory_region_init(&s->container, obj, "mips-cps-container", UINT64_MAX); + sysbus_init_mmio(sbd, &s->container); +} + +static void main_cpu_reset(void *opaque) +{ + MIPSCPU *cpu = opaque; + CPUState *cs = CPU(cpu); + + cpu_reset(cs); + + /* All VPs are halted on reset. Leave powering up to CPC. */ + cs->halted = 1; +} + +static bool cpu_mips_itu_supported(CPUMIPSState *env) +{ + bool is_mt = (env->CP0_Config5 & (1 << CP0C5_VP)) || + (env->CP0_Config3 & (1 << CP0C3_MT)); + + return is_mt && !kvm_enabled(); +} + +static void mips_cps_realize(DeviceState *dev, Error **errp) +{ + MIPSCPSState *s = MIPS_CPS(dev); + CPUMIPSState *env; + MIPSCPU *cpu; + int i; + Error *err = NULL; + target_ulong gcr_base; + bool itu_present = false; + + for (i = 0; i < s->num_vp; i++) { + cpu = cpu_mips_init(s->cpu_model); + if (cpu == NULL) { + error_setg(errp, "%s: CPU initialization failed\n", __func__); + return; + } + env = &cpu->env; + + /* Init internal devices */ + cpu_mips_irq_init_cpu(env); + cpu_mips_clock_init(env); + if (cpu_mips_itu_supported(env)) { + itu_present = true; + /* Attach ITC Tag to the VP */ + env->itc_tag = mips_itu_get_tag_region(&s->itu); + } + qemu_register_reset(main_cpu_reset, cpu); + } + + cpu = MIPS_CPU(first_cpu); + env = &cpu->env; + + /* Inter-Thread Communication Unit */ + if (itu_present) { + object_initialize(&s->itu, sizeof(s->itu), TYPE_MIPS_ITU); + qdev_set_parent_bus(DEVICE(&s->itu), sysbus_get_default()); + + object_property_set_int(OBJECT(&s->itu), 16, "num-fifo", &err); + object_property_set_int(OBJECT(&s->itu), 16, "num-semaphores", &err); + object_property_set_bool(OBJECT(&s->itu), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + + memory_region_add_subregion(&s->container, 0, + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->itu), 0)); + } + + /* Cluster Power Controller */ + object_initialize(&s->cpc, sizeof(s->cpc), TYPE_MIPS_CPC); + qdev_set_parent_bus(DEVICE(&s->cpc), sysbus_get_default()); + + object_property_set_int(OBJECT(&s->cpc), s->num_vp, "num-vp", &err); + object_property_set_int(OBJECT(&s->cpc), 1, "vp-start-running", &err); + object_property_set_bool(OBJECT(&s->cpc), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + + memory_region_add_subregion(&s->container, 0, + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cpc), 0)); + + /* Global Configuration Registers */ + gcr_base = env->CP0_CMGCRBase << 4; + + object_initialize(&s->gcr, sizeof(s->gcr), TYPE_MIPS_GCR); + qdev_set_parent_bus(DEVICE(&s->gcr), sysbus_get_default()); + + object_property_set_int(OBJECT(&s->gcr), s->num_vp, "num-vp", &err); + object_property_set_int(OBJECT(&s->gcr), 0x800, "gcr-rev", &err); + object_property_set_int(OBJECT(&s->gcr), gcr_base, "gcr-base", &err); + object_property_set_link(OBJECT(&s->gcr), OBJECT(&s->cpc.mr), "cpc", &err); + object_property_set_bool(OBJECT(&s->gcr), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + + memory_region_add_subregion(&s->container, gcr_base, + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gcr), 0)); +} + +static Property mips_cps_properties[] = { + DEFINE_PROP_UINT32("num-vp", MIPSCPSState, num_vp, 1), + DEFINE_PROP_UINT32("num-irq", MIPSCPSState, num_irq, 8), + DEFINE_PROP_STRING("cpu-model", MIPSCPSState, cpu_model), + DEFINE_PROP_END_OF_LIST() +}; + +static void mips_cps_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = mips_cps_realize; + dc->props = mips_cps_properties; +} + +static const TypeInfo mips_cps_info = { + .name = TYPE_MIPS_CPS, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(MIPSCPSState), + .instance_init = mips_cps_init, + .class_init = mips_cps_class_init, +}; + +static void mips_cps_register_types(void) +{ + type_register_static(&mips_cps_info); +} + +type_init(mips_cps_register_types) diff --git a/qemu/hw/mips/cputimer.c b/qemu/hw/mips/cputimer.c index 577c9aeab..efb227d06 100644 --- a/qemu/hw/mips/cputimer.c +++ b/qemu/hw/mips/cputimer.c @@ -20,23 +20,32 @@ * THE SOFTWARE. */ +#include "qemu/osdep.h" #include "hw/hw.h" #include "hw/mips/cpudevs.h" #include "qemu/timer.h" #include "sysemu/kvm.h" -#define TIMER_FREQ 100 * 1000 * 1000 +#define TIMER_PERIOD 10 /* 10 ns period for 100 Mhz frequency */ /* XXX: do not use a global */ uint32_t cpu_mips_get_random (CPUMIPSState *env) { - static uint32_t lfsr = 1; + static uint32_t seed = 1; static uint32_t prev_idx = 0; uint32_t idx; + uint32_t nb_rand_tlb = env->tlb->nb_tlb - env->CP0_Wired; + + if (nb_rand_tlb == 1) { + return env->tlb->nb_tlb - 1; + } + /* Don't return same value twice, so get another value */ do { - lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xd0000001u); - idx = lfsr % (env->tlb->nb_tlb - env->CP0_Wired) + env->CP0_Wired; + /* Use a simple algorithm of Linear Congruential Generator + * from ISO/IEC 9899 standard. */ + seed = 1103515245 * seed + 12345; + idx = (seed >> 16) % nb_rand_tlb + env->CP0_Wired; } while (idx == prev_idx); prev_idx = idx; return idx; @@ -49,9 +58,8 @@ static void cpu_mips_timer_update(CPUMIPSState *env) uint32_t wait; now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - wait = env->CP0_Compare - env->CP0_Count - - (uint32_t)muldiv64(now, TIMER_FREQ, get_ticks_per_sec()); - next = now + muldiv64(wait, get_ticks_per_sec(), TIMER_FREQ); + wait = env->CP0_Compare - env->CP0_Count - (uint32_t)(now / TIMER_PERIOD); + next = now + (uint64_t)wait * TIMER_PERIOD; timer_mod(env->timer, next); } @@ -79,8 +87,7 @@ uint32_t cpu_mips_get_count (CPUMIPSState *env) cpu_mips_timer_expire(env); } - return env->CP0_Count + - (uint32_t)muldiv64(now, TIMER_FREQ, get_ticks_per_sec()); + return env->CP0_Count + (uint32_t)(now / TIMER_PERIOD); } } @@ -95,9 +102,8 @@ void cpu_mips_store_count (CPUMIPSState *env, uint32_t count) env->CP0_Count = count; else { /* Store new count register */ - env->CP0_Count = - count - (uint32_t)muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), - TIMER_FREQ, get_ticks_per_sec()); + env->CP0_Count = count - + (uint32_t)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / TIMER_PERIOD); /* Update timer timer */ cpu_mips_timer_update(env); } @@ -121,8 +127,8 @@ void cpu_mips_start_count(CPUMIPSState *env) void cpu_mips_stop_count(CPUMIPSState *env) { /* Store the current value */ - env->CP0_Count += (uint32_t)muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), - TIMER_FREQ, get_ticks_per_sec()); + env->CP0_Count += (uint32_t)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / + TIMER_PERIOD); } static void mips_timer_cb (void *opaque) diff --git a/qemu/hw/mips/gt64xxx_pci.c b/qemu/hw/mips/gt64xxx_pci.c index 10fcca33f..3f4523df2 100644 --- a/qemu/hw/mips/gt64xxx_pci.c +++ b/qemu/hw/mips/gt64xxx_pci.c @@ -22,6 +22,7 @@ * THE SOFTWARE. */ +#include "qemu/osdep.h" #include "hw/hw.h" #include "hw/mips/mips.h" #include "hw/pci/pci.h" @@ -275,7 +276,8 @@ static void check_reserved_space (hwaddr *start, static void gt64120_isd_mapping(GT64120State *s) { - hwaddr start = s->regs[GT_ISD] << 21; + /* Bits 14:0 of ISD map to bits 35:21 of the start address. */ + hwaddr start = ((hwaddr)s->regs[GT_ISD] << 21) & 0xFFFE00000ull; hwaddr length = 0x1000; if (s->ISD_length) { @@ -1192,7 +1194,7 @@ static int gt64120_init(SysBusDevice *dev) return 0; } -static int gt64120_pci_init(PCIDevice *d) +static void gt64120_pci_realize(PCIDevice *d, Error **errp) { /* FIXME: Malta specific hw assumptions ahead */ pci_set_word(d->config + PCI_COMMAND, 0); @@ -1206,8 +1208,6 @@ static int gt64120_pci_init(PCIDevice *d) pci_set_long(d->config + PCI_BASE_ADDRESS_4, 0x14000000); pci_set_long(d->config + PCI_BASE_ADDRESS_5, 0x14000001); pci_set_byte(d->config + 0x3d, 0x01); - - return 0; } static void gt64120_pci_class_init(ObjectClass *klass, void *data) @@ -1215,7 +1215,7 @@ static void gt64120_pci_class_init(ObjectClass *klass, void *data) PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); - k->init = gt64120_pci_init; + k->realize = gt64120_pci_realize; k->vendor_id = PCI_VENDOR_ID_MARVELL; k->device_id = PCI_DEVICE_ID_MARVELL_GT6412X; k->revision = 0x10; diff --git a/qemu/hw/mips/mips_fulong2e.c b/qemu/hw/mips/mips_fulong2e.c index dea941ad8..bdb716e72 100644 --- a/qemu/hw/mips/mips_fulong2e.c +++ b/qemu/hw/mips/mips_fulong2e.c @@ -18,6 +18,8 @@ * http://www.loongsondeveloper.com/doc/Loongson2EUserGuide.pdf */ +#include "qemu/osdep.h" +#include "qapi/error.h" #include "hw/hw.h" #include "hw/i386/pc.h" #include "hw/char/serial.h" @@ -116,7 +118,7 @@ static int64_t load_kernel (CPUMIPSState *env) if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL, (uint64_t *)&kernel_entry, (uint64_t *)&kernel_low, - (uint64_t *)&kernel_high, 0, ELF_MACHINE, 1) < 0) { + (uint64_t *)&kernel_high, 0, EM_MIPS, 1, 0) < 0) { fprintf(stderr, "qemu: could not load kernel '%s'\n", loaderparams.kernel_filename); exit(1); @@ -251,15 +253,6 @@ static void network_init (PCIBus *pci_bus) } } -static void cpu_request_exit(void *opaque, int irq, int level) -{ - CPUState *cpu = current_cpu; - - if (cpu && level) { - cpu_exit(cpu); - } -} - static void mips_fulong2e_init(MachineState *machine) { ram_addr_t ram_size = machine->ram_size; @@ -274,7 +267,6 @@ static void mips_fulong2e_init(MachineState *machine) long bios_size; int64_t kernel_entry; qemu_irq *i8259; - qemu_irq *cpu_exit_irq; PCIBus *pci_bus; ISABus *isa_bus; I2CBus *smbus; @@ -304,7 +296,7 @@ static void mips_fulong2e_init(MachineState *machine) /* allocate RAM */ memory_region_allocate_system_memory(ram, NULL, "fulong2e.ram", ram_size); memory_region_init_ram(bios, NULL, "fulong2e.bios", bios_size, - &error_abort); + &error_fatal); vmstate_register_ram_global(bios); memory_region_set_readonly(bios, true); @@ -375,8 +367,7 @@ static void mips_fulong2e_init(MachineState *machine) /* init other devices */ 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"); @@ -392,15 +383,10 @@ static void mips_fulong2e_init(MachineState *machine) network_init(pci_bus); } -static QEMUMachine mips_fulong2e_machine = { - .name = "fulong2e", - .desc = "Fulong 2e mini pc", - .init = mips_fulong2e_init, -}; - -static void mips_fulong2e_machine_init(void) +static void mips_fulong2e_machine_init(MachineClass *mc) { - qemu_register_machine(&mips_fulong2e_machine); + mc->desc = "Fulong 2e mini pc"; + mc->init = mips_fulong2e_init; } -machine_init(mips_fulong2e_machine_init); +DEFINE_MACHINE("fulong2e", mips_fulong2e_machine_init) diff --git a/qemu/hw/mips/mips_int.c b/qemu/hw/mips/mips_int.c index d740046ba..59081f9d1 100644 --- a/qemu/hw/mips/mips_int.c +++ b/qemu/hw/mips/mips_int.c @@ -20,6 +20,7 @@ * THE SOFTWARE. */ +#include "qemu/osdep.h" #include "hw/hw.h" #include "hw/mips/cpudevs.h" #include "cpu.h" diff --git a/qemu/hw/mips/mips_jazz.c b/qemu/hw/mips/mips_jazz.c index 9d60633ef..ac7c64125 100644 --- a/qemu/hw/mips/mips_jazz.c +++ b/qemu/hw/mips/mips_jazz.c @@ -22,6 +22,7 @@ * THE SOFTWARE. */ +#include "qemu/osdep.h" #include "hw/hw.h" #include "hw/mips/mips.h" #include "hw/mips/cpudevs.h" @@ -44,6 +45,7 @@ #include "exec/address-spaces.h" #include "sysemu/qtest.h" #include "qemu/error-report.h" +#include "qemu/help_option.h" enum jazz_model_e { @@ -104,15 +106,6 @@ static const MemoryRegionOps dma_dummy_ops = { #define MAGNUM_BIOS_SIZE_MAX 0x7e000 #define MAGNUM_BIOS_SIZE (BIOS_SIZE < MAGNUM_BIOS_SIZE_MAX ? BIOS_SIZE : MAGNUM_BIOS_SIZE_MAX) -static void cpu_request_exit(void *opaque, int irq, int level) -{ - CPUState *cpu = current_cpu; - - if (cpu && level) { - cpu_exit(cpu); - } -} - static CPUUnassignedAccess real_do_unassigned_access; static void mips_jazz_do_unassigned_access(CPUState *cpu, hwaddr addr, bool is_write, bool is_exec, @@ -150,7 +143,6 @@ static void mips_jazz_init(MachineState *machine, ISADevice *pit; DriveInfo *fds[MAX_FD]; qemu_irq esp_reset, dma_enable; - qemu_irq *cpu_exit_irq; MemoryRegion *ram = g_new(MemoryRegion, 1); MemoryRegion *bios = g_new(MemoryRegion, 1); MemoryRegion *bios2 = g_new(MemoryRegion, 1); @@ -184,7 +176,7 @@ static void mips_jazz_init(MachineState *machine, memory_region_add_subregion(address_space, 0, ram); memory_region_init_ram(bios, NULL, "mips_jazz.bios", MAGNUM_BIOS_SIZE, - &error_abort); + &error_fatal); vmstate_register_ram_global(bios); memory_region_set_readonly(bios, true); memory_region_init_alias(bios2, NULL, "mips_jazz.bios", bios, @@ -229,13 +221,12 @@ static void mips_jazz_init(MachineState *machine, memory_region_init(isa_mem, NULL, "isa-mem", 0x01000000); memory_region_add_subregion(address_space, 0x90000000, isa_io); memory_region_add_subregion(address_space, 0x91000000, isa_mem); - isa_bus = isa_bus_new(NULL, isa_mem, isa_io); + isa_bus = isa_bus_new(NULL, isa_mem, isa_io, &error_abort); /* ISA devices */ i8259 = i8259_init(isa_bus, env->irq[4]); isa_bus_irqs(isa_bus, i8259); - cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1); - DMA_init(0, cpu_exit_irq); + DMA_init(isa_bus, 0); pit = pit_init(isa_bus, 0x40, 0, NULL); pcspk_init(isa_bus, pit); @@ -252,7 +243,7 @@ static void mips_jazz_init(MachineState *machine, /* Simple ROM, so user doesn't have to provide one */ MemoryRegion *rom_mr = g_new(MemoryRegion, 1); memory_region_init_ram(rom_mr, NULL, "g364fb.rom", 0x80000, - &error_abort); + &error_fatal); vmstate_register_ram_global(rom_mr); memory_region_set_readonly(rom_mr, true); uint8_t *rom = memory_region_get_ram_ptr(rom_mr); @@ -307,7 +298,8 @@ static void mips_jazz_init(MachineState *machine, for (n = 0; n < MAX_FD; n++) { fds[n] = drive_get(IF_FLOPPY, 0, n); } - fdctrl_init_sysbus(qdev_get_gpio_in(rc4030, 1), 0, 0x80003000, fds); + /* FIXME: we should enable DMA with a custom IsaDma device */ + fdctrl_init_sysbus(qdev_get_gpio_in(rc4030, 1), -1, 0x80003000, fds); /* Real time clock */ rtc_init(isa_bus, 1980, NULL); @@ -360,24 +352,40 @@ void mips_pica61_init(MachineState *machine) mips_jazz_init(machine, JAZZ_PICA61); } -static QEMUMachine mips_magnum_machine = { - .name = "magnum", - .desc = "MIPS Magnum", - .init = mips_magnum_init, - .block_default_type = IF_SCSI, +static void mips_magnum_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->desc = "MIPS Magnum"; + mc->init = mips_magnum_init; + mc->block_default_type = IF_SCSI; +} + +static const TypeInfo mips_magnum_type = { + .name = MACHINE_TYPE_NAME("magnum"), + .parent = TYPE_MACHINE, + .class_init = mips_magnum_class_init, }; -static QEMUMachine mips_pica61_machine = { - .name = "pica61", - .desc = "Acer Pica 61", - .init = mips_pica61_init, - .block_default_type = IF_SCSI, +static void mips_pica61_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->desc = "Acer Pica 61"; + mc->init = mips_pica61_init; + mc->block_default_type = IF_SCSI; +} + +static const TypeInfo mips_pica61_type = { + .name = MACHINE_TYPE_NAME("pica61"), + .parent = TYPE_MACHINE, + .class_init = mips_pica61_class_init, }; static void mips_jazz_machine_init(void) { - qemu_register_machine(&mips_magnum_machine); - qemu_register_machine(&mips_pica61_machine); + type_register_static(&mips_magnum_type); + type_register_static(&mips_pica61_type); } -machine_init(mips_jazz_machine_init); +type_init(mips_jazz_machine_init) 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); diff --git a/qemu/hw/mips/mips_mipssim.c b/qemu/hw/mips/mips_mipssim.c index 61f74a631..a2c2a1646 100644 --- a/qemu/hw/mips/mips_mipssim.c +++ b/qemu/hw/mips/mips_mipssim.c @@ -24,6 +24,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu-common.h" +#include "cpu.h" #include "hw/hw.h" #include "hw/mips/mips.h" #include "hw/mips/cpudevs.h" @@ -69,7 +73,7 @@ static int64_t load_kernel(void) kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL, (uint64_t *)&entry, NULL, (uint64_t *)&kernel_high, big_endian, - ELF_MACHINE, 1); + EM_MIPS, 1, 0); if (kernel_size >= 0) { if ((entry & ~0x7fffffffULL) == 0x80000000) entry = (int32_t)entry; @@ -174,7 +178,7 @@ mips_mipssim_init(MachineState *machine) memory_region_allocate_system_memory(ram, NULL, "mips_mipssim.ram", ram_size); memory_region_init_ram(bios, NULL, "mips_mipssim.bios", BIOS_SIZE, - &error_abort); + &error_fatal); vmstate_register_ram_global(bios); memory_region_set_readonly(bios, true); @@ -231,15 +235,10 @@ mips_mipssim_init(MachineState *machine) mipsnet_init(0x4200, env->irq[2], &nd_table[0]); } -static QEMUMachine mips_mipssim_machine = { - .name = "mipssim", - .desc = "MIPS MIPSsim platform", - .init = mips_mipssim_init, -}; - -static void mips_mipssim_machine_init(void) +static void mips_mipssim_machine_init(MachineClass *mc) { - qemu_register_machine(&mips_mipssim_machine); + mc->desc = "MIPS MIPSsim platform"; + mc->init = mips_mipssim_init; } -machine_init(mips_mipssim_machine_init); +DEFINE_MACHINE("mipssim", mips_mipssim_machine_init) diff --git a/qemu/hw/mips/mips_r4k.c b/qemu/hw/mips/mips_r4k.c index f4dcacd86..21aca981c 100644 --- a/qemu/hw/mips/mips_r4k.c +++ b/qemu/hw/mips/mips_r4k.c @@ -7,6 +7,10 @@ * All peripherial devices are attached to this "bus" with * the standard PC ISA addresses. */ +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu-common.h" +#include "cpu.h" #include "hw/hw.h" #include "hw/mips/mips.h" #include "hw/mips/cpudevs.h" @@ -87,7 +91,7 @@ static int64_t load_kernel(void) kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL, (uint64_t *)&entry, NULL, (uint64_t *)&kernel_high, big_endian, - ELF_MACHINE, 1); + EM_MIPS, 1, 0); if (kernel_size >= 0) { if ((entry & ~0x7fffffffULL) == 0x80000000) entry = (int32_t)entry; @@ -233,7 +237,7 @@ void mips_r4k_init(MachineState *machine) if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) { bios = g_new(MemoryRegion, 1); memory_region_init_ram(bios, NULL, "mips_r4k.bios", BIOS_SIZE, - &error_abort); + &error_fatal); vmstate_register_ram_global(bios); memory_region_set_readonly(bios, true); memory_region_add_subregion(get_system_memory(), 0x1fc00000, bios); @@ -252,9 +256,7 @@ void mips_r4k_init(MachineState *machine) fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n", bios_name); } - if (filename) { - g_free(filename); - } + g_free(filename); if (kernel_filename) { loaderparams.ram_size = ram_size; @@ -274,7 +276,7 @@ void mips_r4k_init(MachineState *machine) memory_region_init(isa_mem, NULL, "isa-mem", 0x01000000); memory_region_add_subregion(get_system_memory(), 0x14000000, isa_io); memory_region_add_subregion(get_system_memory(), 0x10000000, isa_mem); - isa_bus = isa_bus_new(NULL, isa_mem, get_system_io()); + isa_bus = isa_bus_new(NULL, isa_mem, get_system_io(), &error_abort); /* The PIC is attached to the MIPS CPU INT0 pin */ i8259 = i8259_init(isa_bus, env->irq[2]); @@ -300,15 +302,10 @@ void mips_r4k_init(MachineState *machine) isa_create_simple(isa_bus, "i8042"); } -static QEMUMachine mips_machine = { - .name = "mips", - .desc = "mips r4k platform", - .init = mips_r4k_init, -}; - -static void mips_machine_init(void) +static void mips_machine_init(MachineClass *mc) { - qemu_register_machine(&mips_machine); + mc->desc = "mips r4k platform"; + mc->init = mips_r4k_init; } -machine_init(mips_machine_init); +DEFINE_MACHINE("mips", mips_machine_init) |