Commit b9f5fdad authored by Peter Maydell's avatar Peter Maydell
Browse files

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: default avatarPeter Maydell <peter.maydell@linaro.org>
Reviewed-by: default avatarRichard Henderson <richard.henderson@linaro.org>
Tested-by: default avatarMark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Message-id: 20190801183012.17564-3-peter.maydell@linaro.org
parent c9d793f4
Loading
Loading
Loading
Loading
+33 −16
Original line number Diff line number Diff line
@@ -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 */