Create new OpenRISC machine(asim) with default IDE support. It will incude more peripherals in order to run a fully fledged Linux computer.
Signed-off-by: Valentin Manea <valentin.ma...@gmail.com> --- default-configs/or32-softmmu.mak | 3 + hw/openrisc/Makefile.objs | 1 + hw/openrisc/openrisc_asim.c | 202 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 206 insertions(+) create mode 100644 hw/openrisc/openrisc_asim.c diff --git a/default-configs/or32-softmmu.mak b/default-configs/or32-softmmu.mak index cce4746..c3ff078 100644 --- a/default-configs/or32-softmmu.mak +++ b/default-configs/or32-softmmu.mak @@ -2,3 +2,6 @@ CONFIG_SERIAL=y CONFIG_OPENCORES_ETH=y +CONFIG_IDE_CORE=y +CONFIG_IDE_QDEV=y +CONFIG_IDE_MMIO=y diff --git a/hw/openrisc/Makefile.objs b/hw/openrisc/Makefile.objs index 61246b1..f266f5d 100644 --- a/hw/openrisc/Makefile.objs +++ b/hw/openrisc/Makefile.objs @@ -1,2 +1,3 @@ obj-y = pic_cpu.o cputimer.o obj-y += openrisc_sim.o +obj-y += openrisc_asim.o diff --git a/hw/openrisc/openrisc_asim.c b/hw/openrisc/openrisc_asim.c new file mode 100644 index 0000000..80aa5ed --- /dev/null +++ b/hw/openrisc/openrisc_asim.c @@ -0,0 +1,202 @@ +/* + * OpenRISC simulator with more peripherals + * + * Copyright (c) 2011-2014 Jia Liu <pro...@gmail.com> + * Feng Gao <gf91...@gmail.com> + * Valentin Manea <valentin.ma...@gmail.com> + * + * This OpenRISC machine supports more hardware - same configuration as the + * jor1k(http://s-macke.github.io/jor1k). Currently the default Linux branch + * does not have all the support for this machine so the jor1k Linux kernel is + * needed for more advanced usecases: X support, compiling etc. You can download + * a precompiled image here http://mrs.ro/dl/or1k/vmlinux or compile it using + * the instructions at https://github.com/s-macke/jor1k/wiki + * + * 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 "hw/hw.h" +#include "hw/boards.h" +#include "elf.h" +#include "hw/char/serial.h" +#include "net/net.h" +#include "hw/loader.h" +#include "hw/ide.h" +#include "exec/address-spaces.h" +#include "sysemu/sysemu.h" +#include "hw/sysbus.h" +#include "sysemu/blockdev.h" +#include "sysemu/qtest.h" + +#define KERNEL_LOAD_ADDR 0x100 + +enum { + OR_UART0, + OR_IDE, + OR_OPENETH +}; + +static hwaddr mem_map[] = { + [OR_UART0] = 0x90000000, + [OR_IDE] = 0x9e000000, + [OR_OPENETH] = 0x92000000, +}; + + +static void main_cpu_reset(void *opaque) +{ + OpenRISCCPU *cpu = opaque; + + cpu_reset(CPU(cpu)); +} + +static void openrisc_sim_ide_init(MemoryRegion *address_space, + hwaddr base, + hwaddr descriptors, + qemu_irq irq) +{ + DeviceState *dev; + SysBusDevice *busdev; + DriveInfo *dinfo; + + + dinfo = drive_get(IF_IDE, 0, 0); + if (!dinfo) { + return; + } + dev = qdev_create(NULL, "mmio-ide"); + busdev = SYS_BUS_DEVICE(dev); + sysbus_connect_irq(busdev, 0, irq); + qdev_prop_set_uint32(dev, "shift", 2); + qdev_init_nofail(dev); + memory_region_add_subregion(address_space, base, + sysbus_mmio_get_region(busdev, 0)); + memory_region_add_subregion(address_space, descriptors, + sysbus_mmio_get_region(busdev, 1)); + mmio_ide_init_drives(dev, dinfo, NULL); +} + +static void openrisc_sim_net_init(MemoryRegion *address_space, + hwaddr base, + hwaddr descriptors, + qemu_irq irq, NICInfo *nd) +{ + DeviceState *dev; + SysBusDevice *s; + + 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)); +} + +static void cpu_openrisc_load_kernel(ram_addr_t ram_size, + const char *kernel_filename, + OpenRISCCPU *cpu) +{ + long kernel_size; + uint64_t elf_entry; + hwaddr entry; + + if (kernel_filename && !qtest_enabled()) { + kernel_size = load_elf(kernel_filename, NULL, NULL, + &elf_entry, NULL, NULL, 1, ELF_MACHINE, 1); + entry = elf_entry; + if (kernel_size < 0) { + kernel_size = load_uimage(kernel_filename, + &entry, NULL, NULL); + } + if (kernel_size < 0) { + kernel_size = load_image_targphys(kernel_filename, + KERNEL_LOAD_ADDR, + ram_size - KERNEL_LOAD_ADDR); + entry = KERNEL_LOAD_ADDR; + } + + if (kernel_size < 0) { + fprintf(stderr, "QEMU: couldn't load the kernel '%s'\n", + kernel_filename); + exit(1); + } + cpu->env.pc = entry; + } +} + +static void openrisc_sim_init(MachineState *machine) +{ + ram_addr_t ram_size = machine->ram_size; + const char *cpu_model = machine->cpu_model; + const char *kernel_filename = machine->kernel_filename; + OpenRISCCPU *cpu = NULL; + MemoryRegion *ram; + int n; + + if (!cpu_model) { + cpu_model = "or1200"; + } + + for (n = 0; n < smp_cpus; n++) { + cpu = cpu_openrisc_init(cpu_model); + if (cpu == NULL) { + fprintf(stderr, "Unable to find CPU definition!\n"); + exit(1); + } + 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_abort); + vmstate_register_ram_global(ram); + memory_region_add_subregion(get_system_memory(), 0, ram); + + cpu_openrisc_pic_init(cpu); + cpu_openrisc_clock_init(cpu); + + serial_mm_init(get_system_memory(), mem_map[OR_UART0], 0, cpu->env.irq[2], + 115200, serial_hds[0], DEVICE_NATIVE_ENDIAN); + + if (nd_table[0].used) { + openrisc_sim_net_init(get_system_memory(), mem_map[OR_OPENETH], + mem_map[OR_OPENETH] + 0x400, cpu->env.irq[4], + nd_table); + } + + /* Platform ATA device */ + openrisc_sim_ide_init(get_system_memory(), mem_map[OR_IDE], + mem_map[OR_IDE] + 0x100, cpu->env.irq[15]); + + + cpu_openrisc_load_kernel(ram_size, kernel_filename, cpu); +} + +static QEMUMachine openrisc_sim_machine = { + .name = "asim", + .desc = "or32 simulation", + .init = openrisc_sim_init, + .max_cpus = 1, +}; + +static void openrisc_sim_machine_init(void) +{ + qemu_register_machine(&openrisc_sim_machine); +} + +machine_init(openrisc_sim_machine_init); -- 1.9.1