1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <linux/entry-kvm.h> 4 #include <linux/kvm_host.h> 5 6 static int xfer_to_guest_mode_work(struct kvm_vcpu *vcpu, unsigned long ti_work) 7 { 8 do { 9 int ret; 10 11 if (ti_work & _TIF_SIGPENDING) { 12 kvm_handle_signal_exit(vcpu); 13 return -EINTR; 14 } 15 16 if (ti_work & _TIF_NEED_RESCHED) 17 schedule(); 18 19 if (ti_work & _TIF_NOTIFY_RESUME) { 20 clear_thread_flag(TIF_NOTIFY_RESUME); 21 tracehook_notify_resume(NULL); 22 } 23 24 ret = arch_xfer_to_guest_mode_handle_work(vcpu, ti_work); 25 if (ret) 26 return ret; 27 28 ti_work = READ_ONCE(current_thread_info()->flags); 29 } while (ti_work & XFER_TO_GUEST_MODE_WORK || need_resched()); 30 return 0; 31 } 32 33 int xfer_to_guest_mode_handle_work(struct kvm_vcpu *vcpu) 34 { 35 unsigned long ti_work; 36 37 /* 38 * This is invoked from the outer guest loop with interrupts and 39 * preemption enabled. 40 * 41 * KVM invokes xfer_to_guest_mode_work_pending() with interrupts 42 * disabled in the inner loop before going into guest mode. No need 43 * to disable interrupts here. 44 */ 45 ti_work = READ_ONCE(current_thread_info()->flags); 46 if (!(ti_work & XFER_TO_GUEST_MODE_WORK)) 47 return 0; 48 49 return xfer_to_guest_mode_work(vcpu, ti_work); 50 } 51 EXPORT_SYMBOL_GPL(xfer_to_guest_mode_handle_work); 52