public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/2] KVM: x86: Check hypercall's exit to userspace generically
@ 2024-08-13  5:12 Binbin Wu
  2024-08-13  5:12 ` [PATCH v2 1/2] " Binbin Wu
  2024-08-13  5:12 ` [PATCH v2 2/2] KVM: x86: Use is_kvm_hc_exit_enabled() instead of opencode Binbin Wu
  0 siblings, 2 replies; 19+ messages in thread
From: Binbin Wu @ 2024-08-13  5:12 UTC (permalink / raw)
  To: kvm, linux-kernel
  Cc: pbonzini, seanjc, isaku.yamahata, rick.p.edgecombe, michael.roth,
	binbin.wu

Currently in kvm_emulate_hypercall, KVM_HC_MAP_GPA_RANGE is checked
specifically to decide whether a KVM hypercall needs to exit to userspace
or not.  Do the check based on the hypercall_exit_enabled field of
struct kvm_arch.

Also use the API is_kvm_hc_exit_enabled() to replace the opencode.

---
v2:
- Check the return value of __kvm_emulate_hypercall() before checking
  hypercall_exit_enabled to avoid an invalid KVM hypercall nr.
  https://lore.kernel.org/kvm/184d90a8-14a0-494a-9112-365417245911@linux.intel.com/
- Add a warning if a hypercall nr out of the range of hypercall_exit_enabled
  can express.

Binbin Wu (2):
  KVM: x86: Check hypercall's exit to userspace generically
  KVM: x86: Use is_kvm_hc_exit_enabled() instead of opencode

 arch/x86/kvm/svm/sev.c | 4 ++--
 arch/x86/kvm/x86.c     | 6 +++---
 arch/x86/kvm/x86.h     | 7 +++++++
 3 files changed, 12 insertions(+), 5 deletions(-)


base-commit: 332d2c1d713e232e163386c35a3ba0c1b90df83f
-- 
2.43.2


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH v2 1/2] KVM: x86: Check hypercall's exit to userspace generically
  2024-08-13  5:12 [PATCH v2 0/2] KVM: x86: Check hypercall's exit to userspace generically Binbin Wu
@ 2024-08-13  5:12 ` Binbin Wu
  2024-08-13  5:56   ` Yuan Yao
                     ` (2 more replies)
  2024-08-13  5:12 ` [PATCH v2 2/2] KVM: x86: Use is_kvm_hc_exit_enabled() instead of opencode Binbin Wu
  1 sibling, 3 replies; 19+ messages in thread
From: Binbin Wu @ 2024-08-13  5:12 UTC (permalink / raw)
  To: kvm, linux-kernel
  Cc: pbonzini, seanjc, isaku.yamahata, rick.p.edgecombe, michael.roth,
	binbin.wu

Check whether a KVM hypercall needs to exit to userspace or not based on
hypercall_exit_enabled field of struct kvm_arch.

Userspace can request a hypercall to exit to userspace for handling by
enable KVM_CAP_EXIT_HYPERCALL and the enabled hypercall will be set in
hypercall_exit_enabled.  Make the check code generic based on it.

Signed-off-by: Binbin Wu <binbin.wu@linux.intel.com>
---
 arch/x86/kvm/x86.c | 4 ++--
 arch/x86/kvm/x86.h | 7 +++++++
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index af6c8cf6a37a..6e16c9751af7 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -10226,8 +10226,8 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
 	cpl = kvm_x86_call(get_cpl)(vcpu);
 
 	ret = __kvm_emulate_hypercall(vcpu, nr, a0, a1, a2, a3, op_64_bit, cpl);
-	if (nr == KVM_HC_MAP_GPA_RANGE && !ret)
-		/* MAP_GPA tosses the request to the user space. */
+	if (!ret && is_kvm_hc_exit_enabled(vcpu->kvm, nr))
+		/* The hypercall is requested to exit to userspace. */
 		return 0;
 
 	if (!op_64_bit)
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
index 50596f6f8320..0cbec76b42e6 100644
--- a/arch/x86/kvm/x86.h
+++ b/arch/x86/kvm/x86.h
@@ -547,4 +547,11 @@ int kvm_sev_es_string_io(struct kvm_vcpu *vcpu, unsigned int size,
 			 unsigned int port, void *data,  unsigned int count,
 			 int in);
 
+static inline bool is_kvm_hc_exit_enabled(struct kvm *kvm, unsigned long hc_nr)
+{
+	if(WARN_ON_ONCE(hc_nr >= sizeof(kvm->arch.hypercall_exit_enabled) * 8))
+		return false;
+
+	return kvm->arch.hypercall_exit_enabled & (1 << hc_nr);
+}
 #endif
-- 
2.43.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v2 2/2] KVM: x86: Use is_kvm_hc_exit_enabled() instead of opencode
  2024-08-13  5:12 [PATCH v2 0/2] KVM: x86: Check hypercall's exit to userspace generically Binbin Wu
  2024-08-13  5:12 ` [PATCH v2 1/2] " Binbin Wu
@ 2024-08-13  5:12 ` Binbin Wu
  2024-08-13 17:51   ` Isaku Yamahata
  2024-08-13 23:18   ` Huang, Kai
  1 sibling, 2 replies; 19+ messages in thread
From: Binbin Wu @ 2024-08-13  5:12 UTC (permalink / raw)
  To: kvm, linux-kernel
  Cc: pbonzini, seanjc, isaku.yamahata, rick.p.edgecombe, michael.roth,
	binbin.wu

Use is_kvm_hc_exit_enabled() instead of opencode.

No functional change intended.

Signed-off-by: Binbin Wu <binbin.wu@linux.intel.com>
---
 arch/x86/kvm/svm/sev.c | 4 ++--
 arch/x86/kvm/x86.c     | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index a16c873b3232..d622aab8351d 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -3635,7 +3635,7 @@ static int snp_begin_psc_msr(struct vcpu_svm *svm, u64 ghcb_msr)
 		return 1; /* resume guest */
 	}
 
