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