diff mbox series

[v2,06/11] KVM: SVM: add wrappers to enable/disable IRET interception

Message ID 20221129193717.513824-7-mlevitsk@redhat.com (mailing list archive)
State New, archived
Headers show
Series SVM: vNMI (with my fixes) | expand

Commit Message

Maxim Levitsky Nov. 29, 2022, 7:37 p.m. UTC
SEV-ES guests don't use IRET interception for the detection of
an end of a NMI.

Therefore it makes sense to create a wrapper to avoid repeating
the check for the SEV-ES.

No functional change is intended.

Suggested-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
---
 arch/x86/kvm/svm/svm.c | 28 +++++++++++++++++++---------
 1 file changed, 19 insertions(+), 9 deletions(-)

Comments

Shukla, Santosh Dec. 5, 2022, 3:41 p.m. UTC | #1
On 11/30/2022 1:07 AM, Maxim Levitsky wrote:
> SEV-ES guests don't use IRET interception for the detection of
> an end of a NMI.
> 
> Therefore it makes sense to create a wrapper to avoid repeating
> the check for the SEV-ES.
> 
> No functional change is intended.
> 
> Suggested-by: Sean Christopherson <seanjc@google.com>
> Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
> ---
>  arch/x86/kvm/svm/svm.c | 28 +++++++++++++++++++---------
>  1 file changed, 19 insertions(+), 9 deletions(-)
> 
> diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
> index 512b2aa21137e2..cfed6ab29c839a 100644
> --- a/arch/x86/kvm/svm/svm.c
> +++ b/arch/x86/kvm/svm/svm.c
> @@ -2468,16 +2468,29 @@ static int task_switch_interception(struct kvm_vcpu *vcpu)
>  			       has_error_code, error_code);
>  }
>  
> +static void svm_disable_iret_interception(struct vcpu_svm *svm)
> +{
> +	if (!sev_es_guest(svm->vcpu.kvm))
> +		svm_clr_intercept(svm, INTERCEPT_IRET);
> +}
> +
> +static void svm_enable_iret_interception(struct vcpu_svm *svm)
> +{
> +	if (!sev_es_guest(svm->vcpu.kvm))
> +		svm_set_intercept(svm, INTERCEPT_IRET);
> +}
> +

nits:
s/_iret_interception / _iret_intercept
does that make sense?

Thanks,
Santosh

