From: Janosch Frank <frankja@xxxxxxxxxxxxx> The SPX instruction is handled by the ulravisor. We do get a notification intercept, though. Let us update our internal view. In addition to that, when the guest prefix page is not secure, an intercept 112 (0x70) is indicated. To avoid this for the most common cases, we can make the guest prefix page protected whenever we pin it. We have to deal with 112 nevertheless, e.g. when some host code triggers an export (e.g. qemu dump guest memory). We can simply re-run the pinning logic by doing a no-op prefix change. Signed-off-by: Janosch Frank <frankja@xxxxxxxxxxxxx> --- arch/s390/include/asm/kvm_host.h | 1 + arch/s390/kvm/intercept.c | 15 +++++++++++++++ arch/s390/kvm/kvm-s390.c | 14 ++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index 48f382680755..686b00ced55b 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h @@ -225,6 +225,7 @@ struct kvm_s390_sie_block { #define ICPT_PV_INT_EN 0x64 #define ICPT_PV_INSTR 0x68 #define ICPT_PV_NOTIF 0x6c +#define ICPT_PV_PREF 0x70 __u8 icptcode; /* 0x0050 */ __u8 icptstatus; /* 0x0051 */ __u16 ihcpu; /* 0x0052 */ diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c index d63f9cf10360..ceba0abb1900 100644 --- a/arch/s390/kvm/intercept.c +++ b/arch/s390/kvm/intercept.c @@ -451,6 +451,15 @@ static int handle_operexc(struct kvm_vcpu *vcpu) return kvm_s390_inject_program_int(vcpu, PGM_OPERATION); } +static int handle_pv_spx(struct kvm_vcpu *vcpu) +{ + u32 pref = *(u32 *)vcpu->arch.sie_block->sidad; + + kvm_s390_set_prefix(vcpu, pref); + trace_kvm_s390_handle_prefix(vcpu, 1, pref); + return 0; +} + static int handle_pv_sclp(struct kvm_vcpu *vcpu) { struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int; @@ -475,6 +484,8 @@ static int handle_pv_sclp(struct kvm_vcpu *vcpu) static int handle_pv_not(struct kvm_vcpu *vcpu) { + if (vcpu->arch.sie_block->ipa == 0xb210) + return handle_pv_spx(vcpu); if (vcpu->arch.sie_block->ipa == 0xb220) return handle_pv_sclp(vcpu); @@ -533,6 +544,10 @@ int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu) case ICPT_PV_NOTIF: rc = handle_pv_not(vcpu); break; + case ICPT_PV_PREF: + rc = 0; + kvm_s390_set_prefix(vcpu, kvm_s390_get_prefix(vcpu)); + break; default: return -EOPNOTSUPP; } diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 76303b0f1226..6e74c7afae3a 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -3675,6 +3675,20 @@ static int kvm_s390_handle_requests(struct kvm_vcpu *vcpu) rc = gmap_mprotect_notify(vcpu->arch.gmap, kvm_s390_get_prefix(vcpu), PAGE_SIZE * 2, PROT_WRITE); + if (!rc && kvm_s390_pv_is_protected(vcpu->kvm)) { + do { + rc = uv_convert_to_secure( + vcpu->arch.gmap, + kvm_s390_get_prefix(vcpu)); + } while (rc == -EAGAIN); + WARN_ONCE(rc, "Error while importing first prefix page. rc %d", rc); + do { + rc = uv_convert_to_secure( + vcpu->arch.gmap, + kvm_s390_get_prefix(vcpu) + PAGE_SIZE); + } while (rc == -EAGAIN); + WARN_ONCE(rc, "Error while importing second prefix page. rc %d", rc); + } if (rc) { kvm_make_request(KVM_REQ_MMU_RELOAD, vcpu); return rc; -- 2.24.0