aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kvm/gaccess.c
diff options
context:
space:
mode:
authorDavid Hildenbrand <dahi@linux.vnet.ibm.com>2016-04-18 17:46:21 +0200
committerChristian Borntraeger <borntraeger@de.ibm.com>2016-06-20 09:55:00 +0200
commit1c65781b56ce812ce9729bf414201921c9408678 (patch)
treedb27b44256087076cb0a88d0e3e3e63cfc103ad5 /arch/s390/kvm/gaccess.c
parents390/mm: support EDAT2 for gmap shadows (diff)
downloadlinux-dev-1c65781b56ce812ce9729bf414201921c9408678.tar.xz
linux-dev-1c65781b56ce812ce9729bf414201921c9408678.zip
s390/mm: push rte protection down to shadow pte
Just like we already do with ste protection, let's take rte protection into account. This way, the host pte doesn't have to be mapped writable. Acked-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Diffstat (limited to 'arch/s390/kvm/gaccess.c')
-rw-r--r--arch/s390/kvm/gaccess.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c
index fab03ecb5bd5..f6d556dfafcd 100644
--- a/arch/s390/kvm/gaccess.c
+++ b/arch/s390/kvm/gaccess.c
@@ -966,6 +966,7 @@ static int kvm_s390_shadow_tables(struct gmap *sg, unsigned long saddr,
int rc;
*fake = 0;
+ *dat_protection = 0;
parent = sg->parent;
vaddr.addr = saddr;
asce.val = sg->orig_asce;
@@ -1008,6 +1009,8 @@ static int kvm_s390_shadow_tables(struct gmap *sg, unsigned long saddr,
return PGM_TRANSLATION_SPEC;
if (vaddr.rsx01 < rfte.tf || vaddr.rsx01 > rfte.tl)
return PGM_REGION_SECOND_TRANS;
+ if (sg->edat_level >= 1)
+ *dat_protection |= rfte.p;
rc = gmap_shadow_r2t(sg, saddr, rfte.val);
if (rc)
return rc;
@@ -1026,6 +1029,9 @@ static int kvm_s390_shadow_tables(struct gmap *sg, unsigned long saddr,
return PGM_TRANSLATION_SPEC;
if (vaddr.rtx01 < rste.tf || vaddr.rtx01 > rste.tl)
return PGM_REGION_THIRD_TRANS;
+ if (sg->edat_level >= 1)
+ *dat_protection |= rste.p;
+ rste.p |= *dat_protection;
rc = gmap_shadow_r3t(sg, saddr, rste.val);
if (rc)
return rc;
@@ -1045,18 +1051,19 @@ static int kvm_s390_shadow_tables(struct gmap *sg, unsigned long saddr,
if (rtte.cr && asce.p && sg->edat_level >= 2)
return PGM_TRANSLATION_SPEC;
if (rtte.fc && sg->edat_level >= 2) {
- bool prot = rtte.fc1.p;
-
+ *dat_protection |= rtte.fc0.p;
*fake = 1;
ptr = rtte.fc1.rfaa << 31UL;
rtte.val = ptr;
- rtte.fc0.p = prot;
goto shadow_sgt;
}
if (vaddr.sx01 < rtte.fc0.tf || vaddr.sx01 > rtte.fc0.tl)
return PGM_SEGMENT_TRANSLATION;
+ if (sg->edat_level >= 1)
+ *dat_protection |= rtte.fc0.p;
ptr = rtte.fc0.sto << 12UL;
shadow_sgt:
+ rtte.fc0.p |= *dat_protection;
rc = gmap_shadow_sgt(sg, saddr, rtte.val, *fake);
if (rc)
return rc;
@@ -1080,18 +1087,16 @@ shadow_sgt:
return PGM_TRANSLATION_SPEC;
if (ste.cs && asce.p)
return PGM_TRANSLATION_SPEC;
- *dat_protection = ste.fc0.p;
+ *dat_protection |= ste.fc0.p;
if (ste.fc && sg->edat_level >= 1) {
- bool prot = ste.fc1.p;
-
*fake = 1;
ptr = ste.fc1.sfaa << 20UL;
ste.val = ptr;
- ste.fc0.p = prot;
goto shadow_pgt;
}
ptr = ste.fc0.pto << 11UL;
shadow_pgt:
+ ste.fc0.p |= *dat_protection;
rc = gmap_shadow_pgt(sg, saddr, ste.val, *fake);
if (rc)
return rc;