#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
 static u64 vtime_delta(struct vtime *vtime)
 {
-       unsigned long now = READ_ONCE(jiffies);
+       unsigned long long clock;
 
-       if (time_before(now, (unsigned long)vtime->starttime))
+       clock = sched_clock_cpu(smp_processor_id());
+       if (clock < vtime->starttime)
                return 0;
 
-       return jiffies_to_nsecs(now - vtime->starttime);
+       return clock - vtime->starttime;
 }
 
 static u64 get_vtime_delta(struct vtime *vtime)
 {
-       unsigned long now = READ_ONCE(jiffies);
-       u64 delta, other;
+       u64 delta = vtime_delta(vtime);
+       u64 other;
 
        /*
         * Unlike tick based timing, vtime based timing never has lost
         * elapsed time. Limit account_other_time to prevent rounding
         * errors from causing elapsed vtime to go negative.
         */
-       delta = jiffies_to_nsecs(now - vtime->starttime);
        other = account_other_time(delta);
        WARN_ON_ONCE(vtime->state == VTIME_INACTIVE);
-       vtime->starttime = now;
+       vtime->starttime += delta;
 
        return delta - other;
 }
 
-static void __vtime_account_system(struct task_struct *tsk)
+static void __vtime_account_system(struct task_struct *tsk,
+                                  struct vtime *vtime)
 {
-       account_system_time(tsk, irq_count(), get_vtime_delta(&tsk->vtime));
+       vtime->stime += get_vtime_delta(vtime);
+       if (vtime->stime >= TICK_NSEC) {
+               account_system_time(tsk, irq_count(), vtime->stime);
+               vtime->stime = 0;
+       }
+}
+
+static void vtime_account_guest(struct task_struct *tsk,
+                               struct vtime *vtime)
+{
+       vtime->gtime += get_vtime_delta(vtime);
+       if (vtime->gtime >= TICK_NSEC) {
+               account_guest_time(tsk, vtime->gtime);
+               vtime->gtime = 0;
+       }
 }
 
 void vtime_account_system(struct task_struct *tsk)
                return;
 
        write_seqcount_begin(&vtime->seqcount);
-       __vtime_account_system(tsk);
+       /* We might have scheduled out from guest path */
+       if (current->flags & PF_VCPU)
+               vtime_account_guest(tsk, vtime);
+       else
+               __vtime_account_system(tsk, vtime);
        write_seqcount_end(&vtime->seqcount);
 }
 
        struct vtime *vtime = &tsk->vtime;
 
        write_seqcount_begin(&vtime->seqcount);
-       if (vtime_delta(vtime))
-               __vtime_account_system(tsk);
+       __vtime_account_system(tsk, vtime);
        vtime->state = VTIME_USER;
        write_seqcount_end(&vtime->seqcount);
 }
        struct vtime *vtime = &tsk->vtime;
 
        write_seqcount_begin(&vtime->seqcount);
-       if (vtime_delta(vtime))
-               account_user_time(tsk, get_vtime_delta(vtime));
+       vtime->utime += get_vtime_delta(vtime);
+       if (vtime->utime >= TICK_NSEC) {
+               account_user_time(tsk, vtime->utime);
+               vtime->utime = 0;
+       }
        vtime->state = VTIME_SYS;
        write_seqcount_end(&vtime->seqcount);
 }
         * that can thus safely catch up with a tickless delta.
         */
        write_seqcount_begin(&vtime->seqcount);
-       if (vtime_delta(vtime))
-               __vtime_account_system(tsk);
+       __vtime_account_system(tsk, vtime);
        current->flags |= PF_VCPU;
        write_seqcount_end(&vtime->seqcount);
 }
        struct vtime *vtime = &tsk->vtime;
 
        write_seqcount_begin(&vtime->seqcount);
-       __vtime_account_system(tsk);
+       vtime_account_guest(tsk, vtime);
        current->flags &= ~PF_VCPU;
        write_seqcount_end(&vtime->seqcount);
 }
 
        write_seqcount_begin(&vtime->seqcount);
        vtime->state = VTIME_SYS;
-       vtime->starttime = jiffies;
+       vtime->starttime = sched_clock_cpu(smp_processor_id());
        write_seqcount_end(&vtime->seqcount);
 }
 
        local_irq_save(flags);
        write_seqcount_begin(&vtime->seqcount);
        vtime->state = VTIME_SYS;
-       vtime->starttime = jiffies;
+       vtime->starttime = sched_clock_cpu(cpu);
        write_seqcount_end(&vtime->seqcount);
        local_irq_restore(flags);
 }
 
                gtime = t->gtime;
                if (vtime->state == VTIME_SYS && t->flags & PF_VCPU)
-                       gtime += vtime_delta(vtime);
+                       gtime += vtime->gtime + vtime_delta(vtime);
 
        } while (read_seqcount_retry(&vtime->seqcount, seq));
 
                 * the right place.
                 */
                if (vtime->state == VTIME_USER || t->flags & PF_VCPU)
-                       *utime += delta;
+                       *utime += vtime->utime + delta;
                else if (vtime->state == VTIME_SYS)
-                       *stime += delta;
+                       *stime += vtime->stime + delta;
        } while (read_seqcount_retry(&vtime->seqcount, seq));
 }
 #endif /* CONFIG_VIRT_CPU_ACCOUNTING_GEN */