summaryrefslogtreecommitdiffstats
path: root/target/s390x
diff options
context:
space:
mode:
authorDavid Hildenbrand2018-01-15 00:04:07 +0100
committerDavid Hildenbrand2019-10-09 12:49:01 +0200
commit90790898a1c93072d080f46b30259ee5ca4e6435 (patch)
treeb2470b9b7978e28e55ed565ab32ac0c32e956851 /target/s390x
parents390x/mmu: Convert to non-recursive page table walk (diff)
downloadqemu-90790898a1c93072d080f46b30259ee5ca4e6435.tar.gz
qemu-90790898a1c93072d080f46b30259ee5ca4e6435.tar.xz
qemu-90790898a1c93072d080f46b30259ee5ca4e6435.zip
s390x/mmu: Add EDAT2 translation support
This only adds basic support to the DAT translation, but no EDAT2 support for TCG. E.g., the gdbstub under kvm uses this function, too, to translate virtual addresses. Reviewed-by: Thomas Huth <thuth@redhat.com> Signed-off-by: David Hildenbrand <david@redhat.com>
Diffstat (limited to 'target/s390x')
-rw-r--r--target/s390x/mmu_helper.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/target/s390x/mmu_helper.c b/target/s390x/mmu_helper.c
index dc33c63b1d..e27e21328b 100644
--- a/target/s390x/mmu_helper.c
+++ b/target/s390x/mmu_helper.c
@@ -120,6 +120,7 @@ static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr,
{
const bool edat1 = (env->cregs[0] & CR0_EDAT) &&
s390_has_feat(S390_FEAT_EDAT);
+ const bool edat2 = edat1 && s390_has_feat(S390_FEAT_EDAT_2);
const int asce_tl = asce & ASCE_TABLE_LENGTH;
const int asce_p = asce & ASCE_PRIVATE_SPACE;
hwaddr gaddr = asce & ASCE_ORIGIN;
@@ -217,13 +218,21 @@ static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr,
if ((entry & REGION_ENTRY_TT) != REGION_ENTRY_TT_REGION3) {
return PGM_TRANS_SPEC;
}
- if (VADDR_SEGMENT_TL(vaddr) < (entry & REGION_ENTRY_TF) >> 6 ||
- VADDR_SEGMENT_TL(vaddr) > (entry & REGION_ENTRY_TL)) {
- return PGM_SEGMENT_TRANS;
+ if (edat2 && (entry & REGION3_ENTRY_CR) && asce_p) {
+ return PGM_TRANS_SPEC;
}
if (edat1 && (entry & REGION_ENTRY_P)) {
*flags &= ~PAGE_WRITE;
}
+ if (edat2 && (entry & REGION3_ENTRY_FC)) {
+ *raddr = (entry & REGION3_ENTRY_RFAA) |
+ (vaddr & ~REGION3_ENTRY_RFAA);
+ return 0;
+ }
+ if (VADDR_SEGMENT_TL(vaddr) < (entry & REGION_ENTRY_TF) >> 6 ||
+ VADDR_SEGMENT_TL(vaddr) > (entry & REGION_ENTRY_TL)) {
+ return PGM_SEGMENT_TRANS;
+ }
gaddr = (entry & REGION_ENTRY_ORIGIN) + VADDR_SEGMENT_TX(vaddr) * 8;
/* fall through */
case ASCE_TYPE_SEGMENT: