summaryrefslogtreecommitdiffstats
path: root/qemu/hw/mips
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/hw/mips')
-rw-r--r--qemu/hw/mips/Makefile.objs1
-rw-r--r--qemu/hw/mips/addr.c1
-rw-r--r--qemu/hw/mips/cps.c180
-rw-r--r--qemu/hw/mips/cputimer.c34
-rw-r--r--qemu/hw/mips/gt64xxx_pci.c10
-rw-r--r--qemu/hw/mips/mips_fulong2e.c32
-rw-r--r--qemu/hw/mips/mips_int.c1
-rw-r--r--qemu/hw/mips/mips_jazz.c66
-rw-r--r--qemu/hw/mips/mips_malta.c152
-rw-r--r--qemu/hw/mips/mips_mipssim.c21
-rw-r--r--qemu/hw/mips/mips_r4k.c27
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)