aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/openrisc/openrisc_sim.c88
1 files changed, 65 insertions, 23 deletions
diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c
index 86bf2849c4..58638c6ecd 100644
--- a/hw/openrisc/openrisc_sim.c
+++ b/hw/openrisc/openrisc_sim.c
@@ -35,36 +35,60 @@
#define KERNEL_LOAD_ADDR 0x100
+static struct openrisc_boot_info {
+ uint32_t bootstrap_pc;
+} boot_info;
+
static void main_cpu_reset(void *opaque)
{
OpenRISCCPU *cpu = opaque;
+ CPUState *cs = CPU(cpu);
cpu_reset(CPU(cpu));
+
+ cpu_set_pc(cs, boot_info.bootstrap_pc);
}
-static void openrisc_sim_net_init(MemoryRegion *address_space,
- hwaddr base,
- hwaddr descriptors,
- qemu_irq irq, NICInfo *nd)
+static void openrisc_sim_net_init(hwaddr base, hwaddr descriptors,
+ int num_cpus, qemu_irq **cpu_irqs,
+ int irq_pin, NICInfo *nd)
{
DeviceState *dev;
SysBusDevice *s;
+ int i;
dev = qdev_create(NULL, "open_eth");
qdev_set_nic_properties(dev, nd);
qdev_init_nofail(dev);
s = SYS_BUS_DEVICE(dev);
- sysbus_connect_irq(s, 0, irq);
- memory_region_add_subregion(address_space, base,
- sysbus_mmio_get_region(s, 0));
- memory_region_add_subregion(address_space, descriptors,
- sysbus_mmio_get_region(s, 1));
+ for (i = 0; i < num_cpus; i++) {
+ sysbus_connect_irq(s, 0, cpu_irqs[i][irq_pin]);
+ }
+ sysbus_mmio_map(s, 0, base);
+ sysbus_mmio_map(s, 1, descriptors);
+}
+
+static void openrisc_sim_ompic_init(hwaddr base, int num_cpus,
+ qemu_irq **cpu_irqs, int irq_pin)
+{
+ DeviceState *dev;
+ SysBusDevice *s;
+ int i;
+
+ dev = qdev_create(NULL, "or1k-ompic");
+ qdev_prop_set_uint32(dev, "num-cpus", num_cpus);
+ qdev_init_nofail(dev);
+
+ s = SYS_BUS_DEVICE(dev);
+ for (i = 0; i < num_cpus; i++) {
+ sysbus_connect_irq(s, i, cpu_irqs[i][irq_pin]);
+ }
+ sysbus_mmio_map(s, 0, base);
}
-static void cpu_openrisc_load_kernel(ram_addr_t ram_size,
- const char *kernel_filename,
- OpenRISCCPU *cpu)
+static void openrisc_load_kernel(ram_addr_t ram_size,
+ const char *kernel_filename)
{
long kernel_size;
uint64_t elf_entry;
@@ -83,6 +107,9 @@ static void cpu_openrisc_load_kernel(ram_addr_t ram_size,
kernel_size = load_image_targphys(kernel_filename,
KERNEL_LOAD_ADDR,
ram_size - KERNEL_LOAD_ADDR);
+ }
+
+ if (entry <= 0) {
entry = KERNEL_LOAD_ADDR;
}
@@ -91,7 +118,7 @@ static void cpu_openrisc_load_kernel(ram_addr_t ram_size,
kernel_filename);
exit(1);
}
- cpu->env.pc = entry;
+ boot_info.bootstrap_pc = entry;
}
}
@@ -102,6 +129,8 @@ static void openrisc_sim_init(MachineState *machine)
const char *kernel_filename = machine->kernel_filename;
OpenRISCCPU *cpu = NULL;
MemoryRegion *ram;
+ qemu_irq *cpu_irqs[2];
+ qemu_irq serial_irq;
int n;
if (!cpu_model) {
@@ -110,33 +139,46 @@ static void openrisc_sim_init(MachineState *machine)
for (n = 0; n < smp_cpus; n++) {
cpu = OPENRISC_CPU(cpu_generic_init(TYPE_OPENRISC_CPU, cpu_model));
+ if (cpu == NULL) {
+ fprintf(stderr, "Unable to find CPU definition!\n");
+ exit(1);
+ }
+ cpu_openrisc_pic_init(cpu);
+ cpu_irqs[n] = (qemu_irq *) cpu->env.irq;
+
+ cpu_openrisc_clock_init(cpu);
+
qemu_register_reset(main_cpu_reset, cpu);
- main_cpu_reset(cpu);
}
ram = g_malloc(sizeof(*ram));
memory_region_init_ram(ram, NULL, "openrisc.ram", ram_size, &error_fatal);
memory_region_add_subregion(get_system_memory(), 0, ram);
- cpu_openrisc_pic_init(cpu);
- cpu_openrisc_clock_init(cpu);
+ if (nd_table[0].used) {
+ openrisc_sim_net_init(0x92000000, 0x92000400, smp_cpus,
+ cpu_irqs, 4, nd_table);
+ }
- serial_mm_init(get_system_memory(), 0x90000000, 0, cpu->env.irq[2],
- 115200, serial_hds[0], DEVICE_NATIVE_ENDIAN);
+ if (smp_cpus > 1) {
+ openrisc_sim_ompic_init(0x98000000, smp_cpus, cpu_irqs, 1);
- if (nd_table[0].used) {
- openrisc_sim_net_init(get_system_memory(), 0x92000000,
- 0x92000400, cpu->env.irq[4], nd_table);
+ serial_irq = qemu_irq_split(cpu_irqs[0][2], cpu_irqs[1][2]);
+ } else {
+ serial_irq = cpu_irqs[0][2];
}
- cpu_openrisc_load_kernel(ram_size, kernel_filename, cpu);
+ serial_mm_init(get_system_memory(), 0x90000000, 0, serial_irq,
+ 115200, serial_hds[0], DEVICE_NATIVE_ENDIAN);
+
+ openrisc_load_kernel(ram_size, kernel_filename);
}
static void openrisc_sim_machine_init(MachineClass *mc)
{
mc->desc = "or1k simulation";
mc->init = openrisc_sim_init;
- mc->max_cpus = 1;
+ mc->max_cpus = 2;
mc->is_default = 1;
}