aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kvm
diff options
context:
space:
mode:
authorDavid Hildenbrand <dahi@linux.vnet.ibm.com>2016-04-18 07:42:05 -0400
committerChristian Borntraeger <borntraeger@de.ibm.com>2016-06-20 03:54:56 -0400
commit18b89809881834cecd2977e6048a30c4c8f140fe (patch)
tree7542079e9cbb1b59df833981ddd005a3524178bc /arch/s390/kvm
parentfd8d4e3ab6993e194287a59c4d3a6a43da86b8dc (diff)
s390/mm: support EDAT2 for gmap shadows
If the guest is enabled for EDAT2, we can easily create shadows for guest2 -> guest3 provided tables that make use of EDAT2. If guest2 references a 2GB page, this memory looks consecutive for guest2, but it does not have to be so for us. Therefore we have to create fake segment and page tables. This works just like EDAT1 support, so page tables are removed when the parent table (r3t table entry) is changed. We don't hve to care about: - ACCF-Validity Control in RTTE - Access-Control Bits in RTTE - Fetch-Protection Bit in RTTE - Common-Region Bit in RTTE Just like for EDAT1, all bits might be dropped and there is no guaranteed that they are active. 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.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c
index af1fc6fa7b74..fab03ecb5bd5 100644
--- a/arch/s390/kvm/gaccess.c
+++ b/arch/s390/kvm/gaccess.c
@@ -1042,17 +1042,35 @@ static int kvm_s390_shadow_tables(struct gmap *sg, unsigned long saddr,
1042 return PGM_REGION_THIRD_TRANS; 1042 return PGM_REGION_THIRD_TRANS;
1043 if (rtte.tt != TABLE_TYPE_REGION3) 1043 if (rtte.tt != TABLE_TYPE_REGION3)
1044 return PGM_TRANSLATION_SPEC; 1044 return PGM_TRANSLATION_SPEC;
1045 if (rtte.cr && asce.p && sg->edat_level >= 2)
1046 return PGM_TRANSLATION_SPEC;
1047 if (rtte.fc && sg->edat_level >= 2) {
1048 bool prot = rtte.fc1.p;
1049
1050 *fake = 1;
1051 ptr = rtte.fc1.rfaa << 31UL;
1052 rtte.val = ptr;
1053 rtte.fc0.p = prot;
1054 goto shadow_sgt;
1055 }
1045 if (vaddr.sx01 < rtte.fc0.tf || vaddr.sx01 > rtte.fc0.tl) 1056 if (vaddr.sx01 < rtte.fc0.tf || vaddr.sx01 > rtte.fc0.tl)
1046 return PGM_SEGMENT_TRANSLATION; 1057 return PGM_SEGMENT_TRANSLATION;
1047 rc = gmap_shadow_sgt(sg, saddr, rtte.val); 1058 ptr = rtte.fc0.sto << 12UL;
1059shadow_sgt:
1060 rc = gmap_shadow_sgt(sg, saddr, rtte.val, *fake);
1048 if (rc) 1061 if (rc)
1049 return rc; 1062 return rc;
1050 ptr = rtte.fc0.sto * 4096;
1051 /* fallthrough */ 1063 /* fallthrough */
1052 } 1064 }
1053 case ASCE_TYPE_SEGMENT: { 1065 case ASCE_TYPE_SEGMENT: {
1054 union segment_table_entry ste; 1066 union segment_table_entry ste;
1055 1067
1068 if (*fake) {
1069 /* offset in 2G guest memory block */
1070 ptr = ptr + ((unsigned long) vaddr.sx << 20UL);
1071 ste.val = ptr;
1072 goto shadow_pgt;
1073 }
1056 rc = gmap_read_table(parent, ptr + vaddr.sx * 8, &ste.val); 1074 rc = gmap_read_table(parent, ptr + vaddr.sx * 8, &ste.val);
1057 if (rc) 1075 if (rc)
1058 return rc; 1076 return rc;