>  static int iret_interception(struct kvm_vcpu *vcpu)
>  {
>  	struct vcpu_svm *svm = to_svm(vcpu);
>  
>  	++vcpu->stat.nmi_window_exits;
>  	svm->awaiting_iret_completion = true;
> -	if (!sev_es_guest(vcpu->kvm)) {
> -		svm_clr_intercept(svm, INTERCEPT_IRET);
> +
> +	svm_disable_iret_interception(svm);
> +	if (!sev_es_guest(vcpu->kvm))
>  		svm->nmi_iret_rip = kvm_rip_read(vcpu);
> -	}
> +
>  	kvm_make_request(KVM_REQ_EVENT, vcpu);
>  	return 1;
>  }
> @@ -3470,8 +3483,7 @@ static void svm_inject_nmi(struct kvm_vcpu *vcpu)
>  		return;
>  
>  	svm->nmi_masked = true;
> -	if (!sev_es_guest(vcpu->kvm))
> -		svm_set_intercept(svm, INTERCEPT_IRET);
> +	svm_enable_iret_interception(svm);
>  	++vcpu->stat.nmi_injections;
>  }
>  
> @@ -3614,12 +3626,10 @@ static void svm_set_nmi_mask(struct kvm_vcpu *vcpu, bool masked)
>  
>  	if (masked) {
>  		svm->nmi_masked = true;
> -		if (!sev_es_guest(vcpu->kvm))
> -			svm_set_intercept(svm, INTERCEPT_IRET);
> +		svm_enable_iret_interception(svm);
>  	} else {
>  		svm->nmi_masked = false;
> -		if (!sev_es_guest(vcpu->kvm))
> -			svm_clr_intercept(svm, INTERCEPT_IRET);
> +		svm_disable_iret_interception(svm);
>  	}
>  }
>
Maxim Levitsky Dec. 6, 2022, 12:14 p.m. UTC | #2
On Mon, 2022-12-05 at 21:11 +0530, Santosh Shukla wrote:
> On 11/30/2022 1:07 AM, Maxim Levitsky wrote:
> > SEV-ES guests don't use IRET interception for the detection of
> > an end of a NMI.
> > 
> > Therefore it makes sense to create a wrapper to avoid repeating
> > the check for the SEV-ES.
> > 
> > No functional change is intended.
> > 
> > Suggested-by: Sean Christopherson <seanjc@google.com>
> > Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
> > ---
> >  arch/x86/kvm/svm/svm.c | 28 +++++++++++++++++++---------
> >  1 file changed, 19 insertions(+), 9 deletions(-)
> > 
> > diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
> > index 512b2aa21137e2..cfed6ab29c839a 100644
> > --- a/arch/x86/kvm/svm/svm.c
> > +++ b/arch/x86/kvm/svm/svm.c
> > @@ -2468,16 +2468,29 @@ static int task_switch_interception(struct kvm_vcpu *vcpu)
> >  			       has_error_code, error_code);
> >  }
> >  
> > +static void svm_disable_iret_interception(struct vcpu_svm *svm)
> > +{
> > +	if (!sev_es_guest(svm->vcpu.kvm))
> > +		svm_clr_intercept(svm, INTERCEPT_IRET);
> > +}
> > +
> > +static void svm_enable_iret_interception(struct vcpu_svm *svm)
> > +{
> > +	if (!sev_es_guest(svm->vcpu.kvm))
> > +		svm_set_intercept(svm, INTERCEPT_IRET);
> > +}
> > +
> 
> nits:
> s/_iret_interception / _iret_intercept
> does that make sense?

Makes sense. I can also move this to svm.h near the svm_set_intercept(), I think
it better a better place for this function there if no objections.

Best regards,
	Maxim Levitsky
