target/sparc: Correctly handle bus errors in page table walks
Currently we use the ldl_phys() function to read page table entries. With the unassigned_access hook in place, if these hit an unassigned area of memory then the hook will cause us to wrongly generate an exception with a fault address matching the address of the page table entry. Change to using address_space_ldl() so we can detect and correctly handle bus errors and give them their correct behaviour of causing a translation error with a suitable fault status register. Note that this won't actually take effect until we switch the over to using the do_translation_failed hook. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Tested-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Message-id: 20190801183012.17564-5-peter.maydell@linaro.org
This commit is contained in:
parent
776095d3cd
commit
3c818dfcc2
@ -98,6 +98,7 @@ static int get_physical_address(CPUSPARCState *env, hwaddr *physical,
|
||||
int error_code = 0, is_dirty, is_user;
|
||||
unsigned long page_offset;
|
||||
CPUState *cs = env_cpu(env);
|
||||
MemTxResult result;
|
||||
|
||||
is_user = mmu_idx == MMU_USER_IDX;
|
||||
|
||||
@ -120,7 +121,10 @@ static int get_physical_address(CPUSPARCState *env, hwaddr *physical,
|
||||
/* SPARC reference MMU table walk: Context table->L1->L2->PTE */
|
||||
/* Context base + context number */
|
||||
pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
|
||||
pde = ldl_phys(cs->as, pde_ptr);
|
||||
pde = address_space_ldl(cs->as, pde_ptr, MEMTXATTRS_UNSPECIFIED, &result);
|
||||
if (result != MEMTX_OK) {
|
||||
return 4 << 2; /* Translation fault, L = 0 */
|
||||
}
|
||||
|
||||
/* Ctx pde */
|
||||
switch (pde & PTE_ENTRYTYPE_MASK) {
|
||||
@ -132,7 +136,11 @@ static int get_physical_address(CPUSPARCState *env, hwaddr *physical,
|
||||
return 4 << 2;
|
||||
case 1: /* L0 PDE */
|
||||
pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
|
||||
pde = ldl_phys(cs->as, pde_ptr);
|
||||
pde = address_space_ldl(cs->as, pde_ptr,
|
||||
MEMTXATTRS_UNSPECIFIED, &result);
|
||||
if (result != MEMTX_OK) {
|
||||
return (1 << 8) | (4 << 2); /* Translation fault, L = 1 */
|
||||
}
|
||||
|
||||
switch (pde & PTE_ENTRYTYPE_MASK) {
|
||||
default:
|
||||
@ -142,7 +150,11 @@ static int get_physical_address(CPUSPARCState *env, hwaddr *physical,
|
||||
return (1 << 8) | (4 << 2);
|
||||
case 1: /* L1 PDE */
|
||||
pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
|
||||
pde = ldl_phys(cs->as, pde_ptr);
|
||||
pde = address_space_ldl(cs->as, pde_ptr,
|
||||
MEMTXATTRS_UNSPECIFIED, &result);
|
||||
if (result != MEMTX_OK) {
|
||||
return (2 << 8) | (4 << 2); /* Translation fault, L = 2 */
|
||||
}
|
||||
|
||||
switch (pde & PTE_ENTRYTYPE_MASK) {
|
||||
default:
|
||||
@ -152,7 +164,11 @@ static int get_physical_address(CPUSPARCState *env, hwaddr *physical,
|
||||
return (2 << 8) | (4 << 2);
|
||||
case 1: /* L2 PDE */
|
||||
pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
|
||||
pde = ldl_phys(cs->as, pde_ptr);
|
||||
pde = address_space_ldl(cs->as, pde_ptr,
|
||||
MEMTXATTRS_UNSPECIFIED, &result);
|
||||
if (result != MEMTX_OK) {
|
||||
return (3 << 8) | (4 << 2); /* Translation fault, L = 3 */
|
||||
}
|
||||
|
||||
switch (pde & PTE_ENTRYTYPE_MASK) {
|
||||
default:
|
||||
|
Loading…
Reference in New Issue
Block a user