Commit 6ae817752b72a7c9c3bb031afa7e7cc0e4d10eaf

Authored by ths
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
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 }