> 
> Thanks,
> Santosh
> 
> >  static int iret_interception(struct kvm_vcpu *vcpu)
> >  {
> >  	struct vcpu_svm *svm = to_svm(vcpu);
> >  
> >  	++vcpu->stat.nmi_window_exits;
> >  	svm->awaiting_iret_completion = true;
> > -	if (!sev_es_guest(vcpu->kvm)) {
> > -		svm_clr_intercept(svm, INTERCEPT_IRET);
> > +
> > +	svm_disable_iret_interception(svm);
> > +	if (!sev_es_guest(vcpu->kvm))
> >  		svm->nmi_iret_rip = kvm_rip_read(vcpu);
> > -	}
> > +
> >  	kvm_make_request(KVM_REQ_EVENT, vcpu);
> >  	return 1;
> >  }
> > @@ -3470,8 +3483,7 @@ static void svm_inject_nmi(struct kvm_vcpu *vcpu)
> >  		return;
> >  
> >  	svm->nmi_masked = true;
> > -	if (!sev_es_guest(vcpu->kvm))
> > -		svm_set_intercept(svm, INTERCEPT_IRET);
> > +	svm_enable_iret_interception(svm);
> >  	++vcpu->stat.nmi_injections;
> >  }
> >  
> > @@ -3614,12 +3626,10 @@ static void svm_set_nmi_mask(struct kvm_vcpu *vcpu, bool masked)
> >  
> >  	if (masked) {
> >  		svm->nmi_masked = true;
> > -		if (!sev_es_guest(vcpu->kvm))
> > -			svm_set_intercept(svm, INTERCEPT_IRET);
> > +		svm_enable_iret_interception(svm);
> >  	} else {
> >  		svm->nmi_masked = false;
> > -		if (!sev_es_guest(vcpu->kvm))
> > -			svm_clr_intercept(svm, INTERCEPT_IRET);
> > +		svm_disable_iret_interception(svm);
> >  	}
> >  }
> >
Shukla, Santosh Dec. 8, 2022, 12:09 p.m. UTC | #3
On 12/6/2022 5:44 PM, Maxim Levitsky wrote:
> On Mon, 2022-12-05 at 21:11 +0530, Santosh Shukla wrote:
>> On 11/30/2022 1:07 AM, Maxim Levitsky wrote:
>>> SEV-ES guests don't use IRET interception for the detection of
>>> an end of a NMI.
>>>
>>> Therefore it makes sense to create a wrapper to avoid repeating
>>> the check for the SEV-ES.
>>>
>>> No functional change is intended.
>>>
>>> Suggested-by: Sean Christopherson <seanjc@google.com>
>>> Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
>>> ---
>>>  arch/x86/kvm/svm/svm.c | 28 +++++++++++++++++++---------
>>>  1 file changed, 19 insertions(+), 9 deletions(-)
>>>
>>> diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
>>> index 512b2aa21137e2..cfed6ab29c839a 100644
>>> --- a/arch/x86/kvm/svm/svm.c
>>> +++ b/arch/x86/kvm/svm/svm.c
>>> @@ -2468,16 +2468,29 @@ static int task_switch_interception(struct kvm_vcpu *vcpu)
>>>  			       has_error_code, error_code);
>>>  }
>>>  
>>> +static void svm_disable_iret_interception(struct vcpu_svm *svm)
>>> +{
>>> +	if (!sev_es_guest(svm->vcpu.kvm))
>>> +		svm_clr_intercept(svm, INTERCEPT_IRET);
>>> +}
>>> +
>>> +static void svm_enable_iret_interception(struct vcpu_svm *svm)
>>> +{
>>> +	if (!sev_es_guest(svm->vcpu.kvm))
>>> +		svm_set_intercept(svm, INTERCEPT_IRET);
>>> +}
>>> +
>>
>> nits:
>> s/_iret_interception / _iret_intercept
>> does that make sense?
> 
> Makes sense. I can also move this to svm.h near the svm_set_intercept(), I think
> it better a better place for this function there if no objections.
> 
I think current approach is fine since function used in svm.c only. but I have
no strong opinion on moving to svm.h either ways.

Thanks,
Santosh

