6
6
7
7
#include <linux/bug.h>
8
8
#include <linux/cpu_pm.h>
9
+ #include <linux/entry-kvm.h>
9
10
#include <linux/errno.h>
10
11
#include <linux/err.h>
11
12
#include <linux/kvm_host.h>
@@ -714,6 +715,45 @@ static bool vcpu_mode_is_bad_32bit(struct kvm_vcpu *vcpu)
714
715
static_branch_unlikely (& arm64_mismatched_32bit_el0 );
715
716
}
716
717
718
+ /**
719
+ * kvm_vcpu_exit_request - returns true if the VCPU should *not* enter the guest
720
+ * @vcpu: The VCPU pointer
721
+ * @ret: Pointer to write optional return code
722
+ *
723
+ * Returns: true if the VCPU needs to return to a preemptible + interruptible
724
+ * and skip guest entry.
725
+ *
726
+ * This function disambiguates between two different types of exits: exits to a
727
+ * preemptible + interruptible kernel context and exits to userspace. For an
728
+ * exit to userspace, this function will write the return code to ret and return
729
+ * true. For an exit to preemptible + interruptible kernel context (i.e. check
730
+ * for pending work and re-enter), return true without writing to ret.
731
+ */
732
+ static bool kvm_vcpu_exit_request (struct kvm_vcpu * vcpu , int * ret )
733
+ {
734
+ struct kvm_run * run = vcpu -> run ;
735
+
736
+ /*
737
+ * If we're using a userspace irqchip, then check if we need
738
+ * to tell a userspace irqchip about timer or PMU level
739
+ * changes and if so, exit to userspace (the actual level
740
+ * state gets updated in kvm_timer_update_run and
741
+ * kvm_pmu_update_run below).
742
+ */
743
+ if (static_branch_unlikely (& userspace_irqchip_in_use )) {
744
+ if (kvm_timer_should_notify_user (vcpu ) ||
745
+ kvm_pmu_should_notify_user (vcpu )) {
746
+ * ret = - EINTR ;
747
+ run -> exit_reason = KVM_EXIT_INTR ;
748
+ return true;
749
+ }
750
+ }
751
+
752
+ return kvm_request_pending (vcpu ) ||
753
+ need_new_vmid_gen (& vcpu -> arch .hw_mmu -> vmid ) ||
754
+ xfer_to_guest_mode_work_pending ();
755
+ }
756
+
717
757
/**
718
758
* kvm_arch_vcpu_ioctl_run - the main VCPU run function to execute guest code
719
759
* @vcpu: The VCPU pointer
@@ -757,7 +797,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
757
797
/*
758
798
* Check conditions before entering the guest
759
799
*/
760
- cond_resched ();
800
+ ret = xfer_to_guest_mode_handle_work (vcpu );
801
+ if (!ret )
802
+ ret = 1 ;
761
803
762
804
update_vmid (& vcpu -> arch .hw_mmu -> vmid );
763
805
@@ -776,31 +818,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
776
818
777
819
kvm_vgic_flush_hwstate (vcpu );
778
820
779
- /*
780
- * Exit if we have a signal pending so that we can deliver the
781
- * signal to user space.
782
- */
783
- if (signal_pending (current )) {
784
- ret = - EINTR ;
785
- run -> exit_reason = KVM_EXIT_INTR ;
786
- ++ vcpu -> stat .signal_exits ;
787
- }
788
-
789
- /*
790
- * If we're using a userspace irqchip, then check if we need
791
- * to tell a userspace irqchip about timer or PMU level
792
- * changes and if so, exit to userspace (the actual level
793
- * state gets updated in kvm_timer_update_run and
794
- * kvm_pmu_update_run below).
795
- */
796
- if (static_branch_unlikely (& userspace_irqchip_in_use )) {
797
- if (kvm_timer_should_notify_user (vcpu ) ||
798
- kvm_pmu_should_notify_user (vcpu )) {
799
- ret = - EINTR ;
800
- run -> exit_reason = KVM_EXIT_INTR ;
801
- }
802
- }
803
-
804
821
/*
805
822
* Ensure we set mode to IN_GUEST_MODE after we disable
806
823
* interrupts and before the final VCPU requests check.
@@ -809,8 +826,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
809
826
*/
810
827
smp_store_mb (vcpu -> mode , IN_GUEST_MODE );
811
828
812
- if (ret <= 0 || need_new_vmid_gen (& vcpu -> arch .hw_mmu -> vmid ) ||
813
- kvm_request_pending (vcpu )) {
829
+ if (ret <= 0 || kvm_vcpu_exit_request (vcpu , & ret )) {
814
830
vcpu -> mode = OUTSIDE_GUEST_MODE ;
815
831
isb (); /* Ensure work in x_flush_hwstate is committed */
816
832
kvm_pmu_sync_hwstate (vcpu );
0 commit comments