mirror of https://gitlab.com/qemu-project/qemu
target-mips: split code raising MMU exception in a separate function
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
parent
0ae430454c
commit
1147e18994
|
@ -201,6 +201,58 @@ static int get_physical_address (CPUState *env, target_phys_addr_t *physical,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void raise_mmu_exception(CPUState *env, target_ulong address,
|
||||||
|
int rw, int tlb_error)
|
||||||
|
{
|
||||||
|
int exception = 0, error_code = 0;
|
||||||
|
|
||||||
|
switch (tlb_error) {
|
||||||
|
default:
|
||||||
|
case TLBRET_BADADDR:
|
||||||
|
/* Reference to kernel address from user mode or supervisor mode */
|
||||||
|
/* Reference to supervisor address from user mode */
|
||||||
|
if (rw)
|
||||||
|
exception = EXCP_AdES;
|
||||||
|
else
|
||||||
|
exception = EXCP_AdEL;
|
||||||
|
break;
|
||||||
|
case TLBRET_NOMATCH:
|
||||||
|
/* No TLB match for a mapped address */
|
||||||
|
if (rw)
|
||||||
|
exception = EXCP_TLBS;
|
||||||
|
else
|
||||||
|
exception = EXCP_TLBL;
|
||||||
|
error_code = 1;
|
||||||
|
break;
|
||||||
|
case TLBRET_INVALID:
|
||||||
|
/* TLB match with no valid bit */
|
||||||
|
if (rw)
|
||||||
|
exception = EXCP_TLBS;
|
||||||
|
else
|
||||||
|
exception = EXCP_TLBL;
|
||||||
|
break;
|
||||||
|
case TLBRET_DIRTY:
|
||||||
|
/* TLB match but 'D' bit is cleared */
|
||||||
|
exception = EXCP_LTLBL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
/* Raise exception */
|
||||||
|
env->CP0_BadVAddr = address;
|
||||||
|
env->CP0_Context = (env->CP0_Context & ~0x007fffff) |
|
||||||
|
((address >> 9) & 0x007ffff0);
|
||||||
|
env->CP0_EntryHi =
|
||||||
|
(env->CP0_EntryHi & 0xFF) | (address & (TARGET_PAGE_MASK << 1));
|
||||||
|
#if defined(TARGET_MIPS64)
|
||||||
|
env->CP0_EntryHi &= env->SEGMask;
|
||||||
|
env->CP0_XContext = (env->CP0_XContext & ((~0ULL) << (env->SEGBITS - 7))) |
|
||||||
|
((address & 0xC00000000000ULL) >> (55 - env->SEGBITS)) |
|
||||||
|
((address & ((1ULL << env->SEGBITS) - 1) & 0xFFFFFFFFFFFFE000ULL) >> 9);
|
||||||
|
#endif
|
||||||
|
env->exception_index = exception;
|
||||||
|
env->error_code = error_code;
|
||||||
|
}
|
||||||
|
|
||||||
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
|
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
|
||||||
{
|
{
|
||||||
#if defined(CONFIG_USER_ONLY)
|
#if defined(CONFIG_USER_ONLY)
|
||||||
|
@ -222,7 +274,6 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
|
||||||
target_phys_addr_t physical;
|
target_phys_addr_t physical;
|
||||||
int prot;
|
int prot;
|
||||||
#endif
|
#endif
|
||||||
int exception = 0, error_code = 0;
|
|
||||||
int access_type;
|
int access_type;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
@ -252,51 +303,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
|
||||||
} else if (ret < 0)
|
} else if (ret < 0)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
switch (ret) {
|
raise_mmu_exception(env, address, rw, ret);
|
||||||
default:
|
|
||||||
case TLBRET_BADADDR:
|
|
||||||
/* Reference to kernel address from user mode or supervisor mode */
|
|
||||||
/* Reference to supervisor address from user mode */
|
|
||||||
if (rw)
|
|
||||||
exception = EXCP_AdES;
|
|
||||||
else
|
|
||||||
exception = EXCP_AdEL;
|
|
||||||
break;
|
|
||||||
case TLBRET_NOMATCH:
|
|
||||||
/* No TLB match for a mapped address */
|
|
||||||
if (rw)
|
|
||||||
exception = EXCP_TLBS;
|
|
||||||
else
|
|
||||||
exception = EXCP_TLBL;
|
|
||||||
error_code = 1;
|
|
||||||
break;
|
|
||||||
case TLBRET_INVALID:
|
|
||||||
/* TLB match with no valid bit */
|
|
||||||
if (rw)
|
|
||||||
exception = EXCP_TLBS;
|
|
||||||
else
|
|
||||||
exception = EXCP_TLBL;
|
|
||||||
break;
|
|
||||||
case TLBRET_DIRTY:
|
|
||||||
/* TLB match but 'D' bit is cleared */
|
|
||||||
exception = EXCP_LTLBL;
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
/* Raise exception */
|
|
||||||
env->CP0_BadVAddr = address;
|
|
||||||
env->CP0_Context = (env->CP0_Context & ~0x007fffff) |
|
|
||||||
((address >> 9) & 0x007ffff0);
|
|
||||||
env->CP0_EntryHi =
|
|
||||||
(env->CP0_EntryHi & 0xFF) | (address & (TARGET_PAGE_MASK << 1));
|
|
||||||
#if defined(TARGET_MIPS64)
|
|
||||||
env->CP0_EntryHi &= env->SEGMask;
|
|
||||||
env->CP0_XContext = (env->CP0_XContext & ((~0ULL) << (env->SEGBITS - 7))) |
|
|
||||||
((address & 0xC00000000000ULL) >> (55 - env->SEGBITS)) |
|
|
||||||
((address & ((1ULL << env->SEGBITS) - 1) & 0xFFFFFFFFFFFFE000ULL) >> 9);
|
|
||||||
#endif
|
|
||||||
env->exception_index = exception;
|
|
||||||
env->error_code = error_code;
|
|
||||||
ret = 1;
|
ret = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue