[PATCH v12 15/24] KVM: VMX: Emulate read and write to CET MSRs

Chao Gao posted 24 patches 1 month, 3 weeks ago
There is a newer version of this series
[PATCH v12 15/24] KVM: VMX: Emulate read and write to CET MSRs
Posted by Chao Gao 1 month, 3 weeks ago
From: Yang Weijiang <weijiang.yang@intel.com>

Add emulation interface for CET MSR access. The emulation code is split
into common part and vendor specific part. The former does common checks
for MSRs, e.g., accessibility, data validity etc., then passes operation
to either XSAVE-managed MSRs via the helpers or CET VMCS fields.

SSP can only be read via RDSSP. Writing even requires destructive and
potentially faulting operations such as SAVEPREVSSP/RSTORSSP or
SETSSBSY/CLRSSBSY. Let the host use a pseudo-MSR that is just a wrapper
for the GUEST_SSP field of the VMCS.

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>
Signed-off-by: Chao Gao <chao.gao@intel.com>
---
 arch/x86/kvm/vmx/vmx.c | 18 ++++++++++++++++++
 arch/x86/kvm/x86.c     | 43 ++++++++++++++++++++++++++++++++++++++++++
 arch/x86/kvm/x86.h     | 23 ++++++++++++++++++++++
 3 files changed, 84 insertions(+)

diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index aa157fe5b7b3..bd572c8c7bc3 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -2093,6 +2093,15 @@ int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 		else
 			msr_info->data = vmx->pt_desc.guest.addr_a[index / 2];
 		break;
+	case MSR_IA32_S_CET:
+		msr_info->data = vmcs_readl(GUEST_S_CET);
+		break;
+	case MSR_KVM_INTERNAL_GUEST_SSP:
+		msr_info->data = vmcs_readl(GUEST_SSP);
+		break;
+	case MSR_IA32_INT_SSP_TAB:
+		msr_info->data = vmcs_readl(GUEST_INTR_SSP_TABLE);
+		break;
 	case MSR_IA32_DEBUGCTLMSR:
 		msr_info->data = vmx_guest_debugctl_read();
 		break;
@@ -2411,6 +2420,15 @@ int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 		else
 			vmx->pt_desc.guest.addr_a[index / 2] = data;
 		break;
+	case MSR_IA32_S_CET:
+		vmcs_writel(GUEST_S_CET, data);
+		break;
+	case MSR_KVM_INTERNAL_GUEST_SSP:
+		vmcs_writel(GUEST_SSP, data);
+		break;
+	case MSR_IA32_INT_SSP_TAB:
+		vmcs_writel(GUEST_INTR_SSP_TABLE, data);
+		break;
 	case MSR_IA32_PERF_CAPABILITIES:
 		if (data & PMU_CAP_LBR_FMT) {
 			if ((data & PMU_CAP_LBR_FMT) !=
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index b5c4db4b7e04..cc39ace47262 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1885,6 +1885,27 @@ static int __kvm_set_msr(struct kvm_vcpu *vcpu, u32 index, u64 data,
 
 		data = (u32)data;
 		break;
+	case MSR_IA32_U_CET:
+	case MSR_IA32_S_CET:
+		if (!guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK) &&
+		    !guest_cpu_cap_has(vcpu, X86_FEATURE_IBT))
+			return KVM_MSR_RET_UNSUPPORTED;
+		if (!is_cet_msr_valid(vcpu, data))
+			return 1;
+		break;
+	case MSR_KVM_INTERNAL_GUEST_SSP:
+		if (!host_initiated)
+			return 1;
+		fallthrough;
+	case MSR_IA32_PL0_SSP ... MSR_IA32_INT_SSP_TAB:
+		if (!guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK))
+			return KVM_MSR_RET_UNSUPPORTED;
+		if (is_noncanonical_msr_address(data, vcpu))
+			return 1;
+		/* All SSP MSRs except MSR_IA32_INT_SSP_TAB must be 4-byte aligned */
+		if (index != MSR_IA32_INT_SSP_TAB && !IS_ALIGNED(data, 4))
+			return 1;
+		break;
 	}
 
 	msr.data = data;
