Skip to content

Commit 1c932fc

Browse files
committed
KVM: x86: Add lockdep-guarded asserts on register cache usage
When lockdep is enabled, assert that KVM accesses the register caches if and only if cache fills are guaranteed to consume fresh data, i.e. when KVM when KVM is in control of the code sequence. Concretely, the caches can only be used from task context (synchronous) or when handling a PMI VM-Exit (asynchronous, but only in specific windows where the caches are in a known, stable state). Generally speaking, there are very few flows where reading register state from an asynchronous context is correct or even necessary. So, rather than trying to figure out a generic solution, simply disallow using the caches outside of task context by default, and deal with any future exceptions on a case-by-case basis _if_ they arise. Reviewed-by: Maxim Levitsky <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Sean Christopherson <[email protected]>
1 parent f0e7012 commit 1c932fc

File tree

1 file changed

+17
-0
lines changed

1 file changed

+17
-0
lines changed

arch/x86/kvm/kvm_cache_regs.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,18 @@ BUILD_KVM_GPR_ACCESSORS(r14, R14)
4343
BUILD_KVM_GPR_ACCESSORS(r15, R15)
4444
#endif
4545

46+
/*
47+
* Using the register cache from interrupt context is generally not allowed, as
48+
* caching a register and marking it available/dirty can't be done atomically,
49+
* i.e. accesses from interrupt context may clobber state or read stale data if
50+
* the vCPU task is in the process of updating the cache. The exception is if
51+
* KVM is handling a PMI IRQ/NMI VM-Exit, as that bound code sequence doesn't
52+
* touch the cache, it runs after the cache is reset (post VM-Exit), and PMIs
53+
* need to access several registers that are cacheable.
54+
*/
55+
#define kvm_assert_register_caching_allowed(vcpu) \
56+
lockdep_assert_once(in_task() || kvm_arch_pmi_in_guest(vcpu))
57+
4658
/*
4759
* avail dirty
4860
* 0 0 register in VMCS/VMCB
@@ -53,24 +65,28 @@ BUILD_KVM_GPR_ACCESSORS(r15, R15)
5365
static inline bool kvm_register_is_available(struct kvm_vcpu *vcpu,
5466
enum kvm_reg reg)
5567
{
68+
kvm_assert_register_caching_allowed(vcpu);
5669
return test_bit(reg, (unsigned long *)&vcpu->arch.regs_avail);
5770
}
5871

5972
static inline bool kvm_register_is_dirty(struct kvm_vcpu *vcpu,
6073
enum kvm_reg reg)
6174
{
75+
kvm_assert_register_caching_allowed(vcpu);
6276
return test_bit(reg, (unsigned long *)&vcpu->arch.regs_dirty);
6377
}
6478

6579
static inline void kvm_register_mark_available(struct kvm_vcpu *vcpu,
6680
enum kvm_reg reg)
6781
{
82+
kvm_assert_register_caching_allowed(vcpu);
6883
__set_bit(reg, (unsigned long *)&vcpu->arch.regs_avail);
6984
}
7085

7186
static inline void kvm_register_mark_dirty(struct kvm_vcpu *vcpu,
7287
enum kvm_reg reg)
7388
{
89+
kvm_assert_register_caching_allowed(vcpu);
7490
__set_bit(reg, (unsigned long *)&vcpu->arch.regs_avail);
7591
__set_bit(reg, (unsigned long *)&vcpu->arch.regs_dirty);
7692
}
@@ -84,6 +100,7 @@ static inline void kvm_register_mark_dirty(struct kvm_vcpu *vcpu,
84100
static __always_inline bool kvm_register_test_and_mark_available(struct kvm_vcpu *vcpu,
85101
enum kvm_reg reg)
86102
{
103+
kvm_assert_register_caching_allowed(vcpu);
87104
return arch___test_and_set_bit(reg, (unsigned long *)&vcpu->arch.regs_avail);
88105
}
89106

0 commit comments

Comments
 (0)