-	if (!(vcpu->kvm->arch.hypercall_exit_enabled & (1 << KVM_HC_MAP_GPA_RANGE))) {
+	if (!is_kvm_hc_exit_enabled(vcpu->kvm, KVM_HC_MAP_GPA_RANGE)) {
 		set_ghcb_msr(svm, GHCB_MSR_PSC_RESP_ERROR);
 		return 1; /* resume guest */
 	}
@@ -3718,7 +3718,7 @@ static int snp_begin_psc(struct vcpu_svm *svm, struct psc_buffer *psc)
 	bool huge;
 	u64 gfn;
 
-	if (!(vcpu->kvm->arch.hypercall_exit_enabled & (1 << KVM_HC_MAP_GPA_RANGE))) {
+	if (!is_kvm_hc_exit_enabled(vcpu->kvm, KVM_HC_MAP_GPA_RANGE)) {
 		snp_complete_psc(svm, VMGEXIT_PSC_ERROR_GENERIC);
 		return 1;
 	}
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 6e16c9751af7..9857c1984ef7 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -10171,7 +10171,7 @@ unsigned long __kvm_emulate_hypercall(struct kvm_vcpu *vcpu, unsigned long nr,
 		u64 gpa = a0, npages = a1, attrs = a2;
 
 		ret = -KVM_ENOSYS;
-		if (!(vcpu->kvm->arch.hypercall_exit_enabled & (1 << KVM_HC_MAP_GPA_RANGE)))
+		if (!is_kvm_hc_exit_enabled(vcpu->kvm, KVM_HC_MAP_GPA_RANGE))
 			break;
 
 		if (!PAGE_ALIGNED(gpa) || !npages ||
-- 
2.43.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/2] KVM: x86: Check hypercall's exit to userspace generically
  2024-08-13  5:12 ` [PATCH v2 1/2] " Binbin Wu
@ 2024-08-13  5:56   ` Yuan Yao
  2024-08-13  6:14     ` Yuan Yao
  2024-08-13 17:50   ` Isaku Yamahata
  2024-08-13 23:16   ` Huang, Kai
  2 siblings, 1 reply; 19+ messages in thread
From: Yuan Yao @ 2024-08-13  5:56 UTC (permalink / raw)
  To: Binbin Wu
  Cc: kvm, linux-kernel, pbonzini, seanjc, isaku.yamahata,
	rick.p.edgecombe, michael.roth

On Tue, Aug 13, 2024 at 01:12:55PM +0800, Binbin Wu wrote:
> Check whether a KVM hypercall needs to exit to userspace or not based on
> hypercall_exit_enabled field of struct kvm_arch.
>
> Userspace can request a hypercall to exit to userspace for handling by
> enable KVM_CAP_EXIT_HYPERCALL and the enabled hypercall will be set in
> hypercall_exit_enabled.  Make the check code generic based on it.
>
> Signed-off-by: Binbin Wu <binbin.wu@linux.intel.com>
> ---
>  arch/x86/kvm/x86.c | 4 ++--
>  arch/x86/kvm/x86.h | 7 +++++++
>  2 files changed, 9 insertions(+), 2 deletions(-)
>
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index af6c8cf6a37a..6e16c9751af7 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -10226,8 +10226,8 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
>  	cpl = kvm_x86_call(get_cpl)(vcpu);
>
>  	ret = __kvm_emulate_hypercall(vcpu, nr, a0, a1, a2, a3, op_64_bit, cpl);
> -	if (nr == KVM_HC_MAP_GPA_RANGE && !ret)
> -		/* MAP_GPA tosses the request to the user space. */
> +	if (!ret && is_kvm_hc_exit_enabled(vcpu->kvm, nr))
> +		/* The hypercall is requested to exit to userspace. */
>  		return 0;
>
>  	if (!op_64_bit)
> diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
> index 50596f6f8320..0cbec76b42e6 100644
> --- a/arch/x86/kvm/x86.h
> +++ b/arch/x86/kvm/x86.h
> @@ -547,4 +547,11 @@ int kvm_sev_es_string_io(struct kvm_vcpu *vcpu, unsigned int size,
>  			 unsigned int port, void *data,  unsigned int count,
>  			 int in);
>
> +static inline bool is_kvm_hc_exit_enabled(struct kvm *kvm, unsigned long hc_nr)
> +{
> +	if(WARN_ON_ONCE(hc_nr >= sizeof(kvm->arch.hypercall_exit_enabled) * 8))

How about:

if (!(BIT(hc_nr) & KVM_EXIT_HYPERCALL_VALID_MASK))

KVM_EXIT_HYPERCALL_VALID_MASK is used to guard kvm->arch.hypercall_exit_enabled
on KVM_CAP_EXIT_HYPERCALL, "hc_nr > maximum supported hc" AND "hc_nr <=
bit_count(kvm->arch.hypercall_exit_enabled)" should be treated as invalid yet to
me.

> +		return false;
> +
> +	return kvm->arch.hypercall_exit_enabled & (1 << hc_nr);

BIT(xx) instead of "1 << hc_nr" for better readability.

> +}
>  #endif
> --
> 2.43.2
>
>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/2] KVM: x86: Check hypercall's exit to userspace generically
  2024-08-13  5:56   ` Yuan Yao
@ 2024-08-13  6:14     ` Yuan Yao
  0 siblings, 0 replies; 19+ messages in thread
From: Yuan Yao @ 2024-08-13  6:14 UTC (permalink / raw)
  To: Binbin Wu
  Cc: kvm, linux-kernel, pbonzini, seanjc, isaku.yamahata,
	rick.p.edgecombe, michael.roth

On Tue, Aug 13, 2024 at 01:56:14PM +0800, Yuan Yao wrote:
> On Tue, Aug 13, 2024 at 01:12:55PM +0800, Binbin Wu wrote:
> > Check whether a KVM hypercall needs to exit to userspace or not based on
> > hypercall_exit_enabled field of struct kvm_arch.
> >
> > Userspace can request a hypercall to exit to userspace for handling by
> > enable KVM_CAP_EXIT_HYPERCALL and the enabled hypercall will be set in
> > hypercall_exit_enabled.  Make the check code generic based on it.
> >
> > Signed-off-by: Binbin Wu <binbin.wu@linux.intel.com>
> > ---
> >  arch/x86/kvm/x86.c | 4 ++--
> >  arch/x86/kvm/x86.h | 7 +++++++
> >  2 files changed, 9 insertions(+), 2 deletions(-)
> >
> > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> > index af6c8cf6a37a..6e16c9751af7 100644
> > --- a/arch/x86/kvm/x86.c
> > +++ b/arch/x86/kvm/x86.c
> > @@ -10226,8 +10226,8 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
> >  	cpl = kvm_x86_call(get_cpl)(vcpu);
> >
> >  	ret = __kvm_emulate_hypercall(vcpu, nr, a0, a1, a2, a3, op_64_bit, cpl);
> > -	if (nr == KVM_HC_MAP_GPA_RANGE && !ret)
> > -		/* MAP_GPA tosses the request to the user space. */
> > +	if (!ret && is_kvm_hc_exit_enabled(vcpu->kvm, nr))
> > +		/* The hypercall is requested to exit to userspace. */
> >  		return 0;
> >
> >  	if (!op_64_bit)
> > diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
> > index 50596f6f8320..0cbec76b42e6 100644
> > --- a/arch/x86/kvm/x86.h
> > +++ b/arch/x86/kvm/x86.h
> > @@ -547,4 +547,11 @@ int kvm_sev_es_string_io(struct kvm_vcpu *vcpu, unsigned int size,
> >  			 unsigned int port, void *data,  unsigned int count,
> >  			 int in);
> >
> > +static inline bool is_kvm_hc_exit_enabled(struct kvm *kvm, unsigned long hc_nr)
> > +{
> > +	if(WARN_ON_ONCE(hc_nr >= sizeof(kvm->arch.hypercall_exit_enabled) * 8))
>
> How about:
>
> if (!(BIT(hc_nr) & KVM_EXIT_HYPERCALL_VALID_MASK))
>
> KVM_EXIT_HYPERCALL_VALID_MASK is used to guard kvm->arch.hypercall_exit_enabled
> on KVM_CAP_EXIT_HYPERCALL, "hc_nr > maximum supported hc" AND "hc_nr <=
> bit_count(kvm->arch.hypercall_exit_enabled)" should be treated as invalid yet to
> me.

Not real good idea. Rely on hypercall_exit_enabled is good enough, this brings
unnecessary complexity.

>
> > +		return false;
> > +
> > +	return kvm->arch.hypercall_exit_enabled & (1 << hc_nr);
>
> BIT(xx) instead of "1 << hc_nr" for better readability.
>
> > +}
> >  #endif
> > --
> > 2.43.2
> >
> >
>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/2] KVM: x86: Check hypercall's exit to userspace generically
  2024-08-13  5:12 ` [PATCH v2 1/2] " Binbin Wu
  2024-08-13  5:56   ` Yuan Yao
@ 2024-08-13 17:50   ` Isaku Yamahata
  2024-08-13 23:11     ` Huang, Kai
  2024-08-13 23:16   ` Huang, Kai
  2 siblings, 1 reply; 19+ messages in thread
From: Isaku Yamahata @ 2024-08-13 17:50 UTC (permalink / raw)
  To: Binbin Wu
  Cc: kvm, linux-kernel, pbonzini, seanjc, isaku.yamahata,
	rick.p.edgecombe, michael.roth

On Tue, Aug 13, 2024 at 01:12:55PM +0800,
Binbin Wu <binbin.wu@linux.intel.com> wrote:

> Check whether a KVM hypercall needs to exit to userspace or not based on
> hypercall_exit_enabled field of struct kvm_arch.
> 
> Userspace can request a hypercall to exit to userspace for handling by
> enable KVM_CAP_EXIT_HYPERCALL and the enabled hypercall will be set in
> hypercall_exit_enabled.  Make the check code generic based on it.
> 
> Signed-off-by: Binbin Wu <binbin.wu@linux.intel.com>
> ---
>  arch/x86/kvm/x86.c | 4 ++--
>  arch/x86/kvm/x86.h | 7 +++++++
>  2 files changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index af6c8cf6a37a..6e16c9751af7 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -10226,8 +10226,8 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
>  	cpl = kvm_x86_call(get_cpl)(vcpu);
>  
>  	ret = __kvm_emulate_hypercall(vcpu, nr, a0, a1, a2, a3, op_64_bit, cpl);
> -	if (nr == KVM_HC_MAP_GPA_RANGE && !ret)
> -		/* MAP_GPA tosses the request to the user space. */
> +	if (!ret && is_kvm_hc_exit_enabled(vcpu->kvm, nr))
> +		/* The hypercall is requested to exit to userspace. */
>  		return 0;
>  
>  	if (!op_64_bit)
> diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
> index 50596f6f8320..0cbec76b42e6 100644
> --- a/arch/x86/kvm/x86.h
> +++ b/arch/x86/kvm/x86.h
> @@ -547,4 +547,11 @@ int kvm_sev_es_string_io(struct kvm_vcpu *vcpu, unsigned int size,
>  			 unsigned int port, void *data,  unsigned int count,
>  			 int in);
>  
> +static inline bool is_kvm_hc_exit_enabled(struct kvm *kvm, unsigned long hc_nr)
> +{
> +	if(WARN_ON_ONCE(hc_nr >= sizeof(kvm->arch.hypercall_exit_enabled) * 8))
> +		return false;

Is this to detect potential bug? Maybe
BUILD_BUG_ON(__builtin_constant_p(hc_nr) &&
             !(BIT(hc_nr) & KVM_EXIT_HYPERCALL_VALID_MASK));
Overkill?
-- 
Isaku Yamahata <isaku.yamahata@intel.com>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 2/2] KVM: x86: Use is_kvm_hc_exit_enabled() instead of opencode
  2024-08-13  5:12 ` [PATCH v2 2/2] KVM: x86: Use is_kvm_hc_exit_enabled() instead of opencode Binbin Wu
@ 2024-08-13 17:51   ` Isaku Yamahata
  2024-08-13 23:18   ` Huang, Kai
  1 sibling, 0 replies; 19+ messages in thread
From: Isaku Yamahata @ 2024-08-13 17:51 UTC (permalink / raw)
  To: Binbin Wu
  Cc: kvm, linux-kernel, pbonzini, seanjc, isaku.yamahata,
	rick.p.edgecombe, michael.roth

On Tue, Aug 13, 2024 at 01:12:56PM +0800,
Binbin Wu <binbin.wu@linux.intel.com> wrote:

> Use is_kvm_hc_exit_enabled() instead of opencode.
> 
> No functional change intended.
> 
> Signed-off-by: Binbin Wu <binbin.wu@linux.intel.com>
> ---
>  arch/x86/kvm/svm/sev.c | 4 ++--
>  arch/x86/kvm/x86.c     | 2 +-
>  2 files changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
> index a16c873b3232..d622aab8351d 100644
> --- a/arch/x86/kvm/svm/sev.c
> +++ b/arch/x86/kvm/svm/sev.c
> @@ -3635,7 +3635,7 @@ static int snp_begin_psc_msr(struct vcpu_svm *svm, u64 ghcb_msr)
>  		return 1; /* resume guest */
>  	}
>  
> -	if (!(vcpu->kvm->arch.hypercall_exit_enabled & (1 << KVM_HC_MAP_GPA_RANGE))) {
> +	if (!is_kvm_hc_exit_enabled(vcpu->kvm, KVM_HC_MAP_GPA_RANGE)) {
>  		set_ghcb_msr(svm, GHCB_MSR_PSC_RESP_ERROR);
>  		return 1; /* resume guest */
>  	}
> @@ -3718,7 +3718,7 @@ static int snp_begin_psc(struct vcpu_svm *svm, struct psc_buffer *psc)
>  	bool huge;
>  	u64 gfn;
>  
> -	if (!(vcpu->kvm->arch.hypercall_exit_enabled & (1 << KVM_HC_MAP_GPA_RANGE))) {
> +	if (!is_kvm_hc_exit_enabled(vcpu->kvm, KVM_HC_MAP_GPA_RANGE)) {
>  		snp_complete_psc(svm, VMGEXIT_PSC_ERROR_GENERIC);
>  		return 1;
>  	}
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 6e16c9751af7..9857c1984ef7 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -10171,7 +10171,7 @@ unsigned long __kvm_emulate_hypercall(struct kvm_vcpu *vcpu, unsigned long nr,
>  		u64 gpa = a0, npages = a1, attrs = a2;
>  
>  		ret = -KVM_ENOSYS;
> -		if (!(vcpu->kvm->arch.hypercall_exit_enabled & (1 << KVM_HC_MAP_GPA_RANGE)))
> +		if (!is_kvm_hc_exit_enabled(vcpu->kvm, KVM_HC_MAP_GPA_RANGE))
>  			break;
>  
>  		if (!PAGE_ALIGNED(gpa) || !npages ||
> -- 
> 2.43.2
> 
> 

Reviewed-by: Isaku Yamahata <isaku.yamahata@intel.com>
-- 
Isaku Yamahata <isaku.yamahata@intel.com>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/2] KVM: x86: Check hypercall's exit to userspace generically
  2024-08-13 17:50   ` Isaku Yamahata
@ 2024-08-13 23:11     ` Huang, Kai
  2024-08-14  0:52       ` Isaku Yamahata
  0 siblings, 1 reply; 19+ messages in thread
From: Huang, Kai @ 2024-08-13 23:11 UTC (permalink / raw)
  To: Isaku Yamahata, Binbin Wu
  Cc: kvm, linux-kernel, pbonzini, seanjc, rick.p.edgecombe,
	michael.roth



On 14/08/2024 5:50 am, Isaku Yamahata wrote:
> On Tue, Aug 13, 2024 at 01:12:55PM +0800,
> Binbin Wu <binbin.wu@linux.intel.com> wrote:
> 
>> Check whether a KVM hypercall needs to exit to userspace or not based on
>> hypercall_exit_enabled field of struct kvm_arch.
>>
>> Userspace can request a hypercall to exit to userspace for handling by
>> enable KVM_CAP_EXIT_HYPERCALL and the enabled hypercall will be set in
>> hypercall_exit_enabled.  Make the check code generic based on it.
>>
>> Signed-off-by: Binbin Wu <binbin.wu@linux.intel.com>
>> ---
>>   arch/x86/kvm/x86.c | 4 ++--
>>   arch/x86/kvm/x86.h | 7 +++++++
>>   2 files changed, 9 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
>> index af6c8cf6a37a..6e16c9751af7 100644
>> --- a/arch/x86/kvm/x86.c
>> +++ b/arch/x86/kvm/x86.c
>> @@ -10226,8 +10226,8 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
>>   	cpl = kvm_x86_call(get_cpl)(vcpu);
>>   
>>   	ret = __kvm_emulate_hypercall(vcpu, nr, a0, a1, a2, a3, op_64_bit, cpl);
>> -	if (nr == KVM_HC_MAP_GPA_RANGE && !ret)
>> -		/* MAP_GPA tosses the request to the user space. */
>> +	if (!ret && is_kvm_hc_exit_enabled(vcpu->kvm, nr))
>> +		/* The hypercall is requested to exit to userspace. */
>>   		return 0;
>>   
>>   	if (!op_64_bit)
>> diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
>> index 50596f6f8320..0cbec76b42e6 100644
>> --- a/arch/x86/kvm/x86.h
>> +++ b/arch/x86/kvm/x86.h
>> @@ -547,4 +547,11 @@ int kvm_sev_es_string_io(struct kvm_vcpu *vcpu, unsigned int size,
>>   			 unsigned int port, void *data,  unsigned int count,
>>   			 int in);
>>   
>> +static inline bool is_kvm_hc_exit_enabled(struct kvm *kvm, unsigned long hc_nr)
>> +{
>> +	if(WARN_ON_ONCE(hc_nr >= sizeof(kvm->arch.hypercall_exit_enabled) * 8))
>> +		return false;
> 
> Is this to detect potential bug? Maybe
> BUILD_BUG_ON(__builtin_constant_p(hc_nr) &&
>               !(BIT(hc_nr) & KVM_EXIT_HYPERCALL_VALID_MASK));
> Overkill?

I don't think this is the correct way to use __builtin_constant_p(), 
i.e. it doesn't make sense to use __builtin_constant_p() in BUILD_BUG_ON().

IIUC you need some build time guarantee here, but __builtin_constant_p() 
can return false, in which case the above BUILD_BUG_ON() does nothing, 
which defeats the purpose.

On the other hand, albeit WARN_ON_ONCE() is runtime check, but it is 
always there.

In fact, the @hc_nr (or @nr) in the kvm_emulate_hypercall() is read from 
the RAX register:

         nr = kvm_rax_read(vcpu);

So I don't see how the compiler can be smart enough to determine the 
value at compile time.

In fact, I tried to build by removing the __builtin_constant_p() but got 
below error (sorry for text wrap but you can see the error I believe).

root@server:/home/kai/tdx/linux# make M=arch/x86/kvm/ W=1
   CC [M]  arch/x86/kvm/x86.o
In file included from <command-line>:
In function ‘is_kvm_hc_exit_enabled’,
     inlined from ‘kvm_emulate_hypercall’ at arch/x86/kvm/x86.c:10254:14:
././include/linux/compiler_types.h:510:45: error: call to 
‘__compiletime_assert_3873’ declared with attribute error: BUILD_BUG_ON 
failed: !(BIT(hc_nr) & KVM_EXIT_HYPERCALL_VALID_MASK)
   510 |         _compiletime_assert(condition, msg, 
__compiletime_assert_, __COUNTER__)
       |                                             ^



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/2] KVM: x86: Check hypercall's exit to userspace generically
  2024-08-13  5:12 ` [PATCH v2 1/2] " Binbin Wu
  2024-08-13  5:56   ` Yuan Yao
  2024-08-13 17:50   ` Isaku Yamahata
@ 2024-08-13 23:16   ` Huang, Kai
  2024-08-14  0:53     ` Isaku Yamahata
  2024-08-14  1:08     ` Binbin Wu
  2 siblings, 2 replies; 19+ messages in thread
From: Huang, Kai @ 2024-08-13 23:16 UTC (permalink / raw)
  To: Binbin Wu, kvm, linux-kernel
  Cc: pbonzini, seanjc, isaku.yamahata, rick.p.edgecombe, michael.roth



On 13/08/2024 5:12 pm, Binbin Wu wrote:
> Check whether a KVM hypercall needs to exit to userspace or not based on
> hypercall_exit_enabled field of struct kvm_arch.
> 
> Userspace can request a hypercall to exit to userspace for handling by
> enable KVM_CAP_EXIT_HYPERCALL and the enabled hypercall will be set in
> hypercall_exit_enabled.  Make the check code generic based on it.
> 
> Signed-off-by: Binbin Wu <binbin.wu@linux.intel.com>

Reviewed-by: Kai Huang <kai.huang@intel.com>

One nitpicking below:

> ---
>   arch/x86/kvm/x86.c | 4 ++--
>   arch/x86/kvm/x86.h | 7 +++++++
>   2 files changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index af6c8cf6a37a..6e16c9751af7 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -10226,8 +10226,8 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
>   	cpl = kvm_x86_call(get_cpl)(vcpu);
>   
>   	ret = __kvm_emulate_hypercall(vcpu, nr, a0, a1, a2, a3, op_64_bit, cpl);
> -	if (nr == KVM_HC_MAP_GPA_RANGE && !ret)
> -		/* MAP_GPA tosses the request to the user space. */
> +	if (!ret && is_kvm_hc_exit_enabled(vcpu->kvm, nr))
> +		/* The hypercall is requested to exit to userspace. */
>   		return 0;

I believe you put "!ret" check first for a reason?  Perhaps you can add 
a comment.


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 2/2] KVM: x86: Use is_kvm_hc_exit_enabled() instead of opencode
  2024-08-13  5:12 ` [PATCH v2 2/2] KVM: x86: Use is_kvm_hc_exit_enabled() instead of opencode Binbin Wu
  2024-08-13 17:51   ` Isaku Yamahata
@ 2024-08-13 23:18   ` Huang, Kai
  2024-08-19 10:07     ` Binbin Wu
  1 sibling, 1 reply; 19+ messages in thread
From: Huang, Kai @ 2024-08-13 23:18 UTC (permalink / raw)
  To: Binbin Wu, kvm, linux-kernel
  Cc: pbonzini, seanjc, isaku.yamahata, rick.p.edgecombe, michael.roth



On 13/08/2024 5:12 pm, Binbin Wu wrote:
> Use is_kvm_hc_exit_enabled() instead of opencode.
> 
> No functional change intended.

It would be helpful to mention currently hypercall_exit_enabled  can 
only have KVM_HC_MAP_GPA_RANGE bit set (so that there will be no 
functional change).

> 
> Signed-off-by: Binbin Wu <binbin.wu@linux.intel.com>

Reviewed-by: Kai Huang <kai.huang@intel.com>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/2] KVM: x86: Check hypercall's exit to userspace generically
  2024-08-13 23:11     ` Huang, Kai
@ 2024-08-14  0:52       ` Isaku Yamahata
  2024-08-14  1:27         ` Binbin Wu
  2024-08-14  1:31         ` Sean Christopherson
  0 siblings, 2 replies; 19+ messages in thread
From: Isaku Yamahata @ 2024-08-14  0:52 UTC (permalink / raw)
  To: Huang, Kai
  Cc: Isaku Yamahata, Binbin Wu, kvm, linux-kernel, pbonzini, seanjc,
	rick.p.edgecombe, michael.roth

On Wed, Aug 14, 2024 at 11:11:29AM +1200,
"Huang, Kai" <kai.huang@intel.com> wrote:

> 
> 
> On 14/08/2024 5:50 am, Isaku Yamahata wrote:
> > On Tue, Aug 13, 2024 at 01:12:55PM +0800,
> > Binbin Wu <binbin.wu@linux.intel.com> wrote:
> > 
> > > Check whether a KVM hypercall needs to exit to userspace or not based on
> > > hypercall_exit_enabled field of struct kvm_arch.
> > > 
> > > Userspace can request a hypercall to exit to userspace for handling by
> > > enable KVM_CAP_EXIT_HYPERCALL and the enabled hypercall will be set in
> > > hypercall_exit_enabled.  Make the check code generic based on it.
> > > 
> > > Signed-off-by: Binbin Wu <binbin.wu@linux.intel.com>
> > > ---
> > >   arch/x86/kvm/x86.c | 4 ++--
> > >   arch/x86/kvm/x86.h | 7 +++++++
> > >   2 files changed, 9 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> > > index af6c8cf6a37a..6e16c9751af7 100644
> > > --- a/arch/x86/kvm/x86.c
> > > +++ b/arch/x86/kvm/x86.c
> > > @@ -10226,8 +10226,8 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
> > >   	cpl = kvm_x86_call(get_cpl)(vcpu);
> > >   	ret = __kvm_emulate_hypercall(vcpu, nr, a0, a1, a2, a3, op_64_bit, cpl);
> > > -	if (nr == KVM_HC_MAP_GPA_RANGE && !ret)
> > > -		/* MAP_GPA tosses the request to the user space. */
> > > +	if (!ret && is_kvm_hc_exit_enabled(vcpu->kvm, nr))
> > > +		/* The hypercall is requested to exit to userspace. */
> > >   		return 0;
> > >   	if (!op_64_bit)
> > > diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
> > > index 50596f6f8320..0cbec76b42e6 100644
> > > --- a/arch/x86/kvm/x86.h
> > > +++ b/arch/x86/kvm/x86.h
> > > @@ -547,4 +547,11 @@ int kvm_sev_es_string_io(struct kvm_vcpu *vcpu, unsigned int size,
> > >   			 unsigned int port, void *data,  unsigned int count,
> > >   			 int in);
> > > +static inline bool is_kvm_hc_exit_enabled(struct kvm *kvm, unsigned long hc_nr)
> > > +{
> > > +	if(WARN_ON_ONCE(hc_nr >= sizeof(kvm->arch.hypercall_exit_enabled) * 8))
> > > +		return false;
> > 
> > Is this to detect potential bug? Maybe
> > BUILD_BUG_ON(__builtin_constant_p(hc_nr) &&
> >               !(BIT(hc_nr) & KVM_EXIT_HYPERCALL_VALID_MASK));
> > Overkill?
> 
> I don't think this is the correct way to use __builtin_constant_p(), i.e. it
> doesn't make sense to use __builtin_constant_p() in BUILD_BUG_ON().
> 
> IIUC you need some build time guarantee here, but __builtin_constant_p() can
> return false, in which case the above BUILD_BUG_ON() does nothing, which
> defeats the purpose.

It depends on what we'd like to detect.  BUILT_BUG_ON(__builtin_constant_p())
can detect the usage in the patch 2/2,
is_kvm_hc_exit_enabled(vcpu->kvm, KVM_HC_MAP_GPA_RANGE).  The potential
future use of is_kvm_hc_exit_enabled(, KVM_HC_MAP_future_hypercall).

Although this version doesn't help for the one in kvm_emulate_hypercall(),
!ret check is done first to avoid WARN_ON_ONCE() to hit here.

Maybe we can just drop this WARN_ON_ONCE().
-- 
Isaku Yamahata <isaku.yamahata@intel.com>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/2] KVM: x86: Check hypercall's exit to userspace generically
  2024-08-13 23:16   ` Huang, Kai
@ 2024-08-14  0:53     ` Isaku Yamahata
  2024-08-14  1:08     ` Binbin Wu
  1 sibling, 0 replies; 19+ messages in thread
From: Isaku Yamahata @ 2024-08-14  0:53 UTC (permalink / raw)
  To: Huang, Kai
  Cc: Binbin Wu, kvm, linux-kernel, pbonzini, seanjc, isaku.yamahata,
	rick.p.edgecombe, michael.roth

On Wed, Aug 14, 2024 at 11:16:44AM +1200,
"Huang, Kai" <kai.huang@intel.com> wrote:

> > ---
> >   arch/x86/kvm/x86.c | 4 ++--
> >   arch/x86/kvm/x86.h | 7 +++++++
> >   2 files changed, 9 insertions(+), 2 deletions(-)
> > 
> > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> > index af6c8cf6a37a..6e16c9751af7 100644
> > --- a/arch/x86/kvm/x86.c
> > +++ b/arch/x86/kvm/x86.c
> > @@ -10226,8 +10226,8 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
> >   	cpl = kvm_x86_call(get_cpl)(vcpu);
> >   	ret = __kvm_emulate_hypercall(vcpu, nr, a0, a1, a2, a3, op_64_bit, cpl);
> > -	if (nr == KVM_HC_MAP_GPA_RANGE && !ret)
> > -		/* MAP_GPA tosses the request to the user space. */
> > +	if (!ret && is_kvm_hc_exit_enabled(vcpu->kvm, nr))
> > +		/* The hypercall is requested to exit to userspace. */
> >   		return 0;
> 
> I believe you put "!ret" check first for a reason?  Perhaps you can add a
> comment.

I think he'd like to avoid to hit WARN_ON_ONCE().
-- 
Isaku Yamahata <isaku.yamahata@intel.com>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/2] KVM: x86: Check hypercall's exit to userspace generically
  2024-08-13 23:16   ` Huang, Kai
  2024-08-14  0:53     ` Isaku Yamahata
@ 2024-08-14  1:08     ` Binbin Wu
  1 sibling, 0 replies; 19+ messages in thread
From: Binbin Wu @ 2024-08-14  1:08 UTC (permalink / raw)
  To: Huang, Kai, kvm, linux-kernel
  Cc: pbonzini, seanjc, isaku.yamahata, rick.p.edgecombe, michael.roth




On 8/14/2024 7:16 AM, Huang, Kai wrote:
>
>
> On 13/08/2024 5:12 pm, Binbin Wu wrote:
>> Check whether a KVM hypercall needs to exit to userspace or not based on
>> hypercall_exit_enabled field of struct kvm_arch.
>>
>> Userspace can request a hypercall to exit to userspace for handling by
>> enable KVM_CAP_EXIT_HYPERCALL and the enabled hypercall will be set in
>> hypercall_exit_enabled.  Make the check code generic based on it.
>>
>> Signed-off-by: Binbin Wu <binbin.wu@linux.intel.com>
>
> Reviewed-by: Kai Huang <kai.huang@intel.com>
>
> One nitpicking below:
>
>> ---
>>   arch/x86/kvm/x86.c | 4 ++--
>>   arch/x86/kvm/x86.h | 7 +++++++
>>   2 files changed, 9 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
>> index af6c8cf6a37a..6e16c9751af7 100644
>> --- a/arch/x86/kvm/x86.c
>> +++ b/arch/x86/kvm/x86.c
>> @@ -10226,8 +10226,8 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
>>       cpl = kvm_x86_call(get_cpl)(vcpu);
>>         ret = __kvm_emulate_hypercall(vcpu, nr, a0, a1, a2, a3, 
>> op_64_bit, cpl);
>> -    if (nr == KVM_HC_MAP_GPA_RANGE && !ret)
>> -        /* MAP_GPA tosses the request to the user space. */
>> +    if (!ret && is_kvm_hc_exit_enabled(vcpu->kvm, nr))
>> +        /* The hypercall is requested to exit to userspace. */
>>           return 0;
>
> I believe you put "!ret" check first for a reason?  Perhaps you can 
> add a comment.
>
>
Yes, check "!ret" first to make sure the input of 
is_kvm_hc_exit_enabled() is a valid KVM_HC_*.
Will add a comment.
Thanks.


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/2] KVM: x86: Check hypercall's exit to userspace generically
  2024-08-14  0:52       ` Isaku Yamahata
@ 2024-08-14  1:27         ` Binbin Wu
  2024-08-14  1:31         ` Sean Christopherson
  1 sibling, 0 replies; 19+ messages in thread
From: Binbin Wu @ 2024-08-14  1:27 UTC (permalink / raw)
  To: Isaku Yamahata, Huang, Kai
  Cc: kvm, linux-kernel, pbonzini, seanjc, rick.p.edgecombe,
	michael.roth




On 8/14/2024 8:52 AM, Isaku Yamahata wrote:
> On Wed, Aug 14, 2024 at 11:11:29AM +1200,
> "Huang, Kai" <kai.huang@intel.com> wrote:
>
>>
>> On 14/08/2024 5:50 am, Isaku Yamahata wrote:
>>> On Tue, Aug 13, 2024 at 01:12:55PM +0800,
>>> Binbin Wu <binbin.wu@linux.intel.com> wrote:
>>>
>>>> Check whether a KVM hypercall needs to exit to userspace or not based on
>>>> hypercall_exit_enabled field of struct kvm_arch.
>>>>
>>>> Userspace can request a hypercall to exit to userspace for handling by
>>>> enable KVM_CAP_EXIT_HYPERCALL and the enabled hypercall will be set in
>>>> hypercall_exit_enabled.  Make the check code generic based on it.
>>>>
>>>> Signed-off-by: Binbin Wu <binbin.wu@linux.intel.com>
>>>> ---
>>>>    arch/x86/kvm/x86.c | 4 ++--
>>>>    arch/x86/kvm/x86.h | 7 +++++++
>>>>    2 files changed, 9 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
>>>> index af6c8cf6a37a..6e16c9751af7 100644
>>>> --- a/arch/x86/kvm/x86.c
>>>> +++ b/arch/x86/kvm/x86.c
>>>> @@ -10226,8 +10226,8 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
>>>>    	cpl = kvm_x86_call(get_cpl)(vcpu);
>>>>    	ret = __kvm_emulate_hypercall(vcpu, nr, a0, a1, a2, a3, op_64_bit, cpl);
>>>> -	if (nr == KVM_HC_MAP_GPA_RANGE && !ret)
>>>> -		/* MAP_GPA tosses the request to the user space. */
>>>> +	if (!ret && is_kvm_hc_exit_enabled(vcpu->kvm, nr))
>>>> +		/* The hypercall is requested to exit to userspace. */
>>>>    		return 0;
>>>>    	if (!op_64_bit)
>>>> diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
>>>> index 50596f6f8320..0cbec76b42e6 100644
>>>> --- a/arch/x86/kvm/x86.h
>>>> +++ b/arch/x86/kvm/x86.h
>>>> @@ -547,4 +547,11 @@ int kvm_sev_es_string_io(struct kvm_vcpu *vcpu, unsigned int size,
>>>>    			 unsigned int port, void *data,  unsigned int count,
>>>>    			 int in);
>>>> +static inline bool is_kvm_hc_exit_enabled(struct kvm *kvm, unsigned long hc_nr)
>>>> +{
>>>> +	if(WARN_ON_ONCE(hc_nr >= sizeof(kvm->arch.hypercall_exit_enabled) * 8))
>>>> +		return false;
>>> Is this to detect potential bug? Maybe
>>> BUILD_BUG_ON(__builtin_constant_p(hc_nr) &&
>>>                !(BIT(hc_nr) & KVM_EXIT_HYPERCALL_VALID_MASK));
>>> Overkill?
My intention was to catch issue when KVM_HC_* grows and exceeds 32.
I was looking a compile time check, but didn't find a proper one.

>> I don't think this is the correct way to use __builtin_constant_p(), i.e. it
>> doesn't make sense to use __builtin_constant_p() in BUILD_BUG_ON().
>>
>> IIUC you need some build time guarantee here, but __builtin_constant_p() can
>> return false, in which case the above BUILD_BUG_ON() does nothing, which
>> defeats the purpose.
> It depends on what we'd like to detect.  BUILT_BUG_ON(__builtin_constant_p())
> can detect the usage in the patch 2/2,
> is_kvm_hc_exit_enabled(vcpu->kvm, KVM_HC_MAP_GPA_RANGE).  The potential
> future use of is_kvm_hc_exit_enabled(, KVM_HC_MAP_future_hypercall).
>
> Although this version doesn't help for the one in kvm_emulate_hypercall(),
> !ret check is done first to avoid WARN_ON_ONCE() to hit here.
Even !ret is checked first, it's still possible to hit the warning
if KVM_HC_furture_hypercall >=32.

>
> Maybe we can just drop this WARN_ON_ONCE().

Agree that a warning may not be a good option.
What I wanted to guarantee was that "KVM_HC_* < 32" when
hypercall_exit_enabled is u32.


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/2] KVM: x86: Check hypercall's exit to userspace generically
  2024-08-14  0:52       ` Isaku Yamahata
  2024-08-14  1:27         ` Binbin Wu
@ 2024-08-14  1:31         ` Sean Christopherson
  2024-08-14  2:36           ` Huang, Kai
  2024-08-14  4:59           ` Binbin Wu
  1 sibling, 2 replies; 19+ messages in thread
