153018216SPaolo Bonzini /*
253018216SPaolo Bonzini * OpenRISC simulator for use as an IIS.
353018216SPaolo Bonzini *
453018216SPaolo Bonzini * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
553018216SPaolo Bonzini * Feng Gao <gf91597@gmail.com>
653018216SPaolo Bonzini *
753018216SPaolo Bonzini * This library is free software; you can redistribute it and/or
853018216SPaolo Bonzini * modify it under the terms of the GNU Lesser General Public
953018216SPaolo Bonzini * License as published by the Free Software Foundation; either
10198a2d21SThomas Huth * version 2.1 of the License, or (at your option) any later version.
1153018216SPaolo Bonzini *
1253018216SPaolo Bonzini * This library is distributed in the hope that it will be useful,
1353018216SPaolo Bonzini * but WITHOUT ANY WARRANTY; without even the implied warranty of
1453018216SPaolo Bonzini * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1553018216SPaolo Bonzini * Lesser General Public License for more details.
1653018216SPaolo Bonzini *
1753018216SPaolo Bonzini * You should have received a copy of the GNU Lesser General Public
1853018216SPaolo Bonzini * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1953018216SPaolo Bonzini */
2053018216SPaolo Bonzini
21ed2decc6SPeter Maydell #include "qemu/osdep.h"
22fe2d93c8SAlistair Francis #include "qemu/error-report.h"
23da34e65cSMarkus Armbruster #include "qapi/error.h"
244771d756SPaolo Bonzini #include "cpu.h"
2564552b6bSMarkus Armbruster #include "hw/irq.h"
2653018216SPaolo Bonzini #include "hw/boards.h"
277e6b5497SBernhard Beschow #include "hw/char/serial-mm.h"
2853018216SPaolo Bonzini #include "net/net.h"
297025114bSStafford Horne #include "hw/openrisc/boot.h"
30a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
315852c1f8SStafford Horne #include "exec/address-spaces.h"
325852c1f8SStafford Horne #include "sysemu/device_tree.h"
3353018216SPaolo Bonzini #include "sysemu/sysemu.h"
3453018216SPaolo Bonzini #include "hw/sysbus.h"
3553018216SPaolo Bonzini #include "sysemu/qtest.h"
3671e8a915SMarkus Armbruster #include "sysemu/reset.h"
371eeffbebSPeter Maydell #include "hw/core/split-irq.h"
3853018216SPaolo Bonzini
395852c1f8SStafford Horne #include <libfdt.h>
405852c1f8SStafford Horne
4153018216SPaolo Bonzini #define KERNEL_LOAD_ADDR 0x100
4253018216SPaolo Bonzini
43f42e09e6SStafford Horne #define OR1KSIM_CPUS_MAX 4
445852c1f8SStafford Horne #define OR1KSIM_CLK_MHZ 20000000
45f42e09e6SStafford Horne
46f85ad231SStafford Horne #define TYPE_OR1KSIM_MACHINE MACHINE_TYPE_NAME("or1k-sim")
47f85ad231SStafford Horne #define OR1KSIM_MACHINE(obj) \
48f85ad231SStafford Horne OBJECT_CHECK(Or1ksimState, (obj), TYPE_OR1KSIM_MACHINE)
49f85ad231SStafford Horne
50f85ad231SStafford Horne typedef struct Or1ksimState {
51f85ad231SStafford Horne /*< private >*/
52f85ad231SStafford Horne MachineState parent_obj;
53f85ad231SStafford Horne
54f85ad231SStafford Horne /*< public >*/
555852c1f8SStafford Horne void *fdt;
565852c1f8SStafford Horne int fdt_size;
57f85ad231SStafford Horne
58f85ad231SStafford Horne } Or1ksimState;
59f85ad231SStafford Horne
6076f36985SStafford Horne enum {
6176f36985SStafford Horne OR1KSIM_DRAM,
6276f36985SStafford Horne OR1KSIM_UART,
6376f36985SStafford Horne OR1KSIM_ETHOC,
6476f36985SStafford Horne OR1KSIM_OMPIC,
6576f36985SStafford Horne };
6676f36985SStafford Horne
6776f36985SStafford Horne enum {
6876f36985SStafford Horne OR1KSIM_OMPIC_IRQ = 1,
6976f36985SStafford Horne OR1KSIM_UART_IRQ = 2,
7076f36985SStafford Horne OR1KSIM_ETHOC_IRQ = 4,
7176f36985SStafford Horne };
7276f36985SStafford Horne
73777784bdSJason A. Donenfeld enum {
74777784bdSJason A. Donenfeld OR1KSIM_UART_COUNT = 4
75777784bdSJason A. Donenfeld };
76777784bdSJason A. Donenfeld
7776f36985SStafford Horne static const struct MemmapEntry {
7876f36985SStafford Horne hwaddr base;
7976f36985SStafford Horne hwaddr size;
8076f36985SStafford Horne } or1ksim_memmap[] = {
8176f36985SStafford Horne [OR1KSIM_DRAM] = { 0x00000000, 0 },
8276f36985SStafford Horne [OR1KSIM_UART] = { 0x90000000, 0x100 },
8376f36985SStafford Horne [OR1KSIM_ETHOC] = { 0x92000000, 0x800 },
84a92162f4SJason A. Donenfeld [OR1KSIM_OMPIC] = { 0x98000000, OR1KSIM_CPUS_MAX * 8 },
8576f36985SStafford Horne };
8676f36985SStafford Horne
8713f1c773SStafford Horne static struct openrisc_boot_info {
8813f1c773SStafford Horne uint32_t bootstrap_pc;
895852c1f8SStafford Horne uint32_t fdt_addr;
9013f1c773SStafford Horne } boot_info;
9113f1c773SStafford Horne
main_cpu_reset(void * opaque)9253018216SPaolo Bonzini static void main_cpu_reset(void *opaque)
9353018216SPaolo Bonzini {
9453018216SPaolo Bonzini OpenRISCCPU *cpu = opaque;
9513f1c773SStafford Horne CPUState *cs = CPU(cpu);
9653018216SPaolo Bonzini
9753018216SPaolo Bonzini cpu_reset(CPU(cpu));
9813f1c773SStafford Horne
9913f1c773SStafford Horne cpu_set_pc(cs, boot_info.bootstrap_pc);
1005852c1f8SStafford Horne cpu_set_gpr(&cpu->env, 3, boot_info.fdt_addr);
10153018216SPaolo Bonzini }
10253018216SPaolo Bonzini
get_cpu_irq(OpenRISCCPU * cpus[],int cpunum,int irq_pin)103eaca43a0SPeter Maydell static qemu_irq get_cpu_irq(OpenRISCCPU *cpus[], int cpunum, int irq_pin)
104eaca43a0SPeter Maydell {
10571b3254dSPeter Maydell return qdev_get_gpio_in_named(DEVICE(cpus[cpunum]), "IRQ", irq_pin);
106eaca43a0SPeter Maydell }
107eaca43a0SPeter Maydell
openrisc_create_fdt(Or1ksimState * state,const struct MemmapEntry * memmap,int num_cpus,uint64_t mem_size,const char * cmdline)1085852c1f8SStafford Horne static void openrisc_create_fdt(Or1ksimState *state,
1095852c1f8SStafford Horne const struct MemmapEntry *memmap,
1105852c1f8SStafford Horne int num_cpus, uint64_t mem_size,
1115852c1f8SStafford Horne const char *cmdline)
1125852c1f8SStafford Horne {
1135852c1f8SStafford Horne void *fdt;
1145852c1f8SStafford Horne int cpu;
1155852c1f8SStafford Horne char *nodename;
1165852c1f8SStafford Horne int pic_ph;
1175852c1f8SStafford Horne
1185852c1f8SStafford Horne fdt = state->fdt = create_device_tree(&state->fdt_size);
1195852c1f8SStafford Horne if (!fdt) {
1205852c1f8SStafford Horne error_report("create_device_tree() failed");
1215852c1f8SStafford Horne exit(1);
1225852c1f8SStafford Horne }
1235852c1f8SStafford Horne
1245852c1f8SStafford Horne qemu_fdt_setprop_string(fdt, "/", "compatible", "opencores,or1ksim");
1255852c1f8SStafford Horne qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x1);
1265852c1f8SStafford Horne qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x1);
1275852c1f8SStafford Horne
1285852c1f8SStafford Horne nodename = g_strdup_printf("/memory@%" HWADDR_PRIx,
1295852c1f8SStafford Horne memmap[OR1KSIM_DRAM].base);
1305852c1f8SStafford Horne qemu_fdt_add_subnode(fdt, nodename);
1315852c1f8SStafford Horne qemu_fdt_setprop_cells(fdt, nodename, "reg",
1325852c1f8SStafford Horne memmap[OR1KSIM_DRAM].base, mem_size);
1335852c1f8SStafford Horne qemu_fdt_setprop_string(fdt, nodename, "device_type", "memory");
1345852c1f8SStafford Horne g_free(nodename);
1355852c1f8SStafford Horne
1365852c1f8SStafford Horne qemu_fdt_add_subnode(fdt, "/cpus");
1375852c1f8SStafford Horne qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0);
1385852c1f8SStafford Horne qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1);
1395852c1f8SStafford Horne
1405852c1f8SStafford Horne for (cpu = 0; cpu < num_cpus; cpu++) {
1415852c1f8SStafford Horne nodename = g_strdup_printf("/cpus/cpu@%d", cpu);
1425852c1f8SStafford Horne qemu_fdt_add_subnode(fdt, nodename);
1435852c1f8SStafford Horne qemu_fdt_setprop_string(fdt, nodename, "compatible",
1445852c1f8SStafford Horne "opencores,or1200-rtlsvn481");
1455852c1f8SStafford Horne qemu_fdt_setprop_cell(fdt, nodename, "reg", cpu);
1465852c1f8SStafford Horne qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency",
1475852c1f8SStafford Horne OR1KSIM_CLK_MHZ);
1485852c1f8SStafford Horne g_free(nodename);
1495852c1f8SStafford Horne }
1505852c1f8SStafford Horne
1515852c1f8SStafford Horne nodename = (char *)"/pic";
1525852c1f8SStafford Horne qemu_fdt_add_subnode(fdt, nodename);
1535852c1f8SStafford Horne pic_ph = qemu_fdt_alloc_phandle(fdt);
1545852c1f8SStafford Horne qemu_fdt_setprop_string(fdt, nodename, "compatible",
1555852c1f8SStafford Horne "opencores,or1k-pic-level");
1565852c1f8SStafford Horne qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells", 1);
1575852c1f8SStafford Horne qemu_fdt_setprop(fdt, nodename, "interrupt-controller", NULL, 0);
1585852c1f8SStafford Horne qemu_fdt_setprop_cell(fdt, nodename, "phandle", pic_ph);
1595852c1f8SStafford Horne
1605852c1f8SStafford Horne qemu_fdt_setprop_cell(fdt, "/", "interrupt-parent", pic_ph);
1615852c1f8SStafford Horne
1625852c1f8SStafford Horne qemu_fdt_add_subnode(fdt, "/chosen");
1635852c1f8SStafford Horne if (cmdline) {
1645852c1f8SStafford Horne qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline);
1655852c1f8SStafford Horne }
1665852c1f8SStafford Horne
1675852c1f8SStafford Horne /* Create aliases node for use by devices. */
1685852c1f8SStafford Horne qemu_fdt_add_subnode(fdt, "/aliases");
1695852c1f8SStafford Horne }
1705852c1f8SStafford Horne
openrisc_sim_net_init(Or1ksimState * state,hwaddr base,hwaddr size,int num_cpus,OpenRISCCPU * cpus[],int irq_pin)1715852c1f8SStafford Horne static void openrisc_sim_net_init(Or1ksimState *state, hwaddr base, hwaddr size,
172eaca43a0SPeter Maydell int num_cpus, OpenRISCCPU *cpus[],
1735fcc5154SDavid Woodhouse int irq_pin)
17453018216SPaolo Bonzini {
1755852c1f8SStafford Horne void *fdt = state->fdt;
17653018216SPaolo Bonzini DeviceState *dev;
17753018216SPaolo Bonzini SysBusDevice *s;
1785852c1f8SStafford Horne char *nodename;
17913f1c773SStafford Horne int i;
18053018216SPaolo Bonzini
1815fcc5154SDavid Woodhouse dev = qemu_create_nic_device("open_eth", true, NULL);
1825fcc5154SDavid Woodhouse if (!dev) {
1835fcc5154SDavid Woodhouse return;
1845fcc5154SDavid Woodhouse }
18553018216SPaolo Bonzini
18653018216SPaolo Bonzini s = SYS_BUS_DEVICE(dev);
1873c6ef471SMarkus Armbruster sysbus_realize_and_unref(s, &error_fatal);
1881eeffbebSPeter Maydell if (num_cpus > 1) {
1891eeffbebSPeter Maydell DeviceState *splitter = qdev_new(TYPE_SPLIT_IRQ);
1901eeffbebSPeter Maydell qdev_prop_set_uint32(splitter, "num-lines", num_cpus);
1911eeffbebSPeter Maydell qdev_realize_and_unref(splitter, NULL, &error_fatal);
19213f1c773SStafford Horne for (i = 0; i < num_cpus; i++) {
193eaca43a0SPeter Maydell qdev_connect_gpio_out(splitter, i, get_cpu_irq(cpus, i, irq_pin));
1941eeffbebSPeter Maydell }
1951eeffbebSPeter Maydell sysbus_connect_irq(s, 0, qdev_get_gpio_in(splitter, 0));
1961eeffbebSPeter Maydell } else {
197eaca43a0SPeter Maydell sysbus_connect_irq(s, 0, get_cpu_irq(cpus, 0, irq_pin));
19813f1c773SStafford Horne }
19913f1c773SStafford Horne sysbus_mmio_map(s, 0, base);
2005852c1f8SStafford Horne sysbus_mmio_map(s, 1, base + 0x400);
2015852c1f8SStafford Horne
2025852c1f8SStafford Horne /* Init device tree node for ethoc. */
2035852c1f8SStafford Horne nodename = g_strdup_printf("/ethoc@%" HWADDR_PRIx, base);
2045852c1f8SStafford Horne qemu_fdt_add_subnode(fdt, nodename);
2055852c1f8SStafford Horne qemu_fdt_setprop_string(fdt, nodename, "compatible", "opencores,ethoc");
2065852c1f8SStafford Horne qemu_fdt_setprop_cells(fdt, nodename, "reg", base, size);
2075852c1f8SStafford Horne qemu_fdt_setprop_cell(fdt, nodename, "interrupts", irq_pin);
2085852c1f8SStafford Horne qemu_fdt_setprop(fdt, nodename, "big-endian", NULL, 0);
2095852c1f8SStafford Horne
2105852c1f8SStafford Horne qemu_fdt_setprop_string(fdt, "/aliases", "enet0", nodename);
2115852c1f8SStafford Horne g_free(nodename);
21253018216SPaolo Bonzini }
21353018216SPaolo Bonzini
openrisc_sim_ompic_init(Or1ksimState * state,hwaddr base,hwaddr size,int num_cpus,OpenRISCCPU * cpus[],int irq_pin)2145852c1f8SStafford Horne static void openrisc_sim_ompic_init(Or1ksimState *state, hwaddr base,
2155852c1f8SStafford Horne hwaddr size, int num_cpus,
216eaca43a0SPeter Maydell OpenRISCCPU *cpus[], int irq_pin)
21713f1c773SStafford Horne {
2185852c1f8SStafford Horne void *fdt = state->fdt;
21913f1c773SStafford Horne DeviceState *dev;
22013f1c773SStafford Horne SysBusDevice *s;
2215852c1f8SStafford Horne char *nodename;
22213f1c773SStafford Horne int i;
22313f1c773SStafford Horne
2243e80f690SMarkus Armbruster dev = qdev_new("or1k-ompic");
22513f1c773SStafford Horne qdev_prop_set_uint32(dev, "num-cpus", num_cpus);
22613f1c773SStafford Horne
22713f1c773SStafford Horne s = SYS_BUS_DEVICE(dev);
2283c6ef471SMarkus Armbruster sysbus_realize_and_unref(s, &error_fatal);
22913f1c773SStafford Horne for (i = 0; i < num_cpus; i++) {
230eaca43a0SPeter Maydell sysbus_connect_irq(s, i, get_cpu_irq(cpus, i, irq_pin));
23113f1c773SStafford Horne }
23213f1c773SStafford Horne sysbus_mmio_map(s, 0, base);
2335852c1f8SStafford Horne
2345852c1f8SStafford Horne /* Add device tree node for ompic. */
2355852c1f8SStafford Horne nodename = g_strdup_printf("/ompic@%" HWADDR_PRIx, base);
2365852c1f8SStafford Horne qemu_fdt_add_subnode(fdt, nodename);
2375852c1f8SStafford Horne qemu_fdt_setprop_string(fdt, nodename, "compatible", "openrisc,ompic");
2385852c1f8SStafford Horne qemu_fdt_setprop_cells(fdt, nodename, "reg", base, size);
2395852c1f8SStafford Horne qemu_fdt_setprop(fdt, nodename, "interrupt-controller", NULL, 0);
2405852c1f8SStafford Horne qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells", 0);
2415852c1f8SStafford Horne qemu_fdt_setprop_cell(fdt, nodename, "interrupts", irq_pin);
2425852c1f8SStafford Horne g_free(nodename);
24313f1c773SStafford Horne }
24413f1c773SStafford Horne
openrisc_sim_serial_init(Or1ksimState * state,hwaddr base,hwaddr size,int num_cpus,OpenRISCCPU * cpus[],int irq_pin,int uart_idx)2455852c1f8SStafford Horne static void openrisc_sim_serial_init(Or1ksimState *state, hwaddr base,
2465852c1f8SStafford Horne hwaddr size, int num_cpus,
247777784bdSJason A. Donenfeld OpenRISCCPU *cpus[], int irq_pin,
248777784bdSJason A. Donenfeld int uart_idx)
24922991cfbSStafford Horne {
2505852c1f8SStafford Horne void *fdt = state->fdt;
2515852c1f8SStafford Horne char *nodename;
25222991cfbSStafford Horne qemu_irq serial_irq;
253*26dcf2beSAhmad Fatoum char alias[sizeof("serial0")];
25422991cfbSStafford Horne int i;
25522991cfbSStafford Horne
25622991cfbSStafford Horne if (num_cpus > 1) {
25722991cfbSStafford Horne DeviceState *splitter = qdev_new(TYPE_SPLIT_IRQ);
25822991cfbSStafford Horne qdev_prop_set_uint32(splitter, "num-lines", num_cpus);
25922991cfbSStafford Horne qdev_realize_and_unref(splitter, NULL, &error_fatal);
26022991cfbSStafford Horne for (i = 0; i < num_cpus; i++) {
26122991cfbSStafford Horne qdev_connect_gpio_out(splitter, i, get_cpu_irq(cpus, i, irq_pin));
26222991cfbSStafford Horne }
26322991cfbSStafford Horne serial_irq = qdev_get_gpio_in(splitter, 0);
26422991cfbSStafford Horne } else {
26522991cfbSStafford Horne serial_irq = get_cpu_irq(cpus, 0, irq_pin);
26622991cfbSStafford Horne }
26722991cfbSStafford Horne serial_mm_init(get_system_memory(), base, 0, serial_irq, 115200,
268*26dcf2beSAhmad Fatoum serial_hd(uart_idx),
269777784bdSJason A. Donenfeld DEVICE_NATIVE_ENDIAN);
2705852c1f8SStafford Horne
2715852c1f8SStafford Horne /* Add device tree node for serial. */
2725852c1f8SStafford Horne nodename = g_strdup_printf("/serial@%" HWADDR_PRIx, base);
2735852c1f8SStafford Horne qemu_fdt_add_subnode(fdt, nodename);
2745852c1f8SStafford Horne qemu_fdt_setprop_string(fdt, nodename, "compatible", "ns16550a");
2755852c1f8SStafford Horne qemu_fdt_setprop_cells(fdt, nodename, "reg", base, size);
2765852c1f8SStafford Horne qemu_fdt_setprop_cell(fdt, nodename, "interrupts", irq_pin);
2775852c1f8SStafford Horne qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency", OR1KSIM_CLK_MHZ);
2785852c1f8SStafford Horne qemu_fdt_setprop(fdt, nodename, "big-endian", NULL, 0);
2795852c1f8SStafford Horne
280*26dcf2beSAhmad Fatoum if (uart_idx == 0) {
2815852c1f8SStafford Horne /* The /chosen node is created during fdt creation. */
2825852c1f8SStafford Horne qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", nodename);
283*26dcf2beSAhmad Fatoum }
284*26dcf2beSAhmad Fatoum snprintf(alias, sizeof(alias), "serial%d", uart_idx);
285777784bdSJason A. Donenfeld qemu_fdt_setprop_string(fdt, "/aliases", alias, nodename);
286*26dcf2beSAhmad Fatoum
2875852c1f8SStafford Horne g_free(nodename);
28822991cfbSStafford Horne }
28922991cfbSStafford Horne
openrisc_sim_init(MachineState * machine)2903ef96221SMarcel Apfelbaum static void openrisc_sim_init(MachineState *machine)
29153018216SPaolo Bonzini {
2923ef96221SMarcel Apfelbaum ram_addr_t ram_size = machine->ram_size;
2933ef96221SMarcel Apfelbaum const char *kernel_filename = machine->kernel_filename;
294f42e09e6SStafford Horne OpenRISCCPU *cpus[OR1KSIM_CPUS_MAX] = {};
2955852c1f8SStafford Horne Or1ksimState *state = OR1KSIM_MACHINE(machine);
29653018216SPaolo Bonzini MemoryRegion *ram;
2975852c1f8SStafford Horne hwaddr load_addr;
29853018216SPaolo Bonzini int n;
29933decbd2SLike Xu unsigned int smp_cpus = machine->smp.cpus;
30053018216SPaolo Bonzini
301f42e09e6SStafford Horne assert(smp_cpus >= 1 && smp_cpus <= OR1KSIM_CPUS_MAX);
30253018216SPaolo Bonzini for (n = 0; n < smp_cpus; n++) {
303eaca43a0SPeter Maydell cpus[n] = OPENRISC_CPU(cpu_create(machine->cpu_type));
304eaca43a0SPeter Maydell if (cpus[n] == NULL) {
30513f1c773SStafford Horne fprintf(stderr, "Unable to find CPU definition!\n");
30613f1c773SStafford Horne exit(1);
30713f1c773SStafford Horne }
30813f1c773SStafford Horne
309eaca43a0SPeter Maydell cpu_openrisc_clock_init(cpus[n]);
31013f1c773SStafford Horne
311eaca43a0SPeter Maydell qemu_register_reset(main_cpu_reset, cpus[n]);
31253018216SPaolo Bonzini }
31353018216SPaolo Bonzini
31453018216SPaolo Bonzini ram = g_malloc(sizeof(*ram));
31598a99ce0SPeter Maydell memory_region_init_ram(ram, NULL, "openrisc.ram", ram_size, &error_fatal);
31653018216SPaolo Bonzini memory_region_add_subregion(get_system_memory(), 0, ram);
31753018216SPaolo Bonzini
3185852c1f8SStafford Horne openrisc_create_fdt(state, or1ksim_memmap, smp_cpus, machine->ram_size,
3195852c1f8SStafford Horne machine->kernel_cmdline);
3205852c1f8SStafford Horne
3215852c1f8SStafford Horne openrisc_sim_net_init(state, or1ksim_memmap[OR1KSIM_ETHOC].base,
3225852c1f8SStafford Horne or1ksim_memmap[OR1KSIM_ETHOC].size,
32376f36985SStafford Horne smp_cpus, cpus,
3245fcc5154SDavid Woodhouse OR1KSIM_ETHOC_IRQ);
32553018216SPaolo Bonzini
32613f1c773SStafford Horne if (smp_cpus > 1) {
3275852c1f8SStafford Horne openrisc_sim_ompic_init(state, or1ksim_memmap[OR1KSIM_OMPIC].base,
328a92162f4SJason A. Donenfeld or1ksim_memmap[OR1KSIM_OMPIC].size,
3295852c1f8SStafford Horne smp_cpus, cpus, OR1KSIM_OMPIC_IRQ);
33013f1c773SStafford Horne }
33113f1c773SStafford Horne
332*26dcf2beSAhmad Fatoum /*
333*26dcf2beSAhmad Fatoum * We create the UART nodes starting with the highest address and
334*26dcf2beSAhmad Fatoum * working downwards, because in QEMU the DTB nodes end up in the
335*26dcf2beSAhmad Fatoum * DTB in reverse order of creation. Correctly-written guest software
336*26dcf2beSAhmad Fatoum * will not care about the node order (it will look at stdout-path
337*26dcf2beSAhmad Fatoum * or the alias nodes), but for the benefit of guest software which
338*26dcf2beSAhmad Fatoum * just looks for the first UART node in the DTB, make sure the
339*26dcf2beSAhmad Fatoum * lowest-address UART (which is QEMU's first serial port) appears
340*26dcf2beSAhmad Fatoum * first in the DTB.
341*26dcf2beSAhmad Fatoum */
342*26dcf2beSAhmad Fatoum for (n = OR1KSIM_UART_COUNT - 1; n >= 0; n--) {
343777784bdSJason A. Donenfeld openrisc_sim_serial_init(state, or1ksim_memmap[OR1KSIM_UART].base +
344777784bdSJason A. Donenfeld or1ksim_memmap[OR1KSIM_UART].size * n,
345777784bdSJason A. Donenfeld or1ksim_memmap[OR1KSIM_UART].size,
346777784bdSJason A. Donenfeld smp_cpus, cpus, OR1KSIM_UART_IRQ, n);
347*26dcf2beSAhmad Fatoum }
34813f1c773SStafford Horne
3497025114bSStafford Horne load_addr = openrisc_load_kernel(ram_size, kernel_filename,
3507025114bSStafford Horne &boot_info.bootstrap_pc);
3515852c1f8SStafford Horne if (load_addr > 0) {
3529576abf2SStafford Horne if (machine->initrd_filename) {
3537025114bSStafford Horne load_addr = openrisc_load_initrd(state->fdt,
3547025114bSStafford Horne machine->initrd_filename,
3559576abf2SStafford Horne load_addr, machine->ram_size);
3569576abf2SStafford Horne }
3577025114bSStafford Horne boot_info.fdt_addr = openrisc_load_fdt(state->fdt, load_addr,
3585852c1f8SStafford Horne machine->ram_size);
3595852c1f8SStafford Horne }
36053018216SPaolo Bonzini }
36153018216SPaolo Bonzini
openrisc_sim_machine_init(ObjectClass * oc,void * data)362f85ad231SStafford Horne static void openrisc_sim_machine_init(ObjectClass *oc, void *data)
36353018216SPaolo Bonzini {
364f85ad231SStafford Horne MachineClass *mc = MACHINE_CLASS(oc);
365f85ad231SStafford Horne
3664a09d0bbSRichard Henderson mc->desc = "or1k simulation";
367e264d29dSEduardo Habkost mc->init = openrisc_sim_init;
368f42e09e6SStafford Horne mc->max_cpus = OR1KSIM_CPUS_MAX;
369ea0ac7f6SPhilippe Mathieu-Daudé mc->is_default = true;
3701498e970SIgor Mammedov mc->default_cpu_type = OPENRISC_CPU_TYPE_NAME("or1200");
37153018216SPaolo Bonzini }
37253018216SPaolo Bonzini
373f85ad231SStafford Horne static const TypeInfo or1ksim_machine_typeinfo = {
374f85ad231SStafford Horne .name = TYPE_OR1KSIM_MACHINE,
375f85ad231SStafford Horne .parent = TYPE_MACHINE,
376f85ad231SStafford Horne .class_init = openrisc_sim_machine_init,
377f85ad231SStafford Horne .instance_size = sizeof(Or1ksimState),
378f85ad231SStafford Horne };
379f85ad231SStafford Horne
or1ksim_machine_init_register_types(void)380f85ad231SStafford Horne static void or1ksim_machine_init_register_types(void)
381f85ad231SStafford Horne {
382f85ad231SStafford Horne type_register_static(&or1ksim_machine_typeinfo);
383f85ad231SStafford Horne }
384f85ad231SStafford Horne
385f85ad231SStafford Horne type_init(or1ksim_machine_init_register_types)
386