aboutsummaryrefslogtreecommitdiff
path: root/target-mips/machine.c
diff options
context:
space:
mode:
authorths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>2008-12-20 19:44:31 +0000
committerths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>2008-12-20 19:44:31 +0000
commit33a84765e34421dc4e009dea8176ac17474aff97 (patch)
tree03b5347b69728533cf4845a868c30acad94dc913 /target-mips/machine.c
parentf9480ffc140bbdde991fd33c534cc146501a1db0 (diff)
A first attempt on supporting snapshots for the MIPS target.
Signed-off-by: Thiemo Seufer <ths@networkno.de> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6112 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-mips/machine.c')
-rw-r--r--target-mips/machine.c291
1 files changed, 291 insertions, 0 deletions
diff --git a/target-mips/machine.c b/target-mips/machine.c
index 15ce73cd4b..543778dc5d 100644
--- a/target-mips/machine.c
+++ b/target-mips/machine.c
@@ -1,6 +1,8 @@
#include "hw/hw.h"
#include "hw/boards.h"
+#include "exec-all.h"
+
void register_machines(void)
{
qemu_register_machine(&mips_malta_machine);
@@ -10,11 +12,300 @@ void register_machines(void)
qemu_register_machine(&mips_machine);
}
+static void save_tc(QEMUFile *f, TCState *tc)
+{
+ int i;
+
+ /* Save active TC */
+ for(i = 0; i < 32; i++)
+ qemu_put_betls(f, &tc->gpr[i]);
+ qemu_put_betls(f, &tc->PC);
+ for(i = 0; i < MIPS_DSP_ACC; i++)
+ qemu_put_betls(f, &tc->HI[i]);
+ for(i = 0; i < MIPS_DSP_ACC; i++)
+ qemu_put_betls(f, &tc->LO[i]);
+ for(i = 0; i < MIPS_DSP_ACC; i++)
+ qemu_put_betls(f, &tc->ACX[i]);
+ qemu_put_betls(f, &tc->DSPControl);
+ qemu_put_sbe32s(f, &tc->CP0_TCStatus);
+ qemu_put_sbe32s(f, &tc->CP0_TCBind);
+ qemu_put_betls(f, &tc->CP0_TCHalt);
+ qemu_put_betls(f, &tc->CP0_TCContext);
+ qemu_put_betls(f, &tc->CP0_TCSchedule);
+ qemu_put_betls(f, &tc->CP0_TCScheFBack);
+ qemu_put_sbe32s(f, &tc->CP0_Debug_tcstatus);
+}
+
+static void save_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu)
+{
+ int i;
+
+ for(i = 0; i < 32; i++)
+ qemu_put_be64s(f, &fpu->fpr[i].d);
+ qemu_put_s8s(f, &fpu->fp_status.float_detect_tininess);
+ qemu_put_s8s(f, &fpu->fp_status.float_rounding_mode);
+ qemu_put_s8s(f, &fpu->fp_status.float_exception_flags);
+ qemu_put_be32s(f, &fpu->fcr0);
+ qemu_put_be32s(f, &fpu->fcr31);
+}
+
void cpu_save(QEMUFile *f, void *opaque)
{
+ CPUState *env = opaque;
+ int i;
+
+ /* Save active TC */
+ save_tc(f, &env->active_tc);
+
+ /* Save active FPU */
+ save_fpu(f, &env->active_fpu);
+
+ /* Save MVP */
+ qemu_put_sbe32s(f, &env->mvp->CP0_MVPControl);
+ qemu_put_sbe32s(f, &env->mvp->CP0_MVPConf0);
+ qemu_put_sbe32s(f, &env->mvp->CP0_MVPConf1);
+
+ /* Save TLB */
+ qemu_put_be32s(f, &env->tlb->nb_tlb);
+ qemu_put_be32s(f, &env->tlb->tlb_in_use);
+ for(i = 0; i < MIPS_TLB_MAX; i++) {
+ uint16_t flags = ((env->tlb->mmu.r4k.tlb[i].G << 10) |
+ (env->tlb->mmu.r4k.tlb[i].C0 << 7) |
+ (env->tlb->mmu.r4k.tlb[i].C1 << 4) |
+ (env->tlb->mmu.r4k.tlb[i].V0 << 3) |
+ (env->tlb->mmu.r4k.tlb[i].V1 << 2) |
+ (env->tlb->mmu.r4k.tlb[i].D0 << 1) |
+ (env->tlb->mmu.r4k.tlb[i].D1 << 0));
+
+ qemu_put_betls(f, &env->tlb->mmu.r4k.tlb[i].VPN);
+ qemu_put_be32s(f, &env->tlb->mmu.r4k.tlb[i].PageMask);
+ qemu_put_8s(f, &env->tlb->mmu.r4k.tlb[i].ASID);
+ qemu_put_be16s(f, &flags);
+ qemu_put_betls(f, &env->tlb->mmu.r4k.tlb[i].PFN[0]);
+ qemu_put_betls(f, &env->tlb->mmu.r4k.tlb[i].PFN[1]);
+ }
+
+ /* Save CPU metastate */
+ qemu_put_be32s(f, &env->current_tc);
+ qemu_put_be32s(f, &env->current_fpu);
+ qemu_put_sbe32s(f, &env->error_code);
+ qemu_put_be32s(f, &env->hflags);
+ qemu_put_betls(f, &env->btarget);
+ qemu_put_sbe32s(f, &env->bcond);
+
+ /* Save remaining CP1 registers */
+ qemu_put_sbe32s(f, &env->CP0_Index);
+ qemu_put_sbe32s(f, &env->CP0_Random);
+ qemu_put_sbe32s(f, &env->CP0_VPEControl);
+ qemu_put_sbe32s(f, &env->CP0_VPEConf0);
+ qemu_put_sbe32s(f, &env->CP0_VPEConf1);
+ qemu_put_betls(f, &env->CP0_YQMask);
+ qemu_put_betls(f, &env->CP0_VPESchedule);
+ qemu_put_betls(f, &env->CP0_VPEScheFBack);
+ qemu_put_sbe32s(f, &env->CP0_VPEOpt);
+ qemu_put_betls(f, &env->CP0_EntryLo0);
+ qemu_put_betls(f, &env->CP0_EntryLo1);
+ qemu_put_betls(f, &env->CP0_Context);
+ qemu_put_sbe32s(f, &env->CP0_PageMask);
+ qemu_put_sbe32s(f, &env->CP0_PageGrain);
+ qemu_put_sbe32s(f, &env->CP0_Wired);
+ qemu_put_sbe32s(f, &env->CP0_SRSConf0);
+ qemu_put_sbe32s(f, &env->CP0_SRSConf1);
+ qemu_put_sbe32s(f, &env->CP0_SRSConf2);
+ qemu_put_sbe32s(f, &env->CP0_SRSConf3);
+ qemu_put_sbe32s(f, &env->CP0_SRSConf4);
+ qemu_put_sbe32s(f, &env->CP0_HWREna);
+ qemu_put_betls(f, &env->CP0_BadVAddr);
+ qemu_put_sbe32s(f, &env->CP0_Count);
+ qemu_put_betls(f, &env->CP0_EntryHi);
+ qemu_put_sbe32s(f, &env->CP0_Compare);
+ qemu_put_sbe32s(f, &env->CP0_Status);
+ qemu_put_sbe32s(f, &env->CP0_IntCtl);
+ qemu_put_sbe32s(f, &env->CP0_SRSCtl);
+ qemu_put_sbe32s(f, &env->CP0_SRSMap);
+ qemu_put_sbe32s(f, &env->CP0_Cause);
+ qemu_put_betls(f, &env->CP0_EPC);
+ qemu_put_sbe32s(f, &env->CP0_PRid);
+ qemu_put_sbe32s(f, &env->CP0_EBase);
+ qemu_put_sbe32s(f, &env->CP0_Config0);
+ qemu_put_sbe32s(f, &env->CP0_Config1);
+ qemu_put_sbe32s(f, &env->CP0_Config2);
+ qemu_put_sbe32s(f, &env->CP0_Config3);
+ qemu_put_sbe32s(f, &env->CP0_Config6);
+ qemu_put_sbe32s(f, &env->CP0_Config7);
+ qemu_put_betls(f, &env->CP0_LLAddr);
+ for(i = 0; i < 8; i++)
+ qemu_put_betls(f, &env->CP0_WatchLo[i]);
+ for(i = 0; i < 8; i++)
+ qemu_put_sbe32s(f, &env->CP0_WatchHi[i]);
+ qemu_put_betls(f, &env->CP0_XContext);
+ qemu_put_sbe32s(f, &env->CP0_Framemask);
+ qemu_put_sbe32s(f, &env->CP0_Debug);
+ qemu_put_betls(f, &env->CP0_DEPC);
+ qemu_put_sbe32s(f, &env->CP0_Performance0);
+ qemu_put_sbe32s(f, &env->CP0_TagLo);
+ qemu_put_sbe32s(f, &env->CP0_DataLo);
+ qemu_put_sbe32s(f, &env->CP0_TagHi);
+ qemu_put_sbe32s(f, &env->CP0_DataHi);
+ qemu_put_betls(f, &env->CP0_ErrorEPC);
+ qemu_put_sbe32s(f, &env->CP0_DESAVE);
+
+ /* Save inactive TC state */
+ for (i = 0; i < MIPS_SHADOW_SET_MAX; i++)
+ save_tc(f, &env->tcs[i]);
+ for (i = 0; i < MIPS_FPU_MAX; i++)
+ save_fpu(f, &env->fpus[i]);
+}
+
+static void load_tc(QEMUFile *f, TCState *tc)
+{
+ int i;
+
+ /* Save active TC */
+ for(i = 0; i < 32; i++)
+ qemu_get_betls(f, &tc->gpr[i]);
+ qemu_get_betls(f, &tc->PC);
+ for(i = 0; i < MIPS_DSP_ACC; i++)
+ qemu_get_betls(f, &tc->HI[i]);
+ for(i = 0; i < MIPS_DSP_ACC; i++)
+ qemu_get_betls(f, &tc->LO[i]);
+ for(i = 0; i < MIPS_DSP_ACC; i++)
+ qemu_get_betls(f, &tc->ACX[i]);
+ qemu_get_betls(f, &tc->DSPControl);
+ qemu_get_sbe32s(f, &tc->CP0_TCStatus);
+ qemu_get_sbe32s(f, &tc->CP0_TCBind);
+ qemu_get_betls(f, &tc->CP0_TCHalt);
+ qemu_get_betls(f, &tc->CP0_TCContext);
+ qemu_get_betls(f, &tc->CP0_TCSchedule);
+ qemu_get_betls(f, &tc->CP0_TCScheFBack);
+ qemu_get_sbe32s(f, &tc->CP0_Debug_tcstatus);
+}
+
+static void load_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu)
+{
+ int i;
+
+ for(i = 0; i < 32; i++)
+ qemu_get_be64s(f, &fpu->fpr[i].d);
+ qemu_get_s8s(f, &fpu->fp_status.float_detect_tininess);
+ qemu_get_s8s(f, &fpu->fp_status.float_rounding_mode);
+ qemu_get_s8s(f, &fpu->fp_status.float_exception_flags);
+ qemu_get_be32s(f, &fpu->fcr0);
+ qemu_get_be32s(f, &fpu->fcr31);
}
int cpu_load(QEMUFile *f, void *opaque, int version_id)
{
+ CPUState *env = opaque;
+ int i;
+
+ if (version_id != 3)
+ return -EINVAL;
+
+ /* Load active TC */
+ load_tc(f, &env->active_tc);
+
+ /* Load active FPU */
+ load_fpu(f, &env->active_fpu);
+
+ /* Load MVP */
+ qemu_get_sbe32s(f, &env->mvp->CP0_MVPControl);
+ qemu_get_sbe32s(f, &env->mvp->CP0_MVPConf0);
+ qemu_get_sbe32s(f, &env->mvp->CP0_MVPConf1);
+
+ /* Load TLB */
+ qemu_get_be32s(f, &env->tlb->nb_tlb);
+ qemu_get_be32s(f, &env->tlb->tlb_in_use);
+ for(i = 0; i < MIPS_TLB_MAX; i++) {
+ uint16_t flags;
+
+ qemu_get_betls(f, &env->tlb->mmu.r4k.tlb[i].VPN);
+ qemu_get_be32s(f, &env->tlb->mmu.r4k.tlb[i].PageMask);
+ qemu_get_8s(f, &env->tlb->mmu.r4k.tlb[i].ASID);
+ qemu_get_be16s(f, &flags);
+ env->tlb->mmu.r4k.tlb[i].G = (flags >> 10) & 1;
+ env->tlb->mmu.r4k.tlb[i].C0 = (flags >> 7) & 3;
+ env->tlb->mmu.r4k.tlb[i].C1 = (flags >> 4) & 3;
+ env->tlb->mmu.r4k.tlb[i].V0 = (flags >> 3) & 1;
+ env->tlb->mmu.r4k.tlb[i].V1 = (flags >> 2) & 1;
+ env->tlb->mmu.r4k.tlb[i].D0 = (flags >> 1) & 1;
+ env->tlb->mmu.r4k.tlb[i].D1 = (flags >> 0) & 1;
+ qemu_get_betls(f, &env->tlb->mmu.r4k.tlb[i].PFN[0]);
+ qemu_get_betls(f, &env->tlb->mmu.r4k.tlb[i].PFN[1]);
+ }
+
+ /* Load CPU metastate */
+ qemu_get_be32s(f, &env->current_tc);
+ qemu_get_be32s(f, &env->current_fpu);
+ qemu_get_sbe32s(f, &env->error_code);
+ qemu_get_be32s(f, &env->hflags);
+ qemu_get_betls(f, &env->btarget);
+ qemu_get_sbe32s(f, &env->bcond);
+
+ /* Load remaining CP1 registers */
+ qemu_get_sbe32s(f, &env->CP0_Index);
+ qemu_get_sbe32s(f, &env->CP0_Random);
+ qemu_get_sbe32s(f, &env->CP0_VPEControl);
+ qemu_get_sbe32s(f, &env->CP0_VPEConf0);
+ qemu_get_sbe32s(f, &env->CP0_VPEConf1);
+ qemu_get_betls(f, &env->CP0_YQMask);
+ qemu_get_betls(f, &env->CP0_VPESchedule);
+ qemu_get_betls(f, &env->CP0_VPEScheFBack);
+ qemu_get_sbe32s(f, &env->CP0_VPEOpt);
+ qemu_get_betls(f, &env->CP0_EntryLo0);
+ qemu_get_betls(f, &env->CP0_EntryLo1);
+ qemu_get_betls(f, &env->CP0_Context);
+ qemu_get_sbe32s(f, &env->CP0_PageMask);
+ qemu_get_sbe32s(f, &env->CP0_PageGrain);
+ qemu_get_sbe32s(f, &env->CP0_Wired);
+ qemu_get_sbe32s(f, &env->CP0_SRSConf0);
+ qemu_get_sbe32s(f, &env->CP0_SRSConf1);
+ qemu_get_sbe32s(f, &env->CP0_SRSConf2);
+ qemu_get_sbe32s(f, &env->CP0_SRSConf3);
+ qemu_get_sbe32s(f, &env->CP0_SRSConf4);
+ qemu_get_sbe32s(f, &env->CP0_HWREna);
+ qemu_get_betls(f, &env->CP0_BadVAddr);
+ qemu_get_sbe32s(f, &env->CP0_Count);
+ qemu_get_betls(f, &env->CP0_EntryHi);
+ qemu_get_sbe32s(f, &env->CP0_Compare);
+ qemu_get_sbe32s(f, &env->CP0_Status);
+ qemu_get_sbe32s(f, &env->CP0_IntCtl);
+ qemu_get_sbe32s(f, &env->CP0_SRSCtl);
+ qemu_get_sbe32s(f, &env->CP0_SRSMap);
+ qemu_get_sbe32s(f, &env->CP0_Cause);
+ qemu_get_betls(f, &env->CP0_EPC);
+ qemu_get_sbe32s(f, &env->CP0_PRid);
+ qemu_get_sbe32s(f, &env->CP0_EBase);
+ qemu_get_sbe32s(f, &env->CP0_Config0);
+ qemu_get_sbe32s(f, &env->CP0_Config1);
+ qemu_get_sbe32s(f, &env->CP0_Config2);
+ qemu_get_sbe32s(f, &env->CP0_Config3);
+ qemu_get_sbe32s(f, &env->CP0_Config6);
+ qemu_get_sbe32s(f, &env->CP0_Config7);
+ qemu_get_betls(f, &env->CP0_LLAddr);
+ for(i = 0; i < 8; i++)
+ qemu_get_betls(f, &env->CP0_WatchLo[i]);
+ for(i = 0; i < 8; i++)
+ qemu_get_sbe32s(f, &env->CP0_WatchHi[i]);
+ qemu_get_betls(f, &env->CP0_XContext);
+ qemu_get_sbe32s(f, &env->CP0_Framemask);
+ qemu_get_sbe32s(f, &env->CP0_Debug);
+ qemu_get_betls(f, &env->CP0_DEPC);
+ qemu_get_sbe32s(f, &env->CP0_Performance0);
+ qemu_get_sbe32s(f, &env->CP0_TagLo);
+ qemu_get_sbe32s(f, &env->CP0_DataLo);
+ qemu_get_sbe32s(f, &env->CP0_TagHi);
+ qemu_get_sbe32s(f, &env->CP0_DataHi);
+ qemu_get_betls(f, &env->CP0_ErrorEPC);
+ qemu_get_sbe32s(f, &env->CP0_DESAVE);
+
+ /* Load inactive TC state */
+ for (i = 0; i < MIPS_SHADOW_SET_MAX; i++)
+ load_tc(f, &env->tcs[i]);
+ for (i = 0; i < MIPS_FPU_MAX; i++)
+ load_fpu(f, &env->fpus[i]);
+
+ /* XXX: ensure compatiblity for halted bit ? */
+ tlb_flush(env, 1);
return 0;
}