From: Sean Christopherson @ 2024-08-14  1:31 UTC (permalink / raw)
  To: Isaku Yamahata
  Cc: Kai Huang, Binbin Wu, kvm, linux-kernel, pbonzini,
	rick.p.edgecombe, michael.roth

On Tue, Aug 13, 2024, Isaku Yamahata wrote:
> On Wed, Aug 14, 2024 at 11:11:29AM +1200,
> Kai Huang <kai.huang@intel.com> wrote:
> 
> > 
> > 
> > On 14/08/2024 5:50 am, Isaku Yamahata wrote:
> > > On Tue, Aug 13, 2024 at 01:12:55PM +0800,
> > > Binbin Wu <binbin.wu@linux.intel.com> wrote:
> > > 
> > > > Check whether a KVM hypercall needs to exit to userspace or not based on
> > > > hypercall_exit_enabled field of struct kvm_arch.
> > > > 
> > > > Userspace can request a hypercall to exit to userspace for handling by
> > > > enable KVM_CAP_EXIT_HYPERCALL and the enabled hypercall will be set in
> > > > hypercall_exit_enabled.  Make the check code generic based on it.
> > > > 
> > > > Signed-off-by: Binbin Wu <binbin.wu@linux.intel.com>
> > > > ---
> > > >   arch/x86/kvm/x86.c | 4 ++--
> > > >   arch/x86/kvm/x86.h | 7 +++++++
> > > >   2 files changed, 9 insertions(+), 2 deletions(-)
> > > > 
> > > > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> > > > index af6c8cf6a37a..6e16c9751af7 100644
> > > > --- a/arch/x86/kvm/x86.c
> > > > +++ b/arch/x86/kvm/x86.c
> > > > @@ -10226,8 +10226,8 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
> > > >   	cpl = kvm_x86_call(get_cpl)(vcpu);
> > > >   	ret = __kvm_emulate_hypercall(vcpu, nr, a0, a1, a2, a3, op_64_bit, cpl);
> > > > -	if (nr == KVM_HC_MAP_GPA_RANGE && !ret)
> > > > -		/* MAP_GPA tosses the request to the user space. */
> > > > +	if (!ret && is_kvm_hc_exit_enabled(vcpu->kvm, nr))
> > > > +		/* The hypercall is requested to exit to userspace. */
> > > >   		return 0;
> > > >   	if (!op_64_bit)
> > > > diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
> > > > index 50596f6f8320..0cbec76b42e6 100644
> > > > --- a/arch/x86/kvm/x86.h
> > > > +++ b/arch/x86/kvm/x86.h
> > > > @@ -547,4 +547,11 @@ int kvm_sev_es_string_io(struct kvm_vcpu *vcpu, unsigned int size,
> > > >   			 unsigned int port, void *data,  unsigned int count,
> > > >   			 int in);
> > > > +static inline bool is_kvm_hc_exit_enabled(struct kvm *kvm, unsigned long hc_nr)

