From: Thiemo Seufer <ths@networkno.de>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH 4/6] A cumulative MIPS patchset
Date: Tue, 21 Nov 2006 14:43:31 +0000 [thread overview]
Message-ID: <20061121144331.GE12745@networkno.de> (raw)
[-- Attachment #1: Type: text/plain, Size: 11339 bytes --]
Hello All,
this patch inlines mfc0 instructions for the MIPS system emulation.
Thiemo
Index: qemu-work/target-mips/exec.h
===================================================================
--- qemu-work.orig/target-mips/exec.h 2006-11-15 22:41:21.000000000 +0000
+++ qemu-work/target-mips/exec.h 2006-11-15 22:41:24.000000000 +0000
@@ -66,7 +66,8 @@
void do_msub (void);
void do_msubu (void);
#endif
-void do_mfc0(int reg, int sel);
+void do_mfc0_random(void);
+void do_mfc0_count(void);
void do_mtc0(int reg, int sel);
void do_tlbwi (void);
void do_tlbwr (void);
Index: qemu-work/target-mips/op.c
===================================================================
--- qemu-work.orig/target-mips/op.c 2006-11-15 22:41:18.000000000 +0000
+++ qemu-work/target-mips/op.c 2006-11-15 22:41:24.000000000 +0000
@@ -688,9 +688,167 @@
}
/* CP0 functions */
-void op_mfc0 (void)
+void op_mfc0_index (void)
{
- CALL_FROM_TB2(do_mfc0, PARAM1, PARAM2);
+ T0 = env->CP0_index;
+ RETURN();
+}
+
+void op_mfc0_random (void)
+{
+ CALL_FROM_TB0(do_mfc0_random);
+ RETURN();
+}
+
+void op_mfc0_entrylo0 (void)
+{
+ T0 = env->CP0_EntryLo0;
+ RETURN();
+}
+
+void op_mfc0_entrylo1 (void)
+{
+ T0 = env->CP0_EntryLo1;
+ RETURN();
+}
+
+void op_mfc0_context (void)
+{
+ T0 = env->CP0_Context;
+ RETURN();
+}
+
+void op_mfc0_pagemask (void)
+{
+ T0 = env->CP0_PageMask;
+ RETURN();
+}
+
+void op_mfc0_wired (void)
+{
+ T0 = env->CP0_Wired;
+ RETURN();
+}
+
+void op_mfc0_badvaddr (void)
+{
+ T0 = env->CP0_BadVAddr;
+ RETURN();
+}
+
+void op_mfc0_count (void)
+{
+ CALL_FROM_TB0(do_mfc0_count);
+ RETURN();
+}
+
+void op_mfc0_entryhi (void)
+{
+ T0 = env->CP0_EntryHi;
+ RETURN();
+}
+
+void op_mfc0_compare (void)
+{
+ T0 = env->CP0_Compare;
+ RETURN();
+}
+
+void op_mfc0_status (void)
+{
+ T0 = env->CP0_Status;
+ if (env->hflags & MIPS_HFLAG_UM)
+ T0 |= (1 << CP0St_UM);
+ if (env->hflags & MIPS_HFLAG_ERL)
+ T0 |= (1 << CP0St_ERL);
+ if (env->hflags & MIPS_HFLAG_EXL)
+ T0 |= (1 << CP0St_EXL);
+ RETURN();
+}
+
+void op_mfc0_cause (void)
+{
+ T0 = env->CP0_Cause;
+ RETURN();
+}
+
+void op_mfc0_epc (void)
+{
+ T0 = env->CP0_EPC;
+ RETURN();
+}
+
+void op_mfc0_prid (void)
+{
+ T0 = env->CP0_PRid;
+ RETURN();
+}
+
+void op_mfc0_config0 (void)
+{
+ T0 = env->CP0_Config0;
+ RETURN();
+}
+
+void op_mfc0_config1 (void)
+{
+ T0 = env->CP0_Config1;
+ RETURN();
+}
+
+void op_mfc0_lladdr (void)
+{
+ T0 = env->CP0_LLAddr >> 4;
+ RETURN();
+}
+
+void op_mfc0_watchlo (void)
+{
+ T0 = env->CP0_WatchLo;
+ RETURN();
+}
+
+void op_mfc0_watchhi (void)
+{
+ T0 = env->CP0_WatchHi;
+ RETURN();
+}
+
+void op_mfc0_debug (void)
+{
+ T0 = env->CP0_Debug;
+ if (env->hflags & MIPS_HFLAG_DM)
+ T0 |= 1 << CP0DB_DM;
+ RETURN();
+}
+
+void op_mfc0_depc (void)
+{
+ T0 = env->CP0_DEPC;
+ RETURN();
+}
+
+void op_mfc0_taglo (void)
+{
+ T0 = env->CP0_TagLo;
+ RETURN();
+}
+
+void op_mfc0_datalo (void)
+{
+ T0 = env->CP0_DataLo;
+ RETURN();
+}
+
+void op_mfc0_errorepc (void)
+{
+ T0 = env->CP0_ErrorEPC;
+ RETURN();
+}
+
+void op_mfc0_desave (void)
+{
+ T0 = env->CP0_DESAVE;
RETURN();
}
Index: qemu-work/target-mips/op_helper.c
===================================================================
--- qemu-work.orig/target-mips/op_helper.c 2006-11-15 22:41:04.000000000 +0000
+++ qemu-work/target-mips/op_helper.c 2006-11-15 22:41:24.000000000 +0000
@@ -132,10 +132,16 @@
#endif
#if defined(CONFIG_USER_ONLY)
-void do_mfc0 (int reg, int sel)
+void do_mfc0_random (void)
{
- cpu_abort(env, "mfc0 reg=%d sel=%d\n", reg, sel);
+ cpu_abort(env, "mfc0 random\n");
}
+
+void do_mfc0_count (void)
+{
+ cpu_abort(env, "mfc0 count\n");
+}
+
void do_mtc0 (int reg, int sel)
{
cpu_abort(env, "mtc0 reg=%d sel=%d\n", reg, sel);
@@ -160,152 +166,18 @@
{
cpu_abort(env, "tlbr\n");
}
+
#else
/* CP0 helpers */
-void do_mfc0 (int reg, int sel)
+void do_mfc0_random (void)
{
- const unsigned char *rn;
+ T0 = cpu_mips_get_random(env);
+}
- if (sel != 0 && reg != 16 && reg != 28) {
- rn = "invalid";
- goto print;
- }
- switch (reg) {
- case 0:
- T0 = env->CP0_index;
- rn = "Index";
- break;
- case 1:
- T0 = cpu_mips_get_random(env);
- rn = "Random";
- break;
- case 2:
- T0 = env->CP0_EntryLo0;
- rn = "EntryLo0";
- break;
- case 3:
- T0 = env->CP0_EntryLo1;
- rn = "EntryLo1";
- break;
- case 4:
- T0 = env->CP0_Context;
- rn = "Context";
- break;
- case 5:
- T0 = env->CP0_PageMask;
- rn = "PageMask";
- break;
- case 6:
- T0 = env->CP0_Wired;
- rn = "Wired";
- break;
- case 8:
- T0 = env->CP0_BadVAddr;
- rn = "BadVaddr";
- break;
- case 9:
- T0 = cpu_mips_get_count(env);
- rn = "Count";
- break;
- case 10:
- T0 = env->CP0_EntryHi;
- rn = "EntryHi";
- break;
- case 11:
- T0 = env->CP0_Compare;
- rn = "Compare";
- break;
- case 12:
- T0 = env->CP0_Status;
- if (env->hflags & MIPS_HFLAG_UM)
- T0 |= (1 << CP0St_UM);
- rn = "Status";
- break;
- case 13:
- T0 = env->CP0_Cause;
- rn = "Cause";
- break;
- case 14:
- T0 = env->CP0_EPC;
- rn = "EPC";
- break;
- case 15:
- T0 = env->CP0_PRid;
- rn = "PRid";
- break;
- case 16:
- switch (sel) {
- case 0:
- T0 = env->CP0_Config0;
- rn = "Config";
- break;
- case 1:
- T0 = env->CP0_Config1;
- rn = "Config1";
- break;
- default:
- rn = "Unknown config register";
- break;
- }
- break;
- case 17:
- T0 = env->CP0_LLAddr >> 4;
- rn = "LLAddr";
- break;
- case 18:
- T0 = env->CP0_WatchLo;
- rn = "WatchLo";
- break;
- case 19:
- T0 = env->CP0_WatchHi;
- rn = "WatchHi";
- break;
- case 23:
- T0 = env->CP0_Debug;
- if (env->hflags & MIPS_HFLAG_DM)
- T0 |= 1 << CP0DB_DM;
- rn = "Debug";
- break;
- case 24:
- T0 = env->CP0_DEPC;
- rn = "DEPC";
- break;
- case 28:
- switch (sel) {
- case 0:
- T0 = env->CP0_TagLo;
- rn = "TagLo";
- break;
- case 1:
- T0 = env->CP0_DataLo;
- rn = "DataLo";
- break;
- default:
- rn = "unknown sel";
- break;
- }
- break;
- case 30:
- T0 = env->CP0_ErrorEPC;
- rn = "ErrorEPC";
- break;
- case 31:
- T0 = env->CP0_DESAVE;
- rn = "DESAVE";
- break;
- default:
- rn = "unknown";
- break;
- }
- print:
-#if defined MIPS_DEBUG_DISAS
- if (loglevel & CPU_LOG_TB_IN_ASM) {
- fprintf(logfile, "%08x mfc0 %s => %08x (%d %d)\n",
- env->PC, rn, T0, reg, sel);
- }
-#endif
- return;
+void do_mfc0_count (void)
+{
+ T0 = cpu_mips_get_count(env);
}
void do_mtc0 (int reg, int sel)
Index: qemu-work/target-mips/translate.c
===================================================================
--- qemu-work.orig/target-mips/translate.c 2006-11-15 22:41:18.000000000 +0000
+++ qemu-work/target-mips/translate.c 2006-11-15 22:41:24.000000000 +0000
@@ -1349,6 +1349,155 @@
}
/* CP0 (MMU and control) */
+static void gen_mfc0 (DisasContext *ctx, int reg, int sel)
+{
+ const unsigned char *rn;
+
+ if (sel != 0 && reg != 16 && reg != 28) {
+ rn = "invalid";
+ goto die;
+ }
+ switch (reg) {
+ case 0:
+ gen_op_mfc0_index();
+ rn = "Index";
+ break;
+ case 1:
+ gen_op_mfc0_random();
+ rn = "Random";
+ break;
+ case 2:
+ gen_op_mfc0_entrylo0();
+ rn = "EntryLo0";
+ break;
+ case 3:
+ gen_op_mfc0_entrylo1();
+ rn = "EntryLo1";
+ break;
+ case 4:
+ gen_op_mfc0_context();
+ rn = "Context";
+ break;
+ case 5:
+ gen_op_mfc0_pagemask();
+ rn = "PageMask";
+ break;
+ case 6:
+ gen_op_mfc0_wired();
+ rn = "Wired";
+ break;
+ case 8:
+ gen_op_mfc0_badvaddr();
+ rn = "BadVaddr";
+ break;
+ case 9:
+ gen_op_mfc0_count();
+ rn = "Count";
+ break;
+ case 10:
+ gen_op_mfc0_entryhi();
+ rn = "EntryHi";
+ break;
+ case 11:
+ gen_op_mfc0_compare();
+ rn = "Compare";
+ break;
+ case 12:
+ gen_op_mfc0_status();
+ rn = "Status";
+ break;
+ case 13:
+ gen_op_mfc0_cause();
+ rn = "Cause";
+ break;
+ case 14:
+ gen_op_mfc0_epc();
+ rn = "EPC";
+ break;
+ case 15:
+ gen_op_mfc0_prid();
+ rn = "PRid";
+ break;
+ case 16:
+ switch (sel) {
+ case 0:
+ gen_op_mfc0_config0();
+ rn = "Config";
+ break;
+ case 1:
+ gen_op_mfc0_config1();
+ rn = "Config1";
+ break;
+ default:
+ rn = "Unknown config register";
+ goto die;
+ }
+ break;
+ case 17:
+ gen_op_mfc0_lladdr();
+ rn = "LLAddr";
+ break;
+ case 18:
+ gen_op_mfc0_watchlo();
+ rn = "WatchLo";
+ break;
+ case 19:
+ gen_op_mfc0_watchhi();
+ rn = "WatchHi";
+ break;
+ case 23:
+ gen_op_mfc0_debug();
+ rn = "Debug";
+ break;
+ case 24:
+ gen_op_mfc0_depc();
+ rn = "DEPC";
+ break;
+ case 28:
+ switch (sel) {
+ case 0:
+ gen_op_mfc0_taglo();
+ rn = "TagLo";
+ break;
+ case 1:
+ gen_op_mfc0_datalo();
+ rn = "DataLo";
+ break;
+ default:
+ rn = "unknown sel";
+ goto die;
+ }
+ break;
+ case 30:
+ gen_op_mfc0_errorepc();
+ rn = "ErrorEPC";
+ break;
+ case 31:
+ gen_op_mfc0_desave();
+ rn = "DESAVE";
+ break;
+ default:
+ rn = "unknown";
+ goto die;
+ }
+#if defined MIPS_DEBUG_DISAS
+ if (loglevel & CPU_LOG_TB_IN_ASM) {
+ fprintf(logfile, "%08x mfc0 %s => %08x (%d %d)\n",
+ env->PC, rn, T0, reg, sel);
+ }
+#endif
+ return;
+
+die:
+#if defined MIPS_DEBUG_DISAS
+ if (loglevel & CPU_LOG_TB_IN_ASM) {
+ fprintf(logfile, "%08x mfc0 %s => %08x (%d %d)\n",
+ env->PC, rn, T0, reg, sel);
+ }
+#endif
+ generate_exception(ctx, EXCP_RI);
+}
+
static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd)
{
const unsigned char *opn = "unk";
@@ -1370,7 +1519,7 @@
/* Treat as NOP */
return;
}
- gen_op_mfc0(rd, ctx->opcode & 0x7);
+ gen_mfc0(ctx, rd, ctx->opcode & 0x7);
gen_op_store_T0_gpr(rt);
opn = "mfc0";
break;
[-- 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;
}
next reply other threads:[~2006-11-21 14:44 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-11-21 14:43 Thiemo Seufer [this message]
-- strict thread matches above, loose matches on Subject: below --
2006-11-21 14:44 [Qemu-devel] [PATCH 4/6] A cumulative MIPS patchset 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=20061121144331.GE12745@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 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).