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:
pbrook 2008-10-22 19:22:30 +00:00
parent 83c1f87cc8
commit b2fa17977f
2 changed files with 23 additions and 22 deletions

View File

@ -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

View File

@ -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;
}