I would rather have "hypercall" in the name, "hc" never jumps out to me as being
"hypercall". Maybe is_hypercall_exit_enabled(), user_exit_on_hypercall(), or just
exit_on_hypercall()?

I'd probably vote for user_exit_on_hypercall(), as that clarifies it's all about
exiting to userspace, not from the guest.

> > > > +{
> > > > +	if(WARN_ON_ONCE(hc_nr >= sizeof(kvm->arch.hypercall_exit_enabled) * 8))
> > > > +		return false;
> > > 
> > > Is this to detect potential bug? Maybe
> > > BUILD_BUG_ON(__builtin_constant_p(hc_nr) &&
> > >               !(BIT(hc_nr) & KVM_EXIT_HYPERCALL_VALID_MASK));
> > > Overkill?
> > 
> > I don't think this is the correct way to use __builtin_constant_p(), i.e. it
> > doesn't make sense to use __builtin_constant_p() in BUILD_BUG_ON().

KVM does use __builtin_constant_p() to effectively disable some assertions when
it's allowed (by KVM's arbitrary rules) to pass in a non-constant value.  E.g.
see all the vmcs_checkNN() helpers.  If we didn't waive the assertion for values
that aren't constant at compile-time, all of the segmentation code would need to
be unwound into switch statements.

