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.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-Id: <20181210165636.28366-3-peter.maydell@linaro.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
This commit is contained in:
Peter Maydell 2018-12-10 16:56:35 +00:00 committed by Laurent Vivier
parent f80b551ddc
commit adcf0bf017
1 changed files with 52 additions and 10 deletions

View File

@ -651,6 +651,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++) {
@ -680,12 +681,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) {
@ -700,12 +708,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) {
@ -724,27 +739,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;
}
} }
} }
@ -776,6 +810,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)