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 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 }
... ...