kvm_vgic_flush_hwstate(vcpu);
                kvm_timer_flush_hwstate(vcpu);
 
+               preempt_disable();
                local_irq_disable();
 
                /*
 
                if (ret <= 0 || need_new_vmid_gen(vcpu->kvm)) {
                        local_irq_enable();
+                       preempt_enable();
                        kvm_timer_sync_hwstate(vcpu);
                        kvm_vgic_sync_hwstate(vcpu);
                        continue;
                ret = kvm_call_hyp(__kvm_vcpu_run, vcpu);
 
                vcpu->mode = OUTSIDE_GUEST_MODE;
-               __kvm_guest_exit();
-               trace_kvm_exit(kvm_vcpu_trap_get_class(vcpu), *vcpu_pc(vcpu));
+               /*
+                * Back from guest
+                *************************************************************/
+
                /*
                 * We may have taken a host interrupt in HYP mode (ie
                 * while executing the guest). This interrupt is still
                local_irq_enable();
 
                /*
-                * Back from guest
-                *************************************************************/
+                * We do local_irq_enable() before calling kvm_guest_exit() so
+                * that if a timer interrupt hits while running the guest we
+                * account that tick as being spent in the guest.  We enable
+                * preemption after calling kvm_guest_exit() so that if we get
+                * preempted we make sure ticks after that is not counted as
+                * guest time.
+                */
+               kvm_guest_exit();
+               trace_kvm_exit(kvm_vcpu_trap_get_class(vcpu), *vcpu_pc(vcpu));
+               preempt_enable();
+
 
                kvm_timer_sync_hwstate(vcpu);
                kvm_vgic_sync_hwstate(vcpu);