From 7d2ca16d7f2095482cc625357251dd5366f90ab9 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Wed, 20 Nov 2019 13:37:45 -0500 Subject: [PATCH] target/sparc: Handle bus errors in mmu_probe() Convert the mmu_probe() function to using address_space_ldl() rather than ldl_phys(), so we can explicitly detect memory transaction failures. This makes no practical difference at the moment, because ldl_phys() will return 0 on a transaction failure, and we treat transaction failures and 0 PDEs identically. However the spec says that MMU probe operations are supposed to update the fault status registers, and if we ever implement that we'll want to distinguish the difference. For the moment, just add a TODO comment about the bug. Backports commit d86a9ad33c75ed795f09fb43243d0acecd583f24 from qemu --- qemu/target/sparc/mmu_helper.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/qemu/target/sparc/mmu_helper.c b/qemu/target/sparc/mmu_helper.c index fdea39c2..5a4264a2 100644 --- a/qemu/target/sparc/mmu_helper.c +++ b/qemu/target/sparc/mmu_helper.c @@ -285,11 +285,20 @@ target_ulong mmu_probe(CPUSPARCState *env, target_ulong address, int mmulev) CPUState *cs = env_cpu(env); hwaddr pde_ptr; uint32_t pde; + MemTxResult result; + + /* + * TODO: MMU probe operations are supposed to set the fault + * status registers, but we don't do this. + */ /* Context base + context number */ pde_ptr = (hwaddr)(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 0; + } switch (pde & PTE_ENTRYTYPE_MASK) { default: @@ -302,7 +311,11 @@ target_ulong mmu_probe(CPUSPARCState *env, target_ulong address, int mmulev) return 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 0; + } switch (pde & PTE_ENTRYTYPE_MASK) { default: @@ -316,7 +329,11 @@ target_ulong mmu_probe(CPUSPARCState *env, target_ulong address, int mmulev) return 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 0; + } switch (pde & PTE_ENTRYTYPE_MASK) { default: @@ -330,7 +347,11 @@ target_ulong mmu_probe(CPUSPARCState *env, target_ulong address, int mmulev) return 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 0; + } switch (pde & PTE_ENTRYTYPE_MASK) { default: