Add an APIs to assert that a vCPU is unreachable, along with a helper to deduplicate the "is unreachable" logic with the existing "assert the vCPU is locked or unreachable". The new assert API will be used by VMX to ensure a not-so-innocuous vCPU teardown helper is really only used when the vCPU is unreachable and being destroyed.
Disallow using the query API without lockdep to prevent it from being used to make control-flow decisions in KVM. Taking different actions based on whether or not a vCPU is reachable isn't fundamentally broken, but would all but guarantee other code _is_ flawed and/or brittle, e.g. that unwind error code relies on common functionality to behave differently. Signed-off-by: Sean Christopherson <[email protected]> --- include/linux/kvm_host.h | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index ba8ea62b7304..28a0c01d6a55 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -984,11 +984,26 @@ static inline struct kvm_io_bus *kvm_get_bus(struct kvm *kvm, enum kvm_bus idx) lockdep_is_held(&kvm->slots_lock)); } +static inline bool kvm_is_vcpu_unreachable(struct kvm_vcpu *vcpu) +{ + /* + * There is no actual dependency on lockdep, but generally speaking KVM + * shouldn't be making runtime decisions based on whether or not a vCPU + * is reachable. + */ + BUILD_BUG_ON(!IS_ENABLED(CONFIG_LOCKDEP)); + return vcpu->vcpu_idx < 0 || !refcount_read(&vcpu->kvm->users_count); +} + +static inline void kvm_lockdep_assert_vcpu_is_unreachable(struct kvm_vcpu *vcpu) +{ + lockdep_assert_once(kvm_is_vcpu_unreachable(vcpu)); +} + static inline void kvm_lockdep_assert_vcpu_is_locked_or_unreachable(struct kvm_vcpu *vcpu) { lockdep_assert_once(lockdep_is_held(&vcpu->mutex) || - vcpu->vcpu_idx < 0 || - !refcount_read(&vcpu->kvm->users_count)); + kvm_is_vcpu_unreachable(vcpu)); } static inline struct kvm_vcpu *kvm_get_vcpu(struct kvm *kvm, int i) -- 2.56.0.385.gac671c819a-goog
