xref: /openbmc/qemu/hw/openrisc/openrisc_sim.c (revision b733701533232a2b6821470fe4edc1ab212c4532)
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