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".

Backports commit b9f5fdad49c74583dcf9fcba0805b148e3992e13 from qemu
This commit is contained in:
Peter Maydell 2019-11-20 13:23:25 -05:00 committed by Lioncash
parent 0b48392779
commit a9e087b252
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7

View file

@ -721,26 +721,36 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr,
/* MMU passthrough, 0x100000000 to 0xfffffffff */ /* MMU passthrough, 0x100000000 to 0xfffffffff */
case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
{
MemTxResult result;
hwaddr access_addr = (hwaddr)addr | ((hwaddr)(asi & 0xf) << 32);
switch (size) { switch (size) {
case 1: case 1:
ret = ldub_phys(cs->as, (hwaddr)addr ret = address_space_ldub(cs->as, access_addr,
| ((hwaddr)(asi & 0xf) << 32)); MEMTXATTRS_UNSPECIFIED, &result);
break; break;
case 2: case 2:
ret = lduw_phys(cs->as, (hwaddr)addr ret = address_space_lduw(cs->as, access_addr,
| ((hwaddr)(asi & 0xf) << 32)); MEMTXATTRS_UNSPECIFIED, &result);
break; break;
default: default:
case 4: case 4:
ret = ldl_phys(cs->as, (hwaddr)addr ret = address_space_ldl(cs->as, access_addr,
| ((hwaddr)(asi & 0xf) << 32)); MEMTXATTRS_UNSPECIFIED, &result);
break; break;
case 8: case 8:
ret = ldq_phys(cs->as, (hwaddr)addr ret = address_space_ldq(cs->as, access_addr,
| ((hwaddr)(asi & 0xf) << 32)); MEMTXATTRS_UNSPECIFIED, &result);
break; break;
} }
if (result != MEMTX_OK) {
sparc_raise_mmu_fault(cs, access_addr, false, false, false,
size, GETPC());
}
break; break;
}
case 0x30: /* Turbosparc secondary cache diagnostic */ case 0x30: /* Turbosparc secondary cache diagnostic */
case 0x31: /* Turbosparc RAM snoop */ case 0x31: /* Turbosparc RAM snoop */
case 0x32: /* Turbosparc page table descriptor diagnostic */ case 0x32: /* Turbosparc page table descriptor diagnostic */
@ -1058,25 +1068,32 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val,
case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
{ {
MemTxResult result;
hwaddr access_addr = (hwaddr)addr | ((hwaddr)(asi & 0xf) << 32);
switch (size) { switch (size) {
case 1: case 1:
stb_phys(cs->as, (hwaddr)addr address_space_stb(cs->as, access_addr, val,
| ((hwaddr)(asi & 0xf) << 32), val); MEMTXATTRS_UNSPECIFIED, &result);
break; break;
case 2: case 2:
stw_phys(cs->as, (hwaddr)addr address_space_stw(cs->as, access_addr, val,
| ((hwaddr)(asi & 0xf) << 32), val); MEMTXATTRS_UNSPECIFIED, &result);
break; break;
case 4: case 4:
default: default:
stl_phys(cs->as, (hwaddr)addr address_space_stl(cs->as, access_addr, val,
| ((hwaddr)(asi & 0xf) << 32), val); MEMTXATTRS_UNSPECIFIED, &result);
break; break;
case 8: case 8:
stq_phys(cs->as, (hwaddr)addr address_space_stq(cs->as, access_addr, val,
| ((hwaddr)(asi & 0xf) << 32), val); MEMTXATTRS_UNSPECIFIED, &result);
break; break;
} }
if (result != MEMTX_OK) {
sparc_raise_mmu_fault(cs, access_addr, true, false, false,
size, GETPC());
}
} }
break; break;
case 0x30: /* store buffer tags or Turbosparc secondary cache diagnostic */ case 0x30: /* store buffer tags or Turbosparc secondary cache diagnostic */