1935ace2fSThomas Gleixner // SPDX-License-Identifier: GPL-2.0 2935ace2fSThomas Gleixner 3935ace2fSThomas Gleixner #include <linux/entry-kvm.h> 4935ace2fSThomas Gleixner #include <linux/kvm_host.h> 5935ace2fSThomas Gleixner 6935ace2fSThomas Gleixner static int xfer_to_guest_mode_work(struct kvm_vcpu *vcpu, unsigned long ti_work) 7935ace2fSThomas Gleixner { 8935ace2fSThomas Gleixner do { 9935ace2fSThomas Gleixner int ret; 10935ace2fSThomas Gleixner 11*7c5d8fa6SEric W. Biederman if (ti_work & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL)) { 12*7c5d8fa6SEric W. Biederman clear_notify_signal(); 13*7c5d8fa6SEric W. Biederman if (task_work_pending(current)) 14*7c5d8fa6SEric W. Biederman task_work_run(); 15*7c5d8fa6SEric W. Biederman } 1612db8b69SJens Axboe 17935ace2fSThomas Gleixner if (ti_work & _TIF_SIGPENDING) { 18935ace2fSThomas Gleixner kvm_handle_signal_exit(vcpu); 19935ace2fSThomas Gleixner return -EINTR; 20935ace2fSThomas Gleixner } 21935ace2fSThomas Gleixner 22935ace2fSThomas Gleixner if (ti_work & _TIF_NEED_RESCHED) 23935ace2fSThomas Gleixner schedule(); 24935ace2fSThomas Gleixner 253c532798SJens Axboe if (ti_work & _TIF_NOTIFY_RESUME) 26935ace2fSThomas Gleixner tracehook_notify_resume(NULL); 27935ace2fSThomas Gleixner 28935ace2fSThomas Gleixner ret = arch_xfer_to_guest_mode_handle_work(vcpu, ti_work); 29935ace2fSThomas Gleixner if (ret) 30935ace2fSThomas Gleixner return ret; 31935ace2fSThomas Gleixner 326ce89512SMark Rutland ti_work = read_thread_flags(); 33935ace2fSThomas Gleixner } while (ti_work & XFER_TO_GUEST_MODE_WORK || need_resched()); 34935ace2fSThomas Gleixner return 0; 35935ace2fSThomas Gleixner } 36935ace2fSThomas Gleixner 37935ace2fSThomas Gleixner int xfer_to_guest_mode_handle_work(struct kvm_vcpu *vcpu) 38935ace2fSThomas Gleixner { 39935ace2fSThomas Gleixner unsigned long ti_work; 40935ace2fSThomas Gleixner 41935ace2fSThomas Gleixner /* 42935ace2fSThomas Gleixner * This is invoked from the outer guest loop with interrupts and 43935ace2fSThomas Gleixner * preemption enabled. 44935ace2fSThomas Gleixner * 45935ace2fSThomas Gleixner * KVM invokes xfer_to_guest_mode_work_pending() with interrupts 46935ace2fSThomas Gleixner * disabled in the inner loop before going into guest mode. No need 47935ace2fSThomas Gleixner * to disable interrupts here. 48935ace2fSThomas Gleixner */ 496ce89512SMark Rutland ti_work = read_thread_flags(); 50935ace2fSThomas Gleixner if (!(ti_work & XFER_TO_GUEST_MODE_WORK)) 51935ace2fSThomas Gleixner return 0; 52935ace2fSThomas Gleixner 53935ace2fSThomas Gleixner return xfer_to_guest_mode_work(vcpu, ti_work); 54935ace2fSThomas Gleixner } 55935ace2fSThomas Gleixner EXPORT_SYMBOL_GPL(xfer_to_guest_mode_handle_work); 56