summaryrefslogtreecommitdiff
path: root/target-ppc/helper.c
diff options
context:
space:
mode:
authorj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>2007-04-16 08:56:52 +0000
committerj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>2007-04-16 08:56:52 +0000
commit0a032cbec69c268272a118f19e64c16e73d56cc0 (patch)
treec2e2f0a67ac42a5729aaa50b73aebf5dca13f00a /target-ppc/helper.c
parentdd37a5e4d7ebc4e698f4c69ad2a5ee922824703f (diff)
downloadqemu-0a032cbec69c268272a118f19e64c16e73d56cc0.tar.gz
Add reset callbacks for PowerPC CPU.
Move cpu_ppc_init, cpu_ppc_close, cpu_ppc_reset and ppc_tlb_invalidate into helper.c as they are to be called from outside of the translated code. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2682 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-ppc/helper.c')
-rw-r--r--target-ppc/helper.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 161cc1b14b..5f46ae0fdc 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -630,6 +630,25 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx,
return ret;
}
+void ppc4xx_tlb_invalidate_all (CPUState *env)
+{
+ ppcemb_tlb_t *tlb;
+ int i;
+
+ for (i = 0; i < env->nb_tlb; i++) {
+ tlb = &env->tlb[i].tlbe;
+ if (tlb->prot & PAGE_VALID) {
+#if 0 // XXX: TLB have variable sizes then we flush all Qemu TLB.
+ end = tlb->EPN + tlb->size;
+ for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
+ tlb_flush_page(env, page);
+#endif
+ tlb->prot &= ~PAGE_VALID;
+ }
+ }
+ tlb_flush(env, 1);
+}
+
int mmu4xx_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
target_ulong address, int rw, int access_type)
{
@@ -1105,6 +1124,20 @@ void do_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
env->DBAT[1][nr] = value;
}
+
+/*****************************************************************************/
+/* TLB management */
+void ppc_tlb_invalidate_all (CPUPPCState *env)
+{
+ if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) {
+ ppc6xx_tlb_invalidate_all(env);
+ } else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) {
+ ppc4xx_tlb_invalidate_all(env);
+ } else {
+ tlb_flush(env, 1);
+ }
+}
+
/*****************************************************************************/
/* Special registers manipulation */
#if defined(TARGET_PPC64)
@@ -2039,3 +2072,48 @@ void cpu_dump_EA (target_ulong EA)
fprintf(f, "Memory access at address " TARGET_FMT_lx "\n", EA);
}
+void cpu_ppc_reset (void *opaque)
+{
+ CPUPPCState *env;
+
+ env = opaque;
+#if defined (DO_SINGLE_STEP) && 0
+ /* Single step trace mode */
+ msr_se = 1;
+ msr_be = 1;
+#endif
+ msr_fp = 1; /* Allow floating point exceptions */
+ msr_me = 1; /* Allow machine check exceptions */
+#if defined(TARGET_PPC64)
+ msr_sf = 0; /* Boot in 32 bits mode */
+ msr_cm = 0;
+#endif
+#if defined(CONFIG_USER_ONLY)
+ msr_pr = 1;
+ tlb_flush(env, 1);
+#else
+ env->nip = 0xFFFFFFFC;
+ ppc_tlb_invalidate_all(env);
+#endif
+ do_compute_hflags(env);
+ env->reserve = -1;
+}
+
+CPUPPCState *cpu_ppc_init (void)
+{
+ CPUPPCState *env;
+
+ env = qemu_mallocz(sizeof(CPUPPCState));
+ if (!env)
+ return NULL;
+ cpu_exec_init(env);
+ cpu_ppc_reset(env);
+
+ return env;
+}
+
+void cpu_ppc_close (CPUPPCState *env)
+{
+ /* Should also remove all opcode tables... */
+ free(env);
+}