diff options
author | Brijesh Singh <brijesh.singh@amd.com> | 2018-02-19 11:14:44 -0500 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2018-02-23 20:24:12 -0500 |
commit | 7607b7174405aec7441ff6c970833c463114040a (patch) | |
tree | b507a9bd87b758a01a532ac98814f614bffd3b38 | |
parent | 3e233385ef4a217a2812115ed84d4be36eb16817 (diff) |
KVM: SVM: install RSM intercept
RSM instruction is used by the SMM handler to return from SMM mode.
Currently, rsm causes a #UD - which results in instruction fetch, decode,
and emulate. By installing the RSM intercept we can avoid the instruction
fetch since we know that #VMEXIT was due to rsm.
The patch is required for the SEV guest, because in case of SEV guest
memory is encrypted with guest-specific key and hypervisor will not
able to fetch the instruction bytes from the guest memory.
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Radim Krčmář <rkrcmar@redhat.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Borislav Petkov <bp@suse.de>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r-- | arch/x86/kvm/svm.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index ca69d53d7e6d..4aeb665ffbb0 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c | |||
@@ -300,6 +300,8 @@ module_param(vgif, int, 0444); | |||
300 | static int sev = IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT); | 300 | static int sev = IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT); |
301 | module_param(sev, int, 0444); | 301 | module_param(sev, int, 0444); |
302 | 302 | ||
303 | static u8 rsm_ins_bytes[] = "\x0f\xaa"; | ||
304 | |||
303 | static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0); | 305 | static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0); |
304 | static void svm_flush_tlb(struct kvm_vcpu *vcpu, bool invalidate_gpa); | 306 | static void svm_flush_tlb(struct kvm_vcpu *vcpu, bool invalidate_gpa); |
305 | static void svm_complete_interrupts(struct vcpu_svm *svm); | 307 | static void svm_complete_interrupts(struct vcpu_svm *svm); |
@@ -1383,6 +1385,7 @@ static void init_vmcb(struct vcpu_svm *svm) | |||
1383 | set_intercept(svm, INTERCEPT_SKINIT); | 1385 | set_intercept(svm, INTERCEPT_SKINIT); |
1384 | set_intercept(svm, INTERCEPT_WBINVD); | 1386 | set_intercept(svm, INTERCEPT_WBINVD); |
1385 | set_intercept(svm, INTERCEPT_XSETBV); | 1387 | set_intercept(svm, INTERCEPT_XSETBV); |
1388 | set_intercept(svm, INTERCEPT_RSM); | ||
1386 | 1389 | ||
1387 | if (!kvm_mwait_in_guest()) { | 1390 | if (!kvm_mwait_in_guest()) { |
1388 | set_intercept(svm, INTERCEPT_MONITOR); | 1391 | set_intercept(svm, INTERCEPT_MONITOR); |
@@ -3699,6 +3702,12 @@ static int emulate_on_interception(struct vcpu_svm *svm) | |||
3699 | return emulate_instruction(&svm->vcpu, 0) == EMULATE_DONE; | 3702 | return emulate_instruction(&svm->vcpu, 0) == EMULATE_DONE; |
3700 | } | 3703 | } |
3701 | 3704 | ||
3705 | static int rsm_interception(struct vcpu_svm *svm) | ||
3706 | { | ||
3707 | return x86_emulate_instruction(&svm->vcpu, 0, 0, | ||
3708 | rsm_ins_bytes, 2) == EMULATE_DONE; | ||
3709 | } | ||
3710 | |||
3702 | static int rdpmc_interception(struct vcpu_svm *svm) | 3711 | static int rdpmc_interception(struct vcpu_svm *svm) |
3703 | { | 3712 | { |
3704 | int err; | 3713 | int err; |
@@ -4541,7 +4550,7 @@ static int (*const svm_exit_handlers[])(struct vcpu_svm *svm) = { | |||
4541 | [SVM_EXIT_MWAIT] = mwait_interception, | 4550 | [SVM_EXIT_MWAIT] = mwait_interception, |
4542 | [SVM_EXIT_XSETBV] = xsetbv_interception, | 4551 | [SVM_EXIT_XSETBV] = xsetbv_interception, |
4543 | [SVM_EXIT_NPF] = npf_interception, | 4552 | [SVM_EXIT_NPF] = npf_interception, |
4544 | [SVM_EXIT_RSM] = emulate_on_interception, | 4553 | [SVM_EXIT_RSM] = rsm_interception, |
4545 | [SVM_EXIT_AVIC_INCOMPLETE_IPI] = avic_incomplete_ipi_interception, | 4554 | [SVM_EXIT_AVIC_INCOMPLETE_IPI] = avic_incomplete_ipi_interception, |
4546 | [SVM_EXIT_AVIC_UNACCELERATED_ACCESS] = avic_unaccelerated_access_interception, | 4555 | [SVM_EXIT_AVIC_UNACCELERATED_ACCESS] = avic_unaccelerated_access_interception, |
4547 | }; | 4556 | }; |