diff --git a/hw/ppc_chrp.c b/hw/ppc_chrp.c index 8eef289828..456832824e 100644 --- a/hw/ppc_chrp.c +++ b/hw/ppc_chrp.c @@ -317,6 +317,7 @@ static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device, /* init CPUs */ env = cpu_init(); + qemu_register_reset(&cpu_ppc_reset, env); register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); /* Default CPU is a generic 74x/75x */ diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c index 8fce9cc6cd..2f10338b13 100644 --- a/hw/ppc_prep.c +++ b/hw/ppc_prep.c @@ -531,13 +531,14 @@ static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device, sysctrl = qemu_mallocz(sizeof(sysctrl_t)); if (sysctrl == NULL) - return; + return; linux_boot = (kernel_filename != NULL); - + /* init CPUs */ env = cpu_init(); + qemu_register_reset(&cpu_ppc_reset, env); register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); /* Default CPU is a 604 */ diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 1e309f91d1..5cd1b6008c 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -860,6 +860,9 @@ void do_store_msr (CPUPPCState *env, target_ulong value); void ppc_store_msr_32 (CPUPPCState *env, uint32_t value); void do_compute_hflags (CPUPPCState *env); +void cpu_ppc_reset (void *opaque); +CPUPPCState *cpu_ppc_init (void); +void cpu_ppc_close(CPUPPCState *env); int ppc_find_by_name (const unsigned char *name, ppc_def_t **def); int ppc_find_by_pvr (uint32_t apvr, ppc_def_t **def); @@ -883,6 +886,7 @@ target_ulong load_40x_pit (CPUPPCState *env); void store_40x_pit (CPUPPCState *env, target_ulong val); void store_booke_tcr (CPUPPCState *env, target_ulong val); void store_booke_tsr (CPUPPCState *env, target_ulong val); +void ppc_tlb_invalidate_all (CPUPPCState *env); #endif #endif 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); +} diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c index 140b7f5cb2..590b31e725 100644 --- a/target-ppc/op_helper.c +++ b/target-ppc/op_helper.c @@ -2256,16 +2256,7 @@ void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr) /* TLB invalidation helpers */ void do_tlbia (void) { - 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)) { - /* XXX: TODO */ -#if 0 - ppcbooke_tlb_invalidate_all(env); -#endif - } else { - tlb_flush(env, 1); - } + ppc_tlb_invalidate_all(env); } void do_tlbie (void) @@ -2473,25 +2464,6 @@ static int booke_page_size_to_tlb (target_ulong page_size) } /* Helpers for 4xx TLB management */ -void do_4xx_tlbia (void) -{ - ppcemb_tlb_t *tlb; - int i; - - for (i = 0; i < 64; i++) { - tlb = &env->tlb[i].tlbe; - if (tlb->prot & PAGE_VALID) { -#if 0 - 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); -} - void do_4xx_tlbre_lo (void) { ppcemb_tlb_t *tlb; diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 018512328e..ab8d8694a8 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -2713,39 +2713,6 @@ int cpu_ppc_register (CPUPPCState *env, ppc_def_t *def) return 0; } -void do_compute_hflags (CPUPPCState *env); -CPUPPCState *cpu_ppc_init (void) -{ - CPUPPCState *env; - - env = qemu_mallocz(sizeof(CPUPPCState)); - if (!env) - return NULL; - cpu_exec_init(env); - tlb_flush(env, 1); -#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(CONFIG_USER_ONLY) - msr_pr = 1; -#else - env->nip = 0xFFFFFFFC; -#endif - do_compute_hflags(env); - env->reserve = -1; - return env; -} - -void cpu_ppc_close(CPUPPCState *env) -{ - /* Should also remove all opcode tables... */ - free(env); -} - /*****************************************************************************/ /* PowerPC CPU definitions */ static ppc_def_t ppc_defs[] =