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
This commit is contained in:
j_mayer 2007-04-16 08:56:52 +00:00
parent dd37a5e4d7
commit 0a032cbec6
6 changed files with 87 additions and 64 deletions

View File

@ -317,6 +317,7 @@ static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device,
/* init CPUs */ /* init CPUs */
env = cpu_init(); env = cpu_init();
qemu_register_reset(&cpu_ppc_reset, env);
register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
/* Default CPU is a generic 74x/75x */ /* Default CPU is a generic 74x/75x */

View File

@ -538,6 +538,7 @@ static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device,
/* init CPUs */ /* init CPUs */
env = cpu_init(); env = cpu_init();
qemu_register_reset(&cpu_ppc_reset, env);
register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
/* Default CPU is a 604 */ /* Default CPU is a 604 */

View File

@ -860,6 +860,9 @@ void do_store_msr (CPUPPCState *env, target_ulong value);
void ppc_store_msr_32 (CPUPPCState *env, uint32_t value); void ppc_store_msr_32 (CPUPPCState *env, uint32_t value);
void do_compute_hflags (CPUPPCState *env); 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_name (const unsigned char *name, ppc_def_t **def);
int ppc_find_by_pvr (uint32_t apvr, 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_40x_pit (CPUPPCState *env, target_ulong val);
void store_booke_tcr (CPUPPCState *env, target_ulong val); void store_booke_tcr (CPUPPCState *env, target_ulong val);
void store_booke_tsr (CPUPPCState *env, target_ulong val); void store_booke_tsr (CPUPPCState *env, target_ulong val);
void ppc_tlb_invalidate_all (CPUPPCState *env);
#endif #endif
#endif #endif

View File

@ -630,6 +630,25 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx,
return ret; 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, int mmu4xx_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
target_ulong address, int rw, int access_type) 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; 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 */ /* Special registers manipulation */
#if defined(TARGET_PPC64) #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); 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);
}

View File

@ -2256,16 +2256,7 @@ void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr)
/* TLB invalidation helpers */ /* TLB invalidation helpers */
void do_tlbia (void) void do_tlbia (void)
{ {
if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) { ppc_tlb_invalidate_all(env);
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);
}
} }
void do_tlbie (void) void do_tlbie (void)
@ -2473,25 +2464,6 @@ static int booke_page_size_to_tlb (target_ulong page_size)
} }
/* Helpers for 4xx TLB management */ /* 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) void do_4xx_tlbre_lo (void)
{ {
ppcemb_tlb_t *tlb; ppcemb_tlb_t *tlb;

View File

@ -2713,39 +2713,6 @@ int cpu_ppc_register (CPUPPCState *env, ppc_def_t *def)
return 0; 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 */ /* PowerPC CPU definitions */
static ppc_def_t ppc_defs[] = static ppc_def_t ppc_defs[] =