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