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";
Date: Sat, 11 Nov 2006 20:02:40 -0500 From: Daniel Jacobowitz <[EMAIL PROTECTED]> 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; }
_______________________________________________ Qemu-devel mailing list Qemu-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/qemu-devel