^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * handling privileged instructions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright IBM Corp. 2008, 2020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Author(s): Carsten Otte <cotte@de.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Christian Borntraeger <borntraeger@de.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/kvm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/gfp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/compat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/mm_types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/pgtable.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <asm/asm-offsets.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <asm/facility.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/current.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/debug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <asm/ebcdic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <asm/sysinfo.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <asm/page-states.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <asm/gmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <asm/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <asm/sclp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <asm/ap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include "gaccess.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include "kvm-s390.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include "trace.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static int handle_ri(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) vcpu->stat.instruction_ri++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) if (test_kvm_facility(vcpu->kvm, 64)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) VCPU_EVENT(vcpu, 3, "%s", "ENABLE: RI (lazy)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) vcpu->arch.sie_block->ecb3 |= ECB3_RI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) kvm_s390_retry_instr(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) return kvm_s390_inject_program_int(vcpu, PGM_OPERATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) int kvm_s390_handle_aa(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) if ((vcpu->arch.sie_block->ipa & 0xf) <= 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return handle_ri(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) static int handle_gs(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) vcpu->stat.instruction_gs++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (test_kvm_facility(vcpu->kvm, 133)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) VCPU_EVENT(vcpu, 3, "%s", "ENABLE: GS (lazy)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) preempt_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) __ctl_set_bit(2, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) current->thread.gs_cb = (struct gs_cb *)&vcpu->run->s.regs.gscb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) restore_gs_cb(current->thread.gs_cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) preempt_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) vcpu->arch.sie_block->ecb |= ECB_GS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) vcpu->arch.sie_block->ecd |= ECD_HOSTREGMGMT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) vcpu->arch.gs_enabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) kvm_s390_retry_instr(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return kvm_s390_inject_program_int(vcpu, PGM_OPERATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) int kvm_s390_handle_e3(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) int code = vcpu->arch.sie_block->ipb & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (code == 0x49 || code == 0x4d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return handle_gs(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /* Handle SCK (SET CLOCK) interception */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static int handle_set_clock(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct kvm_s390_vm_tod_clock gtod = { 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) u8 ar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) u64 op2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) vcpu->stat.instruction_sck++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) op2 = kvm_s390_get_base_disp_s(vcpu, &ar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (op2 & 7) /* Operand must be on a doubleword boundary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) rc = read_guest(vcpu, op2, ar, >od.tod, sizeof(gtod.tod));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return kvm_s390_inject_prog_cond(vcpu, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) VCPU_EVENT(vcpu, 3, "SCK: setting guest TOD to 0x%llx", gtod.tod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) kvm_s390_set_tod_clock(vcpu->kvm, >od);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) kvm_s390_set_psw_cc(vcpu, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static int handle_set_prefix(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) u64 operand2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) u32 address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) u8 ar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) vcpu->stat.instruction_spx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) operand2 = kvm_s390_get_base_disp_s(vcpu, &ar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) /* must be word boundary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (operand2 & 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /* get the value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) rc = read_guest(vcpu, operand2, ar, &address, sizeof(address));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return kvm_s390_inject_prog_cond(vcpu, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) address &= 0x7fffe000u;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * Make sure the new value is valid memory. We only need to check the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * first page, since address is 8k aligned and memory pieces are always
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * at least 1MB aligned and have at least a size of 1MB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (kvm_is_error_gpa(vcpu->kvm, address))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) kvm_s390_set_prefix(vcpu, address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) trace_kvm_s390_handle_prefix(vcpu, 1, address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static int handle_store_prefix(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) u64 operand2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) u32 address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) u8 ar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) vcpu->stat.instruction_stpx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) operand2 = kvm_s390_get_base_disp_s(vcpu, &ar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) /* must be word boundary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (operand2 & 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) address = kvm_s390_get_prefix(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) /* get the value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) rc = write_guest(vcpu, operand2, ar, &address, sizeof(address));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return kvm_s390_inject_prog_cond(vcpu, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) VCPU_EVENT(vcpu, 3, "STPX: storing prefix 0x%x into 0x%llx", address, operand2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) trace_kvm_s390_handle_prefix(vcpu, 0, address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static int handle_store_cpu_address(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) u16 vcpu_id = vcpu->vcpu_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) u64 ga;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) u8 ar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) vcpu->stat.instruction_stap++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) ga = kvm_s390_get_base_disp_s(vcpu, &ar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (ga & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) rc = write_guest(vcpu, ga, ar, &vcpu_id, sizeof(vcpu_id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return kvm_s390_inject_prog_cond(vcpu, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) VCPU_EVENT(vcpu, 3, "STAP: storing cpu address (%u) to 0x%llx", vcpu_id, ga);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) trace_kvm_s390_handle_stap(vcpu, ga);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) int kvm_s390_skey_check_enable(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) trace_kvm_s390_skey_related_inst(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /* Already enabled? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (vcpu->arch.skey_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) rc = s390_enable_skey();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) VCPU_EVENT(vcpu, 3, "enabling storage keys for guest: %d", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (kvm_s390_test_cpuflags(vcpu, CPUSTAT_KSS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) kvm_s390_clear_cpuflags(vcpu, CPUSTAT_KSS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (!vcpu->kvm->arch.use_skf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) vcpu->arch.sie_block->ictl |= ICTL_ISKE | ICTL_SSKE | ICTL_RRBE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) vcpu->arch.sie_block->ictl &= ~(ICTL_ISKE | ICTL_SSKE | ICTL_RRBE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) vcpu->arch.skey_enabled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) static int try_handle_skey(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) rc = kvm_s390_skey_check_enable(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (vcpu->kvm->arch.use_skf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /* with storage-key facility, SIE interprets it for us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) kvm_s390_retry_instr(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) VCPU_EVENT(vcpu, 4, "%s", "retrying storage key operation");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) static int handle_iske(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) unsigned long gaddr, vmaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) unsigned char key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) int reg1, reg2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) bool unlocked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) vcpu->stat.instruction_iske++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) rc = try_handle_skey(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return rc != -EAGAIN ? rc : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) kvm_s390_get_regs_rre(vcpu, ®1, ®2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) gaddr = vcpu->run->s.regs.gprs[reg2] & PAGE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) gaddr = kvm_s390_logical_to_effective(vcpu, gaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) gaddr = kvm_s390_real_to_abs(vcpu, gaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) vmaddr = gfn_to_hva(vcpu->kvm, gpa_to_gfn(gaddr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (kvm_is_error_hva(vmaddr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) retry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) unlocked = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) mmap_read_lock(current->mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) rc = get_guest_storage_key(current->mm, vmaddr, &key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) rc = fixup_user_fault(current->mm, vmaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) FAULT_FLAG_WRITE, &unlocked);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (!rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) mmap_read_unlock(current->mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) goto retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) mmap_read_unlock(current->mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (rc == -EFAULT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) vcpu->run->s.regs.gprs[reg1] &= ~0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) vcpu->run->s.regs.gprs[reg1] |= key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) static int handle_rrbe(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) unsigned long vmaddr, gaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) int reg1, reg2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) bool unlocked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) vcpu->stat.instruction_rrbe++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) rc = try_handle_skey(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return rc != -EAGAIN ? rc : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) kvm_s390_get_regs_rre(vcpu, ®1, ®2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) gaddr = vcpu->run->s.regs.gprs[reg2] & PAGE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) gaddr = kvm_s390_logical_to_effective(vcpu, gaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) gaddr = kvm_s390_real_to_abs(vcpu, gaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) vmaddr = gfn_to_hva(vcpu->kvm, gpa_to_gfn(gaddr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (kvm_is_error_hva(vmaddr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) retry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) unlocked = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) mmap_read_lock(current->mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) rc = reset_guest_reference_bit(current->mm, vmaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) rc = fixup_user_fault(current->mm, vmaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) FAULT_FLAG_WRITE, &unlocked);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (!rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) mmap_read_unlock(current->mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) goto retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) mmap_read_unlock(current->mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (rc == -EFAULT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) kvm_s390_set_psw_cc(vcpu, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) #define SSKE_NQ 0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) #define SSKE_MR 0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) #define SSKE_MC 0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) #define SSKE_MB 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) static int handle_sske(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) unsigned char m3 = vcpu->arch.sie_block->ipb >> 28;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) unsigned long start, end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) unsigned char key, oldkey;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) int reg1, reg2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) bool unlocked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) vcpu->stat.instruction_sske++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) rc = try_handle_skey(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) return rc != -EAGAIN ? rc : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (!test_kvm_facility(vcpu->kvm, 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) m3 &= ~SSKE_MB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (!test_kvm_facility(vcpu->kvm, 10))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) m3 &= ~(SSKE_MC | SSKE_MR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (!test_kvm_facility(vcpu->kvm, 14))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) m3 &= ~SSKE_NQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) kvm_s390_get_regs_rre(vcpu, ®1, ®2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) key = vcpu->run->s.regs.gprs[reg1] & 0xfe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) start = vcpu->run->s.regs.gprs[reg2] & PAGE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) start = kvm_s390_logical_to_effective(vcpu, start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (m3 & SSKE_MB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) /* start already designates an absolute address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) end = (start + _SEGMENT_SIZE) & ~(_SEGMENT_SIZE - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) start = kvm_s390_real_to_abs(vcpu, start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) end = start + PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) while (start != end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) unsigned long vmaddr = gfn_to_hva(vcpu->kvm, gpa_to_gfn(start));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) unlocked = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if (kvm_is_error_hva(vmaddr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) mmap_read_lock(current->mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) rc = cond_set_guest_storage_key(current->mm, vmaddr, key, &oldkey,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) m3 & SSKE_NQ, m3 & SSKE_MR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) m3 & SSKE_MC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) rc = fixup_user_fault(current->mm, vmaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) FAULT_FLAG_WRITE, &unlocked);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) rc = !rc ? -EAGAIN : rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) mmap_read_unlock(current->mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (rc == -EFAULT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) if (rc == -EAGAIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) start += PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) if (m3 & (SSKE_MC | SSKE_MR)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (m3 & SSKE_MB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) /* skey in reg1 is unpredictable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) kvm_s390_set_psw_cc(vcpu, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) kvm_s390_set_psw_cc(vcpu, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) vcpu->run->s.regs.gprs[reg1] &= ~0xff00UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) vcpu->run->s.regs.gprs[reg1] |= (u64) oldkey << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (m3 & SSKE_MB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (psw_bits(vcpu->arch.sie_block->gpsw).eaba == PSW_BITS_AMODE_64BIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) vcpu->run->s.regs.gprs[reg2] &= ~PAGE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) vcpu->run->s.regs.gprs[reg2] &= ~0xfffff000UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) end = kvm_s390_logical_to_effective(vcpu, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) vcpu->run->s.regs.gprs[reg2] |= end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) static int handle_ipte_interlock(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) vcpu->stat.instruction_ipte_interlock++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (psw_bits(vcpu->arch.sie_block->gpsw).pstate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) wait_event(vcpu->kvm->arch.ipte_wq, !ipte_lock_held(vcpu));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) kvm_s390_retry_instr(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) VCPU_EVENT(vcpu, 4, "%s", "retrying ipte interlock operation");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) static int handle_test_block(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) gpa_t addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) int reg2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) vcpu->stat.instruction_tb++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) kvm_s390_get_regs_rre(vcpu, NULL, ®2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) addr = vcpu->run->s.regs.gprs[reg2] & PAGE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) addr = kvm_s390_logical_to_effective(vcpu, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (kvm_s390_check_low_addr_prot_real(vcpu, addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return kvm_s390_inject_prog_irq(vcpu, &vcpu->arch.pgm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) addr = kvm_s390_real_to_abs(vcpu, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (kvm_is_error_gpa(vcpu->kvm, addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) * We don't expect errors on modern systems, and do not care
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) * about storage keys (yet), so let's just clear the page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) if (kvm_clear_guest(vcpu->kvm, addr, PAGE_SIZE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) kvm_s390_set_psw_cc(vcpu, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) vcpu->run->s.regs.gprs[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) static int handle_tpi(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) struct kvm_s390_interrupt_info *inti;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) unsigned long len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) u32 tpi_data[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) u64 addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) u8 ar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) vcpu->stat.instruction_tpi++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) addr = kvm_s390_get_base_disp_s(vcpu, &ar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (addr & 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) inti = kvm_s390_get_io_int(vcpu->kvm, vcpu->arch.sie_block->gcr[6], 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) if (!inti) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) kvm_s390_set_psw_cc(vcpu, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) tpi_data[0] = inti->io.subchannel_id << 16 | inti->io.subchannel_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) tpi_data[1] = inti->io.io_int_parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) tpi_data[2] = inti->io.io_int_word;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) if (addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) * Store the two-word I/O interruption code into the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) * provided area.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) len = sizeof(tpi_data) - 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) rc = write_guest(vcpu, addr, ar, &tpi_data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) rc = kvm_s390_inject_prog_cond(vcpu, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) goto reinject_interrupt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) * Store the three-word I/O interruption code into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) * the appropriate lowcore area.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) len = sizeof(tpi_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) if (write_guest_lc(vcpu, __LC_SUBCHANNEL_ID, &tpi_data, len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) /* failed writes to the low core are not recoverable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) rc = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) goto reinject_interrupt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) /* irq was successfully handed to the guest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) kfree(inti);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) kvm_s390_set_psw_cc(vcpu, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) reinject_interrupt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) * If we encounter a problem storing the interruption code, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) * instruction is suppressed from the guest's view: reinject the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) * interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) if (kvm_s390_reinject_io_int(vcpu->kvm, inti)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) kfree(inti);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) rc = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) /* don't set the cc, a pgm irq was injected or we drop to user space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) return rc ? -EFAULT : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) static int handle_tsch(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) struct kvm_s390_interrupt_info *inti = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) const u64 isc_mask = 0xffUL << 24; /* all iscs set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) vcpu->stat.instruction_tsch++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) /* a valid schid has at least one bit set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (vcpu->run->s.regs.gprs[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) inti = kvm_s390_get_io_int(vcpu->kvm, isc_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) vcpu->run->s.regs.gprs[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) * Prepare exit to userspace.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) * We indicate whether we dequeued a pending I/O interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) * so that userspace can re-inject it if the instruction gets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) * a program check. While this may re-order the pending I/O
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) * interrupts, this is no problem since the priority is kept
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) * intact.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) vcpu->run->exit_reason = KVM_EXIT_S390_TSCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) vcpu->run->s390_tsch.dequeued = !!inti;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) if (inti) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) vcpu->run->s390_tsch.subchannel_id = inti->io.subchannel_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) vcpu->run->s390_tsch.subchannel_nr = inti->io.subchannel_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) vcpu->run->s390_tsch.io_int_parm = inti->io.io_int_parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) vcpu->run->s390_tsch.io_int_word = inti->io.io_int_word;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) vcpu->run->s390_tsch.ipb = vcpu->arch.sie_block->ipb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) kfree(inti);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) return -EREMOTE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) static int handle_io_inst(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) VCPU_EVENT(vcpu, 4, "%s", "I/O instruction");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) if (vcpu->kvm->arch.css_support) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) * Most I/O instructions will be handled by userspace.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) * Exceptions are tpi and the interrupt portion of tsch.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) if (vcpu->arch.sie_block->ipa == 0xb236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) return handle_tpi(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) if (vcpu->arch.sie_block->ipa == 0xb235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) return handle_tsch(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) /* Handle in userspace. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) vcpu->stat.instruction_io_other++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) * Set condition code 3 to stop the guest from issuing channel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) * I/O instructions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) kvm_s390_set_psw_cc(vcpu, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) * handle_pqap: Handling pqap interception
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) * @vcpu: the vcpu having issue the pqap instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) * We now support PQAP/AQIC instructions and we need to correctly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) * answer the guest even if no dedicated driver's hook is available.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) * The intercepting code calls a dedicated callback for this instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) * if a driver did register one in the CRYPTO satellite of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) * SIE block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) * If no callback is available, the queues are not available, return this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) * response code to the caller and set CC to 3.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) * Else return the response code returned by the callback.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) static int handle_pqap(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) struct ap_queue_status status = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) unsigned long reg0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) uint8_t fc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) /* Verify that the AP instruction are available */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) if (!ap_instructions_available())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) /* Verify that the guest is allowed to use AP instructions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) if (!(vcpu->arch.sie_block->eca & ECA_APIE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) * The only possibly intercepted functions when AP instructions are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) * available for the guest are AQIC and TAPQ with the t bit set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) * since we do not set IC.3 (FIII) we currently will only intercept
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) * the AQIC function code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) * Note: running nested under z/VM can result in intercepts for other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) * function codes, e.g. PQAP(QCI). We do not support this and bail out.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) reg0 = vcpu->run->s.regs.gprs[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) fc = (reg0 >> 24) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if (fc != 0x03)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) /* PQAP instruction is allowed for guest kernel only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) /* Common PQAP instruction specification exceptions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) /* bits 41-47 must all be zeros */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) if (reg0 & 0x007f0000UL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) /* APFT not install and T bit set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if (!test_kvm_facility(vcpu->kvm, 15) && (reg0 & 0x00800000UL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) /* APXA not installed and APID greater 64 or APQI greater 16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if (!(vcpu->kvm->arch.crypto.crycbd & 0x02) && (reg0 & 0x0000c0f0UL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) /* AQIC function code specific exception */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) /* facility 65 not present for AQIC function code */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (!test_kvm_facility(vcpu->kvm, 65))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) * Verify that the hook callback is registered, lock the owner
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) * and call the hook.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) if (vcpu->kvm->arch.crypto.pqap_hook) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) if (!try_module_get(vcpu->kvm->arch.crypto.pqap_hook->owner))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) ret = vcpu->kvm->arch.crypto.pqap_hook->hook(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) module_put(vcpu->kvm->arch.crypto.pqap_hook->owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) if (!ret && vcpu->run->s.regs.gprs[1] & 0x00ff0000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) kvm_s390_set_psw_cc(vcpu, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) * A vfio_driver must register a hook.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) * No hook means no driver to enable the SIE CRYCB and no queues.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) * We send this response to the guest.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) status.response_code = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) memcpy(&vcpu->run->s.regs.gprs[1], &status, sizeof(status));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) kvm_s390_set_psw_cc(vcpu, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) static int handle_stfl(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) unsigned int fac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) vcpu->stat.instruction_stfl++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) * We need to shift the lower 32 facility bits (bit 0-31) from a u64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) * into a u32 memory representation. They will remain bits 0-31.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) fac = *vcpu->kvm->arch.model.fac_list >> 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) rc = write_guest_lc(vcpu, offsetof(struct lowcore, stfl_fac_list),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) &fac, sizeof(fac));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) VCPU_EVENT(vcpu, 3, "STFL: store facility list 0x%x", fac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) trace_kvm_s390_handle_stfl(vcpu, fac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) #define PSW_MASK_ADDR_MODE (PSW_MASK_EA | PSW_MASK_BA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) #define PSW_MASK_UNASSIGNED 0xb80800fe7fffffffUL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) #define PSW_ADDR_24 0x0000000000ffffffUL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) #define PSW_ADDR_31 0x000000007fffffffUL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) int is_valid_psw(psw_t *psw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) if (psw->mask & PSW_MASK_UNASSIGNED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) if ((psw->mask & PSW_MASK_ADDR_MODE) == PSW_MASK_BA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) if (psw->addr & ~PSW_ADDR_31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) if (!(psw->mask & PSW_MASK_ADDR_MODE) && (psw->addr & ~PSW_ADDR_24))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) if ((psw->mask & PSW_MASK_ADDR_MODE) == PSW_MASK_EA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) if (psw->addr & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) int kvm_s390_handle_lpsw(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) psw_t *gpsw = &vcpu->arch.sie_block->gpsw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) psw_compat_t new_psw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) u64 addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) u8 ar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) vcpu->stat.instruction_lpsw++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) if (gpsw->mask & PSW_MASK_PSTATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) addr = kvm_s390_get_base_disp_s(vcpu, &ar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) if (addr & 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) rc = read_guest(vcpu, addr, ar, &new_psw, sizeof(new_psw));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) return kvm_s390_inject_prog_cond(vcpu, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) if (!(new_psw.mask & PSW32_MASK_BASE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) gpsw->mask = (new_psw.mask & ~PSW32_MASK_BASE) << 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) gpsw->mask |= new_psw.addr & PSW32_ADDR_AMODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) gpsw->addr = new_psw.addr & ~PSW32_ADDR_AMODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) if (!is_valid_psw(gpsw))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) static int handle_lpswe(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) psw_t new_psw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) u64 addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) u8 ar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) vcpu->stat.instruction_lpswe++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) addr = kvm_s390_get_base_disp_s(vcpu, &ar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) if (addr & 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) rc = read_guest(vcpu, addr, ar, &new_psw, sizeof(new_psw));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) return kvm_s390_inject_prog_cond(vcpu, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) vcpu->arch.sie_block->gpsw = new_psw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) if (!is_valid_psw(&vcpu->arch.sie_block->gpsw))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) static int handle_stidp(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) u64 stidp_data = vcpu->kvm->arch.model.cpuid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) u64 operand2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) u8 ar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) vcpu->stat.instruction_stidp++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) operand2 = kvm_s390_get_base_disp_s(vcpu, &ar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) if (operand2 & 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) rc = write_guest(vcpu, operand2, ar, &stidp_data, sizeof(stidp_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) return kvm_s390_inject_prog_cond(vcpu, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) VCPU_EVENT(vcpu, 3, "STIDP: store cpu id 0x%llx", stidp_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) static void handle_stsi_3_2_2(struct kvm_vcpu *vcpu, struct sysinfo_3_2_2 *mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) int cpus = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) cpus = atomic_read(&vcpu->kvm->online_vcpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) /* deal with other level 3 hypervisors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) if (stsi(mem, 3, 2, 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) mem->count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) if (mem->count < 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) mem->count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) for (n = mem->count - 1; n > 0 ; n--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) memcpy(&mem->vm[n], &mem->vm[n - 1], sizeof(mem->vm[0]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) memset(&mem->vm[0], 0, sizeof(mem->vm[0]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) mem->vm[0].cpus_total = cpus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) mem->vm[0].cpus_configured = cpus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) mem->vm[0].cpus_standby = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) mem->vm[0].cpus_reserved = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) mem->vm[0].caf = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) memcpy(mem->vm[0].name, "KVMguest", 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) ASCEBC(mem->vm[0].name, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) memcpy(mem->vm[0].cpi, "KVM/Linux ", 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) ASCEBC(mem->vm[0].cpi, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) static void insert_stsi_usr_data(struct kvm_vcpu *vcpu, u64 addr, u8 ar,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) u8 fc, u8 sel1, u16 sel2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) vcpu->run->exit_reason = KVM_EXIT_S390_STSI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) vcpu->run->s390_stsi.addr = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) vcpu->run->s390_stsi.ar = ar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) vcpu->run->s390_stsi.fc = fc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) vcpu->run->s390_stsi.sel1 = sel1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) vcpu->run->s390_stsi.sel2 = sel2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) static int handle_stsi(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) int fc = (vcpu->run->s.regs.gprs[0] & 0xf0000000) >> 28;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) int sel1 = vcpu->run->s.regs.gprs[0] & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) int sel2 = vcpu->run->s.regs.gprs[1] & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) unsigned long mem = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) u64 operand2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) u8 ar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) vcpu->stat.instruction_stsi++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) VCPU_EVENT(vcpu, 3, "STSI: fc: %u sel1: %u sel2: %u", fc, sel1, sel2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) if (fc > 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) kvm_s390_set_psw_cc(vcpu, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) if (vcpu->run->s.regs.gprs[0] & 0x0fffff00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) || vcpu->run->s.regs.gprs[1] & 0xffff0000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) if (fc == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) vcpu->run->s.regs.gprs[0] = 3 << 28;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) kvm_s390_set_psw_cc(vcpu, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) operand2 = kvm_s390_get_base_disp_s(vcpu, &ar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) if (!kvm_s390_pv_cpu_is_protected(vcpu) && (operand2 & 0xfff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) switch (fc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) case 1: /* same handling for 1 and 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) mem = get_zeroed_page(GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) if (!mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) goto out_no_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) if (stsi((void *) mem, fc, sel1, sel2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) goto out_no_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) if (sel1 != 2 || sel2 != 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) goto out_no_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) mem = get_zeroed_page(GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) if (!mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) goto out_no_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) handle_stsi_3_2_2(vcpu, (void *) mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) if (kvm_s390_pv_cpu_is_protected(vcpu)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) memcpy((void *)sida_origin(vcpu->arch.sie_block), (void *)mem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) rc = write_guest(vcpu, operand2, ar, (void *)mem, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) rc = kvm_s390_inject_prog_cond(vcpu, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) if (vcpu->kvm->arch.user_stsi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) insert_stsi_usr_data(vcpu, operand2, ar, fc, sel1, sel2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) rc = -EREMOTE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) trace_kvm_s390_handle_stsi(vcpu, fc, sel1, sel2, operand2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) free_page(mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) kvm_s390_set_psw_cc(vcpu, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) vcpu->run->s.regs.gprs[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) out_no_data:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) kvm_s390_set_psw_cc(vcpu, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) free_page(mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) int kvm_s390_handle_b2(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) switch (vcpu->arch.sie_block->ipa & 0x00ff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) case 0x02:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) return handle_stidp(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) case 0x04:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) return handle_set_clock(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) case 0x10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) return handle_set_prefix(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) case 0x11:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) return handle_store_prefix(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) case 0x12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) return handle_store_cpu_address(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) case 0x14:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) return kvm_s390_handle_vsie(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) case 0x21:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) case 0x50:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) return handle_ipte_interlock(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) case 0x29:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) return handle_iske(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) case 0x2a:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) return handle_rrbe(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) case 0x2b:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) return handle_sske(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) case 0x2c:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) return handle_test_block(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) case 0x30:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) case 0x31:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) case 0x32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) case 0x33:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) case 0x34:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) case 0x35:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) case 0x36:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) case 0x37:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) case 0x38:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) case 0x39:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) case 0x3a:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) case 0x3b:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) case 0x3c:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) case 0x5f:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) case 0x74:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) case 0x76:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) return handle_io_inst(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) case 0x56:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) return handle_sthyi(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) case 0x7d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) return handle_stsi(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) case 0xaf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) return handle_pqap(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) case 0xb1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) return handle_stfl(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) case 0xb2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) return handle_lpswe(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) static int handle_epsw(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) int reg1, reg2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) vcpu->stat.instruction_epsw++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) kvm_s390_get_regs_rre(vcpu, ®1, ®2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) /* This basically extracts the mask half of the psw. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) vcpu->run->s.regs.gprs[reg1] &= 0xffffffff00000000UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) vcpu->run->s.regs.gprs[reg1] |= vcpu->arch.sie_block->gpsw.mask >> 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) if (reg2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) vcpu->run->s.regs.gprs[reg2] &= 0xffffffff00000000UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) vcpu->run->s.regs.gprs[reg2] |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) vcpu->arch.sie_block->gpsw.mask & 0x00000000ffffffffUL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) #define PFMF_RESERVED 0xfffc0101UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) #define PFMF_SK 0x00020000UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) #define PFMF_CF 0x00010000UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) #define PFMF_UI 0x00008000UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) #define PFMF_FSC 0x00007000UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) #define PFMF_NQ 0x00000800UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) #define PFMF_MR 0x00000400UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) #define PFMF_MC 0x00000200UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) #define PFMF_KEY 0x000000feUL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) static int handle_pfmf(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) bool mr = false, mc = false, nq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) int reg1, reg2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) unsigned long start, end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) unsigned char key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) vcpu->stat.instruction_pfmf++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) kvm_s390_get_regs_rre(vcpu, ®1, ®2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) if (!test_kvm_facility(vcpu->kvm, 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) return kvm_s390_inject_program_int(vcpu, PGM_OPERATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) if (vcpu->run->s.regs.gprs[reg1] & PFMF_RESERVED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) /* Only provide non-quiescing support if enabled for the guest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (vcpu->run->s.regs.gprs[reg1] & PFMF_NQ &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) !test_kvm_facility(vcpu->kvm, 14))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) /* Only provide conditional-SSKE support if enabled for the guest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) if (vcpu->run->s.regs.gprs[reg1] & PFMF_SK &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) test_kvm_facility(vcpu->kvm, 10)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) mr = vcpu->run->s.regs.gprs[reg1] & PFMF_MR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) mc = vcpu->run->s.regs.gprs[reg1] & PFMF_MC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) nq = vcpu->run->s.regs.gprs[reg1] & PFMF_NQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) key = vcpu->run->s.regs.gprs[reg1] & PFMF_KEY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) start = vcpu->run->s.regs.gprs[reg2] & PAGE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) start = kvm_s390_logical_to_effective(vcpu, start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) if (vcpu->run->s.regs.gprs[reg1] & PFMF_CF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) if (kvm_s390_check_low_addr_prot_real(vcpu, start))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) return kvm_s390_inject_prog_irq(vcpu, &vcpu->arch.pgm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) switch (vcpu->run->s.regs.gprs[reg1] & PFMF_FSC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) case 0x00000000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) /* only 4k frames specify a real address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) start = kvm_s390_real_to_abs(vcpu, start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) end = (start + PAGE_SIZE) & ~(PAGE_SIZE - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) case 0x00001000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) end = (start + _SEGMENT_SIZE) & ~(_SEGMENT_SIZE - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) case 0x00002000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) /* only support 2G frame size if EDAT2 is available and we are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) not in 24-bit addressing mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) if (!test_kvm_facility(vcpu->kvm, 78) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) psw_bits(vcpu->arch.sie_block->gpsw).eaba == PSW_BITS_AMODE_24BIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) end = (start + _REGION3_SIZE) & ~(_REGION3_SIZE - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) while (start != end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) unsigned long vmaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) bool unlocked = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) /* Translate guest address to host address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) vmaddr = gfn_to_hva(vcpu->kvm, gpa_to_gfn(start));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) if (kvm_is_error_hva(vmaddr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) if (vcpu->run->s.regs.gprs[reg1] & PFMF_CF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) if (kvm_clear_guest(vcpu->kvm, start, PAGE_SIZE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) if (vcpu->run->s.regs.gprs[reg1] & PFMF_SK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) int rc = kvm_s390_skey_check_enable(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) mmap_read_lock(current->mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) rc = cond_set_guest_storage_key(current->mm, vmaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) key, NULL, nq, mr, mc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) rc = fixup_user_fault(current->mm, vmaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) FAULT_FLAG_WRITE, &unlocked);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) rc = !rc ? -EAGAIN : rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) mmap_read_unlock(current->mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) if (rc == -EFAULT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) if (rc == -EAGAIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) start += PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) if (vcpu->run->s.regs.gprs[reg1] & PFMF_FSC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) if (psw_bits(vcpu->arch.sie_block->gpsw).eaba == PSW_BITS_AMODE_64BIT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) vcpu->run->s.regs.gprs[reg2] = end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) vcpu->run->s.regs.gprs[reg2] &= ~0xffffffffUL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) end = kvm_s390_logical_to_effective(vcpu, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) vcpu->run->s.regs.gprs[reg2] |= end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) * Must be called with relevant read locks held (kvm->mm->mmap_lock, kvm->srcu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) static inline int __do_essa(struct kvm_vcpu *vcpu, const int orc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) int r1, r2, nappended, entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) unsigned long gfn, hva, res, pgstev, ptev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) unsigned long *cbrlo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) * We don't need to set SD.FPF.SK to 1 here, because if we have a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) * machine check here we either handle it or crash
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) kvm_s390_get_regs_rre(vcpu, &r1, &r2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) gfn = vcpu->run->s.regs.gprs[r2] >> PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) hva = gfn_to_hva(vcpu->kvm, gfn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) entries = (vcpu->arch.sie_block->cbrlo & ~PAGE_MASK) >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) if (kvm_is_error_hva(hva))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) nappended = pgste_perform_essa(vcpu->kvm->mm, hva, orc, &ptev, &pgstev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) if (nappended < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) res = orc ? 0x10 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) vcpu->run->s.regs.gprs[r1] = res; /* Exception Indication */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) res = (pgstev & _PGSTE_GPS_USAGE_MASK) >> 22;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) * Set the block-content state part of the result. 0 means resident, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) * nothing to do if the page is valid. 2 is for preserved pages
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) * (non-present and non-zero), and 3 for zero pages (non-present and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) * zero).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) if (ptev & _PAGE_INVALID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) res |= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) if (pgstev & _PGSTE_GPS_ZERO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) res |= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) if (pgstev & _PGSTE_GPS_NODAT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) res |= 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) vcpu->run->s.regs.gprs[r1] = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) * It is possible that all the normal 511 slots were full, in which case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) * we will now write in the 512th slot, which is reserved for host use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) * In both cases we let the normal essa handling code process all the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) * slots, including the reserved one, if needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) if (nappended > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) cbrlo = phys_to_virt(vcpu->arch.sie_block->cbrlo & PAGE_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) cbrlo[entries] = gfn << PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) if (orc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) struct kvm_memory_slot *ms = gfn_to_memslot(vcpu->kvm, gfn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) /* Increment only if we are really flipping the bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) if (ms && !test_and_set_bit(gfn - ms->base_gfn, kvm_second_dirty_bitmap(ms)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) atomic64_inc(&vcpu->kvm->arch.cmma_dirty_pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) return nappended;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) static int handle_essa(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) /* entries expected to be 1FF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) int entries = (vcpu->arch.sie_block->cbrlo & ~PAGE_MASK) >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) unsigned long *cbrlo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) struct gmap *gmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) int i, orc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) VCPU_EVENT(vcpu, 4, "ESSA: release %d pages", entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) gmap = vcpu->arch.gmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) vcpu->stat.instruction_essa++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) if (!vcpu->kvm->arch.use_cmma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) return kvm_s390_inject_program_int(vcpu, PGM_OPERATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) /* Check for invalid operation request code */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) orc = (vcpu->arch.sie_block->ipb & 0xf0000000) >> 28;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) /* ORCs 0-6 are always valid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) if (orc > (test_kvm_facility(vcpu->kvm, 147) ? ESSA_SET_STABLE_NODAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) : ESSA_SET_STABLE_IF_RESIDENT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) if (!vcpu->kvm->arch.migration_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) * CMMA is enabled in the KVM settings, but is disabled in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) * the SIE block and in the mm_context, and we are not doing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) * a migration. Enable CMMA in the mm_context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) * Since we need to take a write lock to write to the context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) * to avoid races with storage keys handling, we check if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) * value really needs to be written to; if the value is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) * already correct, we do nothing and avoid the lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) if (vcpu->kvm->mm->context.uses_cmm == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) mmap_write_lock(vcpu->kvm->mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) vcpu->kvm->mm->context.uses_cmm = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) mmap_write_unlock(vcpu->kvm->mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) * If we are here, we are supposed to have CMMA enabled in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) * the SIE block. Enabling CMMA works on a per-CPU basis,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) * while the context use_cmma flag is per process.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) * It's possible that the context flag is enabled and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) * SIE flag is not, so we set the flag always; if it was
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) * already set, nothing changes, otherwise we enable it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) * on this CPU too.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) vcpu->arch.sie_block->ecb2 |= ECB2_CMMA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) /* Retry the ESSA instruction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) kvm_s390_retry_instr(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) int srcu_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) mmap_read_lock(vcpu->kvm->mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) i = __do_essa(vcpu, orc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) srcu_read_unlock(&vcpu->kvm->srcu, srcu_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) mmap_read_unlock(vcpu->kvm->mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) if (i < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) /* Account for the possible extra cbrl entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) entries += i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) vcpu->arch.sie_block->cbrlo &= PAGE_MASK; /* reset nceo */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) cbrlo = phys_to_virt(vcpu->arch.sie_block->cbrlo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) mmap_read_lock(gmap->mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) for (i = 0; i < entries; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) __gmap_zap(gmap, cbrlo[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) mmap_read_unlock(gmap->mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) int kvm_s390_handle_b9(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) switch (vcpu->arch.sie_block->ipa & 0x00ff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) case 0x8a:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) case 0x8e:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) case 0x8f:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) return handle_ipte_interlock(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) case 0x8d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) return handle_epsw(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) case 0xab:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) return handle_essa(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) case 0xaf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) return handle_pfmf(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) int kvm_s390_handle_lctl(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) int reg3 = vcpu->arch.sie_block->ipa & 0x000f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) int reg, rc, nr_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) u32 ctl_array[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) u64 ga;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) u8 ar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) vcpu->stat.instruction_lctl++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) ga = kvm_s390_get_base_disp_rs(vcpu, &ar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) if (ga & 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) VCPU_EVENT(vcpu, 4, "LCTL: r1:%d, r3:%d, addr: 0x%llx", reg1, reg3, ga);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) trace_kvm_s390_handle_lctl(vcpu, 0, reg1, reg3, ga);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) nr_regs = ((reg3 - reg1) & 0xf) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) rc = read_guest(vcpu, ga, ar, ctl_array, nr_regs * sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) return kvm_s390_inject_prog_cond(vcpu, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) reg = reg1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) nr_regs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) vcpu->arch.sie_block->gcr[reg] &= 0xffffffff00000000ul;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) vcpu->arch.sie_block->gcr[reg] |= ctl_array[nr_regs++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) if (reg == reg3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) reg = (reg + 1) % 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) } while (1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) int kvm_s390_handle_stctl(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) int reg3 = vcpu->arch.sie_block->ipa & 0x000f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) int reg, rc, nr_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) u32 ctl_array[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) u64 ga;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) u8 ar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) vcpu->stat.instruction_stctl++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) ga = kvm_s390_get_base_disp_rs(vcpu, &ar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) if (ga & 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) VCPU_EVENT(vcpu, 4, "STCTL r1:%d, r3:%d, addr: 0x%llx", reg1, reg3, ga);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) trace_kvm_s390_handle_stctl(vcpu, 0, reg1, reg3, ga);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) reg = reg1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) nr_regs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) ctl_array[nr_regs++] = vcpu->arch.sie_block->gcr[reg];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) if (reg == reg3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) reg = (reg + 1) % 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) } while (1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) rc = write_guest(vcpu, ga, ar, ctl_array, nr_regs * sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) return rc ? kvm_s390_inject_prog_cond(vcpu, rc) : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) static int handle_lctlg(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) int reg3 = vcpu->arch.sie_block->ipa & 0x000f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) int reg, rc, nr_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) u64 ctl_array[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) u64 ga;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) u8 ar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) vcpu->stat.instruction_lctlg++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) ga = kvm_s390_get_base_disp_rsy(vcpu, &ar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) if (ga & 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) VCPU_EVENT(vcpu, 4, "LCTLG: r1:%d, r3:%d, addr: 0x%llx", reg1, reg3, ga);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) trace_kvm_s390_handle_lctl(vcpu, 1, reg1, reg3, ga);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) nr_regs = ((reg3 - reg1) & 0xf) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) rc = read_guest(vcpu, ga, ar, ctl_array, nr_regs * sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) return kvm_s390_inject_prog_cond(vcpu, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) reg = reg1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) nr_regs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) vcpu->arch.sie_block->gcr[reg] = ctl_array[nr_regs++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) if (reg == reg3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) reg = (reg + 1) % 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) } while (1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) static int handle_stctg(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) int reg3 = vcpu->arch.sie_block->ipa & 0x000f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) int reg, rc, nr_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) u64 ctl_array[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) u64 ga;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) u8 ar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) vcpu->stat.instruction_stctg++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) ga = kvm_s390_get_base_disp_rsy(vcpu, &ar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) if (ga & 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) VCPU_EVENT(vcpu, 4, "STCTG r1:%d, r3:%d, addr: 0x%llx", reg1, reg3, ga);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) trace_kvm_s390_handle_stctl(vcpu, 1, reg1, reg3, ga);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) reg = reg1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) nr_regs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) ctl_array[nr_regs++] = vcpu->arch.sie_block->gcr[reg];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) if (reg == reg3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) reg = (reg + 1) % 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) } while (1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) rc = write_guest(vcpu, ga, ar, ctl_array, nr_regs * sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) return rc ? kvm_s390_inject_prog_cond(vcpu, rc) : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) int kvm_s390_handle_eb(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) switch (vcpu->arch.sie_block->ipb & 0x000000ff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) case 0x25:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) return handle_stctg(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) case 0x2f:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) return handle_lctlg(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) case 0x60:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) case 0x61:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) case 0x62:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) return handle_ri(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) static int handle_tprot(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) u64 address1, address2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) unsigned long hva, gpa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) int ret = 0, cc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) bool writable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) u8 ar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) vcpu->stat.instruction_tprot++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) kvm_s390_get_base_disp_sse(vcpu, &address1, &address2, &ar, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) /* we only handle the Linux memory detection case:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) * access key == 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) * everything else goes to userspace. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) if (address2 & 0xf0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_DAT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) ipte_lock(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) ret = guest_translate_address(vcpu, address1, ar, &gpa, GACC_STORE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) if (ret == PGM_PROTECTION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) /* Write protected? Try again with read-only... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) cc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) ret = guest_translate_address(vcpu, address1, ar, &gpa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) GACC_FETCH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) if (ret == PGM_ADDRESSING || ret == PGM_TRANSLATION_SPEC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) ret = kvm_s390_inject_program_int(vcpu, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) } else if (ret > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) /* Translation not available */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) kvm_s390_set_psw_cc(vcpu, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) hva = gfn_to_hva_prot(vcpu->kvm, gpa_to_gfn(gpa), &writable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) if (kvm_is_error_hva(hva)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) ret = kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) if (!writable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) cc = 1; /* Write not permitted ==> read-only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) kvm_s390_set_psw_cc(vcpu, cc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) /* Note: CC2 only occurs for storage keys (not supported yet) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_DAT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) ipte_unlock(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) int kvm_s390_handle_e5(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) switch (vcpu->arch.sie_block->ipa & 0x00ff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) case 0x01:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) return handle_tprot(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) static int handle_sckpf(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) u32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) vcpu->stat.instruction_sckpf++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) if (vcpu->run->s.regs.gprs[0] & 0x00000000ffff0000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) return kvm_s390_inject_program_int(vcpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) PGM_SPECIFICATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) value = vcpu->run->s.regs.gprs[0] & 0x000000000000ffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) vcpu->arch.sie_block->todpr = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) static int handle_ptff(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) vcpu->stat.instruction_ptff++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) /* we don't emulate any control instructions yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) kvm_s390_set_psw_cc(vcpu, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) int kvm_s390_handle_01(struct kvm_vcpu *vcpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) switch (vcpu->arch.sie_block->ipa & 0x00ff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) case 0x04:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) return handle_ptff(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) case 0x07:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) return handle_sckpf(vcpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) }