* [Qemu-devel] [PATCH 2/6] A cumulative MIPS patchset
@ 2006-11-21 14:37 Thiemo Seufer
2006-11-28 17:55 ` Stefan Weil
0 siblings, 1 reply; 3+ messages in thread
From: Thiemo Seufer @ 2006-11-21 14:37 UTC (permalink / raw)
To: qemu-devel
[-- 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;
}
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [Qemu-devel] [PATCH 2/6] A cumulative MIPS patchset
2006-11-21 14:37 [Qemu-devel] [PATCH 2/6] A cumulative MIPS patchset Thiemo Seufer
@ 2006-11-28 17:55 ` Stefan Weil
2006-11-28 18:47 ` Thiemo Seufer
0 siblings, 1 reply; 3+ messages in thread
From: Stefan Weil @ 2006-11-28 17:55 UTC (permalink / raw)
To: qemu-devel
Hello Thiemo,
my reboot patch for MIPS
(http://lists.gnu.org/archive/html/qemu-devel/2006-09/msg00082.html)
is only partially included in Daniel's patch.
As far as I know, a MIPS triggers the reboot exception at power-on.
(at least for MIPS 4KEc), so my patch uses the same code for reboot
exception and power-on.
Why do we need a special QEMU reset device in the Linux kernel?
QEMU might emulate existing real reset devices as well...
Stefan
Thiemo Seufer schrieb:
> Hello All,
>
> the attached patch is an update of Daniel's reboot/halt
> implementation for the MIPS qemu.
>
>
> Thiemo
>
> ------------------------------------------------------------------------
>
> 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.
>
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> Qemu-devel mailing list
> Qemu-devel@nongnu.org
> http://lists.nongnu.org/mailman/listinfo/qemu-devel
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [Qemu-devel] [PATCH 2/6] A cumulative MIPS patchset
2006-11-28 17:55 ` Stefan Weil
@ 2006-11-28 18:47 ` Thiemo Seufer
0 siblings, 0 replies; 3+ messages in thread
From: Thiemo Seufer @ 2006-11-28 18:47 UTC (permalink / raw)
To: Stefan Weil; +Cc: qemu-devel
Stefan Weil wrote:
> Hello Thiemo,
>
> my reboot patch for MIPS
> (http://lists.gnu.org/archive/html/qemu-devel/2006-09/msg00082.html)
> is only partially included in Daniel's patch.
>
> As far as I know, a MIPS triggers the reboot exception at power-on.
> (at least for MIPS 4KEc), so my patch uses the same code for reboot
> exception and power-on.
Actually, a MIPS has no notion of "reboot". Is starts up by executing
from the reset vector at 0xbfc00000, which is the place where the
firmware ROM resides. A "soft reset" exception could be used to signal
reboot, but that is then handled by software, and system specific.
> Why do we need a special QEMU reset device in the Linux kernel?
> QEMU might emulate existing real reset devices as well...
Because we want to have both reboot and halt for linux, and ATM
we have no firmware in Qemu to handle that.
Given the number of incompatible MIPS firmwares out there it might
be a bad idea to rely on any of those, unless we improve the Qemu
emulation to resemble a real system with its respective firmware.
Thiemo
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2006-11-28 18:47 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-11-21 14:37 [Qemu-devel] [PATCH 2/6] A cumulative MIPS patchset Thiemo Seufer
2006-11-28 17:55 ` Stefan Weil
2006-11-28 18:47 ` Thiemo Seufer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).