aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kvm
diff options
context:
space:
mode:
authorDavid Hildenbrand <dahi@linux.vnet.ibm.com>2016-04-18 10:22:24 -0400
committerChristian Borntraeger <borntraeger@de.ibm.com>2016-06-20 03:55:02 -0400
commit3218f7094b6b583f4f01bffcf84572c6beacdcc2 (patch)
tree4ebcd767692fccf684503c8202c00cc87dba3472 /arch/s390/kvm
parent1c65781b56ce812ce9729bf414201921c9408678 (diff)
s390/mm: support real-space for gmap shadows
We can easily support real-space designation just like EDAT1 and EDAT2. So guest2 can provide for guest3 an asce with the real-space control being set. We simply have to allocate the biggest page table possible and fake all levels. There is no protection to consider. If we exceed guest memory, vsie code will inject an addressing exception (via program intercept). In the future, we could limit the fake table level to the gmap page table. As the top level page table can never go away, such gmap shadows will never get unshadowed, we'll have to come up with another way to limit the number of kept gmap shadows. 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')
-rw-r--r--arch/s390/kvm/gaccess.c34
1 files changed, 29 insertions, 5 deletions
diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c
index f6d556dfafcd..54200208bf24 100644
--- a/arch/s390/kvm/gaccess.c
+++ b/arch/s390/kvm/gaccess.c
@@ -971,9 +971,13 @@ static int kvm_s390_shadow_tables(struct gmap *sg, unsigned long saddr,
971 vaddr.addr = saddr; 971 vaddr.addr = saddr;
972 asce.val = sg->orig_asce; 972 asce.val = sg->orig_asce;
973 ptr = asce.origin * 4096; 973 ptr = asce.origin * 4096;
974 if (asce.r) {
975 *fake = 1;
976 asce.dt = ASCE_TYPE_REGION1;
977 }
974 switch (asce.dt) { 978 switch (asce.dt) {
975 case ASCE_TYPE_REGION1: 979 case ASCE_TYPE_REGION1:
976 if (vaddr.rfx01 > asce.tl) 980 if (vaddr.rfx01 > asce.tl && !asce.r)
977 return PGM_REGION_FIRST_TRANS; 981 return PGM_REGION_FIRST_TRANS;
978 break; 982 break;
979 case ASCE_TYPE_REGION2: 983 case ASCE_TYPE_REGION2:
@@ -1000,6 +1004,12 @@ static int kvm_s390_shadow_tables(struct gmap *sg, unsigned long saddr,
1000 case ASCE_TYPE_REGION1: { 1004 case ASCE_TYPE_REGION1: {
1001 union region1_table_entry rfte; 1005 union region1_table_entry rfte;
1002 1006
1007 if (*fake) {
1008 /* offset in 16EB guest memory block */
1009 ptr = ptr + ((unsigned long) vaddr.rsx << 53UL);
1010 rfte.val = ptr;
1011 goto shadow_r2t;
1012 }
1003 rc = gmap_read_table(parent, ptr + vaddr.rfx * 8, &rfte.val); 1013 rc = gmap_read_table(parent, ptr + vaddr.rfx * 8, &rfte.val);
1004 if (rc) 1014 if (rc)
1005 return rc; 1015 return rc;
@@ -1011,15 +1021,22 @@ static int kvm_s390_shadow_tables(struct gmap *sg, unsigned long saddr,
1011 return PGM_REGION_SECOND_TRANS; 1021 return PGM_REGION_SECOND_TRANS;
1012 if (sg->edat_level >= 1) 1022 if (sg->edat_level >= 1)
1013 *dat_protection |= rfte.p; 1023 *dat_protection |= rfte.p;
1014 rc = gmap_shadow_r2t(sg, saddr, rfte.val); 1024 ptr = rfte.rto << 12UL;
1025shadow_r2t:
1026 rc = gmap_shadow_r2t(sg, saddr, rfte.val, *fake);
1015 if (rc) 1027 if (rc)
1016 return rc; 1028 return rc;
1017 ptr = rfte.rto * 4096;
1018 /* fallthrough */ 1029 /* fallthrough */
1019 } 1030 }
1020 case ASCE_TYPE_REGION2: { 1031 case ASCE_TYPE_REGION2: {
1021 union region2_table_entry rste; 1032 union region2_table_entry rste;
1022 1033
1034 if (*fake) {
1035 /* offset in 8PB guest memory block */
1036 ptr = ptr + ((unsigned long) vaddr.rtx << 42UL);
1037 rste.val = ptr;
1038 goto shadow_r3t;
1039 }
1023 rc = gmap_read_table(parent, ptr + vaddr.rsx * 8, &rste.val); 1040 rc = gmap_read_table(parent, ptr + vaddr.rsx * 8, &rste.val);
1024 if (rc) 1041 if (rc)
1025 return rc; 1042 return rc;
@@ -1031,16 +1048,23 @@ static int kvm_s390_shadow_tables(struct gmap *sg, unsigned long saddr,
1031 return PGM_REGION_THIRD_TRANS; 1048 return PGM_REGION_THIRD_TRANS;
1032 if (sg->edat_level >= 1) 1049 if (sg->edat_level >= 1)
1033 *dat_protection |= rste.p; 1050 *dat_protection |= rste.p;
1051 ptr = rste.rto << 12UL;
1052shadow_r3t:
1034 rste.p |= *dat_protection; 1053 rste.p |= *dat_protection;
1035 rc = gmap_shadow_r3t(sg, saddr, rste.val); 1054 rc = gmap_shadow_r3t(sg, saddr, rste.val, *fake);
1036 if (rc) 1055 if (rc)
1037 return rc; 1056 return rc;
1038 ptr = rste.rto * 4096;
1039 /* fallthrough */ 1057 /* fallthrough */
1040 } 1058 }
1041 case ASCE_TYPE_REGION3: { 1059 case ASCE_TYPE_REGION3: {
1042 union region3_table_entry rtte; 1060 union region3_table_entry rtte;
1043 1061
1062 if (*fake) {
1063 /* offset in 4TB guest memory block */
1064 ptr = ptr + ((unsigned long) vaddr.sx << 31UL);
1065 rtte.val = ptr;
1066 goto shadow_sgt;
1067 }
1044 rc = gmap_read_table(parent, ptr + vaddr.rtx * 8, &rtte.val); 1068 rc = gmap_read_table(parent, ptr + vaddr.rtx * 8, &rtte.val);
1045 if (rc) 1069 if (rc)
1046 return rc; 1070 return rc;