Commit 6ae817752b72a7c9c3bb031afa7e7cc0e4d10eaf
1 parent
814b9a47
Halt/reboot support for Linux, by Daniel Jacobowitz. This is a band-aid
until we emulate real MIPS hardware with real firmware. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2221 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
116 additions
and
35 deletions
hw/mips_r4k.c
... | ... | @@ -110,6 +110,93 @@ void cpu_mips_clock_init (CPUState *env) |
110 | 110 | cpu_mips_update_count(env, 1, 0); |
111 | 111 | } |
112 | 112 | |
113 | +static void mips_qemu_writel (void *opaque, target_phys_addr_t addr, | |
114 | + uint32_t val) | |
115 | +{ | |
116 | + if ((addr & 0xffff) == 0 && val == 42) | |
117 | + qemu_system_reset_request (); | |
118 | + else if ((addr & 0xffff) == 4 && val == 42) | |
119 | + qemu_system_shutdown_request (); | |
120 | +} | |
121 | + | |
122 | +static uint32_t mips_qemu_readl (void *opaque, target_phys_addr_t addr) | |
123 | +{ | |
124 | + return 0; | |
125 | +} | |
126 | + | |
127 | +static CPUWriteMemoryFunc *mips_qemu_write[] = { | |
128 | + &mips_qemu_writel, | |
129 | + &mips_qemu_writel, | |
130 | + &mips_qemu_writel, | |
131 | +}; | |
132 | + | |
133 | +static CPUReadMemoryFunc *mips_qemu_read[] = { | |
134 | + &mips_qemu_readl, | |
135 | + &mips_qemu_readl, | |
136 | + &mips_qemu_readl, | |
137 | +}; | |
138 | + | |
139 | +static int mips_qemu_iomemtype = 0; | |
140 | + | |
141 | +void load_kernel (CPUState *env, int ram_size, const char *kernel_filename, | |
142 | + const char *kernel_cmdline, | |
143 | + const char *initrd_filename) | |
144 | +{ | |
145 | + int64_t entry = 0; | |
146 | + long kernel_size, initrd_size; | |
147 | + | |
148 | + kernel_size = load_elf(kernel_filename, VIRT_TO_PHYS_ADDEND, &entry); | |
149 | + if (kernel_size >= 0) | |
150 | + env->PC = entry; | |
151 | + else { | |
152 | + kernel_size = load_image(kernel_filename, | |
153 | + phys_ram_base + KERNEL_LOAD_ADDR + VIRT_TO_PHYS_ADDEND); | |
154 | + if (kernel_size < 0) { | |
155 | + fprintf(stderr, "qemu: could not load kernel '%s'\n", | |
156 | + kernel_filename); | |
157 | + exit(1); | |
158 | + } | |
159 | + env->PC = KERNEL_LOAD_ADDR; | |
160 | + } | |
161 | + | |
162 | + /* load initrd */ | |
163 | + initrd_size = 0; | |
164 | + if (initrd_filename) { | |
165 | + initrd_size = load_image(initrd_filename, | |
166 | + phys_ram_base + INITRD_LOAD_ADDR + VIRT_TO_PHYS_ADDEND); | |
167 | + if (initrd_size == (target_ulong) -1) { | |
168 | + fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", | |
169 | + initrd_filename); | |
170 | + exit(1); | |
171 | + } | |
172 | + } | |
173 | + | |
174 | + /* Store command line. */ | |
175 | + if (initrd_size > 0) { | |
176 | + int ret; | |
177 | + ret = sprintf(phys_ram_base + (16 << 20) - 256, | |
178 | + "rd_start=0x%08x rd_size=%li ", | |
179 | + INITRD_LOAD_ADDR, | |
180 | + initrd_size); | |
181 | + strcpy (phys_ram_base + (16 << 20) - 256 + ret, kernel_cmdline); | |
182 | + } | |
183 | + else { | |
184 | + strcpy (phys_ram_base + (16 << 20) - 256, kernel_cmdline); | |
185 | + } | |
186 | + | |
187 | + *(int *)(phys_ram_base + (16 << 20) - 260) = tswap32 (0x12345678); | |
188 | + *(int *)(phys_ram_base + (16 << 20) - 264) = tswap32 (ram_size); | |
189 | +} | |
190 | + | |
191 | +static void main_cpu_reset(void *opaque) | |
192 | +{ | |
193 | + CPUState *env = opaque; | |
194 | + cpu_reset(env); | |
195 | + | |
196 | + if (env->kernel_filename) | |
197 | + load_kernel (env, env->ram_size, env->kernel_filename, | |
198 | + env->kernel_cmdline, env->initrd_filename); | |
199 | +} | |
113 | 200 | |
114 | 201 | void mips_r4k_init (int ram_size, int vga_ram_size, int boot_device, |
115 | 202 | DisplayState *ds, const char **fd_filename, int snapshot, |
... | ... | @@ -117,19 +204,24 @@ void mips_r4k_init (int ram_size, int vga_ram_size, int boot_device, |
117 | 204 | const char *initrd_filename) |
118 | 205 | { |
119 | 206 | char buf[1024]; |
120 | - int64_t entry = 0; | |
121 | 207 | unsigned long bios_offset; |
122 | 208 | int ret; |
123 | 209 | CPUState *env; |
124 | - long kernel_size; | |
125 | 210 | int i; |
126 | 211 | |
127 | 212 | env = cpu_init(); |
128 | 213 | register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); |
214 | + qemu_register_reset(main_cpu_reset, env); | |
129 | 215 | |
130 | 216 | /* allocate RAM */ |
131 | 217 | cpu_register_physical_memory(0, ram_size, IO_MEM_RAM); |
132 | 218 | |
219 | + if (!mips_qemu_iomemtype) { | |
220 | + mips_qemu_iomemtype = cpu_register_io_memory(0, mips_qemu_read, | |
221 | + mips_qemu_write, NULL); | |
222 | + } | |
223 | + cpu_register_physical_memory(0x1fbf0000, 0x10000, mips_qemu_iomemtype); | |
224 | + | |
133 | 225 | /* Try to load a BIOS image. If this fails, we continue regardless, |
134 | 226 | but initialize the hardware ourselves. When a kernel gets |
135 | 227 | preloaded we also initialize the hardware, since the BIOS wasn't |
... | ... | @@ -146,38 +238,13 @@ void mips_r4k_init (int ram_size, int vga_ram_size, int boot_device, |
146 | 238 | buf); |
147 | 239 | } |
148 | 240 | |
149 | - kernel_size = 0; | |
150 | 241 | if (kernel_filename) { |
151 | - kernel_size = load_elf(kernel_filename, VIRT_TO_PHYS_ADDEND, &entry); | |
152 | - if (kernel_size >= 0) | |
153 | - env->PC = entry; | |
154 | - else { | |
155 | - kernel_size = load_image(kernel_filename, | |
156 | - phys_ram_base + KERNEL_LOAD_ADDR + VIRT_TO_PHYS_ADDEND); | |
157 | - if (kernel_size < 0) { | |
158 | - fprintf(stderr, "qemu: could not load kernel '%s'\n", | |
159 | - kernel_filename); | |
160 | - exit(1); | |
161 | - } | |
162 | - env->PC = KERNEL_LOAD_ADDR; | |
163 | - } | |
164 | - | |
165 | - /* load initrd */ | |
166 | - if (initrd_filename) { | |
167 | - if (load_image(initrd_filename, | |
168 | - phys_ram_base + INITRD_LOAD_ADDR + VIRT_TO_PHYS_ADDEND) | |
169 | - == (target_ulong) -1) { | |
170 | - fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", | |
171 | - initrd_filename); | |
172 | - exit(1); | |
173 | - } | |
174 | - } | |
175 | - | |
176 | - /* Store command line. */ | |
177 | - strcpy (phys_ram_base + (16 << 20) - 256, kernel_cmdline); | |
178 | - /* FIXME: little endian support */ | |
179 | - *(int *)(phys_ram_base + (16 << 20) - 260) = tswap32 (0x12345678); | |
180 | - *(int *)(phys_ram_base + (16 << 20) - 264) = tswap32 (ram_size); | |
242 | + load_kernel (env, ram_size, kernel_filename, kernel_cmdline, | |
243 | + initrd_filename); | |
244 | + env->ram_size = ram_size; | |
245 | + env->kernel_filename = kernel_filename; | |
246 | + env->kernel_cmdline = kernel_cmdline; | |
247 | + env->initrd_filename = initrd_filename; | |
181 | 248 | } |
182 | 249 | |
183 | 250 | /* Init internal devices */ | ... | ... |
target-mips/cpu.h
... | ... | @@ -182,7 +182,6 @@ struct CPUMIPSState { |
182 | 182 | uint32_t CP0_ErrorEPC; |
183 | 183 | uint32_t CP0_DESAVE; |
184 | 184 | /* Qemu */ |
185 | - struct QEMUTimer *timer; /* Internal timer */ | |
186 | 185 | int interrupt_request; |
187 | 186 | jmp_buf jmp_env; |
188 | 187 | int exception_index; |
... | ... | @@ -213,6 +212,13 @@ struct CPUMIPSState { |
213 | 212 | int halted; /* TRUE if the CPU is in suspend state */ |
214 | 213 | |
215 | 214 | CPU_COMMON |
215 | + | |
216 | + int ram_size; | |
217 | + const char *kernel_filename; | |
218 | + const char *kernel_cmdline; | |
219 | + const char *initrd_filename; | |
220 | + | |
221 | + struct QEMUTimer *timer; /* Internal timer */ | |
216 | 222 | }; |
217 | 223 | |
218 | 224 | #include "cpu-all.h" | ... | ... |
target-mips/translate.c
... | ... | @@ -2425,7 +2425,16 @@ CPUMIPSState *cpu_mips_init (void) |
2425 | 2425 | if (!env) |
2426 | 2426 | return NULL; |
2427 | 2427 | cpu_exec_init(env); |
2428 | + cpu_reset(env); | |
2429 | + return env; | |
2430 | +} | |
2431 | + | |
2432 | +void cpu_reset (CPUMIPSState *env) | |
2433 | +{ | |
2434 | + memset(env, 0, offsetof(CPUMIPSState, breakpoints)); | |
2435 | + | |
2428 | 2436 | tlb_flush(env, 1); |
2437 | + | |
2429 | 2438 | /* Minimal init */ |
2430 | 2439 | env->PC = 0xBFC00000; |
2431 | 2440 | #if defined (MIPS_USES_R4K_TLB) |
... | ... | @@ -2456,5 +2465,4 @@ CPUMIPSState *cpu_mips_init (void) |
2456 | 2465 | #ifdef MIPS_USES_FPU |
2457 | 2466 | env->fcr0 = MIPS_FCR0; |
2458 | 2467 | #endif |
2459 | - return env; | |
2460 | 2468 | } | ... | ... |