[PATCH v15 13/41] KVM: x86: Enable guest SSP read/write interface with new uAPIs

Sean Christopherson posted 41 patches 2 weeks, 5 days ago
[PATCH v15 13/41] KVM: x86: Enable guest SSP read/write interface with new uAPIs
Posted by Sean Christopherson 2 weeks, 5 days ago
From: Yang Weijiang <weijiang.yang@intel.com>

Enable guest shadow stack pointer(SSP) access interface with new uAPIs.
CET guest SSP is HW register which has corresponding VMCS field to save
and restore guest values when VM-{Exit,Entry} happens. KVM handles SSP
as a fake/synthetic MSR for userspace access.

Use a translation helper to set up mapping for SSP synthetic index and
KVM-internal MSR index so that userspace doesn't need to take care of
KVM's management for synthetic MSRs and avoid conflicts.

Suggested-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
Tested-by: Mathias Krause <minipli@grsecurity.net>
Tested-by: John Allen <john.allen@amd.com>
Tested-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
Signed-off-by: Chao Gao <chao.gao@intel.com>
Co-developed-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 Documentation/virt/kvm/api.rst  |  8 ++++++++
 arch/x86/include/uapi/asm/kvm.h |  3 +++
 arch/x86/kvm/x86.c              | 23 +++++++++++++++++++++--
 arch/x86/kvm/x86.h              | 10 ++++++++++
 4 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index abd02675a24d..6ae24c5ca559 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -2911,6 +2911,14 @@ such as set vcpu counter or reset vcpu, and they have the following id bit patte
 x86 MSR registers have the following id bit patterns::
   0x2030 0002 <msr number:32>
 
+Following are the KVM-defined registers for x86:
+
+======================= ========= =============================================
+    Encoding            Register  Description
+======================= ========= =============================================
+  0x2030 0003 0000 0000 SSP       Shadow Stack Pointer
+======================= ========= =============================================
+
 4.69 KVM_GET_ONE_REG
 --------------------
 
diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h
index 508b713ca52e..8cc79eca34b2 100644
--- a/arch/x86/include/uapi/asm/kvm.h
+++ b/arch/x86/include/uapi/asm/kvm.h
@@ -437,6 +437,9 @@ struct kvm_xcrs {
 #define KVM_X86_REG_KVM(index)					\
 	KVM_X86_REG_ENCODE(KVM_X86_REG_TYPE_KVM, index)
 
+/* KVM-defined registers starting from 0 */
+#define KVM_REG_GUEST_SSP	0
+
 #define KVM_SYNC_X86_REGS      (1UL << 0)
 #define KVM_SYNC_X86_SREGS     (1UL << 1)
 #define KVM_SYNC_X86_EVENTS    (1UL << 2)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 2c9908bc8b32..460ceae11495 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -6017,7 +6017,15 @@ struct kvm_x86_reg_id {
 
 static int kvm_translate_kvm_reg(struct kvm_x86_reg_id *reg)
 {
-	return -EINVAL;
+	switch (reg->index) {
+	case KVM_REG_GUEST_SSP:
+		reg->type = KVM_X86_REG_TYPE_MSR;
+		reg->index = MSR_KVM_INTERNAL_GUEST_SSP;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
 }
 
 static int kvm_get_one_msr(struct kvm_vcpu *vcpu, u32 msr, u64 __user *user_val)
@@ -6097,11 +6105,22 @@ static int kvm_get_set_one_reg(struct kvm_vcpu *vcpu, unsigned int ioctl,
 static int kvm_get_reg_list(struct kvm_vcpu *vcpu,
 			    struct kvm_reg_list __user *user_list)
 {
-	u64 nr_regs = 0;
+	u64 nr_regs = guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK) ? 1 : 0;
+	u64 user_nr_regs;
+
+	if (get_user(user_nr_regs, &user_list->n))
+		return -EFAULT;
 
 	if (put_user(nr_regs, &user_list->n))
 		return -EFAULT;
 
+	if (user_nr_regs < nr_regs)
+		return -E2BIG;
+
+	if (nr_regs &&
+	    put_user(KVM_X86_REG_KVM(KVM_REG_GUEST_SSP), &user_list->reg[0]))
+		return -EFAULT;
+
 	return 0;
 }
 
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
index 786e36fcd0fb..a7c9c72fca93 100644
--- a/arch/x86/kvm/x86.h
+++ b/arch/x86/kvm/x86.h
@@ -101,6 +101,16 @@ do {											\
 #define KVM_SVM_DEFAULT_PLE_WINDOW_MAX	USHRT_MAX
 #define KVM_SVM_DEFAULT_PLE_WINDOW	3000
 
+/*
+ * KVM's internal, non-ABI indices for synthetic MSRs. The values themselves
+ * are arbitrary and have no meaning, the only requirement is that they don't
+ * conflict with "real" MSRs that KVM supports. Use values at the upper end
+ * of KVM's reserved paravirtual MSR range to minimize churn, i.e. these values
+ * will be usable until KVM exhausts its supply of paravirtual MSR indices.
+ */
+
+#define MSR_KVM_INTERNAL_GUEST_SSP	0x4b564dff
+
 static inline unsigned int __grow_ple_window(unsigned int val,
 		unsigned int base, unsigned int modifier, unsigned int max)
 {
-- 
2.51.0.384.g4c02a37b29-goog
Re: [PATCH v15 13/41] KVM: x86: Enable guest SSP read/write interface with new uAPIs
Posted by Xiaoyao Li 2 weeks, 3 days ago
On 9/13/2025 7:22 AM, Sean Christopherson wrote:
> From: Yang Weijiang <weijiang.yang@intel.com>
> 
> Enable guest shadow stack pointer(SSP) access interface with new uAPIs.
> CET guest SSP is HW register which has corresponding VMCS field to save
> and restore guest values when VM-{Exit,Entry} happens. KVM handles SSP
> as a fake/synthetic MSR for userspace access.
> 
> Use a translation helper to set up mapping for SSP synthetic index and
> KVM-internal MSR index so that userspace doesn't need to take care of
> KVM's management for synthetic MSRs and avoid conflicts.
> 
> Suggested-by: Sean Christopherson <seanjc@google.com>
> Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
> Tested-by: Mathias Krause <minipli@grsecurity.net>
> Tested-by: John Allen <john.allen@amd.com>
> Tested-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
> Signed-off-by: Chao Gao <chao.gao@intel.com>
> Co-developed-by: Sean Christopherson <seanjc@google.com>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
>   Documentation/virt/kvm/api.rst  |  8 ++++++++
>   arch/x86/include/uapi/asm/kvm.h |  3 +++
>   arch/x86/kvm/x86.c              | 23 +++++++++++++++++++++--
>   arch/x86/kvm/x86.h              | 10 ++++++++++
>   4 files changed, 42 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
> index abd02675a24d..6ae24c5ca559 100644
> --- a/Documentation/virt/kvm/api.rst
> +++ b/Documentation/virt/kvm/api.rst
> @@ -2911,6 +2911,14 @@ such as set vcpu counter or reset vcpu, and they have the following id bit patte
>   x86 MSR registers have the following id bit patterns::
>     0x2030 0002 <msr number:32>
>   
> +Following are the KVM-defined registers for x86:
> +
> +======================= ========= =============================================
> +    Encoding            Register  Description
> +======================= ========= =============================================
> +  0x2030 0003 0000 0000 SSP       Shadow Stack Pointer
> +======================= ========= =============================================
> +
>   4.69 KVM_GET_ONE_REG
>   --------------------
>   
> diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h
> index 508b713ca52e..8cc79eca34b2 100644
> --- a/arch/x86/include/uapi/asm/kvm.h
> +++ b/arch/x86/include/uapi/asm/kvm.h
> @@ -437,6 +437,9 @@ struct kvm_xcrs {
>   #define KVM_X86_REG_KVM(index)					\
>   	KVM_X86_REG_ENCODE(KVM_X86_REG_TYPE_KVM, index)
>   
> +/* KVM-defined registers starting from 0 */
> +#define KVM_REG_GUEST_SSP	0
> +
>   #define KVM_SYNC_X86_REGS      (1UL << 0)
>   #define KVM_SYNC_X86_SREGS     (1UL << 1)
>   #define KVM_SYNC_X86_EVENTS    (1UL << 2)
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 2c9908bc8b32..460ceae11495 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -6017,7 +6017,15 @@ struct kvm_x86_reg_id {
>   
>   static int kvm_translate_kvm_reg(struct kvm_x86_reg_id *reg)
>   {
> -	return -EINVAL;
> +	switch (reg->index) {
> +	case KVM_REG_GUEST_SSP:
> +		reg->type = KVM_X86_REG_TYPE_MSR;
> +		reg->index = MSR_KVM_INTERNAL_GUEST_SSP;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +	return 0;
>   }
>   
>   static int kvm_get_one_msr(struct kvm_vcpu *vcpu, u32 msr, u64 __user *user_val)
> @@ -6097,11 +6105,22 @@ static int kvm_get_set_one_reg(struct kvm_vcpu *vcpu, unsigned int ioctl,
>   static int kvm_get_reg_list(struct kvm_vcpu *vcpu,
>   			    struct kvm_reg_list __user *user_list)
>   {
> -	u64 nr_regs = 0;
> +	u64 nr_regs = guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK) ? 1 : 0;

I wonder what's the semantic of KVM returning KVM_REG_GUEST_SSP on 
KVM_GET_REG_LIST. Does it ensure KVM_{G,S}ET_ONE_REG returns -EINVAL on 
KVM_REG_GUEST_SSP when it's not enumerated by KVM_GET_REG_LIST?

If so, but KVM_{G,S}ET_ONE_REG can succeed on GUEST_SSP even if
!guest_cpu_cap_has() when @ignore_msrs is true.

> +	u64 user_nr_regs;
> +
> +	if (get_user(user_nr_regs, &user_list->n))
> +		return -EFAULT;
>   
>   	if (put_user(nr_regs, &user_list->n))
>   		return -EFAULT;
>   
> +	if (user_nr_regs < nr_regs)
> +		return -E2BIG;
> +
> +	if (nr_regs &&
> +	    put_user(KVM_X86_REG_KVM(KVM_REG_GUEST_SSP), &user_list->reg[0]))
> +		return -EFAULT;
> +
>   	return 0;
>   }
>   
> diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
> index 786e36fcd0fb..a7c9c72fca93 100644
> --- a/arch/x86/kvm/x86.h
> +++ b/arch/x86/kvm/x86.h
> @@ -101,6 +101,16 @@ do {											\
>   #define KVM_SVM_DEFAULT_PLE_WINDOW_MAX	USHRT_MAX
>   #define KVM_SVM_DEFAULT_PLE_WINDOW	3000
>   
> +/*
> + * KVM's internal, non-ABI indices for synthetic MSRs. The values themselves
> + * are arbitrary and have no meaning, the only requirement is that they don't
> + * conflict with "real" MSRs that KVM supports. Use values at the upper end
> + * of KVM's reserved paravirtual MSR range to minimize churn, i.e. these values
> + * will be usable until KVM exhausts its supply of paravirtual MSR indices.
> + */
> +
> +#define MSR_KVM_INTERNAL_GUEST_SSP	0x4b564dff
> +
>   static inline unsigned int __grow_ple_window(unsigned int val,
>   		unsigned int base, unsigned int modifier, unsigned int max)
>   {
Re: [PATCH v15 13/41] KVM: x86: Enable guest SSP read/write interface with new uAPIs
Posted by Sean Christopherson 2 weeks, 2 days ago
On Mon, Sep 15, 2025, Xiaoyao Li wrote:
> On 9/13/2025 7:22 AM, Sean Christopherson wrote:
> > @@ -6097,11 +6105,22 @@ static int kvm_get_set_one_reg(struct kvm_vcpu *vcpu, unsigned int ioctl,
> >   static int kvm_get_reg_list(struct kvm_vcpu *vcpu,
> >   			    struct kvm_reg_list __user *user_list)
> >   {
> > -	u64 nr_regs = 0;
> > +	u64 nr_regs = guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK) ? 1 : 0;
> 
> I wonder what's the semantic of KVM returning KVM_REG_GUEST_SSP on
> KVM_GET_REG_LIST. Does it ensure KVM_{G,S}ET_ONE_REG returns -EINVAL on
> KVM_REG_GUEST_SSP when it's not enumerated by KVM_GET_REG_LIST?
> 
> If so, but KVM_{G,S}ET_ONE_REG can succeed on GUEST_SSP even if
> !guest_cpu_cap_has() when @ignore_msrs is true.

Ugh, great catch.  Too many knobs.  The best idea I've got it to to exempt KVM-
internal MSRs from ignore_msrs and report_ignored_msrs on host-initiated writes.
That's unfortunately still a userspace visible change, and would continue to be
userspace-visible, e.g. if we wanted to change the magic value for
MSR_KVM_INTERNAL_GUEST_SSP.

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index c78acab2ff3f..6a50261d1c5c 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -511,6 +511,11 @@ static bool kvm_is_advertised_msr(u32 msr_index)
        return false;
 }
 
+static bool kvm_is_internal_msr(u32 msr)
+{
+       return msr == MSR_KVM_INTERNAL_GUEST_SSP;
+}
+
 typedef int (*msr_access_t)(struct kvm_vcpu *vcpu, u32 index, u64 *data,
                            bool host_initiated);
 
@@ -544,6 +549,9 @@ static __always_inline int kvm_do_msr_access(struct kvm_vcpu *vcpu, u32 msr,
        if (host_initiated && !*data && kvm_is_advertised_msr(msr))
                return 0;
 
+       if (host_initiated && kvm_is_internal_msr(msr))
+               return ret;
+
        if (!ignore_msrs) {
                kvm_debug_ratelimited("unhandled %s: 0x%x data 0x%llx\n",
                                      op, msr, *data);

Alternatively, simply exempt host writes from ignore_msrs.  Aha!  And KVM even
documents that as the behavior:

	kvm.ignore_msrs=[KVM] Ignore guest accesses to unhandled MSRs.
			Default is 0 (don't ignore, but inject #GP)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index c78acab2ff3f..177253e75b41 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -544,7 +544,7 @@ static __always_inline int kvm_do_msr_access(struct kvm_vcpu *vcpu, u32 msr,
        if (host_initiated && !*data && kvm_is_advertised_msr(msr))
                return 0;
 
-       if (!ignore_msrs) {
+       if (host_initiated || !ignore_msrs) {
                kvm_debug_ratelimited("unhandled %s: 0x%x data 0x%llx\n",
                                      op, msr, *data);
                return ret;

So while it's technically an ABI change (arguable since it's guarded by an
off-by-default param), I suspect we can get away with it.  Hmm, commit 6abe9c1386e5
("KVM: X86: Move ignore_msrs handling upper the stack") exempted KVM-internal
MSR accesses from ignore_msrs, but doesn't provide much in the way of justification
for _why_ that's desirable.

Argh, and that same mini-series extended the behavior to feature MSRs, again
without seeming to consider whether or not it's actually desirable to suppress
bad VMM accesses.  Even worse, that decision likely generated an absurd amount
of churn and noise due to splattering helpers and variants all over the place. :-(

commit 12bc2132b15e0a969b3f455d90a5f215ef239eff
Author:     Peter Xu <peterx@redhat.com>
AuthorDate: Mon Jun 22 18:04:42 2020 -0400
Commit:     Paolo Bonzini <pbonzini@redhat.com>
CommitDate: Wed Jul 8 16:21:40 2020 -0400

    KVM: X86: Do the same ignore_msrs check for feature msrs
    
    Logically the ignore_msrs and report_ignored_msrs should also apply to feature
    MSRs.  Add them in.

For 6.18, I think the safe play is to go with the first path (exempt KVM-internal
MSRs), and then try to go for the second approach (exempt all host accesses) for
6.19.  KVM's ABI for ignore_msrs=true is already all kinds of messed up, so I'm
not terribly concerned about temporarily making it marginally worse.
Re: [PATCH v15 13/41] KVM: x86: Enable guest SSP read/write interface with new uAPIs
Posted by Xiaoyao Li 2 weeks, 2 days ago
On 9/16/2025 6:12 AM, Sean Christopherson wrote:
> On Mon, Sep 15, 2025, Xiaoyao Li wrote:
>> On 9/13/2025 7:22 AM, Sean Christopherson wrote:
>>> @@ -6097,11 +6105,22 @@ static int kvm_get_set_one_reg(struct kvm_vcpu *vcpu, unsigned int ioctl,
>>>    static int kvm_get_reg_list(struct kvm_vcpu *vcpu,
>>>    			    struct kvm_reg_list __user *user_list)
>>>    {
>>> -	u64 nr_regs = 0;
>>> +	u64 nr_regs = guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK) ? 1 : 0;
>>
>> I wonder what's the semantic of KVM returning KVM_REG_GUEST_SSP on
>> KVM_GET_REG_LIST. Does it ensure KVM_{G,S}ET_ONE_REG returns -EINVAL on
>> KVM_REG_GUEST_SSP when it's not enumerated by KVM_GET_REG_LIST?
>>
>> If so, but KVM_{G,S}ET_ONE_REG can succeed on GUEST_SSP even if
>> !guest_cpu_cap_has() when @ignore_msrs is true.
> 
> Ugh, great catch.  Too many knobs.  The best idea I've got it to to exempt KVM-
> internal MSRs from ignore_msrs and report_ignored_msrs on host-initiated writes.
> That's unfortunately still a userspace visible change, and would continue to be
> userspace-visible, e.g. if we wanted to change the magic value for
> MSR_KVM_INTERNAL_GUEST_SSP.
> 
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index c78acab2ff3f..6a50261d1c5c 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -511,6 +511,11 @@ static bool kvm_is_advertised_msr(u32 msr_index)
>          return false;
>   }
>   
> +static bool kvm_is_internal_msr(u32 msr)
> +{
> +       return msr == MSR_KVM_INTERNAL_GUEST_SSP;
> +}
> +
>   typedef int (*msr_access_t)(struct kvm_vcpu *vcpu, u32 index, u64 *data,
>                              bool host_initiated);
>   
> @@ -544,6 +549,9 @@ static __always_inline int kvm_do_msr_access(struct kvm_vcpu *vcpu, u32 msr,
>          if (host_initiated && !*data && kvm_is_advertised_msr(msr))
>                  return 0;
>   
> +       if (host_initiated && kvm_is_internal_msr(msr))
> +               return ret;
> +
>          if (!ignore_msrs) {
>                  kvm_debug_ratelimited("unhandled %s: 0x%x data 0x%llx\n",
>                                        op, msr, *data);
> 
> Alternatively, simply exempt host writes from ignore_msrs.  Aha!  And KVM even
> documents that as the behavior:
> 
> 	kvm.ignore_msrs=[KVM] Ignore guest accesses to unhandled MSRs.
> 			Default is 0 (don't ignore, but inject #GP)
> 
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index c78acab2ff3f..177253e75b41 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -544,7 +544,7 @@ static __always_inline int kvm_do_msr_access(struct kvm_vcpu *vcpu, u32 msr,
>          if (host_initiated && !*data && kvm_is_advertised_msr(msr))
>                  return 0;
>   
> -       if (!ignore_msrs) {
> +       if (host_initiated || !ignore_msrs) {
>                  kvm_debug_ratelimited("unhandled %s: 0x%x data 0x%llx\n",
>                                        op, msr, *data);
>                  return ret;
> 
> So while it's technically an ABI change (arguable since it's guarded by an
> off-by-default param), I suspect we can get away with it.  Hmm, commit 6abe9c1386e5
> ("KVM: X86: Move ignore_msrs handling upper the stack") exempted KVM-internal
> MSR accesses from ignore_msrs, but doesn't provide much in the way of justification
> for _why_ that's desirable.
> 
> Argh, and that same mini-series extended the behavior to feature MSRs, again
> without seeming to consider whether or not it's actually desirable to suppress
> bad VMM accesses.  Even worse, that decision likely generated an absurd amount
> of churn and noise due to splattering helpers and variants all over the place. :-(
> 
> commit 12bc2132b15e0a969b3f455d90a5f215ef239eff
> Author:     Peter Xu <peterx@redhat.com>
> AuthorDate: Mon Jun 22 18:04:42 2020 -0400
> Commit:     Paolo Bonzini <pbonzini@redhat.com>
> CommitDate: Wed Jul 8 16:21:40 2020 -0400
> 
>      KVM: X86: Do the same ignore_msrs check for feature msrs
>      
>      Logically the ignore_msrs and report_ignored_msrs should also apply to feature
>      MSRs.  Add them in.
> 
> For 6.18, I think the safe play is to go with the first path (exempt KVM-internal
> MSRs), and then try to go for the second approach (exempt all host accesses) for
> 6.19.  KVM's ABI for ignore_msrs=true is already all kinds of messed up, so I'm
> not terribly concerned about temporarily making it marginally worse.

Looks OK to me.
Re: [PATCH v15 13/41] KVM: x86: Enable guest SSP read/write interface with new uAPIs
Posted by Sean Christopherson 1 week, 6 days ago
On Tue, Sep 16, 2025, Xiaoyao Li wrote:
> On 9/16/2025 6:12 AM, Sean Christopherson wrote:
> > For 6.18, I think the safe play is to go with the first path (exempt KVM-internal
> > MSRs), and then try to go for the second approach (exempt all host accesses) for
> > 6.19.  KVM's ABI for ignore_msrs=true is already all kinds of messed up, so I'm
> > not terribly concerned about temporarily making it marginally worse.
> 
> Looks OK to me.

Actually, better idea.  Just use kvm_msr_{read,write}() for ONE_REG and bypass
the ignore_msrs crud.  It's new uAPI, so we can define the semantics to be anything
we want.  I see zero reason for ignore_msrs to apply to host accesses, and even
less reason for it to apply to ONE_REG.

Then there's no need to special case GUEST_SSP, and what to do about ignore_msrs
for host accesses remains an orthogonal discussion.

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 4ed25d33aaee..4adfece25630 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -5932,7 +5932,7 @@ static int kvm_get_one_msr(struct kvm_vcpu *vcpu, u32 msr, u64 __user *user_val)
 {
        u64 val;
 
-       if (do_get_msr(vcpu, msr, &val))
+       if (kvm_msr_read(vcpu, msr, &val))
                return -EINVAL;
 
        if (put_user(val, user_val))
@@ -5948,7 +5948,7 @@ static int kvm_set_one_msr(struct kvm_vcpu *vcpu, u32 msr, u64 __user *user_val)
        if (get_user(val, user_val))
                return -EFAULT;
 
-       if (do_set_msr(vcpu, msr, &val))
+       if (kvm_msr_write(vcpu, msr, &val))
                return -EINVAL;
 
        return 0;
Re: [PATCH v15 13/41] KVM: x86: Enable guest SSP read/write interface with new uAPIs
Posted by Sean Christopherson 1 week, 6 days ago
On Fri, Sep 19, 2025, Sean Christopherson wrote:
> On Tue, Sep 16, 2025, Xiaoyao Li wrote:
> > On 9/16/2025 6:12 AM, Sean Christopherson wrote:
> > > For 6.18, I think the safe play is to go with the first path (exempt KVM-internal
> > > MSRs), and then try to go for the second approach (exempt all host accesses) for
> > > 6.19.  KVM's ABI for ignore_msrs=true is already all kinds of messed up, so I'm
> > > not terribly concerned about temporarily making it marginally worse.
> > 
> > Looks OK to me.
> 
> Actually, better idea.  Just use kvm_msr_{read,write}() for ONE_REG and bypass
> the ignore_msrs crud.  It's new uAPI, so we can define the semantics to be anything
> we want.  I see zero reason for ignore_msrs to apply to host accesses, and even
> less reason for it to apply to ONE_REG.
> 
> Then there's no need to special case GUEST_SSP, and what to do about ignore_msrs
> for host accesses remains an orthogonal discussion.
> 
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 4ed25d33aaee..4adfece25630 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -5932,7 +5932,7 @@ static int kvm_get_one_msr(struct kvm_vcpu *vcpu, u32 msr, u64 __user *user_val)
>  {
>         u64 val;
>  
> -       if (do_get_msr(vcpu, msr, &val))
> +       if (kvm_msr_read(vcpu, msr, &val))
>                 return -EINVAL;
>  
>         if (put_user(val, user_val))
> @@ -5948,7 +5948,7 @@ static int kvm_set_one_msr(struct kvm_vcpu *vcpu, u32 msr, u64 __user *user_val)
>         if (get_user(val, user_val))
>                 return -EFAULT;
>  
> -       if (do_set_msr(vcpu, msr, &val))
> +       if (kvm_msr_write(vcpu, msr, &val))
>                 return -EINVAL;
>  
>         return 0;

Never mind, that would cause problems for using ONE_REG for actual MSRs.  Most
importantly, it would let userspace bypass the feature MSR restrictions in
do_set_msr().

I think the best option is to immediately reject translation.  That way host
accesses to whatever KVM uses for the internal SSP MSR index are unaffected by
the introduction of ONE_REG support.  E.g. modifying kvm_do_msr_access() would
mean that userspace would see different behavior for MSR_KVM_INTERNAL_GUEST_SSP
versus all other MSRs.

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index ab7f8c41d93b..720540f102e1 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -6016,10 +6016,20 @@ struct kvm_x86_reg_id {
        __u8  x86;
 };
 
-static int kvm_translate_kvm_reg(struct kvm_x86_reg_id *reg)
+static int kvm_translate_kvm_reg(struct kvm_vcpu *vcpu,
+                                struct kvm_x86_reg_id *reg)
 {
        switch (reg->index) {
        case KVM_REG_GUEST_SSP:
+               /*
+                * FIXME: If host-initiated accesses are ever exempted from
+                * ignore_msrs (in kvm_do_msr_access()), drop this manual check
+                * and rely on KVM's standard checks to reject accesses to regs
+                * that don't exist.
+                */
+               if (!guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK))
+                       return -EINVAL;
+
                reg->type = KVM_X86_REG_TYPE_MSR;
                reg->index = MSR_KVM_INTERNAL_GUEST_SSP;
                break;
@@ -6075,7 +6085,7 @@ static int kvm_get_set_one_reg(struct kvm_vcpu *vcpu, unsigned int ioctl,
                return -EINVAL;
 
        if (reg->type == KVM_X86_REG_TYPE_KVM) {
-               r = kvm_translate_kvm_reg(reg);
+               r = kvm_translate_kvm_reg(vcpu, reg);
                if (r)
                        return r;
        }