But for things like guest_cpuid_has(), the rule is that the input must be a
compile-time constant.

> > IIUC you need some build time guarantee here, but __builtin_constant_p() can
> > return false, in which case the above BUILD_BUG_ON() does nothing, which
> > defeats the purpose.
> 
> It depends on what we'd like to detect.  BUILT_BUG_ON(__builtin_constant_p())
> can detect the usage in the patch 2/2,
> is_kvm_hc_exit_enabled(vcpu->kvm, KVM_HC_MAP_GPA_RANGE).  The potential
> future use of is_kvm_hc_exit_enabled(, KVM_HC_MAP_future_hypercall).
> 
> Although this version doesn't help for the one in kvm_emulate_hypercall(),
> !ret check is done first to avoid WARN_ON_ONCE() to hit here.
> 
> Maybe we can just drop this WARN_ON_ONCE().

Yeah, I think it makes sense to drop the WARN, otherwise I suspect we'll end up
dancing around the helper just to avoid the warning.

I'm 50/50 on the BUILD_BUG_ON().  One one hand, it's kinda overkill.  On the other
hand, it's zero generated code.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/2] KVM: x86: Check hypercall's exit to userspace generically
  2024-08-14  1:31         ` Sean Christopherson
@ 2024-08-14  2:36           ` Huang, Kai
  2024-08-14  4:59           ` Binbin Wu
  1 sibling, 0 replies; 19+ messages in thread
From: Huang, Kai @ 2024-08-14  2:36 UTC (permalink / raw)
  To: Sean Christopherson, Isaku Yamahata
  Cc: Binbin Wu, kvm, linux-kernel, pbonzini, rick.p.edgecombe,
	michael.roth


>>>>> +{
>>>>> +	if(WARN_ON_ONCE(hc_nr >= sizeof(kvm->arch.hypercall_exit_enabled) * 8))
>>>>> +		return false;
>>>>
>>>> Is this to detect potential bug? Maybe
>>>> BUILD_BUG_ON(__builtin_constant_p(hc_nr) &&
>>>>                !(BIT(hc_nr) & KVM_EXIT_HYPERCALL_VALID_MASK));
>>>> Overkill?
>>>
>>> I don't think this is the correct way to use __builtin_constant_p(), i.e. it
>>> doesn't make sense to use __builtin_constant_p() in BUILD_BUG_ON().
> 
> KVM does use __builtin_constant_p() to effectively disable some assertions when
> it's allowed (by KVM's arbitrary rules) to pass in a non-constant value.  E.g.
> see all the vmcs_checkNN() helpers.  If we didn't waive the assertion for values
> that aren't constant at compile-time, all of the segmentation code would need to
> be unwound into switch statements.

Yeah I saw vmcs_checkNN(), but I think __builtin_constant_p() makes 
sense for vmcs_checkNN()s because they are widely called.  But 
is_kvm_hc_exit_enabled() doesn't seem so.  But no hard opinion here.  As 
you said, it's kinda overkill (or abused to use) but zero-generated code.

> 
> But for things like guest_cpuid_has(), the rule is that the input must be a
> compile-time constant.
> 
>>> IIUC you need some build time guarantee here, but __builtin_constant_p() can
>>> return false, in which case the above BUILD_BUG_ON() does nothing, which
>>> defeats the purpose.
>>
>> It depends on what we'd like to detect.  BUILT_BUG_ON(__builtin_constant_p())
>> can detect the usage in the patch 2/2,
>> is_kvm_hc_exit_enabled(vcpu->kvm, KVM_HC_MAP_GPA_RANGE).  The potential
>> future use of is_kvm_hc_exit_enabled(, KVM_HC_MAP_future_hypercall).
>>
>> Although this version doesn't help for the one in kvm_emulate_hypercall(),
>> !ret check is done first to avoid WARN_ON_ONCE() to hit here.
>>
>> Maybe we can just drop this WARN_ON_ONCE().
> 
> Yeah, I think it makes sense to drop the WARN, otherwise I suspect we'll end up
> dancing around the helper just to avoid the warning.

Agreed, given @nr is from guest.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/2] KVM: x86: Check hypercall's exit to userspace generically
  2024-08-14  1:31         ` Sean Christopherson
  2024-08-14  2:36           ` Huang, Kai
@ 2024-08-14  4:59           ` Binbin Wu
  1 sibling, 0 replies; 19+ messages in thread