> Best regards,
> 	Maxim Levitsky
>>
>> Thanks,
>> Santosh
>>
>>>  static int iret_interception(struct kvm_vcpu *vcpu)
>>>  {
>>>  	struct vcpu_svm *svm = to_svm(vcpu);
>>>  
>>>  	++vcpu->stat.nmi_window_exits;
>>>  	svm->awaiting_iret_completion = true;
>>> -	if (!sev_es_guest(vcpu->kvm)) {
>>> -		svm_clr_intercept(svm, INTERCEPT_IRET);
>>> +
>>> +	svm_disable_iret_interception(svm);
>>> +	if (!sev_es_guest(vcpu->kvm))
>>>  		svm->nmi_iret_rip = kvm_rip_read(vcpu);
>>> -	}
>>> +
>>>  	kvm_make_request(KVM_REQ_EVENT, vcpu);
>>>  	return 1;
>>>  }
>>> @@ -3470,8 +3483,7 @@ static void svm_inject_nmi(struct kvm_vcpu *vcpu)
>>>  		return;
>>>  
>>>  	svm->nmi_masked = true;
>>> -	if (!sev_es_guest(vcpu->kvm))
>>> -		svm_set_intercept(svm, INTERCEPT_IRET);
>>> +	svm_enable_iret_interception(svm);
>>>  	++vcpu->stat.nmi_injections;
>>>  }
>>>  
>>> @@ -3614,12 +3626,10 @@ static void svm_set_nmi_mask(struct kvm_vcpu *vcpu, bool masked)
>>>  
>>>  	if (masked) {
>>>  		svm->nmi_masked = true;
>>> -		if (!sev_es_guest(vcpu->kvm))
>>> -			svm_set_intercept(svm, INTERCEPT_IRET);
>>> +		svm_enable_iret_interception(svm);
>>>  	} else {
>>>  		svm->nmi_masked = false;
>>> -		if (!sev_es_guest(vcpu->kvm))
>>> -			svm_clr_intercept(svm, INTERCEPT_IRET);
>>> +		svm_disable_iret_interception(svm);
>>>  	}
>>>  }
>>>  
> 
>
Maxim Levitsky Dec. 8, 2022, 1:44 p.m. UTC | #4
On Thu, 2022-12-08 at 17:39 +0530, Santosh Shukla wrote:
> 
> On 12/6/2022 5:44 PM, Maxim Levitsky wrote:
> > On Mon, 2022-12-05 at 21:11 +0530, Santosh Shukla wrote:
> > > On 11/30/2022 1:07 AM, Maxim Levitsky wrote:
> > > > SEV-ES guests don't use IRET interception for the detection of
> > > > an end of a NMI.
> > > > 
> > > > Therefore it makes sense to create a wrapper to avoid repeating
> > > > the check for the SEV-ES.
> > > > 
> > > > No functional change is intended.
> > > > 
> > > > Suggested-by: Sean Christopherson <seanjc@google.com>
> > > > Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
> > > > ---
> > > >  arch/x86/kvm/svm/svm.c | 28 +++++++++++++++++++---------
> > > >  1 file changed, 19 insertions(+), 9 deletions(-)
> > > > 
> > > > diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
> > > > index 512b2aa21137e2..cfed6ab29c839a 100644
> > > > --- a/arch/x86/kvm/svm/svm.c
> > > > +++ b/arch/x86/kvm/svm/svm.c
> > > > @@ -2468,16 +2468,29 @@ static int task_switch_interception(struct kvm_vcpu *vcpu)
> > > >  			       has_error_code, error_code);
> > > >  }
> > > >  
> > > > +static void svm_disable_iret_interception(struct vcpu_svm *svm)
> > > > +{
> > > > +	if (!sev_es_guest(svm->vcpu.kvm))
> > > > +		svm_clr_intercept(svm, INTERCEPT_IRET);
> > > > +}
> > > > +
> > > > +static void svm_enable_iret_interception(struct vcpu_svm *svm)
> > > > +{
> > > > +	if (!sev_es_guest(svm->vcpu.kvm))
> > > > +		svm_set_intercept(svm, INTERCEPT_IRET);
> > > > +}
> > > > +
> > > 
> > > nits:
> > > s/_iret_interception / _iret_intercept
> > > does that make sense?
> > 
> > Makes sense. I can also move this to svm.h near the svm_set_intercept(), I think
> > it better a better place for this function there if no objections.
> > 
> I think current approach is fine since function used in svm.c only. but I have
> no strong opinion on moving to svm.h either ways.

I also think so, just noticed something in case there are any objections.

Best regards,
	Maxim Levitsky

