2 * OpenRISC simulator for use as an IIS.
4 * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
5 * Feng Gao <gf91597@gmail.com>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 #include "qemu/osdep.h"
22 #include "qemu/error-report.h"
23 #include "qapi/error.h"
26 #include "hw/boards.h"
28 #include "hw/char/serial.h"
30 #include "hw/loader.h"
31 #include "hw/qdev-properties.h"
32 #include "exec/address-spaces.h"
33 #include "sysemu/sysemu.h"
34 #include "hw/sysbus.h"
35 #include "sysemu/qtest.h"
36 #include "sysemu/reset.h"
37 #include "hw/core/split-irq.h"
39 #define KERNEL_LOAD_ADDR 0x100
41 static struct openrisc_boot_info
{
42 uint32_t bootstrap_pc
;
45 static void main_cpu_reset(void *opaque
)
47 OpenRISCCPU
*cpu
= opaque
;
48 CPUState
*cs
= CPU(cpu
);
52 cpu_set_pc(cs
, boot_info
.bootstrap_pc
);
55 static qemu_irq
get_cpu_irq(OpenRISCCPU
*cpus
[], int cpunum
, int irq_pin
)
57 return qdev_get_gpio_in_named(DEVICE(cpus
[cpunum
]), "IRQ", irq_pin
);
60 static void openrisc_sim_net_init(hwaddr base
, hwaddr descriptors
,
61 int num_cpus
, OpenRISCCPU
*cpus
[],
62 int irq_pin
, NICInfo
*nd
)
68 dev
= qdev_new("open_eth");
69 qdev_set_nic_properties(dev
, nd
);
71 s
= SYS_BUS_DEVICE(dev
);
72 sysbus_realize_and_unref(s
, &error_fatal
);
74 DeviceState
*splitter
= qdev_new(TYPE_SPLIT_IRQ
);
75 qdev_prop_set_uint32(splitter
, "num-lines", num_cpus
);
76 qdev_realize_and_unref(splitter
, NULL
, &error_fatal
);
77 for (i
= 0; i
< num_cpus
; i
++) {
78 qdev_connect_gpio_out(splitter
, i
, get_cpu_irq(cpus
, i
, irq_pin
));
80 sysbus_connect_irq(s
, 0, qdev_get_gpio_in(splitter
, 0));
82 sysbus_connect_irq(s
, 0, get_cpu_irq(cpus
, 0, irq_pin
));
84 sysbus_mmio_map(s
, 0, base
);
85 sysbus_mmio_map(s
, 1, descriptors
);
88 static void openrisc_sim_ompic_init(hwaddr base
, int num_cpus
,
89 OpenRISCCPU
*cpus
[], int irq_pin
)
95 dev
= qdev_new("or1k-ompic");
96 qdev_prop_set_uint32(dev
, "num-cpus", num_cpus
);
98 s
= SYS_BUS_DEVICE(dev
);
99 sysbus_realize_and_unref(s
, &error_fatal
);
100 for (i
= 0; i
< num_cpus
; i
++) {
101 sysbus_connect_irq(s
, i
, get_cpu_irq(cpus
, i
, irq_pin
));
103 sysbus_mmio_map(s
, 0, base
);
106 static void openrisc_load_kernel(ram_addr_t ram_size
,
107 const char *kernel_filename
)
113 if (kernel_filename
&& !qtest_enabled()) {
114 kernel_size
= load_elf(kernel_filename
, NULL
, NULL
, NULL
,
115 &elf_entry
, NULL
, NULL
, NULL
, 1, EM_OPENRISC
,
118 if (kernel_size
< 0) {
119 kernel_size
= load_uimage(kernel_filename
,
120 &entry
, NULL
, NULL
, NULL
, NULL
);
122 if (kernel_size
< 0) {
123 kernel_size
= load_image_targphys(kernel_filename
,
125 ram_size
- KERNEL_LOAD_ADDR
);
129 entry
= KERNEL_LOAD_ADDR
;
132 if (kernel_size
< 0) {
133 error_report("couldn't load the kernel '%s'", kernel_filename
);
136 boot_info
.bootstrap_pc
= entry
;
140 static void openrisc_sim_init(MachineState
*machine
)
142 ram_addr_t ram_size
= machine
->ram_size
;
143 const char *kernel_filename
= machine
->kernel_filename
;
144 OpenRISCCPU
*cpus
[2] = {};
148 unsigned int smp_cpus
= machine
->smp
.cpus
;
150 assert(smp_cpus
>= 1 && smp_cpus
<= 2);
151 for (n
= 0; n
< smp_cpus
; n
++) {
152 cpus
[n
] = OPENRISC_CPU(cpu_create(machine
->cpu_type
));
153 if (cpus
[n
] == NULL
) {
154 fprintf(stderr
, "Unable to find CPU definition!\n");
158 cpu_openrisc_clock_init(cpus
[n
]);
160 qemu_register_reset(main_cpu_reset
, cpus
[n
]);
163 ram
= g_malloc(sizeof(*ram
));
164 memory_region_init_ram(ram
, NULL
, "openrisc.ram", ram_size
, &error_fatal
);
165 memory_region_add_subregion(get_system_memory(), 0, ram
);
167 if (nd_table
[0].used
) {
168 openrisc_sim_net_init(0x92000000, 0x92000400, smp_cpus
,
173 openrisc_sim_ompic_init(0x98000000, smp_cpus
, cpus
, 1);
175 serial_irq
= qemu_irq_split(get_cpu_irq(cpus
, 0, 2),
176 get_cpu_irq(cpus
, 1, 2));
178 serial_irq
= get_cpu_irq(cpus
, 0, 2);
181 serial_mm_init(get_system_memory(), 0x90000000, 0, serial_irq
,
182 115200, serial_hd(0), DEVICE_NATIVE_ENDIAN
);
184 openrisc_load_kernel(ram_size
, kernel_filename
);
187 static void openrisc_sim_machine_init(MachineClass
*mc
)
189 mc
->desc
= "or1k simulation";
190 mc
->init
= openrisc_sim_init
;
192 mc
->is_default
= true;
193 mc
->default_cpu_type
= OPENRISC_CPU_TYPE_NAME("or1200");
196 DEFINE_MACHINE("or1k-sim", openrisc_sim_machine_init
)