Merge tag 'auxdisplay-for-linus-v5.9-rc1' of git://github.com/ojeda/linux
[linux-2.6-microblaze.git] / kernel / entry / kvm.c
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);