On Tue, Sep 09, 2025 at 02:39:31AM -0700, Chao Gao wrote:
>The FPU support for CET virtualization has already been merged into 6.17-rc1.
>Building on that, this series introduces Intel CET virtualization support for
>KVM.
>
>Changes in v14
>1. rename the type of guest SSP register to KVM_X86_REG_KVM and add docs
> for register IDs in api.rst (Sean, Xiaoyao)
>2. update commit message of patch 1
>3. use rdmsrq/wrmsrq() instead of rdmsrl/wrmsrl() in patch 6 (Xin)
>4. split the introduction of per-guest guest_supported_xss into a
>separate patch. (Xiaoyao)
>5. make guest FPU and VMCS consistent regarding MSR_IA32_S_CET
>6. collect reviews from Xiaoyao.
(Removed Weijiang's Intel email as it is bouncing)
Below is the diff between v13 and v14:
diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index 6aa40ee05a4a..2b999408a768 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -2908,6 +2908,15 @@ such as set vcpu counter or reset vcpu, and they have the following id bit patte
0x9030 0000 0002 <reg:16>
+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/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 061c0cd73d39..e947204b7f21 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -875,8 +875,8 @@ struct kvm_vcpu_arch {
u64 xcr0;
u64 guest_supported_xcr0;
- u64 guest_supported_xss;
u64 ia32_xss;
+ u64 guest_supported_xss;
struct kvm_pio_request pio;
void *pio_data;
diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h
index 478d9b63a9db..8cc79eca34b2 100644
--- a/arch/x86/include/uapi/asm/kvm.h
+++ b/arch/x86/include/uapi/asm/kvm.h
@@ -412,28 +412,33 @@ struct kvm_xcrs {
};
#define KVM_X86_REG_TYPE_MSR 2
-#define KVM_X86_REG_TYPE_SYNTHETIC_MSR 3
+#define KVM_X86_REG_TYPE_KVM 3
-#define KVM_X86_REG_TYPE_SIZE(type) \
+#define KVM_X86_KVM_REG_SIZE(reg) \
+({ \
+ reg == KVM_REG_GUEST_SSP ? KVM_REG_SIZE_U64 : 0; \
+})
+
+#define KVM_X86_REG_TYPE_SIZE(type, reg) \
({ \
__u64 type_size = (__u64)type << 32; \
\
type_size |= type == KVM_X86_REG_TYPE_MSR ? KVM_REG_SIZE_U64 : \
- type == KVM_X86_REG_TYPE_SYNTHETIC_MSR ? KVM_REG_SIZE_U64 :\
+ type == KVM_X86_REG_TYPE_KVM ? KVM_X86_KVM_REG_SIZE(reg) : \
0; \
type_size; \
})
#define KVM_X86_REG_ENCODE(type, index) \
- (KVM_REG_X86 | KVM_X86_REG_TYPE_SIZE(type) | index)
+ (KVM_REG_X86 | KVM_X86_REG_TYPE_SIZE(type, index) | index)
#define KVM_X86_REG_MSR(index) \
KVM_X86_REG_ENCODE(KVM_X86_REG_TYPE_MSR, index)
-#define KVM_X86_REG_SYNTHETIC_MSR(index) \
- KVM_X86_REG_ENCODE(KVM_X86_REG_TYPE_SYNTHETIC_MSR, index)
+#define KVM_X86_REG_KVM(index) \
+ KVM_X86_REG_ENCODE(KVM_X86_REG_TYPE_KVM, index)
-/* KVM synthetic MSR index staring from 0 */
-#define KVM_SYNTHETIC_GUEST_SSP 0
+/* 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)
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 989008f5307e..92daf63c9487 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -2435,6 +2435,7 @@ int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
break;
case MSR_IA32_S_CET:
vmcs_writel(GUEST_S_CET, data);
+ kvm_set_xstate_msr(vcpu, msr_info);
break;
case MSR_KVM_INTERNAL_GUEST_SSP:
vmcs_writel(GUEST_SSP, data);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 9930678f5a3b..6f64a3355274 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4647,6 +4647,7 @@ EXPORT_SYMBOL_GPL(kvm_get_msr_common);
static bool is_xstate_managed_msr(u32 index)
{
switch (index) {
+ case MSR_IA32_S_CET:
case MSR_IA32_U_CET:
case MSR_IA32_PL0_SSP ... MSR_IA32_PL3_SSP:
return true;
@@ -6051,16 +6052,16 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
struct kvm_x86_reg_id {
__u32 index;
__u8 type;
- __u8 rsvd;
- __u8 rsvd4:4;
+ __u8 rsvd1;
+ __u8 rsvd2:4;
__u8 size:4;
__u8 x86;
};
-static int kvm_translate_synthetic_msr(struct kvm_x86_reg_id *reg)
+static int kvm_translate_kvm_reg(struct kvm_x86_reg_id *reg)
{
switch (reg->index) {
- case KVM_SYNTHETIC_GUEST_SSP:
+ case KVM_REG_GUEST_SSP:
reg->type = KVM_X86_REG_TYPE_MSR;
reg->index = MSR_KVM_INTERNAL_GUEST_SSP;
break;
@@ -6201,18 +6202,11 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
break;
id = (struct kvm_x86_reg_id *)®.id;
- if (id->rsvd || id->rsvd4)
- break;
-
- if (id->type != KVM_X86_REG_TYPE_MSR &&
- id->type != KVM_X86_REG_TYPE_SYNTHETIC_MSR)
+ if (id->rsvd1 || id->rsvd2)
break;
- if ((reg.id & KVM_REG_SIZE_MASK) != KVM_REG_SIZE_U64)
- break;
-
- if (id->type == KVM_X86_REG_TYPE_SYNTHETIC_MSR) {
- r = kvm_translate_synthetic_msr(id);
+ if (id->type == KVM_X86_REG_TYPE_KVM) {
+ r = kvm_translate_kvm_reg(id);
if (r)
break;
}
@@ -6221,6 +6215,9 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
if (id->type != KVM_X86_REG_TYPE_MSR)
break;
+ if ((reg.id & KVM_REG_SIZE_MASK) != KVM_REG_SIZE_U64)
+ break;
+
value = u64_to_user_ptr(reg.addr);
if (ioctl == KVM_GET_ONE_REG)
r = kvm_get_one_msr(vcpu, id->index, value);
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
index d6b21ba41416..728e01781ae8 100644
--- a/arch/x86/kvm/x86.h
+++ b/arch/x86/kvm/x86.h
@@ -726,7 +726,7 @@ static inline void kvm_get_xstate_msr(struct kvm_vcpu *vcpu,
{
KVM_BUG_ON(!vcpu->arch.guest_fpu.fpstate->in_use, vcpu->kvm);
kvm_fpu_get();
- rdmsrl(msr_info->index, msr_info->data);
+ rdmsrq(msr_info->index, msr_info->data);
kvm_fpu_put();
}
@@ -735,7 +735,7 @@ static inline void kvm_set_xstate_msr(struct kvm_vcpu *vcpu,
{
KVM_BUG_ON(!vcpu->arch.guest_fpu.fpstate->in_use, vcpu->kvm);
kvm_fpu_get();
- wrmsrl(msr_info->index, msr_info->data);
+ wrmsrq(msr_info->index, msr_info->data);
kvm_fpu_put();
}
diff --git a/tools/arch/x86/include/uapi/asm/kvm.h b/tools/arch/x86/include/uapi/asm/kvm.h
index 590762820a61..59ac0b46ebcc 100644
--- a/tools/arch/x86/include/uapi/asm/kvm.h
+++ b/tools/arch/x86/include/uapi/asm/kvm.h
@@ -412,28 +412,33 @@ struct kvm_xcrs {
};
#define KVM_X86_REG_TYPE_MSR 2
-#define KVM_X86_REG_TYPE_SYNTHETIC_MSR 3
+#define KVM_X86_REG_TYPE_KVM 3
-#define KVM_X86_REG_TYPE_SIZE(type) \
+#define KVM_X86_KVM_REG_SIZE(reg) \
+({ \
+ reg == KVM_REG_GUEST_SSP ? KVM_REG_SIZE_U64 : 0; \
+})
+
+#define KVM_X86_REG_TYPE_SIZE(type, reg) \
({ \
__u64 type_size = (__u64)type << 32; \
\
type_size |= type == KVM_X86_REG_TYPE_MSR ? KVM_REG_SIZE_U64 : \
- type == KVM_X86_REG_TYPE_SYNTHETIC_MSR ? KVM_REG_SIZE_U64 :\
+ type == KVM_X86_REG_TYPE_KVM ? KVM_X86_KVM_REG_SIZE(reg) : \
0; \
type_size; \
})
#define KVM_X86_REG_ENCODE(type, index) \
- (KVM_REG_X86 | KVM_X86_REG_TYPE_SIZE(type) | index)
+ (KVM_REG_X86 | KVM_X86_REG_TYPE_SIZE(type, index) | index)
#define KVM_X86_REG_MSR(index) \
KVM_X86_REG_ENCODE(KVM_X86_REG_TYPE_MSR, index)
-#define KVM_X86_REG_SYNTHETIC_MSR(index) \
- KVM_X86_REG_ENCODE(KVM_X86_REG_TYPE_SYNTHETIC_MSR, index)
+#define KVM_X86_REG_KVM(index) \
+ KVM_X86_REG_ENCODE(KVM_X86_REG_TYPE_KVM, index)
-/* KVM synthetic MSR index staring from 0 */
-#define KVM_SYNTHETIC_GUEST_SSP 0
+/* 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)
diff --git a/tools/testing/selftests/kvm/x86/get_set_one_reg.c b/tools/testing/selftests/kvm/x86/get_set_one_reg.c
index 8b069155ddc7..8a4dbc812214 100644
--- a/tools/testing/selftests/kvm/x86/get_set_one_reg.c
+++ b/tools/testing/selftests/kvm/x86/get_set_one_reg.c
@@ -12,7 +12,6 @@ int main(int argc, char *argv[])
struct kvm_vcpu *vcpu;
struct kvm_vm *vm;
u64 data;
- int r;
TEST_REQUIRE(kvm_has_cap(KVM_CAP_ONE_REG));
@@ -22,12 +21,8 @@ int main(int argc, char *argv[])
TEST_ASSERT_EQ(__vcpu_set_reg(vcpu, KVM_X86_REG_MSR(MSR_EFER), data), 0);
if (kvm_cpu_has(X86_FEATURE_SHSTK)) {
- r = __vcpu_get_reg(vcpu, KVM_X86_REG_SYNTHETIC_MSR(KVM_SYNTHETIC_GUEST_SSP),
- &data);
- TEST_ASSERT_EQ(r, 0);
- r = __vcpu_set_reg(vcpu, KVM_X86_REG_SYNTHETIC_MSR(KVM_SYNTHETIC_GUEST_SSP),
- data);
- TEST_ASSERT_EQ(r, 0);
+ TEST_ASSERT_EQ(__vcpu_get_reg(vcpu, KVM_X86_REG_KVM(KVM_REG_GUEST_SSP), &data), 0);
+ TEST_ASSERT_EQ(__vcpu_set_reg(vcpu, KVM_X86_REG_KVM(KVM_REG_GUEST_SSP), data), 0);
}
kvm_vm_free(vm);