From: Binbin Wu @ 2024-08-14  4:59 UTC (permalink / raw)
  To: Sean Christopherson, Isaku Yamahata
  Cc: Kai Huang, kvm, linux-kernel, pbonzini, rick.p.edgecombe,
	michael.roth




On 8/14/2024 9:31 AM, Sean Christopherson wrote:
> On Tue, Aug 13, 2024, Isaku Yamahata wrote:
>> On Wed, Aug 14, 2024 at 11:11:29AM +1200,
>> Kai Huang <kai.huang@intel.com> wrote:
>>
>>>
>>> On 14/08/2024 5:50 am, Isaku Yamahata wrote:
>>>> On Tue, Aug 13, 2024 at 01:12:55PM +0800,
>>>> Binbin Wu <binbin.wu@linux.intel.com> wrote:
>>>>
>>>>> Check whether a KVM hypercall needs to exit to userspace or not based on
>>>>> hypercall_exit_enabled field of struct kvm_arch.
>>>>>
>>>>> Userspace can request a hypercall to exit to userspace for handling by
>>>>> enable KVM_CAP_EXIT_HYPERCALL and the enabled hypercall will be set in
>>>>> hypercall_exit_enabled.  Make the check code generic based on it.
>>>>>
>>>>> Signed-off-by: Binbin Wu <binbin.wu@linux.intel.com>
>>>>> ---
>>>>>    arch/x86/kvm/x86.c | 4 ++--
>>>>>    arch/x86/kvm/x86.h | 7 +++++++
>>>>>    2 files changed, 9 insertions(+), 2 deletions(-)
>>>>>
>>>>> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
>>>>> index af6c8cf6a37a..6e16c9751af7 100644
>>>>> --- a/arch/x86/kvm/x86.c
>>>>> +++ b/arch/x86/kvm/x86.c
>>>>> @@ -10226,8 +10226,8 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
>>>>>    	cpl = kvm_x86_call(get_cpl)(vcpu);
>>>>>    	ret = __kvm_emulate_hypercall(vcpu, nr, a0, a1, a2, a3, op_64_bit, cpl);
>>>>> -	if (nr == KVM_HC_MAP_GPA_RANGE && !ret)
>>>>> -		/* MAP_GPA tosses the request to the user space. */
>>>>> +	if (!ret && is_kvm_hc_exit_enabled(vcpu->kvm, nr))
>>>>> +		/* The hypercall is requested to exit to userspace. */
>>>>>    		return 0;
>>>>>    	if (!op_64_bit)
>>>>> diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
>>>>> index 50596f6f8320..0cbec76b42e6 100644
>>>>> --- a/arch/x86/kvm/x86.h
>>>>> +++ b/arch/x86/kvm/x86.h
>>>>> @@ -547,4 +547,11 @@ int kvm_sev_es_string_io(struct kvm_vcpu *vcpu, unsigned int size,
>>>>>    			 unsigned int port, void *data,  unsigned int count,
>>>>>    			 int in);
>>>>> +static inline bool is_kvm_hc_exit_enabled(struct kvm *kvm, unsigned long hc_nr)
> I would rather have "hypercall" in the name, "hc" never jumps out to me as being
> "hypercall". Maybe is_hypercall_exit_enabled(), user_exit_on_hypercall(), or just
> exit_on_hypercall()?
>
> I'd probably vote for user_exit_on_hypercall(), as that clarifies it's all about
> exiting to userspace, not from the guest.
user_exit_on_hypercall() looks good to me.
Thanks!


