Patchwork mips: fix CPU reset

login
register
mail settings
Submitter Blue Swirl
Date Nov. 13, 2009, 8:44 p.m.
Message ID <f43fc5580911131244w5f2e19c0t62e3634c2f2251cc@mail.gmail.com>
Download mbox | patch
Permalink /patch/38391/
State New
Headers show

Comments

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(-)
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

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 */