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);