mips: fix CPU reset

Submitted by Blue Swirl on Nov. 13, 2009, 8:44 p.m.

Details

Message ID f43fc5580911131244w5f2e19c0t62e3634c2f2251cc@mail.gmail.com
State New
Headers show

Commit Message

Blue Swirl Nov. 13, 2009, 8:44 p.m.
This patch fixes the MIPS reset problem, so that using instructions
from http://www.aurel32.net/info/debian_mips_qemu.php, I get the
installer prompt.
---
See f2d74978764f62d832d61ac17bb5d934ade58816.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
---
 hw/mips_malta.c   |   23 +++++++++++++++++------
 hw/mips_mipssim.c |   25 +++++++++++++++++--------
 hw/mips_r4k.c     |   25 +++++++++++++++++--------
 3 files changed, 51 insertions(+), 22 deletions(-)

Comments

Aurelien Jarno Nov. 13, 2009, 11:53 p.m.
On Fri, Nov 13, 2009 at 10:44:29PM +0200, Blue Swirl wrote:
> This patch fixes the MIPS reset problem, so that using instructions
> from http://www.aurel32.net/info/debian_mips_qemu.php, I get the
> installer prompt.
> ---
> See f2d74978764f62d832d61ac17bb5d934ade58816.

Thanks for this patch. It seems ok, except for malta. The reset vector
is the default one as we have a bootloader at this address. The patch
from Stefan Weil is correct for the Malta part.

However the reboot is still broken, as we need to reload the kernel into
memory. How it should done now?

> Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
> ---
>  hw/mips_malta.c   |   23 +++++++++++++++++------
>  hw/mips_mipssim.c |   25 +++++++++++++++++--------
>  hw/mips_r4k.c     |   25 +++++++++++++++++--------
>  3 files changed, 51 insertions(+), 22 deletions(-)
> 
> diff --git a/hw/mips_malta.c b/hw/mips_malta.c
> index 30fa6b8..706962b 100644
> --- a/hw/mips_malta.c
> +++ b/hw/mips_malta.c
> @@ -80,6 +80,11 @@ static struct _loaderparams {
>      const char *initrd_filename;
>  } loaderparams;
> 
> +typedef struct ResetData {
> +    CPUState *env;
> +    uint64_t vector;
> +} ResetData;
> +
>  /* Malta FPGA */
>  static void malta_fpga_update_display(void *opaque)
>  {
> @@ -683,7 +688,7 @@ static void prom_set(int index, const char *string, ...)
>  }
> 
>  /* Kernel */
> -static int64_t load_kernel (CPUState *env)
> +static int64_t load_kernel(void)
>  {
>      int64_t kernel_entry, kernel_low, kernel_high;
>      int index = 0;
> @@ -750,15 +755,16 @@ static int64_t load_kernel (CPUState *env)
> 
>  static void main_cpu_reset(void *opaque)
>  {
> -    CPUState *env = opaque;
> -    cpu_reset(env);
> +    ResetData *s = (ResetData *)opaque;
> +    CPUState *env = s->env;
> 
> +    cpu_reset(env);
> +    env->active_tc.PC = s->vector;
>      /* The bootload does not need to be rewritten as it is located in a
>         read only location. The kernel location and the arguments table
>         location does not change. */
>      if (loaderparams.kernel_filename) {
>          env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
> -        load_kernel (env);
>      }
>  }
> 
> @@ -776,6 +782,7 @@ void mips_malta_init (ram_addr_t ram_size,
>      PCIBus *pci_bus;
>      ISADevice *isa_dev;
>      CPUState *env;
> +    ResetData *reset_info;
>      RTCState *rtc_state;
>      fdctrl_t *floppy_controller;
>      MaltaFPGAState *malta_fpga;
> @@ -812,7 +819,10 @@ void mips_malta_init (ram_addr_t ram_size,
>          fprintf(stderr, "Unable to find CPU definition\n");
>          exit(1);
>      }
> -    qemu_register_reset(main_cpu_reset, env);
> +    reset_info = qemu_mallocz(sizeof(ResetData));
> +    reset_info->env = env;
> +    reset_info->vector = env->active_tc.PC;
> +    qemu_register_reset(main_cpu_reset, reset_info);
> 
>      /* allocate RAM */
>      if (ram_size > (256 << 20)) {
> @@ -843,7 +853,8 @@ void mips_malta_init (ram_addr_t ram_size,
>          loaderparams.kernel_filename = kernel_filename;
>          loaderparams.kernel_cmdline = kernel_cmdline;
>          loaderparams.initrd_filename = initrd_filename;
> -        kernel_entry = load_kernel(env);
> +        kernel_entry = load_kernel();
> +        reset_info->vector = kernel_entry;
>          env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
>          write_bootloader(env, qemu_get_ram_ptr(bios_offset), kernel_entry);
>      } else {
> diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c
> index 9aed40e..aa90116 100644
> --- a/hw/mips_mipssim.c
> +++ b/hw/mips_mipssim.c
> @@ -50,7 +50,12 @@ static struct _loaderparams {
>      const char *initrd_filename;
>  } loaderparams;
> 
> -static void load_kernel (CPUState *env)
> +typedef struct ResetData {
> +    CPUState *env;
> +    uint64_t vector;
> +} ResetData;
> +
> +static int64_t load_kernel(void)
>  {
>      int64_t entry, kernel_low, kernel_high;
>      long kernel_size;
> @@ -70,7 +75,6 @@ static void load_kernel (CPUState *env)
>      if (kernel_size >= 0) {
>          if ((entry & ~0x7fffffffULL) == 0x80000000)
>              entry = (int32_t)entry;
> -        env->active_tc.PC = entry;
>      } else {
>          fprintf(stderr, "qemu: could not load kernel '%s'\n",
>                  loaderparams.kernel_filename);
> @@ -99,15 +103,16 @@ static void load_kernel (CPUState *env)
>              exit(1);
>          }
>      }
> +    return entry;
>  }
> 
>  static void main_cpu_reset(void *opaque)
>  {
> -    CPUState *env = opaque;
> -    cpu_reset(env);
> +    ResetData *s = (ResetData *)opaque;
> +    CPUState *env = s->env;
> 
> -    if (loaderparams.kernel_filename)
> -        load_kernel (env);
> +    cpu_reset(env);
> +    env->active_tc.PC = s->vector;
>  }
> 
>  static void
> @@ -120,6 +125,7 @@ mips_mipssim_init (ram_addr_t ram_size,
>      ram_addr_t ram_offset;
>      ram_addr_t bios_offset;
>      CPUState *env;
> +    ResetData *reset_info;
>      int bios_size;
> 
>      /* Init CPUs. */
> @@ -135,7 +141,10 @@ mips_mipssim_init (ram_addr_t ram_size,
>          fprintf(stderr, "Unable to find CPU definition\n");
>          exit(1);
>      }
> -    qemu_register_reset(main_cpu_reset, env);
> +    reset_info = qemu_mallocz(sizeof(ResetData));
> +    reset_info->env = env;
> +    reset_info->vector = env->active_tc.PC;
> +    qemu_register_reset(main_cpu_reset, reset_info);
> 
>      /* Allocate RAM. */
>      ram_offset = qemu_ram_alloc(ram_size);
> @@ -172,7 +181,7 @@ mips_mipssim_init (ram_addr_t ram_size,
>          loaderparams.kernel_filename = kernel_filename;
>          loaderparams.kernel_cmdline = kernel_cmdline;
>          loaderparams.initrd_filename = initrd_filename;
> -        load_kernel(env);
> +        reset_info->vector = load_kernel();
>      }
> 
>      /* Init CPU internal devices. */
> diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
> index d525c63..497885b 100644
> --- a/hw/mips_r4k.c
> +++ b/hw/mips_r4k.c
> @@ -70,7 +70,12 @@ static CPUReadMemoryFunc * const mips_qemu_read[] = {
> 
>  static int mips_qemu_iomemtype = 0;
> 
> -static void load_kernel (CPUState *env)
> +typedef struct ResetData {
> +    CPUState *env;
> +    uint64_t vector;
> +} ResetData;
> +
> +static int64_t load_kernel(void)
>  {
>      int64_t entry, kernel_low, kernel_high;
>      long kernel_size, initrd_size;
> @@ -89,7 +94,6 @@ static void load_kernel (CPUState *env)
>      if (kernel_size >= 0) {
>          if ((entry & ~0x7fffffffULL) == 0x80000000)
>              entry = (int32_t)entry;
> -        env->active_tc.PC = entry;
>      } else {
>          fprintf(stderr, "qemu: could not load kernel '%s'\n",
>                  loaderparams.kernel_filename);
> @@ -135,15 +139,16 @@ static void load_kernel (CPUState *env)
> 
>      stl_phys((16 << 20) - 260, 0x12345678);
>      stl_phys((16 << 20) - 264, ram_size);
> +    return entry;
>  }
> 
>  static void main_cpu_reset(void *opaque)
>  {
> -    CPUState *env = opaque;
> -    cpu_reset(env);
> +    ResetData *s = (ResetData *)opaque;
> +    CPUState *env = s->env;
> 
> -    if (loaderparams.kernel_filename)
> -        load_kernel (env);
> +    cpu_reset(env);
> +    env->active_tc.PC = s->vector;
>  }
> 
>  static const int sector_len = 32 * 1024;
> @@ -158,6 +163,7 @@ void mips_r4k_init (ram_addr_t ram_size,
>      ram_addr_t bios_offset;
>      int bios_size;
>      CPUState *env;
> +    ResetData *reset_info;
>      RTCState *rtc_state;
>      int i;
>      qemu_irq *i8259;
> @@ -177,7 +183,10 @@ void mips_r4k_init (ram_addr_t ram_size,
>          fprintf(stderr, "Unable to find CPU definition\n");
>          exit(1);
>      }
> -    qemu_register_reset(main_cpu_reset, env);
> +    reset_info = qemu_mallocz(sizeof(ResetData));
> +    reset_info->env = env;
> +    reset_info->vector = env->active_tc.PC;
> +    qemu_register_reset(main_cpu_reset, reset_info);
> 
>      /* allocate RAM */
>      if (ram_size > (256 << 20)) {
> @@ -237,7 +246,7 @@ void mips_r4k_init (ram_addr_t ram_size,
>          loaderparams.kernel_filename = kernel_filename;
>          loaderparams.kernel_cmdline = kernel_cmdline;
>          loaderparams.initrd_filename = initrd_filename;
> -        load_kernel (env);
> +        reset_info->vector = load_kernel();
>      }
> 
>      /* Init CPU internal devices */
> -- 
> 1.6.2.4
> 
> 
>

Patch hide | download patch | download mbox

diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 30fa6b8..706962b 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -80,6 +80,11 @@  static struct _loaderparams {
     const char *initrd_filename;
 } loaderparams;

+typedef struct ResetData {
+    CPUState *env;
+    uint64_t vector;
+} ResetData;
+
 /* Malta FPGA */
 static void malta_fpga_update_display(void *opaque)
 {
@@ -683,7 +688,7 @@  static void prom_set(int index, const char *string, ...)
 }

 /* Kernel */
-static int64_t load_kernel (CPUState *env)
+static int64_t load_kernel(void)
 {
     int64_t kernel_entry, kernel_low, kernel_high;
     int index = 0;
@@ -750,15 +755,16 @@  static int64_t load_kernel (CPUState *env)

 static void main_cpu_reset(void *opaque)
 {
-    CPUState *env = opaque;
-    cpu_reset(env);
+    ResetData *s = (ResetData *)opaque;
+    CPUState *env = s->env;

+    cpu_reset(env);
+    env->active_tc.PC = s->vector;
     /* The bootload does not need to be rewritten as it is located in a
        read only location. The kernel location and the arguments table
        location does not change. */
     if (loaderparams.kernel_filename) {
         env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
-        load_kernel (env);
     }
 }

@@ -776,6 +782,7 @@  void mips_malta_init (ram_addr_t ram_size,
     PCIBus *pci_bus;
     ISADevice *isa_dev;
     CPUState *env;
+    ResetData *reset_info;
     RTCState *rtc_state;
     fdctrl_t *floppy_controller;
     MaltaFPGAState *malta_fpga;
@@ -812,7 +819,10 @@  void mips_malta_init (ram_addr_t ram_size,
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
-    qemu_register_reset(main_cpu_reset, env);
+    reset_info = qemu_mallocz(sizeof(ResetData));
+    reset_info->env = env;
+    reset_info->vector = env->active_tc.PC;
+    qemu_register_reset(main_cpu_reset, reset_info);

     /* allocate RAM */
     if (ram_size > (256 << 20)) {
@@ -843,7 +853,8 @@  void mips_malta_init (ram_addr_t ram_size,
         loaderparams.kernel_filename = kernel_filename;
         loaderparams.kernel_cmdline = kernel_cmdline;
         loaderparams.initrd_filename = initrd_filename;
-        kernel_entry = load_kernel(env);
+        kernel_entry = load_kernel();
+        reset_info->vector = kernel_entry;
         env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
         write_bootloader(env, qemu_get_ram_ptr(bios_offset), kernel_entry);
     } else {
diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c
index 9aed40e..aa90116 100644
--- a/hw/mips_mipssim.c
+++ b/hw/mips_mipssim.c
@@ -50,7 +50,12 @@  static struct _loaderparams {
     const char *initrd_filename;
 } loaderparams;

-static void load_kernel (CPUState *env)
+typedef struct ResetData {
+    CPUState *env;
+    uint64_t vector;
+} ResetData;
+
+static int64_t load_kernel(void)
 {
     int64_t entry, kernel_low, kernel_high;
     long kernel_size;
@@ -70,7 +75,6 @@  static void load_kernel (CPUState *env)
     if (kernel_size >= 0) {
         if ((entry & ~0x7fffffffULL) == 0x80000000)
             entry = (int32_t)entry;
-        env->active_tc.PC = entry;
     } else {
         fprintf(stderr, "qemu: could not load kernel '%s'\n",
                 loaderparams.kernel_filename);
@@ -99,15 +103,16 @@  static void load_kernel (CPUState *env)
             exit(1);
         }
     }
+    return entry;
 }

 static void main_cpu_reset(void *opaque)
 {
-    CPUState *env = opaque;
-    cpu_reset(env);
+    ResetData *s = (ResetData *)opaque;
+    CPUState *env = s->env;

-    if (loaderparams.kernel_filename)
-        load_kernel (env);
+    cpu_reset(env);
+    env->active_tc.PC = s->vector;
 }

 static void
@@ -120,6 +125,7 @@  mips_mipssim_init (ram_addr_t ram_size,
     ram_addr_t ram_offset;
     ram_addr_t bios_offset;
     CPUState *env;
+    ResetData *reset_info;
     int bios_size;

     /* Init CPUs. */
@@ -135,7 +141,10 @@  mips_mipssim_init (ram_addr_t ram_size,
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
-    qemu_register_reset(main_cpu_reset, env);
+    reset_info = qemu_mallocz(sizeof(ResetData));
+    reset_info->env = env;
+    reset_info->vector = env->active_tc.PC;
+    qemu_register_reset(main_cpu_reset, reset_info);

     /* Allocate RAM. */
     ram_offset = qemu_ram_alloc(ram_size);
@@ -172,7 +181,7 @@  mips_mipssim_init (ram_addr_t ram_size,
         loaderparams.kernel_filename = kernel_filename;
         loaderparams.kernel_cmdline = kernel_cmdline;
         loaderparams.initrd_filename = initrd_filename;
-        load_kernel(env);
+        reset_info->vector = load_kernel();
     }

     /* Init CPU internal devices. */
diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
index d525c63..497885b 100644
--- a/hw/mips_r4k.c
+++ b/hw/mips_r4k.c
@@ -70,7 +70,12 @@  static CPUReadMemoryFunc * const mips_qemu_read[] = {

 static int mips_qemu_iomemtype = 0;

-static void load_kernel (CPUState *env)
+typedef struct ResetData {
+    CPUState *env;
+    uint64_t vector;
+} ResetData;
+
+static int64_t load_kernel(void)
 {
     int64_t entry, kernel_low, kernel_high;
     long kernel_size, initrd_size;
@@ -89,7 +94,6 @@  static void load_kernel (CPUState *env)
     if (kernel_size >= 0) {
         if ((entry & ~0x7fffffffULL) == 0x80000000)
             entry = (int32_t)entry;
-        env->active_tc.PC = entry;
     } else {
         fprintf(stderr, "qemu: could not load kernel '%s'\n",
                 loaderparams.kernel_filename);
@@ -135,15 +139,16 @@  static void load_kernel (CPUState *env)

     stl_phys((16 << 20) - 260, 0x12345678);
     stl_phys((16 << 20) - 264, ram_size);
+    return entry;
 }

 static void main_cpu_reset(void *opaque)
 {
-    CPUState *env = opaque;
-    cpu_reset(env);
+    ResetData *s = (ResetData *)opaque;
+    CPUState *env = s->env;

-    if (loaderparams.kernel_filename)
-        load_kernel (env);
+    cpu_reset(env);
+    env->active_tc.PC = s->vector;
 }

 static const int sector_len = 32 * 1024;
@@ -158,6 +163,7 @@  void mips_r4k_init (ram_addr_t ram_size,
     ram_addr_t bios_offset;
     int bios_size;
     CPUState *env;
+    ResetData *reset_info;
     RTCState *rtc_state;
     int i;
     qemu_irq *i8259;
@@ -177,7 +183,10 @@  void mips_r4k_init (ram_addr_t ram_size,
         fprintf(stderr, "Unable to find CPU definition\n");
         exit(1);
     }
-    qemu_register_reset(main_cpu_reset, env);
+    reset_info = qemu_mallocz(sizeof(ResetData));
+    reset_info->env = env;
+    reset_info->vector = env->active_tc.PC;
+    qemu_register_reset(main_cpu_reset, reset_info);

     /* allocate RAM */
     if (ram_size > (256 << 20)) {
@@ -237,7 +246,7 @@  void mips_r4k_init (ram_addr_t ram_size,
         loaderparams.kernel_filename = kernel_filename;
         loaderparams.kernel_cmdline = kernel_cmdline;
         loaderparams.initrd_filename = initrd_filename;
-        load_kernel (env);
+        reset_info->vector = load_kernel();
     }

     /* Init CPU internal devices */