target/m68k: In get_physical_address() check for memory access failures

In get_physical_address(), use address_space_ldl() and
address_space_stl() instead of ldl_phys() and stl_phys().
This allows us to check whether the memory access failed.
For the moment, we simply return -1 in this case;
add a TODO comment that we should ideally generate the
appropriate kind of fault.

Backports commit adcf0bf017351776510121e47b9226095836023c from qemu
This commit is contained in:
Peter Maydell 2019-05-17 11:58:13 -04:00 committed by Lioncash
parent 2a4a7b9391
commit ab63f1a102
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7

View file

@ -276,6 +276,7 @@ static int get_physical_address(CPUM68KState *env, hwaddr *physical,
bool debug = access_type & ACCESS_DEBUG; bool debug = access_type & ACCESS_DEBUG;
int page_bits; int page_bits;
int i; int i;
MemTxResult txres;
/* Transparent Translation (physical = logical) */ /* Transparent Translation (physical = logical) */
for (i = 0; i < M68K_MAX_TTR; i++) { for (i = 0; i < M68K_MAX_TTR; i++) {
@ -305,12 +306,19 @@ static int get_physical_address(CPUM68KState *env, hwaddr *physical,
/* Root Index */ /* Root Index */
entry = M68K_POINTER_BASE(next) | M68K_ROOT_INDEX(address); entry = M68K_POINTER_BASE(next) | M68K_ROOT_INDEX(address);
next = ldl_phys(cs->as, entry); next = address_space_ldl(cs->as, entry, MEMTXATTRS_UNSPECIFIED, &txres);
if (txres != MEMTX_OK) {
goto txfail;
}
if (!M68K_UDT_VALID(next)) { if (!M68K_UDT_VALID(next)) {
return -1; return -1;
} }
if (!(next & M68K_DESC_USED) && !debug) { if (!(next & M68K_DESC_USED) && !debug) {
stl_phys(cs->as, entry, next | M68K_DESC_USED); address_space_stl(cs->as, entry, next | M68K_DESC_USED,
MEMTXATTRS_UNSPECIFIED, &txres);
if (txres != MEMTX_OK) {
goto txfail;
}
} }
if (next & M68K_DESC_WRITEPROT) { if (next & M68K_DESC_WRITEPROT) {
if (access_type & ACCESS_PTEST) { if (access_type & ACCESS_PTEST) {
@ -325,12 +333,19 @@ static int get_physical_address(CPUM68KState *env, hwaddr *physical,
/* Pointer Index */ /* Pointer Index */
entry = M68K_POINTER_BASE(next) | M68K_POINTER_INDEX(address); entry = M68K_POINTER_BASE(next) | M68K_POINTER_INDEX(address);
next = ldl_phys(cs->as, entry); next = address_space_ldl(cs->as, entry, MEMTXATTRS_UNSPECIFIED, &txres);
if (txres != MEMTX_OK) {
goto txfail;
}
if (!M68K_UDT_VALID(next)) { if (!M68K_UDT_VALID(next)) {
return -1; return -1;
} }
if (!(next & M68K_DESC_USED) && !debug) { if (!(next & M68K_DESC_USED) && !debug) {
stl_phys(cs->as, entry, next | M68K_DESC_USED); address_space_stl(cs->as, entry, next | M68K_DESC_USED,
MEMTXATTRS_UNSPECIFIED, &txres);
if (txres != MEMTX_OK) {
goto txfail;
}
} }
if (next & M68K_DESC_WRITEPROT) { if (next & M68K_DESC_WRITEPROT) {
if (access_type & ACCESS_PTEST) { if (access_type & ACCESS_PTEST) {
@ -349,27 +364,46 @@ static int get_physical_address(CPUM68KState *env, hwaddr *physical,
entry = M68K_4K_PAGE_BASE(next) | M68K_4K_PAGE_INDEX(address); entry = M68K_4K_PAGE_BASE(next) | M68K_4K_PAGE_INDEX(address);
} }
next = ldl_phys(cs->as, entry); next = address_space_ldl(cs->as, entry, MEMTXATTRS_UNSPECIFIED, &txres);
if (txres != MEMTX_OK) {
goto txfail;
}
if (!M68K_PDT_VALID(next)) { if (!M68K_PDT_VALID(next)) {
return -1; return -1;
} }
if (M68K_PDT_INDIRECT(next)) { if (M68K_PDT_INDIRECT(next)) {
next = ldl_phys(cs->as, M68K_INDIRECT_POINTER(next)); next = address_space_ldl(cs->as, M68K_INDIRECT_POINTER(next),
MEMTXATTRS_UNSPECIFIED, &txres);
if (txres != MEMTX_OK) {
goto txfail;
}
} }
if (access_type & ACCESS_STORE) { if (access_type & ACCESS_STORE) {
if (next & M68K_DESC_WRITEPROT) { if (next & M68K_DESC_WRITEPROT) {
if (!(next & M68K_DESC_USED) && !debug) { if (!(next & M68K_DESC_USED) && !debug) {
stl_phys(cs->as, entry, next | M68K_DESC_USED); address_space_stl(cs->as, entry, next | M68K_DESC_USED,
MEMTXATTRS_UNSPECIFIED, &txres);
if (txres != MEMTX_OK) {
goto txfail;
}
} }
} else if ((next & (M68K_DESC_MODIFIED | M68K_DESC_USED)) != } else if ((next & (M68K_DESC_MODIFIED | M68K_DESC_USED)) !=
(M68K_DESC_MODIFIED | M68K_DESC_USED) && !debug) { (M68K_DESC_MODIFIED | M68K_DESC_USED) && !debug) {
stl_phys(cs->as, entry, address_space_stl(cs->as, entry,
next | (M68K_DESC_MODIFIED | M68K_DESC_USED)); next | (M68K_DESC_MODIFIED | M68K_DESC_USED),
MEMTXATTRS_UNSPECIFIED, &txres);
if (txres != MEMTX_OK) {
goto txfail;
}
} }
} else { } else {
if (!(next & M68K_DESC_USED) && !debug) { if (!(next & M68K_DESC_USED) && !debug) {
stl_phys(cs->as, entry, next | M68K_DESC_USED); address_space_stl(cs->as, entry, next | M68K_DESC_USED,
MEMTXATTRS_UNSPECIFIED, &txres);
if (txres != MEMTX_OK) {
goto txfail;
}
} }
} }
@ -401,6 +435,14 @@ static int get_physical_address(CPUM68KState *env, hwaddr *physical,
} }
return 0; return 0;
txfail:
/*
* A page table load/store failed. TODO: we should really raise a
* suitable guest fault here if this is not a debug access.
* For now just return that the translation failed.
*/
return -1;
} }
hwaddr m68k_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) hwaddr m68k_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)