aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrijesh Singh <brijesh.singh@amd.com>2018-02-19 11:14:44 -0500
committerPaolo Bonzini <pbonzini@redhat.com>2018-02-23 20:24:12 -0500
commit7607b7174405aec7441ff6c970833c463114040a (patch)
treeb507a9bd87b758a01a532ac98814f614bffd3b38
parent3e233385ef4a217a2812115ed84d4be36eb16817 (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.c11
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);
300static int sev = IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT); 300static int sev = IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT);
301module_param(sev, int, 0444); 301module_param(sev, int, 0444);
302 302
303static u8 rsm_ins_bytes[] = "\x0f\xaa";
304
303static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0); 305static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
304static void svm_flush_tlb(struct kvm_vcpu *vcpu, bool invalidate_gpa); 306static void svm_flush_tlb(struct kvm_vcpu *vcpu, bool invalidate_gpa);
305static void svm_complete_interrupts(struct vcpu_svm *svm); 307static 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
3705static 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
3702static int rdpmc_interception(struct vcpu_svm *svm) 3711static 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};