@@ -1929,6 +1950,20 @@ static int __kvm_get_msr(struct kvm_vcpu *vcpu, u32 index, u64 *data,
 		    !guest_cpu_cap_has(vcpu, X86_FEATURE_RDPID))
 			return 1;
 		break;
+	case MSR_IA32_U_CET:
+	case MSR_IA32_S_CET:
+		if (!guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK) &&
+		    !guest_cpu_cap_has(vcpu, X86_FEATURE_IBT))
+			return KVM_MSR_RET_UNSUPPORTED;
+		break;
+	case MSR_KVM_INTERNAL_GUEST_SSP:
+		if (!host_initiated)
+			return 1;
+		fallthrough;
+	case MSR_IA32_PL0_SSP ... MSR_IA32_INT_SSP_TAB:
+		if (!guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK))
+			return KVM_MSR_RET_UNSUPPORTED;
+		break;
 	}
 
 	msr.index = index;
@@ -4207,6 +4242,10 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 		vcpu->arch.guest_fpu.xfd_err = data;
 		break;
 #endif
+	case MSR_IA32_U_CET:
+	case MSR_IA32_PL0_SSP ... MSR_IA32_PL3_SSP:
+		kvm_set_xstate_msr(vcpu, msr_info);
+		break;
 	default:
 		if (kvm_pmu_is_valid_msr(vcpu, msr))
 			return kvm_pmu_set_msr(vcpu, msr_info);
@@ -4556,6 +4595,10 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 		msr_info->data = vcpu->arch.guest_fpu.xfd_err;
 		break;
 #endif
+	case MSR_IA32_U_CET:
+	case MSR_IA32_PL0_SSP ... MSR_IA32_PL3_SSP:
+		kvm_get_xstate_msr(vcpu, msr_info);
+		break;
 	default:
 		if (kvm_pmu_is_valid_msr(vcpu, msr_info->index))
 			return kvm_pmu_get_msr(vcpu, msr_info);
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
index f8fbd33db067..d5b039addd11 100644
--- a/arch/x86/kvm/x86.h
+++ b/arch/x86/kvm/x86.h
@@ -733,4 +733,27 @@ static inline void kvm_set_xstate_msr(struct kvm_vcpu *vcpu,
 	kvm_fpu_put();
 }
 
+#define CET_US_RESERVED_BITS		GENMASK(9, 6)
+#define CET_US_SHSTK_MASK_BITS		GENMASK(1, 0)
+#define CET_US_IBT_MASK_BITS		(GENMASK_ULL(5, 2) | GENMASK_ULL(63, 10))
+#define CET_US_LEGACY_BITMAP_BASE(data)	((data) >> 12)
+
+static inline bool is_cet_msr_valid(struct kvm_vcpu *vcpu, u64 data)
+{
+	if (data & CET_US_RESERVED_BITS)
+		return false;
+	if (!guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK) &&
+	    (data & CET_US_SHSTK_MASK_BITS))
+		return false;
+	if (!guest_cpu_cap_has(vcpu, X86_FEATURE_IBT) &&
+	    (data & CET_US_IBT_MASK_BITS))
+		return false;
+	if (!IS_ALIGNED(CET_US_LEGACY_BITMAP_BASE(data), 4))
+		return false;
+	/* IBT can be suppressed iff the TRACKER isn't WAIT_ENDBR. */
+	if ((data & CET_SUPPRESS) && (data & CET_WAIT_ENDBR))
+		return false;
+
+	return true;
+}
 #endif
-- 
2.47.1
Re: [PATCH v12 15/24] KVM: VMX: Emulate read and write to CET MSRs
Posted by Sean Christopherson 1 month, 2 weeks ago
On Mon, Aug 11, 2025, Chao Gao wrote:
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index b5c4db4b7e04..cc39ace47262 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -1885,6 +1885,27 @@ static int __kvm_set_msr(struct kvm_vcpu *vcpu, u32 index, u64 data,
>  
>  		data = (u32)data;
>  		break;
> +	case MSR_IA32_U_CET:
> +	case MSR_IA32_S_CET:
> +		if (!guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK) &&
> +		    !guest_cpu_cap_has(vcpu, X86_FEATURE_IBT))
> +			return KVM_MSR_RET_UNSUPPORTED;
> +		if (!is_cet_msr_valid(vcpu, data))
> +			return 1;
> +		break;
> +	case MSR_KVM_INTERNAL_GUEST_SSP:
> +		if (!host_initiated)
> +			return 1;
> +		fallthrough;
> +	case MSR_IA32_PL0_SSP ... MSR_IA32_INT_SSP_TAB:
> +		if (!guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK))
> +			return KVM_MSR_RET_UNSUPPORTED;
> +		if (is_noncanonical_msr_address(data, vcpu))