>
>>>>> +{
>>>>> +	if(WARN_ON_ONCE(hc_nr >= sizeof(kvm->arch.hypercall_exit_enabled) * 8))
>>>>> +		return false;
>>>> Is this to detect potential bug? Maybe
>>>> BUILD_BUG_ON(__builtin_constant_p(hc_nr) &&
>>>>                !(BIT(hc_nr) & KVM_EXIT_HYPERCALL_VALID_MASK));
>>>> Overkill?
>>> I don't think this is the correct way to use __builtin_constant_p(), i.e. it
>>> doesn't make sense to use __builtin_constant_p() in BUILD_BUG_ON().
> KVM does use __builtin_constant_p() to effectively disable some assertions when
> it's allowed (by KVM's arbitrary rules) to pass in a non-constant value.  E.g.
> see all the vmcs_checkNN() helpers.  If we didn't waive the assertion for values
> that aren't constant at compile-time, all of the segmentation code would need to
> be unwound into switch statements.
>
> But for things like guest_cpuid_has(), the rule is that the input must be a
> compile-time constant.
>
>>> IIUC you need some build time guarantee here, but __builtin_constant_p() can
>>> return false, in which case the above BUILD_BUG_ON() does nothing, which
>>> defeats the purpose.
>> It depends on what we'd like to detect.  BUILT_BUG_ON(__builtin_constant_p())
>> can detect the usage in the patch 2/2,
>> is_kvm_hc_exit_enabled(vcpu->kvm, KVM_HC_MAP_GPA_RANGE).  The potential
>> future use of is_kvm_hc_exit_enabled(, KVM_HC_MAP_future_hypercall).
>>
>> Although this version doesn't help for the one in kvm_emulate_hypercall(),
>> !ret check is done first to avoid WARN_ON_ONCE() to hit here.
>>
>> Maybe we can just drop this WARN_ON_ONCE().
> Yeah, I think it makes sense to drop the WARN, otherwise I suspect we'll end up
> dancing around the helper just to avoid the warning.
>
> I'm 50/50 on the BUILD_BUG_ON().  One one hand, it's kinda overkill.  On the other
> hand, it's zero generated code.
>
Will remove the WARN_ON_ONCE().


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 2/2] KVM: x86: Use is_kvm_hc_exit_enabled() instead of opencode
  2024-08-13 23:18   ` Huang, Kai
@ 2024-08-19 10:07     ` Binbin Wu
  2024-08-19 22:24       ` Huang, Kai
  0 siblings, 1 reply; 19+ messages in thread
From: Binbin Wu @ 2024-08-19 10:07 UTC (permalink / raw)
  To: Huang, Kai
  Cc: kvm, linux-kernel, pbonzini, seanjc, isaku.yamahata,
	rick.p.edgecombe, michael.roth




On 8/14/2024 7:18 AM, Huang, Kai wrote:
>
>
> On 13/08/2024 5:12 pm, Binbin Wu wrote:
>> Use is_kvm_hc_exit_enabled() instead of opencode.
>>
>> No functional change intended.
>
> It would be helpful to mention currently hypercall_exit_enabled can 
> only have KVM_HC_MAP_GPA_RANGE bit set (so that there will be no 
> functional change).
I think it's not needed, because is_kvm_hc_exit_enabled() takes the input.
It just replaces the opencode with a helper API.

Maybe your comment was for the patch 1?

>
>>
>> Signed-off-by: Binbin Wu <binbin.wu@linux.intel.com>
>
> Reviewed-by: Kai Huang <kai.huang@intel.com>
>
Thanks for your review.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 2/2] KVM: x86: Use is_kvm_hc_exit_enabled() instead of opencode
  2024-08-19 10:07     ` Binbin Wu
