aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRadim Krčmář <rkrcmar@redhat.com>2017-06-22 10:13:06 -0400
committerRadim Krčmář <rkrcmar@redhat.com>2017-06-22 10:13:06 -0400
commitd6aa07c16941dcf438bd526a56dcf227991c5907 (patch)
tree8a1f69436d3fa9355459fd79661d9a177001a39e
parente27a9eca5d4a392b96ce5d5238c8d637bcb0a52c (diff)
parentaddb63c18a0d52a9ce2611d039f981f7b6148d2b (diff)
Merge tag 'kvm-s390-master-4.12-2' of git://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux
KVM: s390: fix shadow table handling for nested guests Some odd-ball cases (real-space designation ASCEs) are handled wrong for the shadow page tables. Fix it.
-rw-r--r--arch/s390/kvm/gaccess.c15
1 files changed, 6 insertions, 9 deletions
diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c
index 9da243d94cc3..3b297fa3aa67 100644
--- a/arch/s390/kvm/gaccess.c
+++ b/arch/s390/kvm/gaccess.c
@@ -977,11 +977,12 @@ static int kvm_s390_shadow_tables(struct gmap *sg, unsigned long saddr,
977 ptr = asce.origin * 4096; 977 ptr = asce.origin * 4096;
978 if (asce.r) { 978 if (asce.r) {
979 *fake = 1; 979 *fake = 1;
980 ptr = 0;
980 asce.dt = ASCE_TYPE_REGION1; 981 asce.dt = ASCE_TYPE_REGION1;
981 } 982 }
982 switch (asce.dt) { 983 switch (asce.dt) {
983 case ASCE_TYPE_REGION1: 984 case ASCE_TYPE_REGION1:
984 if (vaddr.rfx01 > asce.tl && !asce.r) 985 if (vaddr.rfx01 > asce.tl && !*fake)
985 return PGM_REGION_FIRST_TRANS; 986 return PGM_REGION_FIRST_TRANS;
986 break; 987 break;
987 case ASCE_TYPE_REGION2: 988 case ASCE_TYPE_REGION2:
@@ -1009,8 +1010,7 @@ static int kvm_s390_shadow_tables(struct gmap *sg, unsigned long saddr,
1009 union region1_table_entry rfte; 1010 union region1_table_entry rfte;
1010 1011
1011 if (*fake) { 1012 if (*fake) {
1012 /* offset in 16EB guest memory block */ 1013 ptr += (unsigned long) vaddr.rfx << 53;
1013 ptr = ptr + ((unsigned long) vaddr.rsx << 53UL);
1014 rfte.val = ptr; 1014 rfte.val = ptr;
1015 goto shadow_r2t; 1015 goto shadow_r2t;
1016 } 1016 }
@@ -1036,8 +1036,7 @@ shadow_r2t:
1036 union region2_table_entry rste; 1036 union region2_table_entry rste;
1037 1037
1038 if (*fake) { 1038 if (*fake) {
1039 /* offset in 8PB guest memory block */ 1039 ptr += (unsigned long) vaddr.rsx << 42;
1040 ptr = ptr + ((unsigned long) vaddr.rtx << 42UL);
1041 rste.val = ptr; 1040 rste.val = ptr;
1042 goto shadow_r3t; 1041 goto shadow_r3t;
1043 } 1042 }
@@ -1064,8 +1063,7 @@ shadow_r3t:
1064 union region3_table_entry rtte; 1063 union region3_table_entry rtte;
1065 1064
1066 if (*fake) { 1065 if (*fake) {
1067 /* offset in 4TB guest memory block */ 1066 ptr += (unsigned long) vaddr.rtx << 31;
1068 ptr = ptr + ((unsigned long) vaddr.sx << 31UL);
1069 rtte.val = ptr; 1067 rtte.val = ptr;
1070 goto shadow_sgt; 1068 goto shadow_sgt;
1071 } 1069 }
@@ -1101,8 +1099,7 @@ shadow_sgt:
1101 union segment_table_entry ste; 1099 union segment_table_entry ste;
1102 1100
1103 if (*fake) { 1101 if (*fake) {
1104 /* offset in 2G guest memory block */ 1102 ptr += (unsigned long) vaddr.sx << 20;
1105 ptr = ptr + ((unsigned long) vaddr.sx << 20UL);
1106 ste.val = ptr; 1103 ste.val = ptr;
1107 goto shadow_pgt; 1104 goto shadow_pgt;
1108 } 1105 }