From: Mihai Donțu <mdontu@xxxxxxxxxxxxxxx> The introspection requests (KVM_REQ_INTROSPECTION) are checked by any introspected vCPU in two places: * on its way to guest - vcpu_enter_guest() * when halted - kvm_vcpu_block() In kvm_vcpu_block(), we check to see if there are any introspection requests during the swait loop, handle them outside of swait loop and start swait again. Signed-off-by: Mihai Donțu <mdontu@xxxxxxxxxxxxxxx> Co-developed-by: Mircea Cîrjaliu <mcirjaliu@xxxxxxxxxxxxxxx> Signed-off-by: Mircea Cîrjaliu <mcirjaliu@xxxxxxxxxxxxxxx> Signed-off-by: Adalbert Lazăr <alazar@xxxxxxxxxxxxxxx> --- arch/x86/kvm/x86.c | 3 +++ include/linux/kvmi.h | 2 ++ virt/kvm/kvm_main.c | 28 ++++++++++++++++++++++------ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 0163e1ad1aaa..adbdb1ceb618 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -7742,6 +7742,9 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) */ if (kvm_check_request(KVM_REQ_HV_STIMER, vcpu)) kvm_hv_process_stimers(vcpu); + + if (kvm_check_request(KVM_REQ_INTROSPECTION, vcpu)) + kvmi_handle_requests(vcpu); } if (kvm_check_request(KVM_REQ_EVENT, vcpu) || req_int_win) { diff --git a/include/linux/kvmi.h b/include/linux/kvmi.h index e8d25d7da751..ae5de1905b55 100644 --- a/include/linux/kvmi.h +++ b/include/linux/kvmi.h @@ -16,6 +16,7 @@ int kvmi_ioctl_event(struct kvm *kvm, void __user *argp); int kvmi_ioctl_unhook(struct kvm *kvm, bool force_reset); int kvmi_vcpu_init(struct kvm_vcpu *vcpu); void kvmi_vcpu_uninit(struct kvm_vcpu *vcpu); +void kvmi_handle_requests(struct kvm_vcpu *vcpu); #else @@ -25,6 +26,7 @@ static inline void kvmi_create_vm(struct kvm *kvm) { } static inline void kvmi_destroy_vm(struct kvm *kvm) { } static inline int kvmi_vcpu_init(struct kvm_vcpu *vcpu) { return 0; } static inline void kvmi_vcpu_uninit(struct kvm_vcpu *vcpu) { } +static inline void kvmi_handle_requests(struct kvm_vcpu *vcpu) { } #endif /* CONFIG_KVM_INTROSPECTION */ diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 94f15f393e37..2e11069b9565 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -2282,16 +2282,32 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu) kvm_arch_vcpu_blocking(vcpu); for (;;) { - prepare_to_swait_exclusive(&vcpu->wq, &wait, TASK_INTERRUPTIBLE); + bool do_kvmi_work = false; - if (kvm_vcpu_check_block(vcpu) < 0) - break; + for (;;) { + prepare_to_swait_exclusive(&vcpu->wq, &wait, + TASK_INTERRUPTIBLE); + + if (kvm_vcpu_check_block(vcpu) < 0) + break; + + waited = true; + schedule(); + + if (kvm_check_request(KVM_REQ_INTROSPECTION, vcpu)) { + do_kvmi_work = true; + break; + } + } - waited = true; - schedule(); + finish_swait(&vcpu->wq, &wait); + + if (do_kvmi_work) + kvmi_handle_requests(vcpu); + else + break; } - finish_swait(&vcpu->wq, &wait); cur = ktime_get(); kvm_arch_vcpu_unblocking(vcpu);