From b9f5fdad49c74583dcf9fcba0805b148e3992e13 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 1 Aug 2019 19:30:07 +0100 Subject: [PATCH] target/sparc: Check for transaction failures in MMU passthrough ASIs Currently the ld/st_asi helper functions make calls to the ld*_phys() and st*_phys() functions for those ASIs which imply direct accesses to physical addresses. These implicitly rely on the unassigned_access hook to cause them to generate an MMU fault if the access fails. Switch to using the address_space_* functions instead, which return a MemTxResult that we can check. This means that when we switch SPARC over to using the do_transaction_failed hook we'll still get the same MMU faults we did before. This commit converts the ASIs which do "MMU passthrough". Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Tested-by: Mark Cave-Ayland Message-id: 20190801183012.17564-3-peter.maydell@linaro.org --- target/sparc/ldst_helper.c | 49 +++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/target/sparc/ldst_helper.c b/target/sparc/ldst_helper.c index 26876e5a57..39698c5885 100644 --- a/target/sparc/ldst_helper.c +++ b/target/sparc/ldst_helper.c @@ -718,26 +718,36 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, case ASI_M_DATAC_DATA: /* SparcStation 5 D-cache data */ break; case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */ + { + MemTxResult result; + hwaddr access_addr = (hwaddr)addr | ((hwaddr)(asi & 0xf) << 32); + switch (size) { case 1: - ret = ldub_phys(cs->as, (hwaddr)addr - | ((hwaddr)(asi & 0xf) << 32)); + ret = address_space_ldub(cs->as, access_addr, + MEMTXATTRS_UNSPECIFIED, &result); break; case 2: - ret = lduw_phys(cs->as, (hwaddr)addr - | ((hwaddr)(asi & 0xf) << 32)); + ret = address_space_lduw(cs->as, access_addr, + MEMTXATTRS_UNSPECIFIED, &result); break; default: case 4: - ret = ldl_phys(cs->as, (hwaddr)addr - | ((hwaddr)(asi & 0xf) << 32)); + ret = address_space_ldl(cs->as, access_addr, + MEMTXATTRS_UNSPECIFIED, &result); break; case 8: - ret = ldq_phys(cs->as, (hwaddr)addr - | ((hwaddr)(asi & 0xf) << 32)); + ret = address_space_ldq(cs->as, access_addr, + MEMTXATTRS_UNSPECIFIED, &result); break; } + + if (result != MEMTX_OK) { + sparc_raise_mmu_fault(cs, access_addr, false, false, false, + size, GETPC()); + } break; + } case 0x30: /* Turbosparc secondary cache diagnostic */ case 0x31: /* Turbosparc RAM snoop */ case 0x32: /* Turbosparc page table descriptor diagnostic */ @@ -1053,25 +1063,32 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, break; case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */ { + MemTxResult result; + hwaddr access_addr = (hwaddr)addr | ((hwaddr)(asi & 0xf) << 32); + switch (size) { case 1: - stb_phys(cs->as, (hwaddr)addr - | ((hwaddr)(asi & 0xf) << 32), val); + address_space_stb(cs->as, access_addr, val, + MEMTXATTRS_UNSPECIFIED, &result); break; case 2: - stw_phys(cs->as, (hwaddr)addr - | ((hwaddr)(asi & 0xf) << 32), val); + address_space_stw(cs->as, access_addr, val, + MEMTXATTRS_UNSPECIFIED, &result); break; case 4: default: - stl_phys(cs->as, (hwaddr)addr - | ((hwaddr)(asi & 0xf) << 32), val); + address_space_stl(cs->as, access_addr, val, + MEMTXATTRS_UNSPECIFIED, &result); break; case 8: - stq_phys(cs->as, (hwaddr)addr - | ((hwaddr)(asi & 0xf) << 32), val); + address_space_stq(cs->as, access_addr, val, + MEMTXATTRS_UNSPECIFIED, &result); break; } + if (result != MEMTX_OK) { + sparc_raise_mmu_fault(cs, access_addr, true, false, false, + size, GETPC()); + } } break; case 0x30: /* store buffer tags or Turbosparc secondary cache diagnostic */