* [PATCH 1/2] KVM: VMX: Treat UMIP as emulated if and only if the host doesn't have UMIP
2023-04-13 23:19 [PATCH 0/2] KVM: VMX: UMIP emulation related cleanups Sean Christopherson
@ 2023-04-13 23:19 ` Sean Christopherson
2023-04-13 23:19 ` [PATCH 2/2] KVM: VMX: Use proper accessor to read guest CR4 in handle_desc() Sean Christopherson
2023-06-02 1:25 ` [PATCH 0/2] KVM: VMX: UMIP emulation related cleanups Sean Christopherson
2 siblings, 0 replies; 4+ messages in thread
From: Sean Christopherson @ 2023-04-13 23:19 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, linux-kernel, Robert Hoo
Advertise UMIP as emulated if and only if the host doesn't natively
support UMIP, otherwise vmx_umip_emulated() is misleading when the host
_does_ support UMIP. Of the four users of vmx_umip_emulated(), two
already check for native support, and the logic in vmx_set_cpu_caps() is
relevant if and only if UMIP isn't natively supported as UMIP is set in
KVM's caps by kvm_set_cpu_caps() when UMIP is present in hardware.
That leaves KVM's stuffing of X86_CR4_UMIP into the default cr4_fixed1
value enumerated for nested VMX. In that case, checking for (lack of)
host support is actually a bug fix of sorts, as enumerating UMIP support
based solely on descriptor table exiting works only because KVM doesn't
sanity check MSR_IA32_VMX_CR4_FIXED1. E.g. if a (very theoretical) host
supported UMIP in hardware but didn't allow UMIP+VMX, KVM would advertise
UMIP but not actually emulate UMIP. Of course, KVM would explode long
before it could run a nested VM on said theoretical CPU, as KVM doesn't
modify host CR4 when enabling VMX, i.e. would load an "illegal" value into
vmcs.HOST_CR4.
Reported-by: Robert Hoo <robert.hu@intel.com>
Link: https://lore.kernel.org/all/20230310125718.1442088-2-robert.hu@intel.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/kvm/vmx/capabilities.h | 4 ++--
arch/x86/kvm/vmx/nested.c | 3 +--
arch/x86/kvm/vmx/vmx.c | 2 +-
3 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/arch/x86/kvm/vmx/capabilities.h b/arch/x86/kvm/vmx/capabilities.h
index 45162c1bcd8f..d0abee35d7ba 100644
--- a/arch/x86/kvm/vmx/capabilities.h
+++ b/arch/x86/kvm/vmx/capabilities.h
@@ -152,8 +152,8 @@ static inline bool cpu_has_vmx_ept(void)
static inline bool vmx_umip_emulated(void)
{
- return vmcs_config.cpu_based_2nd_exec_ctrl &
- SECONDARY_EXEC_DESC;
+ return !boot_cpu_has(X86_FEATURE_UMIP) &&
+ (vmcs_config.cpu_based_2nd_exec_ctrl & SECONDARY_EXEC_DESC);
}
static inline bool cpu_has_vmx_rdtscp(void)
diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
index 96ede74a6067..4fadf6c661d5 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -2328,8 +2328,7 @@ static void prepare_vmcs02_early(struct vcpu_vmx *vmx, struct loaded_vmcs *vmcs0
* Preset *DT exiting when emulating UMIP, so that vmx_set_cr4()
* will not have to rewrite the controls just for this bit.
*/
- if (!boot_cpu_has(X86_FEATURE_UMIP) && vmx_umip_emulated() &&
- (vmcs12->guest_cr4 & X86_CR4_UMIP))
+ if (vmx_umip_emulated() && (vmcs12->guest_cr4 & X86_CR4_UMIP))
exec_control |= SECONDARY_EXEC_DESC;
if (exec_control & SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY)
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 44fb619803b8..57464c762c79 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -3404,7 +3404,7 @@ void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
else
hw_cr4 |= KVM_PMODE_VM_CR4_ALWAYS_ON;
- if (!boot_cpu_has(X86_FEATURE_UMIP) && vmx_umip_emulated()) {
+ if (vmx_umip_emulated()) {
if (cr4 & X86_CR4_UMIP) {
secondary_exec_controls_setbit(vmx, SECONDARY_EXEC_DESC);
hw_cr4 &= ~X86_CR4_UMIP;
--
2.40.0.634.g4ca3ef3211-goog
^ permalink raw reply [flat|nested] 4+ messages in thread* [PATCH 2/2] KVM: VMX: Use proper accessor to read guest CR4 in handle_desc()
2023-04-13 23:19 [PATCH 0/2] KVM: VMX: UMIP emulation related cleanups Sean Christopherson
2023-04-13 23:19 ` [PATCH 1/2] KVM: VMX: Treat UMIP as emulated if and only if the host doesn't have UMIP Sean Christopherson
@ 2023-04-13 23:19 ` Sean Christopherson
2023-06-02 1:25 ` [PATCH 0/2] KVM: VMX: UMIP emulation related cleanups Sean Christopherson
2 siblings, 0 replies; 4+ messages in thread
From: Sean Christopherson @ 2023-04-13 23:19 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, linux-kernel, Robert Hoo
Use kvm_is_cr4_bit_set() to read guest CR4.UMIP when sanity checking that
a descriptor table VM-Exit occurs if and only if guest.CR4.UMIP=1. UMIP
can't be guest-owned, i.e. using kvm_read_cr4_bits() to decache guest-
owned bits isn't strictly necessary, but eliminating raw reads of
vcpu->arch.cr4 is desirable as it makes it easy to visually audit KVM for
correctness.
Opportunistically add a compile-time assertion that UMIP isn't guest-owned
as letting the guest own UMIP isn't compatible with emulation (or any CR4
bit that is emulated by KVM).
Opportunistically change the WARN_ON() to a ONCE variant. When the WARN
fires, it fires _a lot_, and spamming the kernel logs ends up doing more
harm than whatever led to KVM's unnecessary emulation.
Reported-by: Robert Hoo <robert.hu@intel.com>
Link: https://lore.kernel.org/all/20230310125718.1442088-4-robert.hu@intel.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/kvm/vmx/vmx.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 57464c762c79..f0975e790f7f 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -5402,7 +5402,13 @@ static int handle_set_cr4(struct kvm_vcpu *vcpu, unsigned long val)
static int handle_desc(struct kvm_vcpu *vcpu)
{
- WARN_ON(!(vcpu->arch.cr4 & X86_CR4_UMIP));
+ /*
+ * UMIP emulation relies on intercepting writes to CR4.UMIP, i.e. this
+ * and other code needs to be updated if UMIP can be guest owned.
+ */
+ BUILD_BUG_ON(KVM_POSSIBLE_CR4_GUEST_BITS & X86_CR4_UMIP);
+
+ WARN_ON_ONCE(!kvm_is_cr4_bit_set(vcpu, X86_CR4_UMIP));
return kvm_emulate_instruction(vcpu, 0);
}
--
2.40.0.634.g4ca3ef3211-goog
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH 0/2] KVM: VMX: UMIP emulation related cleanups
2023-04-13 23:19 [PATCH 0/2] KVM: VMX: UMIP emulation related cleanups Sean Christopherson
2023-04-13 23:19 ` [PATCH 1/2] KVM: VMX: Treat UMIP as emulated if and only if the host doesn't have UMIP Sean Christopherson
2023-04-13 23:19 ` [PATCH 2/2] KVM: VMX: Use proper accessor to read guest CR4 in handle_desc() Sean Christopherson
@ 2023-06-02 1:25 ` Sean Christopherson
2 siblings, 0 replies; 4+ messages in thread
From: Sean Christopherson @ 2023-06-02 1:25 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, linux-kernel, Robert Hoo
On Thu, 13 Apr 2023 16:19:12 -0700, Sean Christopherson wrote:
> Two cleanups for UMIP related code, identified by Robert. These are
> *almost* purely cosmetic, I don't expect any functional impact on real
> world setups.
>
> Sean Christopherson (2):
> KVM: VMX: Treat UMIP as emulated if and only if the host doesn't have
> UMIP
> KVM: VMX: Use proper accessor to read guest CR4 in handle_desc()
>
> [...]
Applied to kvm-x86 vmx, thanks!
[1/2] KVM: VMX: Treat UMIP as emulated if and only if the host doesn't have UMIP
https://github.com/kvm-x86/linux/commit/3243b93c16d9
[2/2] KVM: VMX: Use proper accessor to read guest CR4 in handle_desc()
https://github.com/kvm-x86/linux/commit/023cfa6fc200
--
https://github.com/kvm-x86/linux/tree/next
https://github.com/kvm-x86/linux/tree/fixes
^ permalink raw reply [flat|nested] 4+ messages in thread