All of lore.kernel.org
 help / color / mirror / Atom feed
From: Thiemo Seufer <ths@networkno.de>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH 2/6] A cumulative MIPS patchset
Date: Tue, 21 Nov 2006 14:37:36 +0000	[thread overview]
Message-ID: <20061121143736.GC12745@networkno.de> (raw)

[-- Attachment #1: Type: text/plain, Size: 111 bytes --]

Hello All,

the attached patch is an update of Daniel's reboot/halt
implementation for the MIPS qemu.


Thiemo

[-- Attachment #2: qemu.drow-halt-reboot --]
[-- Type: text/plain, Size: 8060 bytes --]

Date: Sat, 11 Nov 2006 20:02:40 -0500
From: Daniel Jacobowitz <drow@false.org>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] MIPS halt / reboot

The MIPS kernel already has a reset/halt device for qemu
(arch/mips/qemu/q-reset.c).  I have no idea at all where this came
from, but hey, it seems sensible enough to me so I implemented it
in qemu.

This requires a bit of additional mucking around, since MIPS doesn't
currently have any BIOS support, so I made the reset vector reload any
specified kernel and initrd.  Works in my Debian rootfs; very handy for
automated benchmarking.

-- 
Daniel Jacobowitz
CodeSourcery

---
 hw/mips_r4k.c           |  144 +++++++++++++++++++++++++++++++++---------------
 target-mips/cpu.h       |    8 ++
 target-mips/translate.c |   10 +++
 3 files changed, 116 insertions(+), 46 deletions(-)

Index: qemu-work/hw/mips_r4k.c
===================================================================
--- qemu-work.orig/hw/mips_r4k.c	2006-11-15 22:40:28.000000000 +0000
+++ qemu-work/hw/mips_r4k.c	2006-11-15 22:41:14.000000000 +0000
@@ -110,6 +110,93 @@
     cpu_mips_update_count(env, 1, 0);
 }
 
+static void mips_qemu_writel (void *opaque, target_phys_addr_t addr,
+			      uint32_t val)
+{
+    if ((addr & 0xffff) == 0 && val == 42)
+        qemu_system_reset_request ();
+    else if ((addr & 0xffff) == 4 && val == 42)
+        qemu_system_shutdown_request ();
+}
+
+static uint32_t mips_qemu_readl (void *opaque, target_phys_addr_t addr)
+{
+    return 0;
+}
+
+static CPUWriteMemoryFunc *mips_qemu_write[] = {
+    &mips_qemu_writel,
+    &mips_qemu_writel,
+    &mips_qemu_writel,
+};
+
+static CPUReadMemoryFunc *mips_qemu_read[] = {
+    &mips_qemu_readl,
+    &mips_qemu_readl,
+    &mips_qemu_readl,
+};
+
+static int mips_qemu_iomemtype = 0;
+
+void load_kernel (CPUState *env, int ram_size, const char *kernel_filename,
+		  const char *kernel_cmdline,
+		  const char *initrd_filename)
+{
+    int64_t entry = 0;
+    long kernel_size, initrd_size;
+
+    kernel_size = load_elf(kernel_filename, VIRT_TO_PHYS_ADDEND, &entry);
+    if (kernel_size >= 0)
+        env->PC = entry;
+    else {
+        kernel_size = load_image(kernel_filename,
+                                 phys_ram_base + KERNEL_LOAD_ADDR + VIRT_TO_PHYS_ADDEND);
+        if (kernel_size < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                    kernel_filename);
+            exit(1);
+        }
+        env->PC = KERNEL_LOAD_ADDR;
+    }
+
+    /* load initrd */
+    initrd_size = 0;
+    if (initrd_filename) {
+        initrd_size = load_image(initrd_filename,
+                                 phys_ram_base + INITRD_LOAD_ADDR + VIRT_TO_PHYS_ADDEND);
+        if (initrd_size == (target_ulong) -1) {
+            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
+                    initrd_filename);
+            exit(1);
+        }
+    }
+
+    /* Store command line.  */
+    if (initrd_size > 0) {
+        int ret;
+        ret = sprintf(phys_ram_base + (16 << 20) - 256,
+                      "rd_start=0x%08x rd_size=%li ",
+                      INITRD_LOAD_ADDR,
+                      initrd_size);
+        strcpy (phys_ram_base + (16 << 20) - 256 + ret, kernel_cmdline);
+    }
+    else {
+        strcpy (phys_ram_base + (16 << 20) - 256, kernel_cmdline);
+    }
+
+    *(int *)(phys_ram_base + (16 << 20) - 260) = tswap32 (0x12345678);
+    *(int *)(phys_ram_base + (16 << 20) - 264) = tswap32 (ram_size);
+}
+
+static void main_cpu_reset(void *opaque)
+{
+    CPUState *env = opaque;
+    cpu_reset(env);
+
+    if (env->kernel_filename)
+        load_kernel (env, env->ram_size, env->kernel_filename,
+                     env->kernel_cmdline, env->initrd_filename);
+}
 
 void mips_r4k_init (int ram_size, int vga_ram_size, int boot_device,
                     DisplayState *ds, const char **fd_filename, int snapshot,
@@ -117,19 +204,24 @@
                     const char *initrd_filename)
 {
     char buf[1024];
-    int64_t entry = 0;
     unsigned long bios_offset;
     int ret;
     CPUState *env;
-    long kernel_size;
     int i;
 
     env = cpu_init();
     register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
+    qemu_register_reset(main_cpu_reset, env);
 
     /* allocate RAM */
     cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
 
+    if (!mips_qemu_iomemtype) {
+        mips_qemu_iomemtype = cpu_register_io_memory(0, mips_qemu_read,
+						     mips_qemu_write, NULL);
+    }
+    cpu_register_physical_memory(0x1fbf0000, 0x10000, mips_qemu_iomemtype);
+
     /* Try to load a BIOS image. If this fails, we continue regardless,
        but initialize the hardware ourselves. When a kernel gets
        preloaded we also initialize the hardware, since the BIOS wasn't
@@ -146,38 +238,13 @@
 		buf);
     }
 
-    kernel_size = 0;
     if (kernel_filename) {
-	kernel_size = load_elf(kernel_filename, VIRT_TO_PHYS_ADDEND, &entry);
-	if (kernel_size >= 0)
-	    env->PC = entry;
-	else {
-	    kernel_size = load_image(kernel_filename,
-                                     phys_ram_base + KERNEL_LOAD_ADDR + VIRT_TO_PHYS_ADDEND);
-            if (kernel_size < 0) {
-                fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                        kernel_filename);
-                exit(1);
-            }
-            env->PC = KERNEL_LOAD_ADDR;
-	}
-
-        /* load initrd */
-        if (initrd_filename) {
-            if (load_image(initrd_filename,
-			   phys_ram_base + INITRD_LOAD_ADDR + VIRT_TO_PHYS_ADDEND)
-		== (target_ulong) -1) {
-                fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", 
-                        initrd_filename);
-                exit(1);
-            }
-        }
-
-	/* Store command line.  */
-        strcpy (phys_ram_base + (16 << 20) - 256, kernel_cmdline);
-        /* FIXME: little endian support */
-        *(int *)(phys_ram_base + (16 << 20) - 260) = tswap32 (0x12345678);
-        *(int *)(phys_ram_base + (16 << 20) - 264) = tswap32 (ram_size);
+        load_kernel (env, ram_size, kernel_filename, kernel_cmdline,
+		     initrd_filename);
+	env->ram_size = ram_size;
+	env->kernel_filename = kernel_filename;
+	env->kernel_cmdline = kernel_cmdline;
+	env->initrd_filename = initrd_filename;
     }
 
     /* Init internal devices */
