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 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 resume_user_mode_work(NULL); 21 22 ret = arch_xfer_to_guest_mode_handle_work(vcpu, ti_work); 23 if (ret) 24 return ret; 25 26 ti_work = read_thread_flags(); 27 } while (ti_work & XFER_TO_GUEST_MODE_WORK || need_resched()); 28 return 0; 29 } 30 31 int xfer_to_guest_mode_handle_work(struct kvm_vcpu *vcpu) 32 { 33 unsigned long ti_work; 34 35 /* 36 * This is invoked from the outer guest loop with interrupts and 37 * preemption enabled. 38 * 39 * KVM invokes xfer_to_guest_mode_work_pending() with interrupts 40 * disabled in the inner loop before going into guest mode. No need 41 * to disable interrupts here. 42 */ 43 ti_work = read_thread_flags(); 44 if (!(ti_work & XFER_TO_GUEST_MODE_WORK)) 45 return 0; 46 47 return xfer_to_guest_mode_work(vcpu, ti_work); 48 } 49 EXPORT_SYMBOL_GPL(xfer_to_guest_mode_handle_work); 50