[1/2,Bionic] KVM: SVM: install RSM intercept
diff mbox series

Message ID 20190829170658.16739-1-rafaeldtinoco@ubuntu.com
State New
Headers show
Series
  • [1/2,Bionic] KVM: SVM: install RSM intercept
Related show

Commit Message

Rafael David Tinoco Aug. 29, 2019, 5:06 p.m. UTC
From: Brijesh Singh <brijesh.singh@amd.com>

BugLink: https://bugs.launchpad.net/bugs/1834522

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>
(cherry-picked from commit 7607b7174405aec7441ff6c970833c463114040a)
Signed-off-by: Rafael David Tinoco <rafaeldtinoco@ubuntu.com>

---
 arch/x86/kvm/svm.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

Comments

Thadeu Lima de Souza Cascardo Aug. 30, 2019, 11:33 a.m. UTC | #1
On Thu, Aug 29, 2019 at 02:06:57PM -0300, Rafael David Tinoco wrote:
> From: Brijesh Singh <brijesh.singh@amd.com>
> 
> BugLink: https://bugs.launchpad.net/bugs/1834522
> 
> 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>
> (cherry-picked from commit 7607b7174405aec7441ff6c970833c463114040a)
> Signed-off-by: Rafael David Tinoco <rafaeldtinoco@ubuntu.com>

Good cherry-picks from upstream, fixes make sense. A cover letter would have
been nicer for a patchset.

Acked-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>