> 
> Thanks,
> Santosh
> 
> > Best regards,
> > 	Maxim Levitsky
> > > Thanks,
> > > Santosh
> > > 
> > > >  static int iret_interception(struct kvm_vcpu *vcpu)
> > > >  {
> > > >  	struct vcpu_svm *svm = to_svm(vcpu);
> > > >  
> > > >  	++vcpu->stat.nmi_window_exits;
> > > >  	svm->awaiting_iret_completion = true;
> > > > -	if (!sev_es_guest(vcpu->kvm)) {
> > > > -		svm_clr_intercept(svm, INTERCEPT_IRET);
> > > > +
> > > > +	svm_disable_iret_interception(svm);
> > > > +	if (!sev_es_guest(vcpu->kvm))
> > > >  		svm->nmi_iret_rip = kvm_rip_read(vcpu);
> > > > -	}
> > > > +
> > > >  	kvm_make_request(KVM_REQ_EVENT, vcpu);
> > > >  	return 1;
> > > >  }
> > > > @@ -3470,8 +3483,7 @@ static void svm_inject_nmi(struct kvm_vcpu *vcpu)
> > > >  		return;
> > > >  
> > > >  	svm->nmi_masked = true;
> > > > -	if (!sev_es_guest(vcpu->kvm))
> > > > -		svm_set_intercept(svm, INTERCEPT_IRET);
> > > > +	svm_enable_iret_interception(svm);
> > > >  	++vcpu->stat.nmi_injections;
> > > >  }
> > > >  
> > > > @@ -3614,12 +3626,10 @@ static void svm_set_nmi_mask(struct kvm_vcpu *vcpu, bool masked)
> > > >  
> > > >  	if (masked) {
> > > >  		svm->nmi_masked = true;
> > > > -		if (!sev_es_guest(vcpu->kvm))
> > > > -			svm_set_intercept(svm, INTERCEPT_IRET);
> > > > +		svm_enable_iret_interception(svm);
> > > >  	} else {
> > > >  		svm->nmi_masked = false;
> > > > -		if (!sev_es_guest(vcpu->kvm))
> > > > -			svm_clr_intercept(svm, INTERCEPT_IRET);
> > > > +		svm_disable_iret_interception(svm);
> > > >  	}
> > > >  }
> > > >
Sean Christopherson Jan. 31, 2023, 9:07 p.m. UTC | #5
On Thu, Dec 08, 2022, Maxim Levitsky wrote:
> On Thu, 2022-12-08 at 17:39 +0530, Santosh Shukla wrote:
> > 
> > On 12/6/2022 5:44 PM, Maxim Levitsky wrote:
> > > > > diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
> > > > > index 512b2aa21137e2..cfed6ab29c839a 100644
> > > > > --- a/arch/x86/kvm/svm/svm.c
> > > > > +++ b/arch/x86/kvm/svm/svm.c
> > > > > @@ -2468,16 +2468,29 @@ static int task_switch_interception(struct kvm_vcpu *vcpu)
> > > > >  			       has_error_code, error_code);
> > > > >  }
> > > > >  
> > > > > +static void svm_disable_iret_interception(struct vcpu_svm *svm)
> > > > > +{
> > > > > +	if (!sev_es_guest(svm->vcpu.kvm))
> > > > > +		svm_clr_intercept(svm, INTERCEPT_IRET);
> > > > > +}
> > > > > +
> > > > > +static void svm_enable_iret_interception(struct vcpu_svm *svm)
> > > > > +{
> > > > > +	if (!sev_es_guest(svm->vcpu.kvm))
> > > > > +		svm_set_intercept(svm, INTERCEPT_IRET);
> > > > > +}
> > > > > +
> > > > 
> > > > nits:
> > > > s/_iret_interception / _iret_intercept
> > > > does that make sense?
> > > 
> > > Makes sense.

I would rather go with svm_{clr,set}_iret_intercept().  I don't particularly like
the SVM naming scheme, but I really dislike inconsistent naming.  If we want to
clean up naming, I would love unify VMX and SVM nomenclature for things like this.

> > >  I can also move this to svm.h near the svm_set_intercept(), I think
> > > it better a better place for this function there if no objections.
> > > 
> > I think current approach is fine since function used in svm.c only. but I have
> > no strong opinion on moving to svm.h either ways.
> 
> I also think so, just noticed something in case there are any objections.

My vote is to keep it in svm.c unless we anticipate usage outside of svm.h.  Keeping
the implementation close to the usage makes it easer to understand what's going on,
especially for something like this where there's a bit of "hidden" logic for SEV-ES.
Shukla, Santosh Feb. 13, 2023, 2:50 p.m. UTC | #6
On 2/1/2023 2:37 AM, Sean Christopherson wrote:
> On Thu, Dec 08, 2022, Maxim Levitsky wrote:
>> On Thu, 2022-12-08 at 17:39 +0530, Santosh Shukla wrote:
>>>
>>> On 12/6/2022 5:44 PM, Maxim Levitsky wrote:
>>>>>> diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
>>>>>> index 512b2aa21137e2..cfed6ab29c839a 100644
>>>>>> --- a/arch/x86/kvm/svm/svm.c
>>>>>> +++ b/arch/x86/kvm/svm/svm.c
>>>>>> @@ -2468,16 +2468,29 @@ static int task_switch_interception(struct kvm_vcpu *vcpu)
>>>>>>  			       has_error_code, error_code);
>>>>>>  }
>>>>>>  
>>>>>> +static void svm_disable_iret_interception(struct vcpu_svm *svm)
>>>>>> +{
>>>>>> +	if (!sev_es_guest(svm->vcpu.kvm))
>>>>>> +		svm_clr_intercept(svm, INTERCEPT_IRET);
>>>>>> +}
>>>>>> +
>>>>>> +static void svm_enable_iret_interception(struct vcpu_svm *svm)
>>>>>> +{
>>>>>> +	if (!sev_es_guest(svm->vcpu.kvm))
>>>>>> +		svm_set_intercept(svm, INTERCEPT_IRET);
>>>>>> +}
>>>>>> +
>>>>>
>>>>> nits:
>>>>> s/_iret_interception / _iret_intercept
>>>>> does that make sense?
>>>>
>>>> Makes sense.
> 
> I would rather go with svm_{clr,set}_iret_intercept().  I don't particularly like

