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 | _TIF_NOTIFY_SIGNAL)) { 12 clear_notify_signal(); 13 if (task_work_pending(current)) 14 task_work_run(); 15 } 16 17 if (ti_work & _TIF_SIGPENDING) { 18 kvm_handle_signal_exit(vcpu); 19 return -EINTR; 20 } 21 22 if (ti_work & _TIF_NEED_RESCHED) 23 schedule(); 24 25 if (ti_work & _TIF_NOTIFY_RESUME) 26 resume_user_mode_work(NULL); 27 28 ret = arch_xfer_to_guest_mode_handle_work(vcpu, ti_work); 29 if (ret) 30 return ret; 31 32 ti_work = read_thread_flags(); 33 } while (ti_work & XFER_TO_GUEST_MODE_WORK || need_resched()); 34 return 0; 35 } 36 37 int xfer_to_guest_mode_handle_work(struct kvm_vcpu *vcpu) 38 { 39 unsigned long ti_work; 40 41 /* 42 * This is invoked from the outer guest loop with interrupts and 43 * preemption enabled. 44 * 45 * KVM invokes xfer_to_guest_mode_work_pending() with interrupts 46 * disabled in the inner loop before going into guest mode. No need 47 * to disable interrupts here. 48 */ 49 ti_work = read_thread_flags(); 50 if (!(ti_work & XFER_TO_GUEST_MODE_WORK)) 51 return 0; 52 53 return xfer_to_guest_mode_work(vcpu, ti_work); 54 } 55 EXPORT_SYMBOL_GPL(xfer_to_guest_mode_handle_work); 56