> 
> ---
>  arch/x86/kvm/svm.c | 11 ++++++++++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
> index 72765bbac9f1..538ca5446cfd 100644
> --- a/arch/x86/kvm/svm.c
> +++ b/arch/x86/kvm/svm.c
> @@ -298,6 +298,8 @@ module_param(vls, int, 0444);
>  static int vgif = true;
>  module_param(vgif, int, 0444);
>  
> +static u8 rsm_ins_bytes[] = "\x0f\xaa";
> +
>  static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
>  static void svm_flush_tlb(struct kvm_vcpu *vcpu);
>  static void svm_complete_interrupts(struct vcpu_svm *svm);
> @@ -1292,6 +1294,7 @@ static void init_vmcb(struct vcpu_svm *svm)
>  	set_intercept(svm, INTERCEPT_SKINIT);
>  	set_intercept(svm, INTERCEPT_WBINVD);
>  	set_intercept(svm, INTERCEPT_XSETBV);
> +	set_intercept(svm, INTERCEPT_RSM);
>  
>  	if (!kvm_mwait_in_guest()) {
>  		set_intercept(svm, INTERCEPT_MONITOR);
> @@ -3441,6 +3444,12 @@ static int emulate_on_interception(struct vcpu_svm *svm)
>  	return emulate_instruction(&svm->vcpu, 0) == EMULATE_DONE;
>  }
>  
> +static int rsm_interception(struct vcpu_svm *svm)
> +{
> +	return x86_emulate_instruction(&svm->vcpu, 0, 0,
> +				       rsm_ins_bytes, 2) == EMULATE_DONE;
> +}
> +
>  static int rdpmc_interception(struct vcpu_svm *svm)
>  {
>  	int err;
> @@ -4327,7 +4336,7 @@ static int (*const svm_exit_handlers[])(struct vcpu_svm *svm) = {
>  	[SVM_EXIT_MWAIT]			= mwait_interception,
>  	[SVM_EXIT_XSETBV]			= xsetbv_interception,
>  	[SVM_EXIT_NPF]				= npf_interception,
> -	[SVM_EXIT_RSM]                          = emulate_on_interception,
> +	[SVM_EXIT_RSM]                          = rsm_interception,
>  	[SVM_EXIT_AVIC_INCOMPLETE_IPI]		= avic_incomplete_ipi_interception,
>  	[SVM_EXIT_AVIC_UNACCELERATED_ACCESS]	= avic_unaccelerated_access_interception,
>  };
> -- 
> 2.17.1
> 
> 
> -- 
> kernel-team mailing list
> kernel-team@lists.ubuntu.com
> https://lists.ubuntu.com/mailman/listinfo/kernel-team
Kleber Souza Sept. 2, 2019, 4:35 p.m. UTC | #2
On 8/29/19 7:06 PM, Rafael David Tinoco wrote:
> From: Brijesh Singh <brijesh.singh@amd.com>
> 
> BugLink: https://bugs.launchpad.net/bugs/1834522
> 
> 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>
> (cherry-picked from commit 7607b7174405aec7441ff6c970833c463114040a)
> Signed-off-by: Rafael David Tinoco <rafaeldtinoco@ubuntu.com>
> 
> ---
>  arch/x86/kvm/svm.c | 11 ++++++++++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
> index 72765bbac9f1..538ca5446cfd 100644
> --- a/arch/x86/kvm/svm.c
> +++ b/arch/x86/kvm/svm.c
> @@ -298,6 +298,8 @@ module_param(vls, int, 0444);
>  static int vgif = true;
>  module_param(vgif, int, 0444);
>  
> +static u8 rsm_ins_bytes[] = "\x0f\xaa";
> +
>  static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
>  static void svm_flush_tlb(struct kvm_vcpu *vcpu);
>  static void svm_complete_interrupts(struct vcpu_svm *svm);
> @@ -1292,6 +1294,7 @@ static void init_vmcb(struct vcpu_svm *svm)
>  	set_intercept(svm, INTERCEPT_SKINIT);
>  	set_intercept(svm, INTERCEPT_WBINVD);
>  	set_intercept(svm, INTERCEPT_XSETBV);
> +	set_intercept(svm, INTERCEPT_RSM);
>  
>  	if (!kvm_mwait_in_guest()) {
>  		set_intercept(svm, INTERCEPT_MONITOR);
> @@ -3441,6 +3444,12 @@ static int emulate_on_interception(struct vcpu_svm *svm)
>  	return emulate_instruction(&svm->vcpu, 0) == EMULATE_DONE;
>  }
>  
> +static int rsm_interception(struct vcpu_svm *svm)
> +{
> +	return x86_emulate_instruction(&svm->vcpu, 0, 0,
> +				       rsm_ins_bytes, 2) == EMULATE_DONE;
> +}
> +
>  static int rdpmc_interception(struct vcpu_svm *svm)
>  {
>  	int err;
> @@ -4327,7 +4336,7 @@ static int (*const svm_exit_handlers[])(struct vcpu_svm *svm) = {
>  	[SVM_EXIT_MWAIT]			= mwait_interception,
>  	[SVM_EXIT_XSETBV]			= xsetbv_interception,
>  	[SVM_EXIT_NPF]				= npf_interception,
> -	[SVM_EXIT_RSM]                          = emulate_on_interception,
> +	[SVM_EXIT_RSM]                          = rsm_interception,
>  	[SVM_EXIT_AVIC_INCOMPLETE_IPI]		= avic_incomplete_ipi_interception,
>  	[SVM_EXIT_AVIC_UNACCELERATED_ACCESS]	= avic_unaccelerated_access_interception,
>  };
> 

Clean cherry-picks, good test results.

For both patches:

Acked-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
Khaled Elmously Sept. 3, 2019, 5:30 a.m. UTC | #3
On 2019-08-29 14:06:57 , Rafael David Tinoco wrote:
> From: Brijesh Singh <brijesh.singh@amd.com>
> 
> BugLink: https://bugs.launchpad.net/bugs/1834522
> 
> 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>
> (cherry-picked from commit 7607b7174405aec7441ff6c970833c463114040a)
> Signed-off-by: Rafael David Tinoco <rafaeldtinoco@ubuntu.com>
> 
> ---
>  arch/x86/kvm/svm.c | 11 ++++++++++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
> index 72765bbac9f1..538ca5446cfd 100644
> --- a/arch/x86/kvm/svm.c
> +++ b/arch/x86/kvm/svm.c
> @@ -298,6 +298,8 @@ module_param(vls, int, 0444);
>  static int vgif = true;
>  module_param(vgif, int, 0444);
>  
> +static u8 rsm_ins_bytes[] = "\x0f\xaa";
> +
>  static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
>  static void svm_flush_tlb(struct kvm_vcpu *vcpu);
>  static void svm_complete_interrupts(struct vcpu_svm *svm);
> @@ -1292,6 +1294,7 @@ static void init_vmcb(struct vcpu_svm *svm)
>  	set_intercept(svm, INTERCEPT_SKINIT);
>  	set_intercept(svm, INTERCEPT_WBINVD);
>  	set_intercept(svm, INTERCEPT_XSETBV);
> +	set_intercept(svm, INTERCEPT_RSM);
>  
>  	if (!kvm_mwait_in_guest()) {
>  		set_intercept(svm, INTERCEPT_MONITOR);
> @@ -3441,6 +3444,12 @@ static int emulate_on_interception(struct vcpu_svm *svm)
>  	return emulate_instruction(&svm->vcpu, 0) == EMULATE_DONE;
>  }
>  
> +static int rsm_interception(struct vcpu_svm *svm)
> +{
> +	return x86_emulate_instruction(&svm->vcpu, 0, 0,
> +				       rsm_ins_bytes, 2) == EMULATE_DONE;
> +}
> +
>  static int rdpmc_interception(struct vcpu_svm *svm)
>  {
>  	int err;
> @@ -4327,7 +4336,7 @@ static int (*const svm_exit_handlers[])(struct vcpu_svm *svm) = {
>  	[SVM_EXIT_MWAIT]			= mwait_interception,
>  	[SVM_EXIT_XSETBV]			= xsetbv_interception,
>  	[SVM_EXIT_NPF]				= npf_interception,
> -	[SVM_EXIT_RSM]                          = emulate_on_interception,
> +	[SVM_EXIT_RSM]                          = rsm_interception,
>  	[SVM_EXIT_AVIC_INCOMPLETE_IPI]		= avic_incomplete_ipi_interception,
>  	[SVM_EXIT_AVIC_UNACCELERATED_ACCESS]	= avic_unaccelerated_access_interception,
>  };
> -- 
> 2.17.1
> 
> 
> -- 
> kernel-team mailing list
> kernel-team@lists.ubuntu.com
> https://lists.ubuntu.com/mailman/listinfo/kernel-team

Patch
diff mbox series

diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 72765bbac9f1..538ca5446cfd 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -298,6 +298,8 @@  module_param(vls, int, 0444);
 static int vgif = true;
 module_param(vgif, int, 0444);
 
+static u8 rsm_ins_bytes[] = "\x0f\xaa";
+
 static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
 static void svm_flush_tlb(struct kvm_vcpu *vcpu);
 static void svm_complete_interrupts(struct vcpu_svm *svm);
@@ -1292,6 +1294,7 @@  static void init_vmcb(struct vcpu_svm *svm)
 	set_intercept(svm, INTERCEPT_SKINIT);
 	set_intercept(svm, INTERCEPT_WBINVD);
 	set_intercept(svm, INTERCEPT_XSETBV);
+	set_intercept(svm, INTERCEPT_RSM);
 
 	if (!kvm_mwait_in_guest()) {
 		set_intercept(svm, INTERCEPT_MONITOR);
@@ -3441,6 +3444,12 @@  static int emulate_on_interception(struct vcpu_svm *svm)
 	return emulate_instruction(&svm->vcpu, 0) == EMULATE_DONE;
 }
 
+static int rsm_interception(struct vcpu_svm *svm)
+{
+	return x86_emulate_instruction(&svm->vcpu, 0, 0,
+				       rsm_ins_bytes, 2) == EMULATE_DONE;
+}
+
 static int rdpmc_interception(struct vcpu_svm *svm)
 {
 	int err;
@@ -4327,7 +4336,7 @@  static int (*const svm_exit_handlers[])(struct vcpu_svm *svm) = {
 	[SVM_EXIT_MWAIT]			= mwait_interception,
 	[SVM_EXIT_XSETBV]			= xsetbv_interception,
 	[SVM_EXIT_NPF]				= npf_interception,
-	[SVM_EXIT_RSM]                          = emulate_on_interception,
+	[SVM_EXIT_RSM]                          = rsm_interception,
 	[SVM_EXIT_AVIC_INCOMPLETE_IPI]		= avic_incomplete_ipi_interception,
 	[SVM_EXIT_AVIC_UNACCELERATED_ACCESS]	= avic_unaccelerated_access_interception,
 };