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:
parent
dd37a5e4d7
commit
0a032cbec6
|
@ -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 */
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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[] =
|
||||||
|
|
Loading…
Reference in a new issue