forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-11 6778948f9de86c3cfaf36725a7c87dcff9ba247f
kernel/arch/s390/kvm/priv.c
....@@ -2,7 +2,7 @@
22 /*
33 * handling privileged instructions
44 *
5
- * Copyright IBM Corp. 2008, 2018
5
+ * Copyright IBM Corp. 2008, 2020
66 *
77 * Author(s): Carsten Otte <cotte@de.ibm.com>
88 * Christian Borntraeger <borntraeger@de.ibm.com>
....@@ -13,6 +13,7 @@
1313 #include <linux/errno.h>
1414 #include <linux/compat.h>
1515 #include <linux/mm_types.h>
16
+#include <linux/pgtable.h>
1617
1718 #include <asm/asm-offsets.h>
1819 #include <asm/facility.h>
....@@ -20,13 +21,12 @@
2021 #include <asm/debug.h>
2122 #include <asm/ebcdic.h>
2223 #include <asm/sysinfo.h>
23
-#include <asm/pgtable.h>
2424 #include <asm/page-states.h>
25
-#include <asm/pgalloc.h>
2625 #include <asm/gmap.h>
2726 #include <asm/io.h>
2827 #include <asm/ptrace.h>
2928 #include <asm/sclp.h>
29
+#include <asm/ap.h>
3030 #include "gaccess.h"
3131 #include "kvm-s390.h"
3232 #include "trace.h"
....@@ -102,7 +102,20 @@
102102 return kvm_s390_inject_prog_cond(vcpu, rc);
103103
104104 VCPU_EVENT(vcpu, 3, "SCK: setting guest TOD to 0x%llx", gtod.tod);
105
- kvm_s390_set_tod_clock(vcpu->kvm, &gtod);
105
+ /*
106
+ * To set the TOD clock the kvm lock must be taken, but the vcpu lock
107
+ * is already held in handle_set_clock. The usual lock order is the
108
+ * opposite. As SCK is deprecated and should not be used in several
109
+ * cases, for example when the multiple epoch facility or TOD clock
110
+ * steering facility is installed (see Principles of Operation), a
111
+ * slow path can be used. If the lock can not be taken via try_lock,
112
+ * the instruction will be retried via -EAGAIN at a later point in
113
+ * time.
114
+ */
115
+ if (!kvm_s390_try_set_tod_clock(vcpu->kvm, &gtod)) {
116
+ kvm_s390_retry_instr(vcpu);
117
+ return -EAGAIN;
118
+ }
106119
107120 kvm_s390_set_psw_cc(vcpu, 0);
108121 return 0;
....@@ -269,18 +282,18 @@
269282 return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
270283 retry:
271284 unlocked = false;
272
- down_read(&current->mm->mmap_sem);
285
+ mmap_read_lock(current->mm);
273286 rc = get_guest_storage_key(current->mm, vmaddr, &key);
274287
275288 if (rc) {
276
- rc = fixup_user_fault(current, current->mm, vmaddr,
289
+ rc = fixup_user_fault(current->mm, vmaddr,
277290 FAULT_FLAG_WRITE, &unlocked);
278291 if (!rc) {
279
- up_read(&current->mm->mmap_sem);
292
+ mmap_read_unlock(current->mm);
280293 goto retry;
281294 }
282295 }
283
- up_read(&current->mm->mmap_sem);
296
+ mmap_read_unlock(current->mm);
284297 if (rc == -EFAULT)
285298 return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
286299 if (rc < 0)
....@@ -316,17 +329,17 @@
316329 return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
317330 retry:
318331 unlocked = false;
319
- down_read(&current->mm->mmap_sem);
332
+ mmap_read_lock(current->mm);
320333 rc = reset_guest_reference_bit(current->mm, vmaddr);
321334 if (rc < 0) {
322
- rc = fixup_user_fault(current, current->mm, vmaddr,
335
+ rc = fixup_user_fault(current->mm, vmaddr,
323336 FAULT_FLAG_WRITE, &unlocked);
324337 if (!rc) {
325
- up_read(&current->mm->mmap_sem);
338
+ mmap_read_unlock(current->mm);
326339 goto retry;
327340 }
328341 }
329
- up_read(&current->mm->mmap_sem);
342
+ mmap_read_unlock(current->mm);
330343 if (rc == -EFAULT)
331344 return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
332345 if (rc < 0)
....@@ -384,17 +397,17 @@
384397 if (kvm_is_error_hva(vmaddr))
385398 return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
386399
387
- down_read(&current->mm->mmap_sem);
400
+ mmap_read_lock(current->mm);
388401 rc = cond_set_guest_storage_key(current->mm, vmaddr, key, &oldkey,
389402 m3 & SSKE_NQ, m3 & SSKE_MR,
390403 m3 & SSKE_MC);
391404
392405 if (rc < 0) {
393
- rc = fixup_user_fault(current, current->mm, vmaddr,
406
+ rc = fixup_user_fault(current->mm, vmaddr,
394407 FAULT_FLAG_WRITE, &unlocked);
395408 rc = !rc ? -EAGAIN : rc;
396409 }
397
- up_read(&current->mm->mmap_sem);
410
+ mmap_read_unlock(current->mm);
398411 if (rc == -EFAULT)
399412 return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
400413 if (rc == -EAGAIN)
....@@ -594,6 +607,91 @@
594607 }
595608 }
596609
610
+/*
611
+ * handle_pqap: Handling pqap interception
612
+ * @vcpu: the vcpu having issue the pqap instruction
613
+ *
614
+ * We now support PQAP/AQIC instructions and we need to correctly
615
+ * answer the guest even if no dedicated driver's hook is available.
616
+ *
617
+ * The intercepting code calls a dedicated callback for this instruction
618
+ * if a driver did register one in the CRYPTO satellite of the
619
+ * SIE block.
620
+ *
621
+ * If no callback is available, the queues are not available, return this
622
+ * response code to the caller and set CC to 3.
623
+ * Else return the response code returned by the callback.
624
+ */
625
+static int handle_pqap(struct kvm_vcpu *vcpu)
626
+{
627
+ struct ap_queue_status status = {};
628
+ unsigned long reg0;
629
+ int ret;
630
+ uint8_t fc;
631
+
632
+ /* Verify that the AP instruction are available */
633
+ if (!ap_instructions_available())
634
+ return -EOPNOTSUPP;
635
+ /* Verify that the guest is allowed to use AP instructions */
636
+ if (!(vcpu->arch.sie_block->eca & ECA_APIE))
637
+ return -EOPNOTSUPP;
638
+ /*
639
+ * The only possibly intercepted functions when AP instructions are
640
+ * available for the guest are AQIC and TAPQ with the t bit set
641
+ * since we do not set IC.3 (FIII) we currently will only intercept
642
+ * the AQIC function code.
643
+ * Note: running nested under z/VM can result in intercepts for other
644
+ * function codes, e.g. PQAP(QCI). We do not support this and bail out.
645
+ */
646
+ reg0 = vcpu->run->s.regs.gprs[0];
647
+ fc = (reg0 >> 24) & 0xff;
648
+ if (fc != 0x03)
649
+ return -EOPNOTSUPP;
650
+
651
+ /* PQAP instruction is allowed for guest kernel only */
652
+ if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
653
+ return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
654
+
655
+ /* Common PQAP instruction specification exceptions */
656
+ /* bits 41-47 must all be zeros */
657
+ if (reg0 & 0x007f0000UL)
658
+ return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
659
+ /* APFT not install and T bit set */
660
+ if (!test_kvm_facility(vcpu->kvm, 15) && (reg0 & 0x00800000UL))
661
+ return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
662
+ /* APXA not installed and APID greater 64 or APQI greater 16 */
663
+ if (!(vcpu->kvm->arch.crypto.crycbd & 0x02) && (reg0 & 0x0000c0f0UL))
664
+ return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
665
+
666
+ /* AQIC function code specific exception */
667
+ /* facility 65 not present for AQIC function code */
668
+ if (!test_kvm_facility(vcpu->kvm, 65))
669
+ return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
670
+
671
+ /*
672
+ * Verify that the hook callback is registered, lock the owner
673
+ * and call the hook.
674
+ */
675
+ if (vcpu->kvm->arch.crypto.pqap_hook) {
676
+ if (!try_module_get(vcpu->kvm->arch.crypto.pqap_hook->owner))
677
+ return -EOPNOTSUPP;
678
+ ret = vcpu->kvm->arch.crypto.pqap_hook->hook(vcpu);
679
+ module_put(vcpu->kvm->arch.crypto.pqap_hook->owner);
680
+ if (!ret && vcpu->run->s.regs.gprs[1] & 0x00ff0000)
681
+ kvm_s390_set_psw_cc(vcpu, 3);
682
+ return ret;
683
+ }
684
+ /*
685
+ * A vfio_driver must register a hook.
686
+ * No hook means no driver to enable the SIE CRYCB and no queues.
687
+ * We send this response to the guest.
688
+ */
689
+ status.response_code = 0x01;
690
+ memcpy(&vcpu->run->s.regs.gprs[1], &status, sizeof(status));
691
+ kvm_s390_set_psw_cc(vcpu, 3);
692
+ return 0;
693
+}
694
+
597695 static int handle_stfl(struct kvm_vcpu *vcpu)
598696 {
599697 int rc;
....@@ -790,7 +888,7 @@
790888
791889 operand2 = kvm_s390_get_base_disp_s(vcpu, &ar);
792890
793
- if (operand2 & 0xfff)
891
+ if (!kvm_s390_pv_cpu_is_protected(vcpu) && (operand2 & 0xfff))
794892 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
795893
796894 switch (fc) {
....@@ -811,8 +909,13 @@
811909 handle_stsi_3_2_2(vcpu, (void *) mem);
812910 break;
813911 }
814
-
815
- rc = write_guest(vcpu, operand2, ar, (void *)mem, PAGE_SIZE);
912
+ if (kvm_s390_pv_cpu_is_protected(vcpu)) {
913
+ memcpy((void *)sida_origin(vcpu->arch.sie_block), (void *)mem,
914
+ PAGE_SIZE);
915
+ rc = 0;
916
+ } else {
917
+ rc = write_guest(vcpu, operand2, ar, (void *)mem, PAGE_SIZE);
918
+ }
816919 if (rc) {
817920 rc = kvm_s390_inject_prog_cond(vcpu, rc);
818921 goto out;
....@@ -880,6 +983,8 @@
880983 return handle_sthyi(vcpu);
881984 case 0x7d:
882985 return handle_stsi(vcpu);
986
+ case 0xaf:
987
+ return handle_pqap(vcpu);
883988 case 0xb1:
884989 return handle_stfl(vcpu);
885990 case 0xb2:
....@@ -1000,15 +1105,15 @@
10001105
10011106 if (rc)
10021107 return rc;
1003
- down_read(&current->mm->mmap_sem);
1108
+ mmap_read_lock(current->mm);
10041109 rc = cond_set_guest_storage_key(current->mm, vmaddr,
10051110 key, NULL, nq, mr, mc);
10061111 if (rc < 0) {
1007
- rc = fixup_user_fault(current, current->mm, vmaddr,
1112
+ rc = fixup_user_fault(current->mm, vmaddr,
10081113 FAULT_FLAG_WRITE, &unlocked);
10091114 rc = !rc ? -EAGAIN : rc;
10101115 }
1011
- up_read(&current->mm->mmap_sem);
1116
+ mmap_read_unlock(current->mm);
10121117 if (rc == -EFAULT)
10131118 return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
10141119 if (rc == -EAGAIN)
....@@ -1031,7 +1136,7 @@
10311136 }
10321137
10331138 /*
1034
- * Must be called with relevant read locks held (kvm->mm->mmap_sem, kvm->srcu)
1139
+ * Must be called with relevant read locks held (kvm->mm->mmap_lock, kvm->srcu)
10351140 */
10361141 static inline int __do_essa(struct kvm_vcpu *vcpu, const int orc)
10371142 {
....@@ -1129,9 +1234,9 @@
11291234 * already correct, we do nothing and avoid the lock.
11301235 */
11311236 if (vcpu->kvm->mm->context.uses_cmm == 0) {
1132
- down_write(&vcpu->kvm->mm->mmap_sem);
1237
+ mmap_write_lock(vcpu->kvm->mm);
11331238 vcpu->kvm->mm->context.uses_cmm = 1;
1134
- up_write(&vcpu->kvm->mm->mmap_sem);
1239
+ mmap_write_unlock(vcpu->kvm->mm);
11351240 }
11361241 /*
11371242 * If we are here, we are supposed to have CMMA enabled in
....@@ -1148,11 +1253,11 @@
11481253 } else {
11491254 int srcu_idx;
11501255
1151
- down_read(&vcpu->kvm->mm->mmap_sem);
1256
+ mmap_read_lock(vcpu->kvm->mm);
11521257 srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
11531258 i = __do_essa(vcpu, orc);
11541259 srcu_read_unlock(&vcpu->kvm->srcu, srcu_idx);
1155
- up_read(&vcpu->kvm->mm->mmap_sem);
1260
+ mmap_read_unlock(vcpu->kvm->mm);
11561261 if (i < 0)
11571262 return i;
11581263 /* Account for the possible extra cbrl entry */
....@@ -1160,10 +1265,10 @@
11601265 }
11611266 vcpu->arch.sie_block->cbrlo &= PAGE_MASK; /* reset nceo */
11621267 cbrlo = phys_to_virt(vcpu->arch.sie_block->cbrlo);
1163
- down_read(&gmap->mm->mmap_sem);
1268
+ mmap_read_lock(gmap->mm);
11641269 for (i = 0; i < entries; ++i)
11651270 __gmap_zap(gmap, cbrlo[i]);
1166
- up_read(&gmap->mm->mmap_sem);
1271
+ mmap_read_unlock(gmap->mm);
11671272 return 0;
11681273 }
11691274