This emulation is wrong (in no small part because the architecture sucks).  From
the SDM:

  If the processor does not support Intel 64 architecture, these fields have only
  32 bits; bits 63:32 of the MSRs are reserved.

  On processors that support Intel 64 architecture this value cannot represent a
  non-canonical address.

  In protected mode, only 31:0 are loaded.

That means KVM needs to drop bits 63:32 if the vCPU doesn't have LM or if the vCPU
isn't in 64-bit mode.  The last one is especially frustrating, because software
can still get a 64-bit value into the MSRs while running in protected, e.g. by
switching to 64-bit mode, doing WRMSRs, then switching back to 32-bit mode.

But, there's probably no point in actually trying to correctly emulate/virtualize
the Protected Mode behavior, because the MSRs can be written via XRSTOR, and to
close that hole KVM would need to trap-and-emulate XRSTOR.  No thanks.

Unless someone has a better idea, I'm inclined to take an erratum for this, i.e.
just sweep it under the rug.

> +			return 1;
> +		/* All SSP MSRs except MSR_IA32_INT_SSP_TAB must be 4-byte aligned */
> +		if (index != MSR_IA32_INT_SSP_TAB && !IS_ALIGNED(data, 4))
> +			return 1;
> +		break;
>  	}
>  
>  	msr.data = data;

...

> diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
> index f8fbd33db067..d5b039addd11 100644
> --- a/arch/x86/kvm/x86.h
> +++ b/arch/x86/kvm/x86.h
> @@ -733,4 +733,27 @@ static inline void kvm_set_xstate_msr(struct kvm_vcpu *vcpu,
>  	kvm_fpu_put();
>  }
>  
> +#define CET_US_RESERVED_BITS		GENMASK(9, 6)
> +#define CET_US_SHSTK_MASK_BITS		GENMASK(1, 0)
> +#define CET_US_IBT_MASK_BITS		(GENMASK_ULL(5, 2) | GENMASK_ULL(63, 10))
> +#define CET_US_LEGACY_BITMAP_BASE(data)	((data) >> 12)
> +
> +static inline bool is_cet_msr_valid(struct kvm_vcpu *vcpu, u64 data)

This name is misleading, e.g. it reads "is this CET MSR valid", whereas the helper
is checking "is this value for U_CET or S_CET valid".  Maybe kvm_is_valid_u_s_cet()?

> +{
> +	if (data & CET_US_RESERVED_BITS)
> +		return false;
> +	if (!guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK) &&
> +	    (data & CET_US_SHSTK_MASK_BITS))
> +		return false;
> +	if (!guest_cpu_cap_has(vcpu, X86_FEATURE_IBT) &&
> +	    (data & CET_US_IBT_MASK_BITS))
> +		return false;
> +	if (!IS_ALIGNED(CET_US_LEGACY_BITMAP_BASE(data), 4))
> +		return false;
> +	/* IBT can be suppressed iff the TRACKER isn't WAIT_ENDBR. */
> +	if ((data & CET_SUPPRESS) && (data & CET_WAIT_ENDBR))
> +		return false;
> +
> +	return true;
> +}
>  #endif
> -- 
> 2.47.1
>
Re: [PATCH v12 15/24] KVM: VMX: Emulate read and write to CET MSRs
Posted by Chao Gao 1 month, 2 weeks ago
>> +	case MSR_IA32_PL0_SSP ... MSR_IA32_INT_SSP_TAB:
>> +		if (!guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK))
>> +			return KVM_MSR_RET_UNSUPPORTED;
>> +		if (is_noncanonical_msr_address(data, vcpu))
>
>This emulation is wrong (in no small part because the architecture sucks).  From
>the SDM:
>
>  If the processor does not support Intel 64 architecture, these fields have only
>  32 bits; bits 63:32 of the MSRs are reserved.
>
>  On processors that support Intel 64 architecture this value cannot represent a
>  non-canonical address.
>
>  In protected mode, only 31:0 are loaded.
>
>That means KVM needs to drop bits 63:32 if the vCPU doesn't have LM or if the vCPU
>isn't in 64-bit mode.  The last one is especially frustrating, because software
>can still get a 64-bit value into the MSRs while running in protected, e.g. by
>switching to 64-bit mode, doing WRMSRs, then switching back to 32-bit mode.
>
>But, there's probably no point in actually trying to correctly emulate/virtualize
>the Protected Mode behavior, because the MSRs can be written via XRSTOR, and to
>close that hole KVM would need to trap-and-emulate XRSTOR.  No thanks.

I don't get why we need to trap-and-emulate XRSTOR. if XRSTOR instruction in
protection mode can change higher 32 bits of CET MSRs, it is the hardware
behavior. why KVM needs to clear the higher 32 bits?

>
>Unless someone has a better idea, I'm inclined to take an erratum for this, i.e.
>just sweep it under the rug.
>
>> +			return 1;
>> +		/* All SSP MSRs except MSR_IA32_INT_SSP_TAB must be 4-byte aligned */
>> +		if (index != MSR_IA32_INT_SSP_TAB && !IS_ALIGNED(data, 4))
>> +			return 1;
>> +		break;
>>  	}
>>  
>>  	msr.data = data;
>
>...
>
>> diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
>> index f8fbd33db067..d5b039addd11 100644
>> --- a/arch/x86/kvm/x86.h
>> +++ b/arch/x86/kvm/x86.h
>> @@ -733,4 +733,27 @@ static inline void kvm_set_xstate_msr(struct kvm_vcpu *vcpu,
>>  	kvm_fpu_put();
>>  }
>>  
>> +#define CET_US_RESERVED_BITS		GENMASK(9, 6)
>> +#define CET_US_SHSTK_MASK_BITS		GENMASK(1, 0)
>> +#define CET_US_IBT_MASK_BITS		(GENMASK_ULL(5, 2) | GENMASK_ULL(63, 10))
>> +#define CET_US_LEGACY_BITMAP_BASE(data)	((data) >> 12)
>> +
>> +static inline bool is_cet_msr_valid(struct kvm_vcpu *vcpu, u64 data)
>
>This name is misleading, e.g. it reads "is this CET MSR valid", whereas the helper
>is checking "is this value for U_CET or S_CET valid".  Maybe kvm_is_valid_u_s_cet()?

Will do.
Re: [PATCH v12 15/24] KVM: VMX: Emulate read and write to CET MSRs
Posted by Sean Christopherson 1 month, 2 weeks ago
On Wed, Aug 20, 2025, Chao Gao wrote:
> >> +	case MSR_IA32_PL0_SSP ... MSR_IA32_INT_SSP_TAB:
> >> +		if (!guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK))
> >> +			return KVM_MSR_RET_UNSUPPORTED;
> >> +		if (is_noncanonical_msr_address(data, vcpu))
> >
> >This emulation is wrong (in no small part because the architecture sucks).  From
> >the SDM:
> >
> >  If the processor does not support Intel 64 architecture, these fields have only
> >  32 bits; bits 63:32 of the MSRs are reserved.
> >
> >  On processors that support Intel 64 architecture this value cannot represent a
> >  non-canonical address.
> >
> >  In protected mode, only 31:0 are loaded.
> >
> >That means KVM needs to drop bits 63:32 if the vCPU doesn't have LM or if the vCPU
> >isn't in 64-bit mode.  The last one is especially frustrating, because software
> >can still get a 64-bit value into the MSRs while running in protected, e.g. by
> >switching to 64-bit mode, doing WRMSRs, then switching back to 32-bit mode.
> >
> >But, there's probably no point in actually trying to correctly emulate/virtualize
> >the Protected Mode behavior, because the MSRs can be written via XRSTOR, and to
> >close that hole KVM would need to trap-and-emulate XRSTOR.  No thanks.
> 
> I don't get why we need to trap-and-emulate XRSTOR. if XRSTOR instruction in
> protection mode can change higher 32 bits of CET MSRs, it is the hardware
> behavior. why KVM needs to clear the higher 32 bits?

If the VMM configures the virtual CPU model to be a 32-bit CPU, i.e. a vCPU that
"does not support Intel 64 architecture", i.e. CPUID.0x80000001.EDX.LM = 0, then
the behavior of the "hardware" that the guest sees should be that the upper 32
bits do not exist and should always read '0'.  But because the actual harware on
which the virtual CPU is running _does_ support Intel 64, XRSTORS/XSAVES in the
guest could observe behavior that violates the architecture.
Re: [PATCH v12 15/24] KVM: VMX: Emulate read and write to CET MSRs
Posted by Xin Li 1 month, 2 weeks ago
On 8/19/2025 9:09 AM, Sean Christopherson wrote:
>> +	case MSR_IA32_PL0_SSP ... MSR_IA32_INT_SSP_TAB:
>> +		if (!guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK))
>> +			return KVM_MSR_RET_UNSUPPORTED;
>> +		if (is_noncanonical_msr_address(data, vcpu))
> This emulation is wrong (in no small part because the architecture sucks).  From
> the SDM:
> 
>    If the processor does not support Intel 64 architecture, these fields have only
>    32 bits; bits 63:32 of the MSRs are reserved.
> 
>    On processors that support Intel 64 architecture this value cannot represent a
>    non-canonical address.
> 
>    In protected mode, only 31:0 are loaded.
> 
> That means KVM needs to drop bits 63:32 if the vCPU doesn't have LM or if the vCPU
> isn't in 64-bit mode.  The last one is especially frustrating, because software
> can still get a 64-bit value into the MSRs while running in protected, e.g. by
> switching to 64-bit mode, doing WRMSRs, then switching back to 32-bit mode.
> 
> But, there's probably no point in actually trying to correctly emulate/virtualize
> the Protected Mode behavior, because the MSRs can be written via XRSTOR, and to
> close that hole KVM would need to trap-and-emulate XRSTOR.  No thanks.
> 
> Unless someone has a better idea, I'm inclined to take an erratum for this, i.e.
> just sweep it under the rug.

Since WRMSR (WRMSRNS) and XRSTORS are the two instructions that write to
MSRs in CPL0, Why KVM doesn't use the XSS-exiting bitmap?
Re: [PATCH v12 15/24] KVM: VMX: Emulate read and write to CET MSRs
Posted by Sean Christopherson 1 month, 2 weeks ago
On Tue, Aug 19, 2025, Xin Li wrote:
> On 8/19/2025 9:09 AM, Sean Christopherson wrote:
> > > +	case MSR_IA32_PL0_SSP ... MSR_IA32_INT_SSP_TAB:
> > > +		if (!guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK))
> > > +			return KVM_MSR_RET_UNSUPPORTED;
> > > +		if (is_noncanonical_msr_address(data, vcpu))
> > This emulation is wrong (in no small part because the architecture sucks).  From
> > the SDM:
> > 
> >    If the processor does not support Intel 64 architecture, these fields have only
> >    32 bits; bits 63:32 of the MSRs are reserved.
> > 
> >    On processors that support Intel 64 architecture this value cannot represent a
> >    non-canonical address.
> > 
> >    In protected mode, only 31:0 are loaded.
> > 
> > That means KVM needs to drop bits 63:32 if the vCPU doesn't have LM or if the vCPU
> > isn't in 64-bit mode.  The last one is especially frustrating, because software
> > can still get a 64-bit value into the MSRs while running in protected, e.g. by
> > switching to 64-bit mode, doing WRMSRs, then switching back to 32-bit mode.
> > 
> > But, there's probably no point in actually trying to correctly emulate/virtualize
> > the Protected Mode behavior, because the MSRs can be written via XRSTOR, and to
> > close that hole KVM would need to trap-and-emulate XRSTOR.  No thanks.
> > 
> > Unless someone has a better idea, I'm inclined to take an erratum for this, i.e.
> > just sweep it under the rug.
> 
> Since WRMSR (WRMSRNS) and XRSTORS are the two instructions that write to
> MSRs in CPL0, Why KVM doesn't use the XSS-exiting bitmap?

Intercepting XRSTORS would introduce (likely) unacceptable performance overhead
if a guest actually used CET in PM, I have zero desire to try and proxy/emulate
XRSTORS from guest memory in KVM, and CET already has big gaping virtualization
holes.
Re: [PATCH v12 15/24] KVM: VMX: Emulate read and write to CET MSRs
Posted by Edgecombe, Rick P 1 month, 2 weeks ago
On Tue, 2025-08-19 at 09:09 -0700, Sean Christopherson wrote:
> This emulation is wrong (in no small part because the architecture sucks).  From
> the SDM:
> 
>   If the processor does not support Intel 64 architecture, these fields have only
>   32 bits; bits 63:32 of the MSRs are reserved.
> 
>   On processors that support Intel 64 architecture this value cannot represent a
>   non-canonical address.
> 
>   In protected mode, only 31:0 are loaded.
> 
> That means KVM needs to drop bits 63:32 if the vCPU doesn't have LM or if the vCPU
> isn't in 64-bit mode.  The last one is especially frustrating, because software
> can still get a 64-bit value into the MSRs while running in protected, e.g. by
> switching to 64-bit mode, doing WRMSRs, then switching back to 32-bit mode.
> 
> But, there's probably no point in actually trying to correctly emulate/virtualize
> the Protected Mode behavior, because the MSRs can be written via XRSTOR, and to
> close that hole KVM would need to trap-and-emulate XRSTOR.  No thanks.
> 
> Unless someone has a better idea, I'm inclined to take an erratum for this, i.e.
> just sweep it under the rug.

Sounds ok to me. All I could think would be something like use the CR/EFER
interceptions and just exit to userspace if (CR0.PE && !EFER.LM && CR4.CET). But
this would require some rototilling and then likely remain un-exercised. Not
sure it's worth it.
Re: [PATCH v12 15/24] KVM: VMX: Emulate read and write to CET MSRs
Posted by Sean Christopherson 1 month, 2 weeks ago
On Tue, Aug 19, 2025, Rick P Edgecombe wrote:
> On Tue, 2025-08-19 at 09:09 -0700, Sean Christopherson wrote:
> > This emulation is wrong (in no small part because the architecture sucks).  From
> > the SDM:
> > 
> >   If the processor does not support Intel 64 architecture, these fields have only
> >   32 bits; bits 63:32 of the MSRs are reserved.
> > 
> >   On processors that support Intel 64 architecture this value cannot represent a
> >   non-canonical address.
> > 
> >   In protected mode, only 31:0 are loaded.
> > 
> > That means KVM needs to drop bits 63:32 if the vCPU doesn't have LM or if the vCPU
> > isn't in 64-bit mode.  The last one is especially frustrating, because software
> > can still get a 64-bit value into the MSRs while running in protected, e.g. by
> > switching to 64-bit mode, doing WRMSRs, then switching back to 32-bit mode.
> > 
> > But, there's probably no point in actually trying to correctly emulate/virtualize
> > the Protected Mode behavior, because the MSRs can be written via XRSTOR, and to
> > close that hole KVM would need to trap-and-emulate XRSTOR.  No thanks.
> > 
> > Unless someone has a better idea, I'm inclined to take an erratum for this, i.e.
> > just sweep it under the rug.
> 
> Sounds ok to me. All I could think would be something like use the CR/EFER
> interceptions and just exit to userspace if (CR0.PE && !EFER.LM && CR4.CET). But
> this would require some rototilling and then likely remain un-exercised.

And a far worse experience if a guest did ever trip that combo.  Letting the guest
set bits 63:32 would only cause problems if the guest is being deliberately weird,
whereas exiting to userspace would terminate even well-behaved guests (though as
you note, the odds of a 32-bit guest using CET is quite small...).

> Not sure it's worth it.