Index: qemu-work/target-mips/cpu.h
===================================================================
--- qemu-work.orig/target-mips/cpu.h	2006-11-15 22:41:04.000000000 +0000
+++ qemu-work/target-mips/cpu.h	2006-11-15 22:41:14.000000000 +0000
@@ -182,7 +182,6 @@
     uint32_t CP0_ErrorEPC;
     uint32_t CP0_DESAVE;
     /* Qemu */
-    struct QEMUTimer *timer; /* Internal timer */
     int interrupt_request;
     jmp_buf jmp_env;
     int exception_index;
@@ -213,6 +212,13 @@
     int halted; /* TRUE if the CPU is in suspend state */
 
     CPU_COMMON
+
+    int ram_size;
+    const char *kernel_filename;
+    const char *kernel_cmdline;
+    const char *initrd_filename;
+
+    struct QEMUTimer *timer; /* Internal timer */
 };
 
 #include "cpu-all.h"
Index: qemu-work/target-mips/translate.c
===================================================================
--- qemu-work.orig/target-mips/translate.c	2006-11-15 22:41:04.000000000 +0000
+++ qemu-work/target-mips/translate.c	2006-11-15 22:41:14.000000000 +0000
@@ -2425,7 +2425,16 @@
     if (!env)
         return NULL;
     cpu_exec_init(env);
+    cpu_reset(env);
+    return env;
+}
+
+void cpu_reset (CPUMIPSState *env)
+{
+    memset(env, 0, offsetof(CPUMIPSState, breakpoints));
+
     tlb_flush(env, 1);
+
     /* Minimal init */
     env->PC = 0xBFC00000;
 #if defined (MIPS_USES_R4K_TLB)
@@ -2456,5 +2465,4 @@
 #ifdef MIPS_USES_FPU
     env->fcr0 = MIPS_FCR0;	
 #endif
-    return env;
 }

             reply	other threads:[~2006-11-21 14:37 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-11-21 14:37 Thiemo Seufer [this message]
2006-11-28 17:55 ` [Qemu-devel] [PATCH 2/6] A cumulative MIPS patchset Stefan Weil
2006-11-28 18:47   ` Thiemo Seufer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20061121143736.GC12745@networkno.de \
    --to=ths@networkno.de \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.