if (vcpu->arch.pause)
                        vcpu_pause(vcpu);
 
+               /*
+                * Disarming the background timer must be done in a
+                * preemptible context, as this call may sleep.
+                */
                kvm_timer_flush_hwstate(vcpu);
-               kvm_vgic_flush_hwstate(vcpu);
 
+               /*
+                * Preparing the interrupts to be injected also
+                * involves poking the GIC, which must be done in a
+                * non-preemptible context.
+                */
                preempt_disable();
+               kvm_vgic_flush_hwstate(vcpu);
+
                local_irq_disable();
 
                /*
 
                if (ret <= 0 || need_new_vmid_gen(vcpu->kvm)) {
                        local_irq_enable();
-                       preempt_enable();
                        kvm_vgic_sync_hwstate(vcpu);
+                       preempt_enable();
                        kvm_timer_sync_hwstate(vcpu);
                        continue;
                }
                 */
                kvm_guest_exit();
                trace_kvm_exit(kvm_vcpu_trap_get_class(vcpu), *vcpu_pc(vcpu));
-               preempt_enable();
 
                kvm_vgic_sync_hwstate(vcpu);
+
+               preempt_enable();
+
                kvm_timer_sync_hwstate(vcpu);
 
                ret = handle_exit(vcpu, run, ret);