@ 2024-08-19 22:24       ` Huang, Kai
  0 siblings, 0 replies; 19+ messages in thread
From: Huang, Kai @ 2024-08-19 22:24 UTC (permalink / raw)
  To: Binbin Wu
  Cc: kvm, linux-kernel, pbonzini, seanjc, isaku.yamahata,
	rick.p.edgecombe, michael.roth



On 19/08/2024 10:07 pm, Binbin Wu wrote:
> 
> 
> 
> On 8/14/2024 7:18 AM, Huang, Kai wrote:
>>
>>
>> On 13/08/2024 5:12 pm, Binbin Wu wrote:
>>> Use is_kvm_hc_exit_enabled() instead of opencode.
>>>
>>> No functional change intended.
>>
>> It would be helpful to mention currently hypercall_exit_enabled can 
>> only have KVM_HC_MAP_GPA_RANGE bit set (so that there will be no 
>> functional change).
> I think it's not needed, because is_kvm_hc_exit_enabled() takes the input.
> It just replaces the opencode with a helper API.
> 
> Maybe your comment was for the patch 1?
> 

OK.  I guess my brain wasn't very clear, feel free to ignore :-)

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2024-08-19 22:24 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-13  5:12 [PATCH v2 0/2] KVM: x86: Check hypercall's exit to userspace generically Binbin Wu
2024-08-13  5:12 ` [PATCH v2 1/2] " Binbin Wu
2024-08-13  5:56   ` Yuan Yao
2024-08-13  6:14     ` Yuan Yao
2024-08-13 17:50   ` Isaku Yamahata
2024-08-13 23:11     ` Huang, Kai
2024-08-14  0:52       ` Isaku Yamahata
2024-08-14  1:27         ` Binbin Wu
2024-08-14  1:31         ` Sean Christopherson
2024-08-14  2:36           ` Huang, Kai
2024-08-14  4:59           ` Binbin Wu
2024-08-13 23:16   ` Huang, Kai
2024-08-14  0:53     ` Isaku Yamahata
2024-08-14  1:08     ` Binbin Wu
2024-08-13  5:12 ` [PATCH v2 2/2] KVM: x86: Use is_kvm_hc_exit_enabled() instead of opencode Binbin Wu
2024-08-13 17:51   ` Isaku Yamahata
2024-08-13 23:18   ` Huang, Kai
2024-08-19 10:07     ` Binbin Wu
2024-08-19 22:24       ` Huang, Kai

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox