On Wed, Feb 07, 2024, Xin Li wrote:
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 264378c3b784..ee61d2c25cb0 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -1420,6 +1420,24 @@ static void vmx_write_guest_kernel_gs_base(struct vcpu_vmx *vmx, u64 data) preempt_enable(); vmx->msr_guest_kernel_gs_base = data; }
+static u64 vmx_read_guest_fred_rsp0(struct vcpu_vmx *vmx) +{
- preempt_disable();
- if (vmx->guest_state_loaded)
vmx->msr_guest_fred_rsp0 = read_msr(MSR_IA32_FRED_RSP0);
- preempt_enable();
- return vmx->msr_guest_fred_rsp0;
+}
+static void vmx_write_guest_fred_rsp0(struct vcpu_vmx *vmx, u64 data) +{
- preempt_disable();
- if (vmx->guest_state_loaded)
wrmsrl(MSR_IA32_FRED_RSP0, data);
- preempt_enable();
- vmx->msr_guest_fred_rsp0 = data;
+}
This should be unnecessary when you switch to the user return framework.
KERNEL_GS_BASE is a bit special because it needs to be reloaded if the kernel switches to a different task, i.e. before an exit to userspace.
@@ -1892,6 +1895,30 @@ static int __kvm_set_msr(struct kvm_vcpu *vcpu, u32 index, u64 data, return 1; data = (u32)data;
break;
- case MSR_IA32_FRED_RSP0 ... MSR_IA32_FRED_CONFIG:
if (index != MSR_IA32_FRED_STKLVLS && is_noncanonical_address(data, vcpu))
return 1;
if ((index >= MSR_IA32_FRED_RSP0 && index <= MSR_IA32_FRED_RSP3) &&
(data & GENMASK_ULL(5, 0)))
return 1;
if ((index >= MSR_IA32_FRED_SSP1 && index <= MSR_IA32_FRED_SSP3) &&
(data & GENMASK_ULL(2, 0)))
return 1;
if (host_initiated) {
if (!kvm_cpu_cap_has(X86_FEATURE_FRED))
return 1;
} else {
/*
* Inject #GP upon FRED MSRs accesses from a non-FRED guest,
* which also ensures no malicious guest can write to FRED
* MSRs to corrupt host FRED MSRs.
*/
Drop the comment, if someone reading KVM code doesn't grok that attempting to access MSRs that shouldn't exist results in #GP, then a comment probably isn't going to save them.
This should also be bumped to the top, i.e. do the "does this exist check" first.
Lastly, the direction we are taking is to NOT exempt host-initiated writes, i.e. userspace has to set CPUID before MSRs. If you base the next version on top of this series, it should just work (and if it doesn't, I definitely want to know):
https://lore.kernel.org/all/20240425181422.3250947-1-seanjc@google.com
if (!guest_can_use(vcpu, X86_FEATURE_FRED))
return 1;
}
Uh, where does the value go? Oh, this is common code. Ah, and it's in common code so that VMX can avoid having to make an extra function call for every MSR. Neat.
break;
} @@ -1936,6 +1963,22 @@ int __kvm_get_msr(struct kvm_vcpu *vcpu, u32 index, u64 *data, !guest_cpuid_has(vcpu, X86_FEATURE_RDPID)) return 1; break;
- case MSR_IA32_FRED_RSP0 ... MSR_IA32_FRED_CONFIG:
if (host_initiated) {
if (!kvm_cpu_cap_has(X86_FEATURE_FRED))
return 1;
} else {
/*
* Inject #GP upon FRED MSRs accesses from a non-FRED guest,
* which also ensures no malicious guest can write to FRED
* MSRs to corrupt host FRED MSRs.
*/
if (!guest_can_use(vcpu, X86_FEATURE_FRED))
return 1;
}
Same comments here.