root / hw / openrisc_sim.c @ 3e3648b2
History | View | Annotate | Download (4.4 kB)
1 | ce6e1e9e | Jia Liu | /*
|
---|---|---|---|
2 | ce6e1e9e | Jia Liu | * OpenRISC simulator for use as an IIS.
|
3 | ce6e1e9e | Jia Liu | *
|
4 | ce6e1e9e | Jia Liu | * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
|
5 | ce6e1e9e | Jia Liu | * Feng Gao <gf91597@gmail.com>
|
6 | ce6e1e9e | Jia Liu | *
|
7 | ce6e1e9e | Jia Liu | * This library is free software; you can redistribute it and/or
|
8 | ce6e1e9e | Jia Liu | * modify it under the terms of the GNU Lesser General Public
|
9 | ce6e1e9e | Jia Liu | * License as published by the Free Software Foundation; either
|
10 | ce6e1e9e | Jia Liu | * version 2 of the License, or (at your option) any later version.
|
11 | ce6e1e9e | Jia Liu | *
|
12 | ce6e1e9e | Jia Liu | * This library is distributed in the hope that it will be useful,
|
13 | ce6e1e9e | Jia Liu | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14 | ce6e1e9e | Jia Liu | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15 | ce6e1e9e | Jia Liu | * Lesser General Public License for more details.
|
16 | ce6e1e9e | Jia Liu | *
|
17 | ce6e1e9e | Jia Liu | * You should have received a copy of the GNU Lesser General Public
|
18 | ce6e1e9e | Jia Liu | * License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
19 | ce6e1e9e | Jia Liu | */
|
20 | ce6e1e9e | Jia Liu | |
21 | ce6e1e9e | Jia Liu | #include "hw.h" |
22 | ce6e1e9e | Jia Liu | #include "boards.h" |
23 | ce6e1e9e | Jia Liu | #include "elf.h" |
24 | 488cb996 | Gerd Hoffmann | #include "serial.h" |
25 | 1422e32d | Paolo Bonzini | #include "net/net.h" |
26 | ce6e1e9e | Jia Liu | #include "loader.h" |
27 | 022c62cb | Paolo Bonzini | #include "exec/address-spaces.h" |
28 | 9c17d615 | Paolo Bonzini | #include "sysemu/sysemu.h" |
29 | ce6e1e9e | Jia Liu | #include "sysbus.h" |
30 | 9c17d615 | Paolo Bonzini | #include "sysemu/qtest.h" |
31 | ce6e1e9e | Jia Liu | |
32 | ce6e1e9e | Jia Liu | #define KERNEL_LOAD_ADDR 0x100 |
33 | ce6e1e9e | Jia Liu | |
34 | ce6e1e9e | Jia Liu | static void main_cpu_reset(void *opaque) |
35 | ce6e1e9e | Jia Liu | { |
36 | ce6e1e9e | Jia Liu | OpenRISCCPU *cpu = opaque; |
37 | ce6e1e9e | Jia Liu | |
38 | ce6e1e9e | Jia Liu | cpu_reset(CPU(cpu)); |
39 | ce6e1e9e | Jia Liu | } |
40 | ce6e1e9e | Jia Liu | |
41 | ce6e1e9e | Jia Liu | static void openrisc_sim_net_init(MemoryRegion *address_space, |
42 | a8170e5e | Avi Kivity | hwaddr base, |
43 | a8170e5e | Avi Kivity | hwaddr descriptors, |
44 | ce6e1e9e | Jia Liu | qemu_irq irq, NICInfo *nd) |
45 | ce6e1e9e | Jia Liu | { |
46 | ce6e1e9e | Jia Liu | DeviceState *dev; |
47 | ce6e1e9e | Jia Liu | SysBusDevice *s; |
48 | ce6e1e9e | Jia Liu | |
49 | ce6e1e9e | Jia Liu | dev = qdev_create(NULL, "open_eth"); |
50 | ce6e1e9e | Jia Liu | qdev_set_nic_properties(dev, nd); |
51 | ce6e1e9e | Jia Liu | qdev_init_nofail(dev); |
52 | ce6e1e9e | Jia Liu | |
53 | 1356b98d | Andreas Färber | s = SYS_BUS_DEVICE(dev); |
54 | ce6e1e9e | Jia Liu | sysbus_connect_irq(s, 0, irq);
|
55 | ce6e1e9e | Jia Liu | memory_region_add_subregion(address_space, base, |
56 | ce6e1e9e | Jia Liu | sysbus_mmio_get_region(s, 0));
|
57 | ce6e1e9e | Jia Liu | memory_region_add_subregion(address_space, descriptors, |
58 | ce6e1e9e | Jia Liu | sysbus_mmio_get_region(s, 1));
|
59 | ce6e1e9e | Jia Liu | } |
60 | ce6e1e9e | Jia Liu | |
61 | ce6e1e9e | Jia Liu | static void cpu_openrisc_load_kernel(ram_addr_t ram_size, |
62 | ce6e1e9e | Jia Liu | const char *kernel_filename, |
63 | ce6e1e9e | Jia Liu | OpenRISCCPU *cpu) |
64 | ce6e1e9e | Jia Liu | { |
65 | ce6e1e9e | Jia Liu | long kernel_size;
|
66 | ce6e1e9e | Jia Liu | uint64_t elf_entry; |
67 | a8170e5e | Avi Kivity | hwaddr entry; |
68 | ce6e1e9e | Jia Liu | |
69 | ce6e1e9e | Jia Liu | if (kernel_filename && !qtest_enabled()) {
|
70 | ce6e1e9e | Jia Liu | kernel_size = load_elf(kernel_filename, NULL, NULL, |
71 | ce6e1e9e | Jia Liu | &elf_entry, NULL, NULL, 1, ELF_MACHINE, 1); |
72 | ce6e1e9e | Jia Liu | entry = elf_entry; |
73 | ce6e1e9e | Jia Liu | if (kernel_size < 0) { |
74 | ce6e1e9e | Jia Liu | kernel_size = load_uimage(kernel_filename, |
75 | ce6e1e9e | Jia Liu | &entry, NULL, NULL); |
76 | ce6e1e9e | Jia Liu | } |
77 | ce6e1e9e | Jia Liu | if (kernel_size < 0) { |
78 | ce6e1e9e | Jia Liu | kernel_size = load_image_targphys(kernel_filename, |
79 | ce6e1e9e | Jia Liu | KERNEL_LOAD_ADDR, |
80 | ce6e1e9e | Jia Liu | ram_size - KERNEL_LOAD_ADDR); |
81 | ce6e1e9e | Jia Liu | entry = KERNEL_LOAD_ADDR; |
82 | ce6e1e9e | Jia Liu | } |
83 | ce6e1e9e | Jia Liu | |
84 | ce6e1e9e | Jia Liu | if (kernel_size < 0) { |
85 | ce6e1e9e | Jia Liu | qemu_log("QEMU: couldn't load the kernel '%s'\n",
|
86 | ce6e1e9e | Jia Liu | kernel_filename); |
87 | ce6e1e9e | Jia Liu | exit(1);
|
88 | ce6e1e9e | Jia Liu | } |
89 | ce6e1e9e | Jia Liu | } |
90 | ce6e1e9e | Jia Liu | |
91 | ce6e1e9e | Jia Liu | cpu->env.pc = entry; |
92 | ce6e1e9e | Jia Liu | } |
93 | ce6e1e9e | Jia Liu | |
94 | 5f072e1f | Eduardo Habkost | static void openrisc_sim_init(QEMUMachineInitArgs *args) |
95 | ce6e1e9e | Jia Liu | { |
96 | 5f072e1f | Eduardo Habkost | ram_addr_t ram_size = args->ram_size; |
97 | 5f072e1f | Eduardo Habkost | const char *cpu_model = args->cpu_model; |
98 | 5f072e1f | Eduardo Habkost | const char *kernel_filename = args->kernel_filename; |
99 | ce6e1e9e | Jia Liu | OpenRISCCPU *cpu = NULL;
|
100 | ce6e1e9e | Jia Liu | MemoryRegion *ram; |
101 | ce6e1e9e | Jia Liu | int n;
|
102 | ce6e1e9e | Jia Liu | |
103 | ce6e1e9e | Jia Liu | if (!cpu_model) {
|
104 | ce6e1e9e | Jia Liu | cpu_model = "or1200";
|
105 | ce6e1e9e | Jia Liu | } |
106 | ce6e1e9e | Jia Liu | |
107 | ce6e1e9e | Jia Liu | for (n = 0; n < smp_cpus; n++) { |
108 | ce6e1e9e | Jia Liu | cpu = cpu_openrisc_init(cpu_model); |
109 | ce6e1e9e | Jia Liu | if (cpu == NULL) { |
110 | d0f54533 | Stefan Weil | qemu_log("Unable to find CPU definition!\n");
|
111 | ce6e1e9e | Jia Liu | exit(1);
|
112 | ce6e1e9e | Jia Liu | } |
113 | ce6e1e9e | Jia Liu | qemu_register_reset(main_cpu_reset, cpu); |
114 | ce6e1e9e | Jia Liu | main_cpu_reset(cpu); |
115 | ce6e1e9e | Jia Liu | } |
116 | ce6e1e9e | Jia Liu | |
117 | ce6e1e9e | Jia Liu | ram = g_malloc(sizeof(*ram));
|
118 | ce6e1e9e | Jia Liu | memory_region_init_ram(ram, "openrisc.ram", ram_size);
|
119 | ce6e1e9e | Jia Liu | vmstate_register_ram_global(ram); |
120 | ce6e1e9e | Jia Liu | memory_region_add_subregion(get_system_memory(), 0, ram);
|
121 | ce6e1e9e | Jia Liu | |
122 | ce6e1e9e | Jia Liu | cpu_openrisc_pic_init(cpu); |
123 | ce6e1e9e | Jia Liu | cpu_openrisc_clock_init(cpu); |
124 | ce6e1e9e | Jia Liu | |
125 | ce6e1e9e | Jia Liu | serial_mm_init(get_system_memory(), 0x90000000, 0, cpu->env.irq[2], |
126 | ce6e1e9e | Jia Liu | 115200, serial_hds[0], DEVICE_NATIVE_ENDIAN); |
127 | ce6e1e9e | Jia Liu | |
128 | a005d073 | Stefan Hajnoczi | if (nd_table[0].used) { |
129 | ce6e1e9e | Jia Liu | openrisc_sim_net_init(get_system_memory(), 0x92000000,
|
130 | ce6e1e9e | Jia Liu | 0x92000400, cpu->env.irq[4], nd_table); |
131 | ce6e1e9e | Jia Liu | } |
132 | ce6e1e9e | Jia Liu | |
133 | ce6e1e9e | Jia Liu | cpu_openrisc_load_kernel(ram_size, kernel_filename, cpu); |
134 | ce6e1e9e | Jia Liu | } |
135 | ce6e1e9e | Jia Liu | |
136 | ce6e1e9e | Jia Liu | static QEMUMachine openrisc_sim_machine = {
|
137 | ce6e1e9e | Jia Liu | .name = "or32-sim",
|
138 | ce6e1e9e | Jia Liu | .desc = "or32 simulation",
|
139 | ce6e1e9e | Jia Liu | .init = openrisc_sim_init, |
140 | ce6e1e9e | Jia Liu | .max_cpus = 1,
|
141 | ce6e1e9e | Jia Liu | .is_default = 1,
|
142 | e4ada29e | Avik Sil | DEFAULT_MACHINE_OPTIONS, |
143 | ce6e1e9e | Jia Liu | }; |
144 | ce6e1e9e | Jia Liu | |
145 | ce6e1e9e | Jia Liu | static void openrisc_sim_machine_init(void) |
146 | ce6e1e9e | Jia Liu | { |
147 | ce6e1e9e | Jia Liu | qemu_register_machine(&openrisc_sim_machine); |
148 | ce6e1e9e | Jia Liu | } |
149 | ce6e1e9e | Jia Liu | |
150 | ce6e1e9e | Jia Liu | machine_init(openrisc_sim_machine_init); |