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:44:43 +0000 [thread overview]
Message-ID: <20061121144443.GF12745@networkno.de> (raw)
[-- Attachment #1: Type: text/plain, Size: 18616 bytes --]
Hello All,
this patch inlines mtc0 instructions for the MIPS system emulation.
Thiemo
Index: qemu-work/target-mips/exec.h
===================================================================
--- qemu-work.orig/target-mips/exec.h 2006-11-17 16:02:11.000000000 +0000
+++ qemu-work/target-mips/exec.h 2006-11-17 16:02:11.000000000 +0000
@@ -68,7 +68,8 @@
#endif
void do_mfc0_random(void);
void do_mfc0_count(void);
-void do_mtc0(int reg, int sel);
+void do_mtc0_status_debug(uint32_t old, uint32_t val);
+void do_mtc0_status_irqraise_debug(void);
void do_tlbwi (void);
void do_tlbwr (void);
void do_tlbp (void);
Index: qemu-work/target-mips/op.c
===================================================================
--- qemu-work.orig/target-mips/op.c 2006-11-17 16:02:11.000000000 +0000
+++ qemu-work/target-mips/op.c 2006-11-17 16:02:11.000000000 +0000
@@ -852,9 +852,185 @@
RETURN();
}
-void op_mtc0 (void)
+void op_mtc0_index (void)
{
- CALL_FROM_TB2(do_mtc0, PARAM1, PARAM2);
+ env->CP0_index = (env->CP0_index & 0x80000000) | (T0 & 0x0000000F);
+ RETURN();
+}
+
+void op_mtc0_entrylo0 (void)
+{
+ env->CP0_EntryLo0 = T0 & 0x3FFFFFFF;
+ RETURN();
+}
+
+void op_mtc0_entrylo1 (void)
+{
+ env->CP0_EntryLo1 = T0 & 0x3FFFFFFF;
+ RETURN();
+}
+
+void op_mtc0_context (void)
+{
+ env->CP0_Context = (env->CP0_Context & 0xFF800000) | (T0 & 0x007FFFF0);
+ RETURN();
+}
+
+void op_mtc0_pagemask (void)
+{
+ env->CP0_PageMask = T0 & 0x01FFE000;
+ RETURN();
+}
+
+void op_mtc0_wired (void)
+{
+ env->CP0_Wired = T0 & 0x0000000F;
+ RETURN();
+}
+
+void op_mtc0_count (void)
+{
+ CALL_FROM_TB2(cpu_mips_store_count, env, T0);
+ RETURN();
+}
+
+void op_mtc0_entryhi (void)
+{
+ uint32_t old, val;
+
+ val = T0 & 0xFFFFE0FF;
+ old = env->CP0_EntryHi;
+ env->CP0_EntryHi = val;
+ /* If the ASID changes, flush qemu's TLB. */
+ if ((old & 0xFF) != (val & 0xFF))
+ CALL_FROM_TB2(cpu_mips_tlb_flush, env, 1);
+ RETURN();
+}
+
+void op_mtc0_compare (void)
+{
+ CALL_FROM_TB2(cpu_mips_store_compare, env, T0);
+ RETURN();
+}
+
+void op_mtc0_status (void)
+{
+ uint32_t val, old, mask;
+
+ val = T0 & 0xFA78FF01;
+ old = env->CP0_Status;
+ if (T0 & (1 << CP0St_UM))
+ env->hflags |= MIPS_HFLAG_UM;
+ else
+ env->hflags &= ~MIPS_HFLAG_UM;
+ if (T0 & (1 << CP0St_ERL))
+ env->hflags |= MIPS_HFLAG_ERL;
+ else
+ env->hflags &= ~MIPS_HFLAG_ERL;
+ if (T0 & (1 << CP0St_EXL))
+ env->hflags |= MIPS_HFLAG_EXL;
+ else
+ env->hflags &= ~MIPS_HFLAG_EXL;
+ env->CP0_Status = val;
+ /* If we unmasked an asserted IRQ, raise it */
+ mask = 0x0000FF00;
+ if (loglevel & CPU_LOG_TB_IN_ASM)
+ CALL_FROM_TB2(do_mtc0_status_debug, old, val);
+ if ((val & (1 << CP0St_IE)) && !(old & (1 << CP0St_IE)) &&
+ !(env->hflags & MIPS_HFLAG_EXL) &&
+ !(env->hflags & MIPS_HFLAG_ERL) &&
+ !(env->hflags & MIPS_HFLAG_DM) &&
+ (env->CP0_Status & env->CP0_Cause & mask)) {
+ env->interrupt_request |= CPU_INTERRUPT_HARD;
+ if (logfile)
+ CALL_FROM_TB0(do_mtc0_status_irqraise_debug);
+ } else if (!(val & (1 << CP0St_IE)) && (old & (1 << CP0St_IE))) {
+ env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+ }
+ RETURN();
+}
+
+void op_mtc0_cause (void)
+{
+ uint32_t val, old;
+
+ val = (env->CP0_Cause & 0xB000F87C) | (T0 & 0x000C00300);
+ old = env->CP0_Cause;
+ env->CP0_Cause = val;
+#if 0
+ {
+ int i, mask;
+
+ /* Check if we ever asserted a software IRQ */
+ for (i = 0; i < 2; i++) {
+ mask = 0x100 << i;
+ if ((val & mask) & !(old & mask))
+ CALL_FROM_TB1(mips_set_irq, i);
+ }
+ }
+#endif
+ RETURN();
+}
+
+void op_mtc0_epc (void)
+{
+ env->CP0_EPC = T0;
+ RETURN();
+}
+
+void op_mtc0_config0 (void)
+{
+#if defined(MIPS_USES_R4K_TLB)
+ env->CP0_Config0 = (env->CP0_Config0 & 0x8017FF80) | (T0 & 0x7E000001);
+#else
+ env->CP0_Config0 = (env->CP0_Config0 & 0xFE17FF80) | (T0 & 0x00000001);
+#endif
+ RETURN();
+}
+
+void op_mtc0_watchlo (void)
+{
+ env->CP0_WatchLo = T0;
+ RETURN();
+}
+
+void op_mtc0_watchhi (void)
+{
+ env->CP0_WatchHi = T0 & 0x40FF0FF8;
+ RETURN();
+}
+
+void op_mtc0_debug (void)
+{
+ env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120);
+ if (T0 & (1 << CP0DB_DM))
+ env->hflags |= MIPS_HFLAG_DM;
+ else
+ env->hflags &= ~MIPS_HFLAG_DM;
+ RETURN();
+}
+
+void op_mtc0_depc (void)
+{
+ env->CP0_DEPC = T0;
+ RETURN();
+}
+
+void op_mtc0_taglo (void)
+{
+ env->CP0_TagLo = T0 & 0xFFFFFCF6;
+ RETURN();
+}
+
+void op_mtc0_errorepc (void)
+{
+ env->CP0_ErrorEPC = T0;
+ RETURN();
+}
+
+void op_mtc0_desave (void)
+{
+ env->CP0_DESAVE = T0;
RETURN();
}
Index: qemu-work/target-mips/op_helper.c
===================================================================
--- qemu-work.orig/target-mips/op_helper.c 2006-11-17 16:02:11.000000000 +0000
+++ qemu-work/target-mips/op_helper.c 2006-11-17 19:47:10.000000000 +0000
@@ -142,9 +142,24 @@
cpu_abort(env, "mfc0 count\n");
}
-void do_mtc0 (int reg, int sel)
+void cpu_mips_store_count(CPUState *env, uint32_t value)
{
- cpu_abort(env, "mtc0 reg=%d sel=%d\n", reg, sel);
+ cpu_abort(env, "mtc0 count\n");
+}
+
+void cpu_mips_store_compare(CPUState *env, uint32_t value)
+{
+ cpu_abort(env, "mtc0 compare\n");
+}
+
+void do_mtc0_status_debug(uint32_t old, uint32_t val)
+{
+ cpu_abort(env, "mtc0 status\n");
+}
+
+void do_mtc0_status_irqraise_debug(void)
+{
+ cpu_abort(env, "mtc0 status\n");
}
void do_tlbwi (void)
@@ -167,6 +182,11 @@
cpu_abort(env, "tlbr\n");
}
+void cpu_mips_tlb_flush (CPUState *env, int flush_global)
+{
+ cpu_abort(env, "mips_tlb_flush\n");
+}
+
#else
/* CP0 helpers */
@@ -180,225 +200,20 @@
T0 = cpu_mips_get_count(env);
}
-void do_mtc0 (int reg, int sel)
+void do_mtc0_status_debug(uint32_t old, uint32_t val)
{
- const unsigned char *rn;
- uint32_t val, old, mask;
+ const uint32_t mask = 0x0000FF00;
+ fprintf(logfile, "Status %08x => %08x Cause %08x (%08x %08x %08x)\n",
+ old, val, env->CP0_Cause, old & mask, val & mask,
+ env->CP0_Cause & mask);
+}
- if (sel != 0 && reg != 16 && reg != 28) {
- val = -1;
- old = -1;
- rn = "invalid";
- goto print;
- }
- switch (reg) {
- case 0:
- val = (env->CP0_index & 0x80000000) | (T0 & 0x0000000F);
- old = env->CP0_index;
- env->CP0_index = val;
- rn = "Index";
- break;
- case 2:
- val = T0 & 0x3FFFFFFF;
- old = env->CP0_EntryLo0;
- env->CP0_EntryLo0 = val;
- rn = "EntryLo0";
- break;
- case 3:
- val = T0 & 0x3FFFFFFF;
- old = env->CP0_EntryLo1;
- env->CP0_EntryLo1 = val;
- rn = "EntryLo1";
- break;
- case 4:
- val = (env->CP0_Context & 0xFF800000) | (T0 & 0x007FFFF0);
- old = env->CP0_Context;
- env->CP0_Context = val;
- rn = "Context";
- break;
- case 5:
- val = T0 & 0x01FFE000;
- old = env->CP0_PageMask;
- env->CP0_PageMask = val;
- rn = "PageMask";
- break;
- case 6:
- val = T0 & 0x0000000F;
- old = env->CP0_Wired;
- env->CP0_Wired = val;
- rn = "Wired";
- break;
- case 9:
- val = T0;
- old = cpu_mips_get_count(env);
- cpu_mips_store_count(env, val);
- rn = "Count";
- break;
- case 10:
- val = T0 & 0xFFFFE0FF;
- old = env->CP0_EntryHi;
- env->CP0_EntryHi = val;
- /* If the ASID changes, flush qemu's TLB. */
- if ((old & 0xFF) != (val & 0xFF))
- cpu_mips_tlb_flush (env, 1);
- rn = "EntryHi";
- break;
- case 11:
- val = T0;
- old = env->CP0_Compare;
- cpu_mips_store_compare(env, val);
- rn = "Compare";
- break;
- case 12:
- val = T0 & 0xFA78FF01;
- if (T0 & (1 << CP0St_UM))
- env->hflags |= MIPS_HFLAG_UM;
- else
- env->hflags &= ~MIPS_HFLAG_UM;
- if (T0 & (1 << CP0St_ERL))
- env->hflags |= MIPS_HFLAG_ERL;
- else
- env->hflags &= ~MIPS_HFLAG_ERL;
- if (T0 & (1 << CP0St_EXL))
- env->hflags |= MIPS_HFLAG_EXL;
- else
- env->hflags &= ~MIPS_HFLAG_EXL;
- old = env->CP0_Status;
- env->CP0_Status = val;
- /* If we unmasked an asserted IRQ, raise it */
- mask = 0x0000FF00;
- if (loglevel & CPU_LOG_TB_IN_ASM) {
- fprintf(logfile, "Status %08x => %08x Cause %08x (%08x %08x %08x)\n",
- old, val, env->CP0_Cause, old & mask, val & mask,
- env->CP0_Cause & mask);
- }
- if ((val & (1 << CP0St_IE)) && !(old & (1 << CP0St_IE)) &&
- !(env->hflags & MIPS_HFLAG_EXL) &&
- !(env->hflags & MIPS_HFLAG_ERL) &&
- !(env->hflags & MIPS_HFLAG_DM) &&
- (env->CP0_Status & env->CP0_Cause & mask)) {
- if (logfile)
- fprintf(logfile, "Raise pending IRQs\n");
- env->interrupt_request |= CPU_INTERRUPT_HARD;
- } else if (!(val & (1 << CP0St_IE)) && (old & (1 << CP0St_IE))) {
- env->interrupt_request &= ~CPU_INTERRUPT_HARD;
- }
- rn = "Status";
- break;
- case 13:
- val = (env->CP0_Cause & 0xB000F87C) | (T0 & 0x000C00300);
- old = env->CP0_Cause;
- env->CP0_Cause = val;
-#if 0
- {
- int i;
- /* Check if we ever asserted a software IRQ */
- for (i = 0; i < 2; i++) {
- mask = 0x100 << i;
- if ((val & mask) & !(old & mask))
- mips_set_irq(i);
- }
- }
-#endif
- rn = "Cause";
- break;
- case 14:
- val = T0;
- old = env->CP0_EPC;
- env->CP0_EPC = val;
- rn = "EPC";
- break;
- case 16:
- switch (sel) {
- case 0:
-#if defined(MIPS_USES_R4K_TLB)
- val = (env->CP0_Config0 & 0x8017FF80) | (T0 & 0x7E000001);
-#else
- val = (env->CP0_Config0 & 0xFE17FF80) | (T0 & 0x00000001);
-#endif
- old = env->CP0_Config0;
- env->CP0_Config0 = val;
- rn = "Config0";
- break;
- default:
- val = -1;
- old = -1;
- rn = "bad config selector";
- break;
- }
- break;
- case 18:
- val = T0;
- old = env->CP0_WatchLo;
- env->CP0_WatchLo = val;
- rn = "WatchLo";
- break;
- case 19:
- val = T0 & 0x40FF0FF8;
- old = env->CP0_WatchHi;
- env->CP0_WatchHi = val;
- rn = "WatchHi";
- break;
- case 23:
- val = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120);
- if (T0 & (1 << CP0DB_DM))
- env->hflags |= MIPS_HFLAG_DM;
- else
- env->hflags &= ~MIPS_HFLAG_DM;
- old = env->CP0_Debug;
- env->CP0_Debug = val;
- rn = "Debug";
- break;
- case 24:
- val = T0;
- old = env->CP0_DEPC;
- env->CP0_DEPC = val;
- rn = "DEPC";
- break;
- case 28:
- switch (sel) {
- case 0:
- val = T0 & 0xFFFFFCF6;
- old = env->CP0_TagLo;
- env->CP0_TagLo = val;
- rn = "TagLo";
- break;
- default:
- val = -1;
- old = -1;
- rn = "invalid sel";
- break;
- }
- break;
- case 30:
- val = T0;
- old = env->CP0_ErrorEPC;
- env->CP0_ErrorEPC = val;
- rn = "EPC";
- break;
- case 31:
- val = T0;
- old = env->CP0_DESAVE;
- env->CP0_DESAVE = val;
- rn = "DESAVE";
- break;
- default:
- val = -1;
- old = -1;
- rn = "unknown";
- break;
- }
- print:
-#if defined MIPS_DEBUG_DISAS
- if (loglevel & CPU_LOG_TB_IN_ASM) {
- fprintf(logfile, "%08x mtc0 %s %08x => %08x (%d %d %08x)\n",
- env->PC, rn, T0, val, reg, sel, old);
- }
-#endif
- return;
+void do_mtc0_status_irqraise_debug(void)
+{
+ fprintf(logfile, "Raise pending IRQs\n");
}
-#ifdef MIPS_USES_FPU
+# ifdef MIPS_USES_FPU
#include "softfloat.h"
void fpu_handle_exception(void)
Index: qemu-work/target-mips/translate.c
===================================================================
--- qemu-work.orig/target-mips/translate.c 2006-11-17 16:02:11.000000000 +0000
+++ qemu-work/target-mips/translate.c 2006-11-17 16:02:11.000000000 +0000
@@ -1371,6 +1371,8 @@
rn = "EntryLo0";
break;
case 3:
+//
+ /* also CONF */
gen_op_mfc0_entrylo1();
rn = "EntryLo1";
break;
@@ -1386,6 +1388,10 @@
gen_op_mfc0_wired();
rn = "Wired";
break;
+ case 7:
+// gen_op_mfc0_info();
+ rn = "Info";
+ break;
case 8:
gen_op_mfc0_badvaddr();
rn = "BadVaddr";
@@ -1445,6 +1451,19 @@
gen_op_mfc0_watchhi();
rn = "WatchHi";
break;
+ case 20:
+ /* 64 bit only */
+// gen_op_mfc0_xcontext();
+ rn = "XContext";
+ break;
+ case 21:
+// gen_op_mfc0_framemask();
+ rn = "Framemask";
+ break;
+ case 22:
+// gen_op_mfc0_diagnostic();
+ rn = "'Diagnostic";
+ break;
case 23:
gen_op_mfc0_debug();
rn = "Debug";
@@ -1453,6 +1472,18 @@
gen_op_mfc0_depc();
rn = "DEPC";
break;
+ case 25:
+// gen_op_mfc0_performance();
+ rn = "Performance";
+ break;
+ case 26:
+// gen_op_mfc0_ecc();
+ rn = "ECC";
+ break;
+ case 27:
+// gen_op_mfc0_cacheerr();
+ rn = "CacheErr";
+ break;
case 28:
switch (sel) {
case 0:
@@ -1468,6 +1499,10 @@
goto die;
}
break;
+ case 29:
+// gen_op_mfc0_taghi();
+ rn = "TagHi";
+ break;
case 30:
gen_op_mfc0_errorepc();
rn = "ErrorEPC";
@@ -1498,6 +1533,183 @@
generate_exception(ctx, EXCP_RI);
}
+static void gen_mtc0 (DisasContext *ctx, int reg, int sel)
+{
+ const unsigned char *rn;
+ uint32_t val, old;
+
+ if (sel != 0 && reg != 16 && reg != 28) {
+ val = -1;
+ old = -1;
+ rn = "invalid";
+ goto die;
+ }
+ switch (reg) {
+ case 0:
+ gen_op_mtc0_index();
+ rn = "Index";
+ break;
+ case 1:
+// ignore or except?
+ rn = "Random";
+ break;
+ case 2:
+ gen_op_mtc0_entrylo0();
+ rn = "EntryLo0";
+ break;
+ case 3:
+ gen_op_mtc0_entrylo1();
+ rn = "EntryLo1";
+ break;
+ case 4:
+ gen_op_mtc0_context();
+ rn = "Context";
+ break;
+ case 5:
+ gen_op_mtc0_pagemask();
+ rn = "PageMask";
+ break;
+ case 6:
+ gen_op_mtc0_wired();
+ rn = "Wired";
+ break;
+ case 7:
+// ignore or except?
+ rn = "Info";
+ break;
+ case 8:
+// ignore or except?
+ rn = "BadVaddr";
+ break;
+ case 9:
+ gen_op_mtc0_count();
+ rn = "Count";
+ break;
+ case 10:
+ gen_op_mtc0_entryhi();
+ rn = "EntryHi";
+ break;
+ case 11:
+ gen_op_mtc0_compare();
+ rn = "Compare";
+ break;
+ case 12:
+ gen_op_mtc0_status();
+ rn = "Status";
+ break;
+ case 13:
+ gen_op_mtc0_cause();
+ rn = "Cause";
+ break;
+ case 14:
+ gen_op_mtc0_epc();
+ rn = "EPC";
+ break;
+ case 15:
+// ignore or except?
+ rn = "PRid";
+ break;
+ case 16:
+ switch (sel) {
+ case 0:
+ gen_op_mtc0_config0();
+ rn = "Config0";
+ break;
+ default:
+ rn = "Invalid config selector";
+ goto die;
+ }
+ break;
+ case 17:
+// ignore or except?
+ rn = "LLaddr";
+ break;
+ case 18:
+ gen_op_mtc0_watchlo();
+ rn = "WatchLo";
+ break;
+ case 19:
+ gen_op_mtc0_watchhi();
+ rn = "WatchHi";
+ break;
+ case 20:
+ /* 64 bit only */
+// gen_op_mtc0_xcontext();
+ rn = "XContext";
+ break;
+ case 21:
+// gen_op_mtc0_framemask();
+ rn = "Framemask";
+ break;
+ case 22:
+// ignore or except?
+ rn = "Diagnostic";
+ break;
+ case 23:
+ gen_op_mtc0_debug();
+ rn = "Debug";
+ break;
+ case 24:
+ gen_op_mtc0_depc();
+ rn = "DEPC";
+ break;
+ case 25:
+// ignore or except?
+ rn = "Performance";
+ break;
+ case 26:
+// ignore or except?
+ rn = "ECC";
+ break;
+ case 27:
+// ignore or except?
+ rn = "CacheErr";
+ break;
+ case 28:
+ switch (sel) {
+ case 0:
+ gen_op_mtc0_taglo();
+ rn = "TagLo";
+ break;
+ default:
+ rn = "invalid sel";
+ goto die;
+ }
+ break;
+ case 29:
+// gen_op_mtc0_taghi();
+ rn = "TagHi";
+ break;
+ case 30:
+ gen_op_mtc0_errorepc();
+ rn = "ErrorEPC";
+ break;
+ case 31:
+ gen_op_mtc0_desave();
+ rn = "DESAVE";
+ break;
+ default:
+ rn = "unknown";
+ goto die;
+ }
+#if defined MIPS_DEBUG_DISAS
+ if (loglevel & CPU_LOG_TB_IN_ASM) {
+ fprintf(logfile, "%08x mtc0 %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 mtc0 %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";
@@ -1529,7 +1741,7 @@
save_cpu_state(ctx, 1);
ctx->pc -= 4;
GEN_LOAD_REG_TN(T0, rt);
- gen_op_mtc0(rd, ctx->opcode & 0x7);
+ gen_mtc0(ctx, rd, ctx->opcode & 0x7);
/* Stop translation as we may have switched the execution mode */
ctx->bstate = BS_STOP;
opn = "mtc0";
[-- 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:47 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-11-21 14:44 Thiemo Seufer [this message]
-- strict thread matches above, loose matches on Subject: below --
2006-11-21 14:43 [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=20061121144443.GF12745@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.