|
|
1.1 root 1: /*
2: * QEMU/mipssim emulation
3: *
1.1.1.7 root 4: * Emulates a very simple machine model similar to the one used by the
1.1 root 5: * proprietary MIPS emulator.
6: *
7: * Copyright (c) 2007 Thiemo Seufer
8: *
9: * Permission is hereby granted, free of charge, to any person obtaining a copy
10: * of this software and associated documentation files (the "Software"), to deal
11: * in the Software without restriction, including without limitation the rights
12: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13: * copies of the Software, and to permit persons to whom the Software is
14: * furnished to do so, subject to the following conditions:
15: *
16: * The above copyright notice and this permission notice shall be included in
17: * all copies or substantial portions of the Software.
18: *
19: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25: * THE SOFTWARE.
26: */
27: #include "hw.h"
28: #include "mips.h"
1.1.1.5 root 29: #include "mips_cpudevs.h"
1.1 root 30: #include "pc.h"
31: #include "isa.h"
32: #include "net.h"
33: #include "sysemu.h"
34: #include "boards.h"
1.1.1.3 root 35: #include "mips-bios.h"
1.1.1.4 root 36: #include "loader.h"
37: #include "elf.h"
1.1.1.7 root 38: #include "sysbus.h"
39: #include "exec-memory.h"
1.1 root 40:
41: static struct _loaderparams {
42: int ram_size;
43: const char *kernel_filename;
44: const char *kernel_cmdline;
45: const char *initrd_filename;
46: } loaderparams;
47:
1.1.1.4 root 48: typedef struct ResetData {
1.1.1.8 ! root 49: CPUMIPSState *env;
1.1.1.4 root 50: uint64_t vector;
51: } ResetData;
52:
53: static int64_t load_kernel(void)
1.1 root 54: {
1.1.1.5 root 55: int64_t entry, kernel_high;
1.1 root 56: long kernel_size;
57: long initrd_size;
58: ram_addr_t initrd_offset;
1.1.1.4 root 59: int big_endian;
60:
61: #ifdef TARGET_WORDS_BIGENDIAN
62: big_endian = 1;
63: #else
64: big_endian = 0;
65: #endif
1.1 root 66:
1.1.1.5 root 67: kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
68: NULL, (uint64_t *)&entry, NULL,
69: (uint64_t *)&kernel_high, big_endian,
70: ELF_MACHINE, 1);
1.1 root 71: if (kernel_size >= 0) {
72: if ((entry & ~0x7fffffffULL) == 0x80000000)
73: entry = (int32_t)entry;
74: } else {
75: fprintf(stderr, "qemu: could not load kernel '%s'\n",
76: loaderparams.kernel_filename);
77: exit(1);
78: }
79:
80: /* load initrd */
81: initrd_size = 0;
82: initrd_offset = 0;
83: if (loaderparams.initrd_filename) {
84: initrd_size = get_image_size (loaderparams.initrd_filename);
85: if (initrd_size > 0) {
86: initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
87: if (initrd_offset + initrd_size > loaderparams.ram_size) {
88: fprintf(stderr,
89: "qemu: memory too small for initial ram disk '%s'\n",
90: loaderparams.initrd_filename);
91: exit(1);
92: }
1.1.1.3 root 93: initrd_size = load_image_targphys(loaderparams.initrd_filename,
94: initrd_offset, loaderparams.ram_size - initrd_offset);
1.1 root 95: }
96: if (initrd_size == (target_ulong) -1) {
97: fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
98: loaderparams.initrd_filename);
99: exit(1);
100: }
101: }
1.1.1.4 root 102: return entry;
1.1 root 103: }
104:
105: static void main_cpu_reset(void *opaque)
106: {
1.1.1.4 root 107: ResetData *s = (ResetData *)opaque;
1.1.1.8 ! root 108: CPUMIPSState *env = s->env;
1.1 root 109:
1.1.1.8 ! root 110: cpu_state_reset(env);
1.1.1.5 root 111: env->active_tc.PC = s->vector & ~(target_ulong)1;
112: if (s->vector & 1) {
113: env->hflags |= MIPS_HFLAG_M16;
114: }
1.1 root 115: }
116:
1.1.1.7 root 117: static void mipsnet_init(int base, qemu_irq irq, NICInfo *nd)
118: {
119: DeviceState *dev;
120: SysBusDevice *s;
121:
122: dev = qdev_create(NULL, "mipsnet");
123: qdev_set_nic_properties(dev, nd);
124: qdev_init_nofail(dev);
125:
126: s = sysbus_from_qdev(dev);
127: sysbus_connect_irq(s, 0, irq);
128: memory_region_add_subregion(get_system_io(),
129: base,
130: sysbus_mmio_get_region(s, 0));
131: }
132:
1.1 root 133: static void
1.1.1.3 root 134: mips_mipssim_init (ram_addr_t ram_size,
1.1.1.2 root 135: const char *boot_device,
1.1 root 136: const char *kernel_filename, const char *kernel_cmdline,
137: const char *initrd_filename, const char *cpu_model)
138: {
1.1.1.3 root 139: char *filename;
1.1.1.7 root 140: MemoryRegion *address_space_mem = get_system_memory();
141: MemoryRegion *ram = g_new(MemoryRegion, 1);
142: MemoryRegion *bios = g_new(MemoryRegion, 1);
1.1.1.8 ! root 143: CPUMIPSState *env;
1.1.1.4 root 144: ResetData *reset_info;
1.1 root 145: int bios_size;
146:
147: /* Init CPUs. */
148: if (cpu_model == NULL) {
149: #ifdef TARGET_MIPS64
150: cpu_model = "5Kf";
151: #else
152: cpu_model = "24Kf";
153: #endif
154: }
155: env = cpu_init(cpu_model);
156: if (!env) {
157: fprintf(stderr, "Unable to find CPU definition\n");
158: exit(1);
159: }
1.1.1.7 root 160: reset_info = g_malloc0(sizeof(ResetData));
1.1.1.4 root 161: reset_info->env = env;
162: reset_info->vector = env->active_tc.PC;
163: qemu_register_reset(main_cpu_reset, reset_info);
1.1 root 164:
165: /* Allocate RAM. */
1.1.1.8 ! root 166: memory_region_init_ram(ram, "mips_mipssim.ram", ram_size);
! 167: vmstate_register_ram_global(ram);
! 168: memory_region_init_ram(bios, "mips_mipssim.bios", BIOS_SIZE);
! 169: vmstate_register_ram_global(bios);
1.1.1.7 root 170: memory_region_set_readonly(bios, true);
1.1 root 171:
1.1.1.7 root 172: memory_region_add_subregion(address_space_mem, 0, ram);
1.1.1.3 root 173:
174: /* Map the BIOS / boot exception handler. */
1.1.1.7 root 175: memory_region_add_subregion(address_space_mem, 0x1fc00000LL, bios);
1.1 root 176: /* Load a BIOS / boot exception handler image. */
177: if (bios_name == NULL)
178: bios_name = BIOS_FILENAME;
1.1.1.3 root 179: filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
180: if (filename) {
181: bios_size = load_image_targphys(filename, 0x1fc00000LL, BIOS_SIZE);
1.1.1.7 root 182: g_free(filename);
1.1.1.3 root 183: } else {
184: bios_size = -1;
185: }
1.1 root 186: if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
187: /* Bail out if we have neither a kernel image nor boot vector code. */
188: fprintf(stderr,
189: "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
1.1.1.3 root 190: filename);
1.1 root 191: exit(1);
192: } else {
193: /* We have a boot vector start address. */
1.1.1.2 root 194: env->active_tc.PC = (target_long)(int32_t)0xbfc00000;
1.1 root 195: }
196:
197: if (kernel_filename) {
198: loaderparams.ram_size = ram_size;
199: loaderparams.kernel_filename = kernel_filename;
200: loaderparams.kernel_cmdline = kernel_cmdline;
201: loaderparams.initrd_filename = initrd_filename;
1.1.1.4 root 202: reset_info->vector = load_kernel();
1.1 root 203: }
204:
205: /* Init CPU internal devices. */
206: cpu_mips_irq_init_cpu(env);
207: cpu_mips_clock_init(env);
208:
209: /* Register 64 KB of ISA IO space at 0x1fd00000. */
1.1.1.6 root 210: isa_mmio_init(0x1fd00000, 0x00010000);
1.1 root 211:
212: /* A single 16450 sits at offset 0x3f8. It is attached to
213: MIPS CPU INT2, which is interrupt 4. */
214: if (serial_hds[0])
1.1.1.2 root 215: serial_init(0x3f8, env->irq[4], 115200, serial_hds[0]);
1.1 root 216:
1.1.1.2 root 217: if (nd_table[0].vlan)
218: /* MIPSnet uses the MIPS CPU INT0, which is interrupt 2. */
219: mipsnet_init(0x4200, env->irq[2], &nd_table[0]);
1.1 root 220: }
221:
1.1.1.3 root 222: static QEMUMachine mips_mipssim_machine = {
1.1.1.2 root 223: .name = "mipssim",
224: .desc = "MIPS MIPSsim platform",
225: .init = mips_mipssim_init,
1.1 root 226: };
1.1.1.3 root 227:
228: static void mips_mipssim_machine_init(void)
229: {
230: qemu_register_machine(&mips_mipssim_machine);
231: }
232:
233: machine_init(mips_mipssim_machine_init);
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.