hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/arch/s390/kvm/gaccess.c
....@@ -9,8 +9,8 @@
99 #include <linux/vmalloc.h>
1010 #include <linux/mm_types.h>
1111 #include <linux/err.h>
12
+#include <linux/pgtable.h>
1213
13
-#include <asm/pgtable.h>
1414 #include <asm/gmap.h>
1515 #include "kvm-s390.h"
1616 #include "gaccess.h"
....@@ -505,7 +505,7 @@
505505 switch (prot) {
506506 case PROT_TYPE_IEP:
507507 tec->b61 = 1;
508
- /* FALL THROUGH */
508
+ fallthrough;
509509 case PROT_TYPE_LA:
510510 tec->b56 = 1;
511511 break;
....@@ -514,12 +514,12 @@
514514 break;
515515 case PROT_TYPE_ALC:
516516 tec->b60 = 1;
517
- /* FALL THROUGH */
517
+ fallthrough;
518518 case PROT_TYPE_DAT:
519519 tec->b61 = 1;
520520 break;
521521 }
522
- /* FALL THROUGH */
522
+ fallthrough;
523523 case PGM_ASCE_TYPE:
524524 case PGM_PAGE_TRANSLATION:
525525 case PGM_REGION_FIRST_TRANS:
....@@ -534,7 +534,7 @@
534534 tec->addr = gva >> PAGE_SHIFT;
535535 tec->fsi = mode == GACC_STORE ? FSI_STORE : FSI_FETCH;
536536 tec->as = psw_bits(vcpu->arch.sie_block->gpsw).as;
537
- /* FALL THROUGH */
537
+ fallthrough;
538538 case PGM_ALEN_TRANSLATION:
539539 case PGM_ALE_SEQUENCE:
540540 case PGM_ASTE_VALIDITY:
....@@ -677,7 +677,7 @@
677677 dat_protection |= rfte.p;
678678 ptr = rfte.rto * PAGE_SIZE + vaddr.rsx * 8;
679679 }
680
- /* fallthrough */
680
+ fallthrough;
681681 case ASCE_TYPE_REGION2: {
682682 union region2_table_entry rste;
683683
....@@ -695,7 +695,7 @@
695695 dat_protection |= rste.p;
696696 ptr = rste.rto * PAGE_SIZE + vaddr.rtx * 8;
697697 }
698
- /* fallthrough */
698
+ fallthrough;
699699 case ASCE_TYPE_REGION3: {
700700 union region3_table_entry rtte;
701701
....@@ -723,7 +723,7 @@
723723 dat_protection |= rtte.fc0.p;
724724 ptr = rtte.fc0.sto * PAGE_SIZE + vaddr.sx * 8;
725725 }
726
- /* fallthrough */
726
+ fallthrough;
727727 case ASCE_TYPE_SEGMENT: {
728728 union segment_table_entry ste;
729729
....@@ -976,7 +976,9 @@
976976 * kvm_s390_shadow_tables - walk the guest page table and create shadow tables
977977 * @sg: pointer to the shadow guest address space structure
978978 * @saddr: faulting address in the shadow gmap
979
- * @pgt: pointer to the page table address result
979
+ * @pgt: pointer to the beginning of the page table for the given address if
980
+ * successful (return value 0), or to the first invalid DAT entry in
981
+ * case of exceptions (return value > 0)
980982 * @fake: pgt references contiguous guest memory block, not a pgtable
981983 */
982984 static int kvm_s390_shadow_tables(struct gmap *sg, unsigned long saddr,
....@@ -1034,6 +1036,7 @@
10341036 rfte.val = ptr;
10351037 goto shadow_r2t;
10361038 }
1039
+ *pgt = ptr + vaddr.rfx * 8;
10371040 rc = gmap_read_table(parent, ptr + vaddr.rfx * 8, &rfte.val);
10381041 if (rc)
10391042 return rc;
....@@ -1050,7 +1053,8 @@
10501053 rc = gmap_shadow_r2t(sg, saddr, rfte.val, *fake);
10511054 if (rc)
10521055 return rc;
1053
- } /* fallthrough */
1056
+ }
1057
+ fallthrough;
10541058 case ASCE_TYPE_REGION2: {
10551059 union region2_table_entry rste;
10561060
....@@ -1059,6 +1063,7 @@
10591063 rste.val = ptr;
10601064 goto shadow_r3t;
10611065 }
1066
+ *pgt = ptr + vaddr.rsx * 8;
10621067 rc = gmap_read_table(parent, ptr + vaddr.rsx * 8, &rste.val);
10631068 if (rc)
10641069 return rc;
....@@ -1076,7 +1081,8 @@
10761081 rc = gmap_shadow_r3t(sg, saddr, rste.val, *fake);
10771082 if (rc)
10781083 return rc;
1079
- } /* fallthrough */
1084
+ }
1085
+ fallthrough;
10801086 case ASCE_TYPE_REGION3: {
10811087 union region3_table_entry rtte;
10821088
....@@ -1085,6 +1091,7 @@
10851091 rtte.val = ptr;
10861092 goto shadow_sgt;
10871093 }
1094
+ *pgt = ptr + vaddr.rtx * 8;
10881095 rc = gmap_read_table(parent, ptr + vaddr.rtx * 8, &rtte.val);
10891096 if (rc)
10901097 return rc;
....@@ -1111,7 +1118,8 @@
11111118 rc = gmap_shadow_sgt(sg, saddr, rtte.val, *fake);
11121119 if (rc)
11131120 return rc;
1114
- } /* fallthrough */
1121
+ }
1122
+ fallthrough;
11151123 case ASCE_TYPE_SEGMENT: {
11161124 union segment_table_entry ste;
11171125
....@@ -1120,6 +1128,7 @@
11201128 ste.val = ptr;
11211129 goto shadow_pgt;
11221130 }
1131
+ *pgt = ptr + vaddr.sx * 8;
11231132 rc = gmap_read_table(parent, ptr + vaddr.sx * 8, &ste.val);
11241133 if (rc)
11251134 return rc;
....@@ -1154,6 +1163,8 @@
11541163 * @vcpu: virtual cpu
11551164 * @sg: pointer to the shadow guest address space structure
11561165 * @saddr: faulting address in the shadow gmap
1166
+ * @datptr: will contain the address of the faulting DAT table entry, or of
1167
+ * the valid leaf, plus some flags
11571168 *
11581169 * Returns: - 0 if the shadow fault was successfully resolved
11591170 * - > 0 (pgm exception code) on exceptions while faulting
....@@ -1162,15 +1173,15 @@
11621173 * - -ENOMEM if out of memory
11631174 */
11641175 int kvm_s390_shadow_fault(struct kvm_vcpu *vcpu, struct gmap *sg,
1165
- unsigned long saddr)
1176
+ unsigned long saddr, unsigned long *datptr)
11661177 {
11671178 union vaddress vaddr;
11681179 union page_table_entry pte;
1169
- unsigned long pgt;
1180
+ unsigned long pgt = 0;
11701181 int dat_protection, fake;
11711182 int rc;
11721183
1173
- down_read(&sg->mm->mmap_sem);
1184
+ mmap_read_lock(sg->mm);
11741185 /*
11751186 * We don't want any guest-2 tables to change - so the parent
11761187 * tables/pointers we read stay valid - unshadowing is however
....@@ -1188,8 +1199,20 @@
11881199 pte.val = pgt + vaddr.px * PAGE_SIZE;
11891200 goto shadow_page;
11901201 }
1191
- if (!rc)
1192
- rc = gmap_read_table(sg->parent, pgt + vaddr.px * 8, &pte.val);
1202
+
1203
+ switch (rc) {
1204
+ case PGM_SEGMENT_TRANSLATION:
1205
+ case PGM_REGION_THIRD_TRANS:
1206
+ case PGM_REGION_SECOND_TRANS:
1207
+ case PGM_REGION_FIRST_TRANS:
1208
+ pgt |= PEI_NOT_PTE;
1209
+ break;
1210
+ case 0:
1211
+ pgt += vaddr.px * 8;
1212
+ rc = gmap_read_table(sg->parent, pgt, &pte.val);
1213
+ }
1214
+ if (datptr)
1215
+ *datptr = pgt | dat_protection * PEI_DAT_PROT;
11931216 if (!rc && pte.i)
11941217 rc = PGM_PAGE_TRANSLATION;
11951218 if (!rc && pte.z)
....@@ -1199,6 +1222,6 @@
11991222 if (!rc)
12001223 rc = gmap_shadow_page(sg, saddr, __pte(pte.val));
12011224 ipte_unlock(vcpu);
1202
- up_read(&sg->mm->mmap_sem);
1225
+ mmap_read_unlock(sg->mm);
12031226 return rc;
12041227 }