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,6 +110,93 @@ void cpu_mips_clock_init (CPUState *env) | ||
| 110 | cpu_mips_update_count(env, 1, 0); | 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 | void mips_r4k_init (int ram_size, int vga_ram_size, int boot_device, | 201 | void mips_r4k_init (int ram_size, int vga_ram_size, int boot_device, |
| 115 | DisplayState *ds, const char **fd_filename, int snapshot, | 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,19 +204,24 @@ void mips_r4k_init (int ram_size, int vga_ram_size, int boot_device, | ||
| 117 | const char *initrd_filename) | 204 | const char *initrd_filename) |
| 118 | { | 205 | { |
| 119 | char buf[1024]; | 206 | char buf[1024]; |
| 120 | - int64_t entry = 0; | ||
| 121 | unsigned long bios_offset; | 207 | unsigned long bios_offset; |
| 122 | int ret; | 208 | int ret; |
| 123 | CPUState *env; | 209 | CPUState *env; |
| 124 | - long kernel_size; | ||
| 125 | int i; | 210 | int i; |
| 126 | 211 | ||
| 127 | env = cpu_init(); | 212 | env = cpu_init(); |
| 128 | register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); | 213 | register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); |
| 214 | + qemu_register_reset(main_cpu_reset, env); | ||
| 129 | 215 | ||
| 130 | /* allocate RAM */ | 216 | /* allocate RAM */ |
| 131 | cpu_register_physical_memory(0, ram_size, IO_MEM_RAM); | 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 | /* Try to load a BIOS image. If this fails, we continue regardless, | 225 | /* Try to load a BIOS image. If this fails, we continue regardless, |
| 134 | but initialize the hardware ourselves. When a kernel gets | 226 | but initialize the hardware ourselves. When a kernel gets |
| 135 | preloaded we also initialize the hardware, since the BIOS wasn't | 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,38 +238,13 @@ void mips_r4k_init (int ram_size, int vga_ram_size, int boot_device, | ||
| 146 | buf); | 238 | buf); |
| 147 | } | 239 | } |
| 148 | 240 | ||
| 149 | - kernel_size = 0; | ||
| 150 | if (kernel_filename) { | 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 | /* Init internal devices */ | 250 | /* Init internal devices */ |
target-mips/cpu.h
| @@ -182,7 +182,6 @@ struct CPUMIPSState { | @@ -182,7 +182,6 @@ struct CPUMIPSState { | ||
| 182 | uint32_t CP0_ErrorEPC; | 182 | uint32_t CP0_ErrorEPC; |
| 183 | uint32_t CP0_DESAVE; | 183 | uint32_t CP0_DESAVE; |
| 184 | /* Qemu */ | 184 | /* Qemu */ |
| 185 | - struct QEMUTimer *timer; /* Internal timer */ | ||
| 186 | int interrupt_request; | 185 | int interrupt_request; |
| 187 | jmp_buf jmp_env; | 186 | jmp_buf jmp_env; |
| 188 | int exception_index; | 187 | int exception_index; |
| @@ -213,6 +212,13 @@ struct CPUMIPSState { | @@ -213,6 +212,13 @@ struct CPUMIPSState { | ||
| 213 | int halted; /* TRUE if the CPU is in suspend state */ | 212 | int halted; /* TRUE if the CPU is in suspend state */ |
| 214 | 213 | ||
| 215 | CPU_COMMON | 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 | #include "cpu-all.h" | 224 | #include "cpu-all.h" |
target-mips/translate.c
| @@ -2425,7 +2425,16 @@ CPUMIPSState *cpu_mips_init (void) | @@ -2425,7 +2425,16 @@ CPUMIPSState *cpu_mips_init (void) | ||
| 2425 | if (!env) | 2425 | if (!env) |
| 2426 | return NULL; | 2426 | return NULL; |
| 2427 | cpu_exec_init(env); | 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 | tlb_flush(env, 1); | 2436 | tlb_flush(env, 1); |
| 2437 | + | ||
| 2429 | /* Minimal init */ | 2438 | /* Minimal init */ |
| 2430 | env->PC = 0xBFC00000; | 2439 | env->PC = 0xBFC00000; |
| 2431 | #if defined (MIPS_USES_R4K_TLB) | 2440 | #if defined (MIPS_USES_R4K_TLB) |
| @@ -2456,5 +2465,4 @@ CPUMIPSState *cpu_mips_init (void) | @@ -2456,5 +2465,4 @@ CPUMIPSState *cpu_mips_init (void) | ||
| 2456 | #ifdef MIPS_USES_FPU | 2465 | #ifdef MIPS_USES_FPU |
| 2457 | env->fcr0 = MIPS_FCR0; | 2466 | env->fcr0 = MIPS_FCR0; |
| 2458 | #endif | 2467 | #endif |
| 2459 | - return env; | ||
| 2460 | } | 2468 | } |