ok.

> the SVM naming scheme, but I really dislike inconsistent naming.  If we want to
> clean up naming, I would love unify VMX and SVM nomenclature for things like this.
> 
>>>>  I can also move this to svm.h near the svm_set_intercept(), I think
>>>> it better a better place for this function there if no objections.
>>>>
>>> I think current approach is fine since function used in svm.c only. but I have
>>> no strong opinion on moving to svm.h either ways.
>>
>> I also think so, just noticed something in case there are any objections.
> 
> My vote is to keep it in svm.c unless we anticipate usage outside of svm.h.  Keeping

ok.

Thanks,
Santosh
> the implementation close to the usage makes it easer to understand what's going on,
> especially for something like this where there's a bit of "hidden" logic for SEV-ES.
diff mbox series

Patch

diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 512b2aa21137e2..cfed6ab29c839a 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -2468,16 +2468,29 @@  static int task_switch_interception(struct kvm_vcpu *vcpu)
 			       has_error_code, error_code);
 }
 
+static void svm_disable_iret_interception(struct vcpu_svm *svm)
+{
+	if (!sev_es_guest(svm->vcpu.kvm))
+		svm_clr_intercept(svm, INTERCEPT_IRET);
+}
+
+static void svm_enable_iret_interception(struct vcpu_svm *svm)
+{
+	if (!sev_es_guest(svm->vcpu.kvm))
+		svm_set_intercept(svm, INTERCEPT_IRET);
+}
+
 static int iret_interception(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
 
 	++vcpu->stat.nmi_window_exits;
 	svm->awaiting_iret_completion = true;
-	if (!sev_es_guest(vcpu->kvm)) {
-		svm_clr_intercept(svm, INTERCEPT_IRET);
+
+	svm_disable_iret_interception(svm);
+	if (!sev_es_guest(vcpu->kvm))
 		svm->nmi_iret_rip = kvm_rip_read(vcpu);
-	}
+
 	kvm_make_request(KVM_REQ_EVENT, vcpu);
 	return 1;
 }
@@ -3470,8 +3483,7 @@  static void svm_inject_nmi(struct kvm_vcpu *vcpu)
 		return;
 
 	svm->nmi_masked = true;
-	if (!sev_es_guest(vcpu->kvm))
-		svm_set_intercept(svm, INTERCEPT_IRET);
+	svm_enable_iret_interception(svm);
 	++vcpu->stat.nmi_injections;
 }
 
@@ -3614,12 +3626,10 @@  static void svm_set_nmi_mask(struct kvm_vcpu *vcpu, bool masked)
 
 	if (masked) {
 		svm->nmi_masked = true;
-		if (!sev_es_guest(vcpu->kvm))
-			svm_set_intercept(svm, INTERCEPT_IRET);
+		svm_enable_iret_interception(svm);
 	} else {
 		svm->nmi_masked = false;
-		if (!sev_es_guest(vcpu->kvm))
-			svm_clr_intercept(svm, INTERCEPT_IRET);
+		svm_disable_iret_interception(svm);
 	}
 }