Fix ARMv6 translation table base address calculation.
Signed-off-by: Paul Brook <paul@codesourcery.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5514 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
83c1f87cc8
commit
b2fa17977f
@ -107,7 +107,9 @@ typedef struct CPUARMState {
|
||||
uint32_t c1_xscaleauxcr; /* XScale auxiliary control register. */
|
||||
uint32_t c2_base0; /* MMU translation table base 0. */
|
||||
uint32_t c2_base1; /* MMU translation table base 1. */
|
||||
uint32_t c2_mask; /* MMU translation table base mask. */
|
||||
uint32_t c2_control; /* MMU translation table base control. */
|
||||
uint32_t c2_mask; /* MMU translation table base selection mask. */
|
||||
uint32_t c2_base_mask; /* MMU translation table base 0 mask. */
|
||||
uint32_t c2_data; /* MPU data cachable bits. */
|
||||
uint32_t c2_insn; /* MPU instruction cachable bits. */
|
||||
uint32_t c3; /* MMU domain access control register
|
||||
|
@ -168,6 +168,7 @@ void cpu_reset(CPUARMState *env)
|
||||
if (IS_M(env))
|
||||
env->uncached_cpsr &= ~CPSR_I;
|
||||
env->vfp.xregs[ARM_VFP_FPEXC] = 0;
|
||||
env->cp15.c2_base_mask = 0xffffc000u;
|
||||
#endif
|
||||
env->regs[15] = 0;
|
||||
tlb_flush(env, 1);
|
||||
@ -910,6 +911,19 @@ static inline int check_ap(CPUState *env, int ap, int domain, int access_type,
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t get_level1_table_address(CPUState *env, uint32_t address)
|
||||
{
|
||||
uint32_t table;
|
||||
|
||||
if (address & env->cp15.c2_mask)
|
||||
table = env->cp15.c2_base1 & 0xffffc000;
|
||||
else
|
||||
table = env->cp15.c2_base0 & env->cp15.c2_base_mask;
|
||||
|
||||
table |= (address >> 18) & 0x3ffc;
|
||||
return table;
|
||||
}
|
||||
|
||||
static int get_phys_addr_v5(CPUState *env, uint32_t address, int access_type,
|
||||
int is_user, uint32_t *phys_ptr, int *prot)
|
||||
{
|
||||
@ -923,11 +937,7 @@ static int get_phys_addr_v5(CPUState *env, uint32_t address, int access_type,
|
||||
|
||||
/* Pagetable walk. */
|
||||
/* Lookup l1 descriptor. */
|
||||
if (address & env->cp15.c2_mask)
|
||||
table = env->cp15.c2_base1;
|
||||
else
|
||||
table = env->cp15.c2_base0;
|
||||
table = (table & 0xffffc000) | ((address >> 18) & 0x3ffc);
|
||||
table = get_level1_table_address(env, address);
|
||||
desc = ldl_phys(table);
|
||||
type = (desc & 3);
|
||||
domain = (env->cp15.c3 >> ((desc >> 4) & 0x1e)) & 3;
|
||||
@ -1015,11 +1025,7 @@ static int get_phys_addr_v6(CPUState *env, uint32_t address, int access_type,
|
||||
|
||||
/* Pagetable walk. */
|
||||
/* Lookup l1 descriptor. */
|
||||
if (address & env->cp15.c2_mask)
|
||||
table = env->cp15.c2_base1;
|
||||
else
|
||||
table = env->cp15.c2_base0;
|
||||
table = (table & 0xffffc000) | ((address >> 18) & 0x3ffc);
|
||||
table = get_level1_table_address(env, address);
|
||||
desc = ldl_phys(table);
|
||||
type = (desc & 3);
|
||||
if (type == 0) {
|
||||
@ -1365,7 +1371,10 @@ void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
|
||||
env->cp15.c2_base1 = val;
|
||||
break;
|
||||
case 2:
|
||||
val &= 7;
|
||||
env->cp15.c2_control = val;
|
||||
env->cp15.c2_mask = ~(((uint32_t)0xffffffffu) >> val);
|
||||
env->cp15.c2_base_mask = ~((uint32_t)0x3fffu >> val);
|
||||
break;
|
||||
default:
|
||||
goto bad_reg;
|
||||
@ -1683,17 +1692,7 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
|
||||
case 1:
|
||||
return env->cp15.c2_base1;
|
||||
case 2:
|
||||
{
|
||||
int n;
|
||||
uint32_t mask;
|
||||
n = 0;
|
||||
mask = env->cp15.c2_mask;
|
||||
while (mask) {
|
||||
n++;
|
||||
mask <<= 1;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
return env->cp15.c2_control;
|
||||
default:
|
||||
goto bad_reg;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user