root / hw / openrisc_sim.c @ a8170e5e
History | View | Annotate | Download (4.4 kB)
1 |
/*
|
---|---|
2 |
* OpenRISC simulator for use as an IIS.
|
3 |
*
|
4 |
* Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
|
5 |
* Feng Gao <gf91597@gmail.com>
|
6 |
*
|
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 of the License, or (at your option) any later version.
|
11 |
*
|
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.
|
16 |
*
|
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/>.
|
19 |
*/
|
20 |
|
21 |
#include "hw.h" |
22 |
#include "boards.h" |
23 |
#include "elf.h" |
24 |
#include "serial.h" |
25 |
#include "net.h" |
26 |
#include "loader.h" |
27 |
#include "exec-memory.h" |
28 |
#include "sysemu.h" |
29 |
#include "sysbus.h" |
30 |
#include "qtest.h" |
31 |
|
32 |
#define KERNEL_LOAD_ADDR 0x100 |
33 |
|
34 |
static void main_cpu_reset(void *opaque) |
35 |
{ |
36 |
OpenRISCCPU *cpu = opaque; |
37 |
|
38 |
cpu_reset(CPU(cpu)); |
39 |
} |
40 |
|
41 |
static void openrisc_sim_net_init(MemoryRegion *address_space, |
42 |
hwaddr base, |
43 |
hwaddr descriptors, |
44 |
qemu_irq irq, NICInfo *nd) |
45 |
{ |
46 |
DeviceState *dev; |
47 |
SysBusDevice *s; |
48 |
|
49 |
dev = qdev_create(NULL, "open_eth"); |
50 |
qdev_set_nic_properties(dev, nd); |
51 |
qdev_init_nofail(dev); |
52 |
|
53 |
s = sysbus_from_qdev(dev); |
54 |
sysbus_connect_irq(s, 0, irq);
|
55 |
memory_region_add_subregion(address_space, base, |
56 |
sysbus_mmio_get_region(s, 0));
|
57 |
memory_region_add_subregion(address_space, descriptors, |
58 |
sysbus_mmio_get_region(s, 1));
|
59 |
} |
60 |
|
61 |
static void cpu_openrisc_load_kernel(ram_addr_t ram_size, |
62 |
const char *kernel_filename, |
63 |
OpenRISCCPU *cpu) |
64 |
{ |
65 |
long kernel_size;
|
66 |
uint64_t elf_entry; |
67 |
hwaddr entry; |
68 |
|
69 |
if (kernel_filename && !qtest_enabled()) {
|
70 |
kernel_size = load_elf(kernel_filename, NULL, NULL, |
71 |
&elf_entry, NULL, NULL, 1, ELF_MACHINE, 1); |
72 |
entry = elf_entry; |
73 |
if (kernel_size < 0) { |
74 |
kernel_size = load_uimage(kernel_filename, |
75 |
&entry, NULL, NULL); |
76 |
} |
77 |
if (kernel_size < 0) { |
78 |
kernel_size = load_image_targphys(kernel_filename, |
79 |
KERNEL_LOAD_ADDR, |
80 |
ram_size - KERNEL_LOAD_ADDR); |
81 |
entry = KERNEL_LOAD_ADDR; |
82 |
} |
83 |
|
84 |
if (kernel_size < 0) { |
85 |
qemu_log("QEMU: couldn't load the kernel '%s'\n",
|
86 |
kernel_filename); |
87 |
exit(1);
|
88 |
} |
89 |
} |
90 |
|
91 |
cpu->env.pc = entry; |
92 |
} |
93 |
|
94 |
static void openrisc_sim_init(QEMUMachineInitArgs *args) |
95 |
{ |
96 |
ram_addr_t ram_size = args->ram_size; |
97 |
const char *cpu_model = args->cpu_model; |
98 |
const char *kernel_filename = args->kernel_filename; |
99 |
OpenRISCCPU *cpu = NULL;
|
100 |
MemoryRegion *ram; |
101 |
int n;
|
102 |
|
103 |
if (!cpu_model) {
|
104 |
cpu_model = "or1200";
|
105 |
} |
106 |
|
107 |
for (n = 0; n < smp_cpus; n++) { |
108 |
cpu = cpu_openrisc_init(cpu_model); |
109 |
if (cpu == NULL) { |
110 |
qemu_log("Unable to find CPU defineition!\n");
|
111 |
exit(1);
|
112 |
} |
113 |
qemu_register_reset(main_cpu_reset, cpu); |
114 |
main_cpu_reset(cpu); |
115 |
} |
116 |
|
117 |
ram = g_malloc(sizeof(*ram));
|
118 |
memory_region_init_ram(ram, "openrisc.ram", ram_size);
|
119 |
vmstate_register_ram_global(ram); |
120 |
memory_region_add_subregion(get_system_memory(), 0, ram);
|
121 |
|
122 |
cpu_openrisc_pic_init(cpu); |
123 |
cpu_openrisc_clock_init(cpu); |
124 |
|
125 |
serial_mm_init(get_system_memory(), 0x90000000, 0, cpu->env.irq[2], |
126 |
115200, serial_hds[0], DEVICE_NATIVE_ENDIAN); |
127 |
|
128 |
if (nd_table[0].used) { |
129 |
openrisc_sim_net_init(get_system_memory(), 0x92000000,
|
130 |
0x92000400, cpu->env.irq[4], nd_table); |
131 |
} |
132 |
|
133 |
cpu_openrisc_load_kernel(ram_size, kernel_filename, cpu); |
134 |
} |
135 |
|
136 |
static QEMUMachine openrisc_sim_machine = {
|
137 |
.name = "or32-sim",
|
138 |
.desc = "or32 simulation",
|
139 |
.init = openrisc_sim_init, |
140 |
.max_cpus = 1,
|
141 |
.is_default = 1,
|
142 |
}; |
143 |
|
144 |
static void openrisc_sim_machine_init(void) |
145 |
{ |
146 |
qemu_register_machine(&openrisc_sim_machine); |
147 |
} |
148 |
|
149 |
machine_init(openrisc_sim_machine_init); |