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*12db8b69SJens Axboe if (ti_work & _TIF_NOTIFY_SIGNAL) 12*12db8b69SJens Axboe tracehook_notify_signal(); 13*12db8b69SJens Axboe 14935ace2fSThomas Gleixner if (ti_work & _TIF_SIGPENDING) { 15935ace2fSThomas Gleixner kvm_handle_signal_exit(vcpu); 16935ace2fSThomas Gleixner return -EINTR; 17935ace2fSThomas Gleixner } 18935ace2fSThomas Gleixner 19935ace2fSThomas Gleixner if (ti_work & _TIF_NEED_RESCHED) 20935ace2fSThomas Gleixner schedule(); 21935ace2fSThomas Gleixner 22935ace2fSThomas Gleixner if (ti_work & _TIF_NOTIFY_RESUME) { 23935ace2fSThomas Gleixner clear_thread_flag(TIF_NOTIFY_RESUME); 24935ace2fSThomas Gleixner tracehook_notify_resume(NULL); 25935ace2fSThomas Gleixner } 26935ace2fSThomas Gleixner 27935ace2fSThomas Gleixner ret = arch_xfer_to_guest_mode_handle_work(vcpu, ti_work); 28935ace2fSThomas Gleixner if (ret) 29935ace2fSThomas Gleixner return ret; 30935ace2fSThomas Gleixner 31935ace2fSThomas Gleixner ti_work = READ_ONCE(current_thread_info()->flags); 32935ace2fSThomas Gleixner } while (ti_work & XFER_TO_GUEST_MODE_WORK || need_resched()); 33935ace2fSThomas Gleixner return 0; 34935ace2fSThomas Gleixner } 35935ace2fSThomas Gleixner 36935ace2fSThomas Gleixner int xfer_to_guest_mode_handle_work(struct kvm_vcpu *vcpu) 37935ace2fSThomas Gleixner { 38935ace2fSThomas Gleixner unsigned long ti_work; 39935ace2fSThomas Gleixner 40935ace2fSThomas Gleixner /* 41935ace2fSThomas Gleixner * This is invoked from the outer guest loop with interrupts and 42935ace2fSThomas Gleixner * preemption enabled. 43935ace2fSThomas Gleixner * 44935ace2fSThomas Gleixner * KVM invokes xfer_to_guest_mode_work_pending() with interrupts 45935ace2fSThomas Gleixner * disabled in the inner loop before going into guest mode. No need 46935ace2fSThomas Gleixner * to disable interrupts here. 47935ace2fSThomas Gleixner */ 48935ace2fSThomas Gleixner ti_work = READ_ONCE(current_thread_info()->flags); 49935ace2fSThomas Gleixner if (!(ti_work & XFER_TO_GUEST_MODE_WORK)) 50935ace2fSThomas Gleixner return 0; 51935ace2fSThomas Gleixner 52935ace2fSThomas Gleixner return xfer_to_guest_mode_work(vcpu, ti_work); 53935ace2fSThomas Gleixner } 54935ace2fSThomas Gleixner EXPORT_SYMBOL_GPL(xfer_to_guest_mode_handle_work); 55