1457c8996SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2325ea10cSIngo Molnar /*
3325ea10cSIngo Molnar * Simple CPU accounting cgroup controller
4325ea10cSIngo Molnar */
573fbec60SFrederic Weisbecker
6c8997020SNicholas Piggin #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
7c8997020SNicholas Piggin #include <asm/cputime.h>
8c8997020SNicholas Piggin #endif
9c8997020SNicholas Piggin
1073fbec60SFrederic Weisbecker #ifdef CONFIG_IRQ_TIME_ACCOUNTING
1173fbec60SFrederic Weisbecker
1273fbec60SFrederic Weisbecker /*
1373fbec60SFrederic Weisbecker * There are no locks covering percpu hardirq/softirq time.
14bf9fae9fSFrederic Weisbecker * They are only modified in vtime_account, on corresponding CPU
1573fbec60SFrederic Weisbecker * with interrupts disabled. So, writes are safe.
1673fbec60SFrederic Weisbecker * They are read and saved off onto struct rq in update_rq_clock().
1773fbec60SFrederic Weisbecker * This may result in other CPU reading this CPU's irq time and can
18bf9fae9fSFrederic Weisbecker * race with irq/vtime_account on this CPU. We would either get old
1973fbec60SFrederic Weisbecker * or new value with a side effect of accounting a slice of irq time to wrong
2073fbec60SFrederic Weisbecker * task when irq is in progress while we read rq->clock. That is a worthy
2173fbec60SFrederic Weisbecker * compromise in place of having locks on each irq in account_system_time.
2273fbec60SFrederic Weisbecker */
2319d23dbfSFrederic Weisbecker DEFINE_PER_CPU(struct irqtime, cpu_irqtime);
2473fbec60SFrederic Weisbecker
2573fbec60SFrederic Weisbecker static int sched_clock_irqtime;
2673fbec60SFrederic Weisbecker
enable_sched_clock_irqtime(void)2773fbec60SFrederic Weisbecker void enable_sched_clock_irqtime(void)
2873fbec60SFrederic Weisbecker {
2973fbec60SFrederic Weisbecker sched_clock_irqtime = 1;
3073fbec60SFrederic Weisbecker }
3173fbec60SFrederic Weisbecker
disable_sched_clock_irqtime(void)3273fbec60SFrederic Weisbecker void disable_sched_clock_irqtime(void)
3373fbec60SFrederic Weisbecker {
3473fbec60SFrederic Weisbecker sched_clock_irqtime = 0;
3573fbec60SFrederic Weisbecker }
3673fbec60SFrederic Weisbecker
irqtime_account_delta(struct irqtime * irqtime,u64 delta,enum cpu_usage_stat idx)3725e2d8c1SFrederic Weisbecker static void irqtime_account_delta(struct irqtime *irqtime, u64 delta,
3825e2d8c1SFrederic Weisbecker enum cpu_usage_stat idx)
3925e2d8c1SFrederic Weisbecker {
4025e2d8c1SFrederic Weisbecker u64 *cpustat = kcpustat_this_cpu->cpustat;
4125e2d8c1SFrederic Weisbecker
4225e2d8c1SFrederic Weisbecker u64_stats_update_begin(&irqtime->sync);
4325e2d8c1SFrederic Weisbecker cpustat[idx] += delta;
4425e2d8c1SFrederic Weisbecker irqtime->total += delta;
4525e2d8c1SFrederic Weisbecker irqtime->tick_delta += delta;
4625e2d8c1SFrederic Weisbecker u64_stats_update_end(&irqtime->sync);
4725e2d8c1SFrederic Weisbecker }
4825e2d8c1SFrederic Weisbecker
4973fbec60SFrederic Weisbecker /*
50d3759e71SFrederic Weisbecker * Called after incrementing preempt_count on {soft,}irq_enter
5173fbec60SFrederic Weisbecker * and before decrementing preempt_count on {soft,}irq_exit.
5273fbec60SFrederic Weisbecker */
irqtime_account_irq(struct task_struct * curr,unsigned int offset)53d3759e71SFrederic Weisbecker void irqtime_account_irq(struct task_struct *curr, unsigned int offset)
5473fbec60SFrederic Weisbecker {
5519d23dbfSFrederic Weisbecker struct irqtime *irqtime = this_cpu_ptr(&cpu_irqtime);
56d3759e71SFrederic Weisbecker unsigned int pc;
5773fbec60SFrederic Weisbecker s64 delta;
5873fbec60SFrederic Weisbecker int cpu;
5973fbec60SFrederic Weisbecker
6073fbec60SFrederic Weisbecker if (!sched_clock_irqtime)
6173fbec60SFrederic Weisbecker return;
6273fbec60SFrederic Weisbecker
6373fbec60SFrederic Weisbecker cpu = smp_processor_id();
6419d23dbfSFrederic Weisbecker delta = sched_clock_cpu(cpu) - irqtime->irq_start_time;
6519d23dbfSFrederic Weisbecker irqtime->irq_start_time += delta;
666516b386SThomas Gleixner pc = irq_count() - offset;
6773fbec60SFrederic Weisbecker
6873fbec60SFrederic Weisbecker /*
6973fbec60SFrederic Weisbecker * We do not account for softirq time from ksoftirqd here.
7073fbec60SFrederic Weisbecker * We want to continue accounting softirq time to ksoftirqd thread
7173fbec60SFrederic Weisbecker * in that case, so as not to confuse scheduler with a special task
7273fbec60SFrederic Weisbecker * that do not consume any time, but still wants to run.
7373fbec60SFrederic Weisbecker */
74d3759e71SFrederic Weisbecker if (pc & HARDIRQ_MASK)
7525e2d8c1SFrederic Weisbecker irqtime_account_delta(irqtime, delta, CPUTIME_IRQ);
76d3759e71SFrederic Weisbecker else if ((pc & SOFTIRQ_OFFSET) && curr != this_cpu_ksoftirqd())
7725e2d8c1SFrederic Weisbecker irqtime_account_delta(irqtime, delta, CPUTIME_SOFTIRQ);
7873fbec60SFrederic Weisbecker }
7973fbec60SFrederic Weisbecker
irqtime_tick_accounted(u64 maxtime)802b1f967dSFrederic Weisbecker static u64 irqtime_tick_accounted(u64 maxtime)
8173fbec60SFrederic Weisbecker {
82a499a5a1SFrederic Weisbecker struct irqtime *irqtime = this_cpu_ptr(&cpu_irqtime);
832b1f967dSFrederic Weisbecker u64 delta;
8473fbec60SFrederic Weisbecker
852b1f967dSFrederic Weisbecker delta = min(irqtime->tick_delta, maxtime);
862b1f967dSFrederic Weisbecker irqtime->tick_delta -= delta;
872810f611SFrederic Weisbecker
88a499a5a1SFrederic Weisbecker return delta;
8973fbec60SFrederic Weisbecker }
9073fbec60SFrederic Weisbecker
9173fbec60SFrederic Weisbecker #else /* CONFIG_IRQ_TIME_ACCOUNTING */
9273fbec60SFrederic Weisbecker
9373fbec60SFrederic Weisbecker #define sched_clock_irqtime (0)
9473fbec60SFrederic Weisbecker
irqtime_tick_accounted(u64 dummy)952b1f967dSFrederic Weisbecker static u64 irqtime_tick_accounted(u64 dummy)
9657430218SRik van Riel {
9757430218SRik van Riel return 0;
9857430218SRik van Riel }
9957430218SRik van Riel
10073fbec60SFrederic Weisbecker #endif /* !CONFIG_IRQ_TIME_ACCOUNTING */
10173fbec60SFrederic Weisbecker
task_group_account_field(struct task_struct * p,int index,u64 tmp)10273fbec60SFrederic Weisbecker static inline void task_group_account_field(struct task_struct *p, int index,
10373fbec60SFrederic Weisbecker u64 tmp)
10473fbec60SFrederic Weisbecker {
10573fbec60SFrederic Weisbecker /*
10673fbec60SFrederic Weisbecker * Since all updates are sure to touch the root cgroup, we
10773fbec60SFrederic Weisbecker * get ourselves ahead and touch it first. If the root cgroup
10873fbec60SFrederic Weisbecker * is the only cgroup, then nothing else should be necessary.
10973fbec60SFrederic Weisbecker *
11073fbec60SFrederic Weisbecker */
111a4f61cc0SChristoph Lameter __this_cpu_add(kernel_cpustat.cpustat[index], tmp);
11273fbec60SFrederic Weisbecker
113d2cc5ed6STejun Heo cgroup_account_cputime_field(p, index, tmp);
11473fbec60SFrederic Weisbecker }
11573fbec60SFrederic Weisbecker
11673fbec60SFrederic Weisbecker /*
11797fb7a0aSIngo Molnar * Account user CPU time to a process.
11897fb7a0aSIngo Molnar * @p: the process that the CPU time gets accounted to
11997fb7a0aSIngo Molnar * @cputime: the CPU time spent in user space since the last update
12073fbec60SFrederic Weisbecker */
account_user_time(struct task_struct * p,u64 cputime)12123244a5cSFrederic Weisbecker void account_user_time(struct task_struct *p, u64 cputime)
12273fbec60SFrederic Weisbecker {
12373fbec60SFrederic Weisbecker int index;
12473fbec60SFrederic Weisbecker
12573fbec60SFrederic Weisbecker /* Add user time to process. */
12623244a5cSFrederic Weisbecker p->utime += cputime;
12723244a5cSFrederic Weisbecker account_group_user_time(p, cputime);
12873fbec60SFrederic Weisbecker
129d0ea0268SDongsheng Yang index = (task_nice(p) > 0) ? CPUTIME_NICE : CPUTIME_USER;
13073fbec60SFrederic Weisbecker
13173fbec60SFrederic Weisbecker /* Add user time to cpustat. */
13223244a5cSFrederic Weisbecker task_group_account_field(p, index, cputime);
13373fbec60SFrederic Weisbecker
13473fbec60SFrederic Weisbecker /* Account for user time used */
1356fac4829SFrederic Weisbecker acct_account_cputime(p);
13673fbec60SFrederic Weisbecker }
13773fbec60SFrederic Weisbecker
13873fbec60SFrederic Weisbecker /*
13997fb7a0aSIngo Molnar * Account guest CPU time to a process.
14097fb7a0aSIngo Molnar * @p: the process that the CPU time gets accounted to
14197fb7a0aSIngo Molnar * @cputime: the CPU time spent in virtual machine since the last update
14273fbec60SFrederic Weisbecker */
account_guest_time(struct task_struct * p,u64 cputime)143fb8b049cSFrederic Weisbecker void account_guest_time(struct task_struct *p, u64 cputime)
14473fbec60SFrederic Weisbecker {
14573fbec60SFrederic Weisbecker u64 *cpustat = kcpustat_this_cpu->cpustat;
14673fbec60SFrederic Weisbecker
14773fbec60SFrederic Weisbecker /* Add guest time to process. */
148fb8b049cSFrederic Weisbecker p->utime += cputime;
149fb8b049cSFrederic Weisbecker account_group_user_time(p, cputime);
150fb8b049cSFrederic Weisbecker p->gtime += cputime;
15173fbec60SFrederic Weisbecker
15273fbec60SFrederic Weisbecker /* Add guest time to cpustat. */
153d0ea0268SDongsheng Yang if (task_nice(p) > 0) {
1549731698eSAndrey Ryabinin task_group_account_field(p, CPUTIME_NICE, cputime);
155fb8b049cSFrederic Weisbecker cpustat[CPUTIME_GUEST_NICE] += cputime;
15673fbec60SFrederic Weisbecker } else {
1579731698eSAndrey Ryabinin task_group_account_field(p, CPUTIME_USER, cputime);
158fb8b049cSFrederic Weisbecker cpustat[CPUTIME_GUEST] += cputime;
15973fbec60SFrederic Weisbecker }
16073fbec60SFrederic Weisbecker }
16173fbec60SFrederic Weisbecker
16273fbec60SFrederic Weisbecker /*
16397fb7a0aSIngo Molnar * Account system CPU time to a process and desired cpustat field
16497fb7a0aSIngo Molnar * @p: the process that the CPU time gets accounted to
16597fb7a0aSIngo Molnar * @cputime: the CPU time spent in kernel space since the last update
16640565b5aSStanislaw Gruszka * @index: pointer to cpustat field that has to be updated
16773fbec60SFrederic Weisbecker */
account_system_index_time(struct task_struct * p,u64 cputime,enum cpu_usage_stat index)168c31cc6a5SFrederic Weisbecker void account_system_index_time(struct task_struct *p,
169fb8b049cSFrederic Weisbecker u64 cputime, enum cpu_usage_stat index)
17073fbec60SFrederic Weisbecker {
17173fbec60SFrederic Weisbecker /* Add system time to process. */
172fb8b049cSFrederic Weisbecker p->stime += cputime;
173fb8b049cSFrederic Weisbecker account_group_system_time(p, cputime);
17473fbec60SFrederic Weisbecker
17573fbec60SFrederic Weisbecker /* Add system time to cpustat. */
176fb8b049cSFrederic Weisbecker task_group_account_field(p, index, cputime);
17773fbec60SFrederic Weisbecker
17873fbec60SFrederic Weisbecker /* Account for system time used */
1796fac4829SFrederic Weisbecker acct_account_cputime(p);
18073fbec60SFrederic Weisbecker }
18173fbec60SFrederic Weisbecker
18273fbec60SFrederic Weisbecker /*
18397fb7a0aSIngo Molnar * Account system CPU time to a process.
18497fb7a0aSIngo Molnar * @p: the process that the CPU time gets accounted to
18573fbec60SFrederic Weisbecker * @hardirq_offset: the offset to subtract from hardirq_count()
18697fb7a0aSIngo Molnar * @cputime: the CPU time spent in kernel space since the last update
18773fbec60SFrederic Weisbecker */
account_system_time(struct task_struct * p,int hardirq_offset,u64 cputime)188fb8b049cSFrederic Weisbecker void account_system_time(struct task_struct *p, int hardirq_offset, u64 cputime)
18973fbec60SFrederic Weisbecker {
19073fbec60SFrederic Weisbecker int index;
19173fbec60SFrederic Weisbecker
19273fbec60SFrederic Weisbecker if ((p->flags & PF_VCPU) && (irq_count() - hardirq_offset == 0)) {
19340565b5aSStanislaw Gruszka account_guest_time(p, cputime);
19473fbec60SFrederic Weisbecker return;
19573fbec60SFrederic Weisbecker }
19673fbec60SFrederic Weisbecker
19773fbec60SFrederic Weisbecker if (hardirq_count() - hardirq_offset)
19873fbec60SFrederic Weisbecker index = CPUTIME_IRQ;
19973fbec60SFrederic Weisbecker else if (in_serving_softirq())
20073fbec60SFrederic Weisbecker index = CPUTIME_SOFTIRQ;
20173fbec60SFrederic Weisbecker else
20273fbec60SFrederic Weisbecker index = CPUTIME_SYSTEM;
20373fbec60SFrederic Weisbecker
204c31cc6a5SFrederic Weisbecker account_system_index_time(p, cputime, index);
20573fbec60SFrederic Weisbecker }
20673fbec60SFrederic Weisbecker
20773fbec60SFrederic Weisbecker /*
20873fbec60SFrederic Weisbecker * Account for involuntary wait time.
20997fb7a0aSIngo Molnar * @cputime: the CPU time spent in involuntary wait
21073fbec60SFrederic Weisbecker */
account_steal_time(u64 cputime)211be9095edSFrederic Weisbecker void account_steal_time(u64 cputime)
21273fbec60SFrederic Weisbecker {
21373fbec60SFrederic Weisbecker u64 *cpustat = kcpustat_this_cpu->cpustat;
21473fbec60SFrederic Weisbecker
215be9095edSFrederic Weisbecker cpustat[CPUTIME_STEAL] += cputime;
21673fbec60SFrederic Weisbecker }
21773fbec60SFrederic Weisbecker
21873fbec60SFrederic Weisbecker /*
21973fbec60SFrederic Weisbecker * Account for idle time.
22097fb7a0aSIngo Molnar * @cputime: the CPU time spent in idle wait
22173fbec60SFrederic Weisbecker */
account_idle_time(u64 cputime)22218b43a9bSFrederic Weisbecker void account_idle_time(u64 cputime)
22373fbec60SFrederic Weisbecker {
22473fbec60SFrederic Weisbecker u64 *cpustat = kcpustat_this_cpu->cpustat;
22573fbec60SFrederic Weisbecker struct rq *rq = this_rq();
22673fbec60SFrederic Weisbecker
22773fbec60SFrederic Weisbecker if (atomic_read(&rq->nr_iowait) > 0)
22818b43a9bSFrederic Weisbecker cpustat[CPUTIME_IOWAIT] += cputime;
22973fbec60SFrederic Weisbecker else
23018b43a9bSFrederic Weisbecker cpustat[CPUTIME_IDLE] += cputime;
23173fbec60SFrederic Weisbecker }
23273fbec60SFrederic Weisbecker
2331fcf54deSJosh Don
2341fcf54deSJosh Don #ifdef CONFIG_SCHED_CORE
2351fcf54deSJosh Don /*
2361fcf54deSJosh Don * Account for forceidle time due to core scheduling.
2371fcf54deSJosh Don *
2381fcf54deSJosh Don * REQUIRES: schedstat is enabled.
2391fcf54deSJosh Don */
__account_forceidle_time(struct task_struct * p,u64 delta)2401fcf54deSJosh Don void __account_forceidle_time(struct task_struct *p, u64 delta)
2411fcf54deSJosh Don {
2421fcf54deSJosh Don __schedstat_add(p->stats.core_forceidle_sum, delta);
2431fcf54deSJosh Don
2441fcf54deSJosh Don task_group_account_field(p, CPUTIME_FORCEIDLE, delta);
2451fcf54deSJosh Don }
2461fcf54deSJosh Don #endif
2471fcf54deSJosh Don
24803cbc732SWanpeng Li /*
24903cbc732SWanpeng Li * When a guest is interrupted for a longer amount of time, missed clock
25003cbc732SWanpeng Li * ticks are not redelivered later. Due to that, this function may on
25103cbc732SWanpeng Li * occasion account more time than the calling functions think elapsed.
25203cbc732SWanpeng Li */
steal_account_process_time(u64 maxtime)2532b1f967dSFrederic Weisbecker static __always_inline u64 steal_account_process_time(u64 maxtime)
25473fbec60SFrederic Weisbecker {
25573fbec60SFrederic Weisbecker #ifdef CONFIG_PARAVIRT
25673fbec60SFrederic Weisbecker if (static_key_false(¶virt_steal_enabled)) {
2572b1f967dSFrederic Weisbecker u64 steal;
25873fbec60SFrederic Weisbecker
25973fbec60SFrederic Weisbecker steal = paravirt_steal_clock(smp_processor_id());
26073fbec60SFrederic Weisbecker steal -= this_rq()->prev_steal_time;
2612b1f967dSFrederic Weisbecker steal = min(steal, maxtime);
2622b1f967dSFrederic Weisbecker account_steal_time(steal);
2632b1f967dSFrederic Weisbecker this_rq()->prev_steal_time += steal;
26473fbec60SFrederic Weisbecker
2652b1f967dSFrederic Weisbecker return steal;
26673fbec60SFrederic Weisbecker }
26773fbec60SFrederic Weisbecker #endif
268807e5b80SWanpeng Li return 0;
26973fbec60SFrederic Weisbecker }
27073fbec60SFrederic Weisbecker
271a634f933SFrederic Weisbecker /*
27257430218SRik van Riel * Account how much elapsed time was spent in steal, irq, or softirq time.
27357430218SRik van Riel */
account_other_time(u64 max)2742b1f967dSFrederic Weisbecker static inline u64 account_other_time(u64 max)
27557430218SRik van Riel {
2762b1f967dSFrederic Weisbecker u64 accounted;
27757430218SRik van Riel
2782c11dba0SFrederic Weisbecker lockdep_assert_irqs_disabled();
2792810f611SFrederic Weisbecker
28057430218SRik van Riel accounted = steal_account_process_time(max);
28157430218SRik van Riel
28257430218SRik van Riel if (accounted < max)
283a499a5a1SFrederic Weisbecker accounted += irqtime_tick_accounted(max - accounted);
28457430218SRik van Riel
28557430218SRik van Riel return accounted;
28657430218SRik van Riel }
28757430218SRik van Riel
288a1eb1411SStanislaw Gruszka #ifdef CONFIG_64BIT
read_sum_exec_runtime(struct task_struct * t)289a1eb1411SStanislaw Gruszka static inline u64 read_sum_exec_runtime(struct task_struct *t)
290a1eb1411SStanislaw Gruszka {
291a1eb1411SStanislaw Gruszka return t->se.sum_exec_runtime;
292a1eb1411SStanislaw Gruszka }
293a1eb1411SStanislaw Gruszka #else
read_sum_exec_runtime(struct task_struct * t)294a1eb1411SStanislaw Gruszka static u64 read_sum_exec_runtime(struct task_struct *t)
295a1eb1411SStanislaw Gruszka {
296a1eb1411SStanislaw Gruszka u64 ns;
297a1eb1411SStanislaw Gruszka struct rq_flags rf;
298a1eb1411SStanislaw Gruszka struct rq *rq;
299a1eb1411SStanislaw Gruszka
300a1eb1411SStanislaw Gruszka rq = task_rq_lock(t, &rf);
301a1eb1411SStanislaw Gruszka ns = t->se.sum_exec_runtime;
302a1eb1411SStanislaw Gruszka task_rq_unlock(rq, t, &rf);
303a1eb1411SStanislaw Gruszka
304a1eb1411SStanislaw Gruszka return ns;
305a1eb1411SStanislaw Gruszka }
306a1eb1411SStanislaw Gruszka #endif
307a1eb1411SStanislaw Gruszka
30857430218SRik van Riel /*
309a634f933SFrederic Weisbecker * Accumulate raw cputime values of dead tasks (sig->[us]time) and live
310a634f933SFrederic Weisbecker * tasks (sum on group iteration) belonging to @tsk's group.
311a634f933SFrederic Weisbecker */
thread_group_cputime(struct task_struct * tsk,struct task_cputime * times)312a634f933SFrederic Weisbecker void thread_group_cputime(struct task_struct *tsk, struct task_cputime *times)
313a634f933SFrederic Weisbecker {
314a634f933SFrederic Weisbecker struct signal_struct *sig = tsk->signal;
3155613fda9SFrederic Weisbecker u64 utime, stime;
316a634f933SFrederic Weisbecker struct task_struct *t;
317e78c3496SRik van Riel unsigned int seq, nextseq;
3189c368b5bSRik van Riel unsigned long flags;
319a634f933SFrederic Weisbecker
320a1eb1411SStanislaw Gruszka /*
321a1eb1411SStanislaw Gruszka * Update current task runtime to account pending time since last
322a1eb1411SStanislaw Gruszka * scheduler action or thread_group_cputime() call. This thread group
323a1eb1411SStanislaw Gruszka * might have other running tasks on different CPUs, but updating
324a1eb1411SStanislaw Gruszka * their runtime can affect syscall performance, so we skip account
325a1eb1411SStanislaw Gruszka * those pending times and rely only on values updated on tick or
326a1eb1411SStanislaw Gruszka * other scheduler action.
327a1eb1411SStanislaw Gruszka */
328a1eb1411SStanislaw Gruszka if (same_thread_group(current, tsk))
329a1eb1411SStanislaw Gruszka (void) task_sched_runtime(current);
330a1eb1411SStanislaw Gruszka
331e78c3496SRik van Riel rcu_read_lock();
332e78c3496SRik van Riel /* Attempt a lockless read on the first round. */
333e78c3496SRik van Riel nextseq = 0;
334e78c3496SRik van Riel do {
335e78c3496SRik van Riel seq = nextseq;
3369c368b5bSRik van Riel flags = read_seqbegin_or_lock_irqsave(&sig->stats_lock, &seq);
337a634f933SFrederic Weisbecker times->utime = sig->utime;
338a634f933SFrederic Weisbecker times->stime = sig->stime;
339a634f933SFrederic Weisbecker times->sum_exec_runtime = sig->sum_sched_runtime;
340a634f933SFrederic Weisbecker
3411e4dda08SOleg Nesterov for_each_thread(tsk, t) {
342e614b333SStanislaw Gruszka task_cputime(t, &utime, &stime);
3436fac4829SFrederic Weisbecker times->utime += utime;
3446fac4829SFrederic Weisbecker times->stime += stime;
345a1eb1411SStanislaw Gruszka times->sum_exec_runtime += read_sum_exec_runtime(t);
3461e4dda08SOleg Nesterov }
347e78c3496SRik van Riel /* If lockless access failed, take the lock. */
348e78c3496SRik van Riel nextseq = 1;
349e78c3496SRik van Riel } while (need_seqretry(&sig->stats_lock, seq));
3509c368b5bSRik van Riel done_seqretry_irqrestore(&sig->stats_lock, seq, flags);
351a634f933SFrederic Weisbecker rcu_read_unlock();
352a634f933SFrederic Weisbecker }
353a634f933SFrederic Weisbecker
35473fbec60SFrederic Weisbecker #ifdef CONFIG_IRQ_TIME_ACCOUNTING
35573fbec60SFrederic Weisbecker /*
35673fbec60SFrederic Weisbecker * Account a tick to a process and cpustat
35797fb7a0aSIngo Molnar * @p: the process that the CPU time gets accounted to
35873fbec60SFrederic Weisbecker * @user_tick: is the tick from userspace
35973fbec60SFrederic Weisbecker * @rq: the pointer to rq
36073fbec60SFrederic Weisbecker *
36173fbec60SFrederic Weisbecker * Tick demultiplexing follows the order
36273fbec60SFrederic Weisbecker * - pending hardirq update
36373fbec60SFrederic Weisbecker * - pending softirq update
36473fbec60SFrederic Weisbecker * - user_time
36573fbec60SFrederic Weisbecker * - idle_time
36673fbec60SFrederic Weisbecker * - system time
36773fbec60SFrederic Weisbecker * - check for guest_time
36873fbec60SFrederic Weisbecker * - else account as system_time
36973fbec60SFrederic Weisbecker *
37073fbec60SFrederic Weisbecker * Check for hardirq is done both for system and user time as there is
37173fbec60SFrederic Weisbecker * no timer going off while we are on hardirq and hence we may never get an
37273fbec60SFrederic Weisbecker * opportunity to update it solely in system time.
37373fbec60SFrederic Weisbecker * p->stime and friends are only updated on system time and not on irq
37473fbec60SFrederic Weisbecker * softirq as those do not count in task exec_runtime any more.
37573fbec60SFrederic Weisbecker */
irqtime_account_process_tick(struct task_struct * p,int user_tick,int ticks)37673fbec60SFrederic Weisbecker static void irqtime_account_process_tick(struct task_struct *p, int user_tick,
3779dec1b69SAlex Shi int ticks)
37873fbec60SFrederic Weisbecker {
3792b1f967dSFrederic Weisbecker u64 other, cputime = TICK_NSEC * ticks;
38073fbec60SFrederic Weisbecker
38157430218SRik van Riel /*
38257430218SRik van Riel * When returning from idle, many ticks can get accounted at
38357430218SRik van Riel * once, including some ticks of steal, irq, and softirq time.
38457430218SRik van Riel * Subtract those ticks from the amount of time accounted to
38557430218SRik van Riel * idle, or potentially user or system time. Due to rounding,
38657430218SRik van Riel * other time can exceed ticks occasionally.
38757430218SRik van Riel */
38803cbc732SWanpeng Li other = account_other_time(ULONG_MAX);
3892b1f967dSFrederic Weisbecker if (other >= cputime)
39073fbec60SFrederic Weisbecker return;
39123244a5cSFrederic Weisbecker
3922b1f967dSFrederic Weisbecker cputime -= other;
39373fbec60SFrederic Weisbecker
39457430218SRik van Riel if (this_cpu_ksoftirqd() == p) {
39573fbec60SFrederic Weisbecker /*
39673fbec60SFrederic Weisbecker * ksoftirqd time do not get accounted in cpu_softirq_time.
39773fbec60SFrederic Weisbecker * So, we have to handle it separately here.
39873fbec60SFrederic Weisbecker * Also, p->stime needs to be updated for ksoftirqd.
39973fbec60SFrederic Weisbecker */
400fb8b049cSFrederic Weisbecker account_system_index_time(p, cputime, CPUTIME_SOFTIRQ);
40173fbec60SFrederic Weisbecker } else if (user_tick) {
40240565b5aSStanislaw Gruszka account_user_time(p, cputime);
4039dec1b69SAlex Shi } else if (p == this_rq()->idle) {
40418b43a9bSFrederic Weisbecker account_idle_time(cputime);
40573fbec60SFrederic Weisbecker } else if (p->flags & PF_VCPU) { /* System time or guest time */
406fb8b049cSFrederic Weisbecker account_guest_time(p, cputime);
40773fbec60SFrederic Weisbecker } else {
408fb8b049cSFrederic Weisbecker account_system_index_time(p, cputime, CPUTIME_SYSTEM);
40973fbec60SFrederic Weisbecker }
41073fbec60SFrederic Weisbecker }
41173fbec60SFrederic Weisbecker
irqtime_account_idle_ticks(int ticks)41273fbec60SFrederic Weisbecker static void irqtime_account_idle_ticks(int ticks)
41373fbec60SFrederic Weisbecker {
4149dec1b69SAlex Shi irqtime_account_process_tick(current, 0, ticks);
41573fbec60SFrederic Weisbecker }
41673fbec60SFrederic Weisbecker #else /* CONFIG_IRQ_TIME_ACCOUNTING */
irqtime_account_idle_ticks(int ticks)4173f4724eaSFrederic Weisbecker static inline void irqtime_account_idle_ticks(int ticks) { }
irqtime_account_process_tick(struct task_struct * p,int user_tick,int nr_ticks)4183f4724eaSFrederic Weisbecker static inline void irqtime_account_process_tick(struct task_struct *p, int user_tick,
4199dec1b69SAlex Shi int nr_ticks) { }
42073fbec60SFrederic Weisbecker #endif /* CONFIG_IRQ_TIME_ACCOUNTING */
42173fbec60SFrederic Weisbecker
42273fbec60SFrederic Weisbecker /*
42373fbec60SFrederic Weisbecker * Use precise platform statistics if available:
42473fbec60SFrederic Weisbecker */
4258d495477SFrederic Weisbecker #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
4268d495477SFrederic Weisbecker
427e3942ba0SFrederic Weisbecker # ifndef __ARCH_HAS_VTIME_TASK_SWITCH
vtime_task_switch(struct task_struct * prev)4288d495477SFrederic Weisbecker void vtime_task_switch(struct task_struct *prev)
429e3942ba0SFrederic Weisbecker {
430e3942ba0SFrederic Weisbecker if (is_idle_task(prev))
431e3942ba0SFrederic Weisbecker vtime_account_idle(prev);
432e3942ba0SFrederic Weisbecker else
433f83eeb1aSFrederic Weisbecker vtime_account_kernel(prev);
434e3942ba0SFrederic Weisbecker
435c8d7dabfSFrederic Weisbecker vtime_flush(prev);
436e3942ba0SFrederic Weisbecker arch_vtime_task_switch(prev);
437e3942ba0SFrederic Weisbecker }
438e3942ba0SFrederic Weisbecker # endif
4390cfdf9a1SFrederic Weisbecker
vtime_account_irq(struct task_struct * tsk,unsigned int offset)440d3759e71SFrederic Weisbecker void vtime_account_irq(struct task_struct *tsk, unsigned int offset)
441a7e1a9e3SFrederic Weisbecker {
4426516b386SThomas Gleixner unsigned int pc = irq_count() - offset;
443d3759e71SFrederic Weisbecker
444d3759e71SFrederic Weisbecker if (pc & HARDIRQ_OFFSET) {
4458a6a5920SFrederic Weisbecker vtime_account_hardirq(tsk);
446d3759e71SFrederic Weisbecker } else if (pc & SOFTIRQ_OFFSET) {
4478a6a5920SFrederic Weisbecker vtime_account_softirq(tsk);
4488a6a5920SFrederic Weisbecker } else if (!IS_ENABLED(CONFIG_HAVE_VIRT_CPU_ACCOUNTING_IDLE) &&
4498a6a5920SFrederic Weisbecker is_idle_task(tsk)) {
450fd25b4c2SFrederic Weisbecker vtime_account_idle(tsk);
4518a6a5920SFrederic Weisbecker } else {
452f83eeb1aSFrederic Weisbecker vtime_account_kernel(tsk);
453a7e1a9e3SFrederic Weisbecker }
4548a6a5920SFrederic Weisbecker }
455a7e1a9e3SFrederic Weisbecker
cputime_adjust(struct task_cputime * curr,struct prev_cputime * prev,u64 * ut,u64 * st)4568157a7faSTejun Heo void cputime_adjust(struct task_cputime *curr, struct prev_cputime *prev,
4578157a7faSTejun Heo u64 *ut, u64 *st)
4588157a7faSTejun Heo {
4598157a7faSTejun Heo *ut = curr->utime;
4608157a7faSTejun Heo *st = curr->stime;
4618157a7faSTejun Heo }
4628157a7faSTejun Heo
task_cputime_adjusted(struct task_struct * p,u64 * ut,u64 * st)4635613fda9SFrederic Weisbecker void task_cputime_adjusted(struct task_struct *p, u64 *ut, u64 *st)
46473fbec60SFrederic Weisbecker {
4659fbc42eaSFrederic Weisbecker *ut = p->utime;
4669fbc42eaSFrederic Weisbecker *st = p->stime;
4679fbc42eaSFrederic Weisbecker }
4689eec50b8SAndrey Smetanin EXPORT_SYMBOL_GPL(task_cputime_adjusted);
46973fbec60SFrederic Weisbecker
thread_group_cputime_adjusted(struct task_struct * p,u64 * ut,u64 * st)4705613fda9SFrederic Weisbecker void thread_group_cputime_adjusted(struct task_struct *p, u64 *ut, u64 *st)
4719fbc42eaSFrederic Weisbecker {
4729fbc42eaSFrederic Weisbecker struct task_cputime cputime;
47373fbec60SFrederic Weisbecker
4749fbc42eaSFrederic Weisbecker thread_group_cputime(p, &cputime);
4759fbc42eaSFrederic Weisbecker
4769fbc42eaSFrederic Weisbecker *ut = cputime.utime;
4779fbc42eaSFrederic Weisbecker *st = cputime.stime;
4789fbc42eaSFrederic Weisbecker }
47997fb7a0aSIngo Molnar
48097fb7a0aSIngo Molnar #else /* !CONFIG_VIRT_CPU_ACCOUNTING_NATIVE: */
48197fb7a0aSIngo Molnar
4829fbc42eaSFrederic Weisbecker /*
48397fb7a0aSIngo Molnar * Account a single tick of CPU time.
48497fb7a0aSIngo Molnar * @p: the process that the CPU time gets accounted to
4859fbc42eaSFrederic Weisbecker * @user_tick: indicates if the tick is a user or a system tick
4869fbc42eaSFrederic Weisbecker */
account_process_tick(struct task_struct * p,int user_tick)4879fbc42eaSFrederic Weisbecker void account_process_tick(struct task_struct *p, int user_tick)
4889fbc42eaSFrederic Weisbecker {
4892b1f967dSFrederic Weisbecker u64 cputime, steal;
4909fbc42eaSFrederic Weisbecker
491e44fcb4bSFrederic Weisbecker if (vtime_accounting_enabled_this_cpu())
4929fbc42eaSFrederic Weisbecker return;
4939fbc42eaSFrederic Weisbecker
4949fbc42eaSFrederic Weisbecker if (sched_clock_irqtime) {
4959dec1b69SAlex Shi irqtime_account_process_tick(p, user_tick, 1);
4969fbc42eaSFrederic Weisbecker return;
4979fbc42eaSFrederic Weisbecker }
4989fbc42eaSFrederic Weisbecker
4992b1f967dSFrederic Weisbecker cputime = TICK_NSEC;
50003cbc732SWanpeng Li steal = steal_account_process_time(ULONG_MAX);
50157430218SRik van Riel
5022b1f967dSFrederic Weisbecker if (steal >= cputime)
5039fbc42eaSFrederic Weisbecker return;
5049fbc42eaSFrederic Weisbecker
5052b1f967dSFrederic Weisbecker cputime -= steal;
50657430218SRik van Riel
5079fbc42eaSFrederic Weisbecker if (user_tick)
50840565b5aSStanislaw Gruszka account_user_time(p, cputime);
5099dec1b69SAlex Shi else if ((p != this_rq()->idle) || (irq_count() != HARDIRQ_OFFSET))
510fb8b049cSFrederic Weisbecker account_system_time(p, HARDIRQ_OFFSET, cputime);
51173fbec60SFrederic Weisbecker else
51218b43a9bSFrederic Weisbecker account_idle_time(cputime);
5139fbc42eaSFrederic Weisbecker }
51473fbec60SFrederic Weisbecker
5159fbc42eaSFrederic Weisbecker /*
5169fbc42eaSFrederic Weisbecker * Account multiple ticks of idle time.
5179fbc42eaSFrederic Weisbecker * @ticks: number of stolen ticks
5189fbc42eaSFrederic Weisbecker */
account_idle_ticks(unsigned long ticks)5199fbc42eaSFrederic Weisbecker void account_idle_ticks(unsigned long ticks)
5209fbc42eaSFrederic Weisbecker {
52118b43a9bSFrederic Weisbecker u64 cputime, steal;
52226f2c75cSFrederic Weisbecker
5239fbc42eaSFrederic Weisbecker if (sched_clock_irqtime) {
5249fbc42eaSFrederic Weisbecker irqtime_account_idle_ticks(ticks);
5259fbc42eaSFrederic Weisbecker return;
5269fbc42eaSFrederic Weisbecker }
5279fbc42eaSFrederic Weisbecker
52818b43a9bSFrederic Weisbecker cputime = ticks * TICK_NSEC;
5292b1f967dSFrederic Weisbecker steal = steal_account_process_time(ULONG_MAX);
530f9bcf1e0SWanpeng Li
531f9bcf1e0SWanpeng Li if (steal >= cputime)
532f9bcf1e0SWanpeng Li return;
533f9bcf1e0SWanpeng Li
534f9bcf1e0SWanpeng Li cputime -= steal;
535f9bcf1e0SWanpeng Li account_idle_time(cputime);
5369fbc42eaSFrederic Weisbecker }
53773fbec60SFrederic Weisbecker
538d9a3c982SFrederic Weisbecker /*
5399d7fb042SPeter Zijlstra * Adjust tick based cputime random precision against scheduler runtime
5409d7fb042SPeter Zijlstra * accounting.
541347abad9SRik van Riel *
5429d7fb042SPeter Zijlstra * Tick based cputime accounting depend on random scheduling timeslices of a
5439d7fb042SPeter Zijlstra * task to be interrupted or not by the timer. Depending on these
5449d7fb042SPeter Zijlstra * circumstances, the number of these interrupts may be over or
5459d7fb042SPeter Zijlstra * under-optimistic, matching the real user and system cputime with a variable
5469d7fb042SPeter Zijlstra * precision.
5479d7fb042SPeter Zijlstra *
5489d7fb042SPeter Zijlstra * Fix this by scaling these tick based values against the total runtime
5499d7fb042SPeter Zijlstra * accounted by the CFS scheduler.
5509d7fb042SPeter Zijlstra *
5519d7fb042SPeter Zijlstra * This code provides the following guarantees:
5529d7fb042SPeter Zijlstra *
5539d7fb042SPeter Zijlstra * stime + utime == rtime
5549d7fb042SPeter Zijlstra * stime_i+1 >= stime_i, utime_i+1 >= utime_i
5559d7fb042SPeter Zijlstra *
5569d7fb042SPeter Zijlstra * Assuming that rtime_i+1 >= rtime_i.
557fa092057SFrederic Weisbecker */
cputime_adjust(struct task_cputime * curr,struct prev_cputime * prev,u64 * ut,u64 * st)558cfb766daSTejun Heo void cputime_adjust(struct task_cputime *curr, struct prev_cputime *prev,
5595613fda9SFrederic Weisbecker u64 *ut, u64 *st)
56073fbec60SFrederic Weisbecker {
5615613fda9SFrederic Weisbecker u64 rtime, stime, utime;
5629d7fb042SPeter Zijlstra unsigned long flags;
563fa092057SFrederic Weisbecker
5649d7fb042SPeter Zijlstra /* Serialize concurrent callers such that we can honour our guarantees */
5659d7fb042SPeter Zijlstra raw_spin_lock_irqsave(&prev->lock, flags);
5665613fda9SFrederic Weisbecker rtime = curr->sum_exec_runtime;
56773fbec60SFrederic Weisbecker
568772c808aSStanislaw Gruszka /*
5699d7fb042SPeter Zijlstra * This is possible under two circumstances:
5709d7fb042SPeter Zijlstra * - rtime isn't monotonic after all (a bug);
5719d7fb042SPeter Zijlstra * - we got reordered by the lock.
5729d7fb042SPeter Zijlstra *
5739d7fb042SPeter Zijlstra * In both cases this acts as a filter such that the rest of the code
5749d7fb042SPeter Zijlstra * can assume it is monotonic regardless of anything else.
575772c808aSStanislaw Gruszka */
576772c808aSStanislaw Gruszka if (prev->stime + prev->utime >= rtime)
577772c808aSStanislaw Gruszka goto out;
578772c808aSStanislaw Gruszka
5795a8e01f8SStanislaw Gruszka stime = curr->stime;
5805a8e01f8SStanislaw Gruszka utime = curr->utime;
5815a8e01f8SStanislaw Gruszka
582173be9a1SPeter Zijlstra /*
5833b9c08aeSIngo Molnar * If either stime or utime are 0, assume all runtime is userspace.
5843b03706fSIngo Molnar * Once a task gets some ticks, the monotonicity code at 'update:'
5853b9c08aeSIngo Molnar * will ensure things converge to the observed ratio.
586173be9a1SPeter Zijlstra */
5873b9c08aeSIngo Molnar if (stime == 0) {
5883b9c08aeSIngo Molnar utime = rtime;
5893b9c08aeSIngo Molnar goto update;
5909d7fb042SPeter Zijlstra }
59173fbec60SFrederic Weisbecker
5923b9c08aeSIngo Molnar if (utime == 0) {
5933b9c08aeSIngo Molnar stime = rtime;
5943b9c08aeSIngo Molnar goto update;
5953b9c08aeSIngo Molnar }
5963b9c08aeSIngo Molnar
5973dc167baSOleg Nesterov stime = mul_u64_u64_div_u64(stime, rtime, stime + utime);
598*12f98cc6SZheng Zucheng /*
599*12f98cc6SZheng Zucheng * Because mul_u64_u64_div_u64() can approximate on some
600*12f98cc6SZheng Zucheng * achitectures; enforce the constraint that: a*b/(b+c) <= a.
601*12f98cc6SZheng Zucheng */
602*12f98cc6SZheng Zucheng if (unlikely(stime > rtime))
603*12f98cc6SZheng Zucheng stime = rtime;
6043b9c08aeSIngo Molnar
6053b9c08aeSIngo Molnar update:
6069d7fb042SPeter Zijlstra /*
6079d7fb042SPeter Zijlstra * Make sure stime doesn't go backwards; this preserves monotonicity
6089d7fb042SPeter Zijlstra * for utime because rtime is monotonic.
6099d7fb042SPeter Zijlstra *
6109d7fb042SPeter Zijlstra * utime_i+1 = rtime_i+1 - stime_i
6119d7fb042SPeter Zijlstra * = rtime_i+1 - (rtime_i - utime_i)
6129d7fb042SPeter Zijlstra * = (rtime_i+1 - rtime_i) + utime_i
6139d7fb042SPeter Zijlstra * >= utime_i
6149d7fb042SPeter Zijlstra */
6159d7fb042SPeter Zijlstra if (stime < prev->stime)
6169d7fb042SPeter Zijlstra stime = prev->stime;
6179d7fb042SPeter Zijlstra utime = rtime - stime;
6189d7fb042SPeter Zijlstra
6199d7fb042SPeter Zijlstra /*
6209d7fb042SPeter Zijlstra * Make sure utime doesn't go backwards; this still preserves
6219d7fb042SPeter Zijlstra * monotonicity for stime, analogous argument to above.
6229d7fb042SPeter Zijlstra */
6239d7fb042SPeter Zijlstra if (utime < prev->utime) {
6249d7fb042SPeter Zijlstra utime = prev->utime;
6259d7fb042SPeter Zijlstra stime = rtime - utime;
6269d7fb042SPeter Zijlstra }
6279d7fb042SPeter Zijlstra
6289d7fb042SPeter Zijlstra prev->stime = stime;
6299d7fb042SPeter Zijlstra prev->utime = utime;
630772c808aSStanislaw Gruszka out:
631d37f761dSFrederic Weisbecker *ut = prev->utime;
632d37f761dSFrederic Weisbecker *st = prev->stime;
6339d7fb042SPeter Zijlstra raw_spin_unlock_irqrestore(&prev->lock, flags);
634d37f761dSFrederic Weisbecker }
635d37f761dSFrederic Weisbecker
task_cputime_adjusted(struct task_struct * p,u64 * ut,u64 * st)6365613fda9SFrederic Weisbecker void task_cputime_adjusted(struct task_struct *p, u64 *ut, u64 *st)
637d37f761dSFrederic Weisbecker {
638d37f761dSFrederic Weisbecker struct task_cputime cputime = {
639d37f761dSFrederic Weisbecker .sum_exec_runtime = p->se.sum_exec_runtime,
640d37f761dSFrederic Weisbecker };
641d37f761dSFrederic Weisbecker
642e7f2be11SFrederic Weisbecker if (task_cputime(p, &cputime.utime, &cputime.stime))
643e7f2be11SFrederic Weisbecker cputime.sum_exec_runtime = task_sched_runtime(p);
644d37f761dSFrederic Weisbecker cputime_adjust(&cputime, &p->prev_cputime, ut, st);
64573fbec60SFrederic Weisbecker }
6469eec50b8SAndrey Smetanin EXPORT_SYMBOL_GPL(task_cputime_adjusted);
64773fbec60SFrederic Weisbecker
thread_group_cputime_adjusted(struct task_struct * p,u64 * ut,u64 * st)6485613fda9SFrederic Weisbecker void thread_group_cputime_adjusted(struct task_struct *p, u64 *ut, u64 *st)
64973fbec60SFrederic Weisbecker {
65073fbec60SFrederic Weisbecker struct task_cputime cputime;
65173fbec60SFrederic Weisbecker
65273fbec60SFrederic Weisbecker thread_group_cputime(p, &cputime);
653d37f761dSFrederic Weisbecker cputime_adjust(&cputime, &p->signal->prev_cputime, ut, st);
65473fbec60SFrederic Weisbecker }
6559fbc42eaSFrederic Weisbecker #endif /* !CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
656abf917cdSFrederic Weisbecker
657abf917cdSFrederic Weisbecker #ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
vtime_delta(struct vtime * vtime)658bac5b6b6SFrederic Weisbecker static u64 vtime_delta(struct vtime *vtime)
659abf917cdSFrederic Weisbecker {
6602a42eb95SWanpeng Li unsigned long long clock;
661abf917cdSFrederic Weisbecker
6620e4097c3SWanpeng Li clock = sched_clock();
6632a42eb95SWanpeng Li if (clock < vtime->starttime)
6646a61671bSFrederic Weisbecker return 0;
6656a61671bSFrederic Weisbecker
6662a42eb95SWanpeng Li return clock - vtime->starttime;
6676a61671bSFrederic Weisbecker }
6686a61671bSFrederic Weisbecker
get_vtime_delta(struct vtime * vtime)669bac5b6b6SFrederic Weisbecker static u64 get_vtime_delta(struct vtime *vtime)
6706a61671bSFrederic Weisbecker {
6712a42eb95SWanpeng Li u64 delta = vtime_delta(vtime);
6722a42eb95SWanpeng Li u64 other;
6736a61671bSFrederic Weisbecker
67403cbc732SWanpeng Li /*
67503cbc732SWanpeng Li * Unlike tick based timing, vtime based timing never has lost
67603cbc732SWanpeng Li * ticks, and no need for steal time accounting to make up for
67703cbc732SWanpeng Li * lost ticks. Vtime accounts a rounded version of actual
67803cbc732SWanpeng Li * elapsed time. Limit account_other_time to prevent rounding
67903cbc732SWanpeng Li * errors from causing elapsed vtime to go negative.
68003cbc732SWanpeng Li */
681b58c3584SRik van Riel other = account_other_time(delta);
682bac5b6b6SFrederic Weisbecker WARN_ON_ONCE(vtime->state == VTIME_INACTIVE);
6832a42eb95SWanpeng Li vtime->starttime += delta;
684abf917cdSFrederic Weisbecker
685b58c3584SRik van Riel return delta - other;
686abf917cdSFrederic Weisbecker }
687abf917cdSFrederic Weisbecker
vtime_account_system(struct task_struct * tsk,struct vtime * vtime)688f83eeb1aSFrederic Weisbecker static void vtime_account_system(struct task_struct *tsk,
6892a42eb95SWanpeng Li struct vtime *vtime)
6906a61671bSFrederic Weisbecker {
6912a42eb95SWanpeng Li vtime->stime += get_vtime_delta(vtime);
6922a42eb95SWanpeng Li if (vtime->stime >= TICK_NSEC) {
6932a42eb95SWanpeng Li account_system_time(tsk, irq_count(), vtime->stime);
6942a42eb95SWanpeng Li vtime->stime = 0;
6952a42eb95SWanpeng Li }
6962a42eb95SWanpeng Li }
6972a42eb95SWanpeng Li
vtime_account_guest(struct task_struct * tsk,struct vtime * vtime)6982a42eb95SWanpeng Li static void vtime_account_guest(struct task_struct *tsk,
6992a42eb95SWanpeng Li struct vtime *vtime)
7002a42eb95SWanpeng Li {
7012a42eb95SWanpeng Li vtime->gtime += get_vtime_delta(vtime);
7022a42eb95SWanpeng Li if (vtime->gtime >= TICK_NSEC) {
7032a42eb95SWanpeng Li account_guest_time(tsk, vtime->gtime);
7042a42eb95SWanpeng Li vtime->gtime = 0;
7052a42eb95SWanpeng Li }
7066a61671bSFrederic Weisbecker }
7076a61671bSFrederic Weisbecker
__vtime_account_kernel(struct task_struct * tsk,struct vtime * vtime)7088d495477SFrederic Weisbecker static void __vtime_account_kernel(struct task_struct *tsk,
7098d495477SFrederic Weisbecker struct vtime *vtime)
7108d495477SFrederic Weisbecker {
7118d495477SFrederic Weisbecker /* We might have scheduled out from guest path */
712e6d5bf3eSFrederic Weisbecker if (vtime->state == VTIME_GUEST)
7138d495477SFrederic Weisbecker vtime_account_guest(tsk, vtime);
7148d495477SFrederic Weisbecker else
7158d495477SFrederic Weisbecker vtime_account_system(tsk, vtime);
7168d495477SFrederic Weisbecker }
7178d495477SFrederic Weisbecker
vtime_account_kernel(struct task_struct * tsk)718f83eeb1aSFrederic Weisbecker void vtime_account_kernel(struct task_struct *tsk)
719abf917cdSFrederic Weisbecker {
720bac5b6b6SFrederic Weisbecker struct vtime *vtime = &tsk->vtime;
721bac5b6b6SFrederic Weisbecker
722bac5b6b6SFrederic Weisbecker if (!vtime_delta(vtime))
723ff9a9b4cSRik van Riel return;
724ff9a9b4cSRik van Riel
725bac5b6b6SFrederic Weisbecker write_seqcount_begin(&vtime->seqcount);
7268d495477SFrederic Weisbecker __vtime_account_kernel(tsk, vtime);
727bac5b6b6SFrederic Weisbecker write_seqcount_end(&vtime->seqcount);
7286a61671bSFrederic Weisbecker }
7296a61671bSFrederic Weisbecker
vtime_user_enter(struct task_struct * tsk)7306a61671bSFrederic Weisbecker void vtime_user_enter(struct task_struct *tsk)
7316a61671bSFrederic Weisbecker {
732bac5b6b6SFrederic Weisbecker struct vtime *vtime = &tsk->vtime;
733bac5b6b6SFrederic Weisbecker
734bac5b6b6SFrederic Weisbecker write_seqcount_begin(&vtime->seqcount);
735f83eeb1aSFrederic Weisbecker vtime_account_system(tsk, vtime);
736bac5b6b6SFrederic Weisbecker vtime->state = VTIME_USER;
737bac5b6b6SFrederic Weisbecker write_seqcount_end(&vtime->seqcount);
7386a61671bSFrederic Weisbecker }
7396a61671bSFrederic Weisbecker
vtime_user_exit(struct task_struct * tsk)7401c3eda01SFrederic Weisbecker void vtime_user_exit(struct task_struct *tsk)
7411c3eda01SFrederic Weisbecker {
742bac5b6b6SFrederic Weisbecker struct vtime *vtime = &tsk->vtime;
743bac5b6b6SFrederic Weisbecker
744bac5b6b6SFrederic Weisbecker write_seqcount_begin(&vtime->seqcount);
7452a42eb95SWanpeng Li vtime->utime += get_vtime_delta(vtime);
7462a42eb95SWanpeng Li if (vtime->utime >= TICK_NSEC) {
7472a42eb95SWanpeng Li account_user_time(tsk, vtime->utime);
7482a42eb95SWanpeng Li vtime->utime = 0;
7492a42eb95SWanpeng Li }
750bac5b6b6SFrederic Weisbecker vtime->state = VTIME_SYS;
751bac5b6b6SFrederic Weisbecker write_seqcount_end(&vtime->seqcount);
7521c3eda01SFrederic Weisbecker }
7531c3eda01SFrederic Weisbecker
vtime_guest_enter(struct task_struct * tsk)7546a61671bSFrederic Weisbecker void vtime_guest_enter(struct task_struct *tsk)
7556a61671bSFrederic Weisbecker {
756bac5b6b6SFrederic Weisbecker struct vtime *vtime = &tsk->vtime;
7575b206d48SFrederic Weisbecker /*
7585b206d48SFrederic Weisbecker * The flags must be updated under the lock with
75960a9ce57SFrederic Weisbecker * the vtime_starttime flush and update.
7605b206d48SFrederic Weisbecker * That enforces a right ordering and update sequence
7615b206d48SFrederic Weisbecker * synchronization against the reader (task_gtime())
7625b206d48SFrederic Weisbecker * that can thus safely catch up with a tickless delta.
7635b206d48SFrederic Weisbecker */
764bac5b6b6SFrederic Weisbecker write_seqcount_begin(&vtime->seqcount);
765f83eeb1aSFrederic Weisbecker vtime_account_system(tsk, vtime);
76668e7a4d6SFrederic Weisbecker tsk->flags |= PF_VCPU;
767e6d5bf3eSFrederic Weisbecker vtime->state = VTIME_GUEST;
768bac5b6b6SFrederic Weisbecker write_seqcount_end(&vtime->seqcount);
7696a61671bSFrederic Weisbecker }
77048d6a816SFrederic Weisbecker EXPORT_SYMBOL_GPL(vtime_guest_enter);
7716a61671bSFrederic Weisbecker
vtime_guest_exit(struct task_struct * tsk)7726a61671bSFrederic Weisbecker void vtime_guest_exit(struct task_struct *tsk)
7736a61671bSFrederic Weisbecker {
774bac5b6b6SFrederic Weisbecker struct vtime *vtime = &tsk->vtime;
775bac5b6b6SFrederic Weisbecker
776bac5b6b6SFrederic Weisbecker write_seqcount_begin(&vtime->seqcount);
7772a42eb95SWanpeng Li vtime_account_guest(tsk, vtime);
77868e7a4d6SFrederic Weisbecker tsk->flags &= ~PF_VCPU;
779e6d5bf3eSFrederic Weisbecker vtime->state = VTIME_SYS;
780bac5b6b6SFrederic Weisbecker write_seqcount_end(&vtime->seqcount);
781abf917cdSFrederic Weisbecker }
78248d6a816SFrederic Weisbecker EXPORT_SYMBOL_GPL(vtime_guest_exit);
783abf917cdSFrederic Weisbecker
vtime_account_idle(struct task_struct * tsk)784abf917cdSFrederic Weisbecker void vtime_account_idle(struct task_struct *tsk)
785abf917cdSFrederic Weisbecker {
786bac5b6b6SFrederic Weisbecker account_idle_time(get_vtime_delta(&tsk->vtime));
787abf917cdSFrederic Weisbecker }
7883f4724eaSFrederic Weisbecker
vtime_task_switch_generic(struct task_struct * prev)7898d495477SFrederic Weisbecker void vtime_task_switch_generic(struct task_struct *prev)
7906a61671bSFrederic Weisbecker {
791bac5b6b6SFrederic Weisbecker struct vtime *vtime = &prev->vtime;
7926a61671bSFrederic Weisbecker
793bac5b6b6SFrederic Weisbecker write_seqcount_begin(&vtime->seqcount);
79414faf6fcSFrederic Weisbecker if (vtime->state == VTIME_IDLE)
7958d495477SFrederic Weisbecker vtime_account_idle(prev);
7968d495477SFrederic Weisbecker else
7978d495477SFrederic Weisbecker __vtime_account_kernel(prev, vtime);
798bac5b6b6SFrederic Weisbecker vtime->state = VTIME_INACTIVE;
799802f4a82SFrederic Weisbecker vtime->cpu = -1;
800bac5b6b6SFrederic Weisbecker write_seqcount_end(&vtime->seqcount);
801bac5b6b6SFrederic Weisbecker
802bac5b6b6SFrederic Weisbecker vtime = ¤t->vtime;
803bac5b6b6SFrederic Weisbecker
804bac5b6b6SFrederic Weisbecker write_seqcount_begin(&vtime->seqcount);
80514faf6fcSFrederic Weisbecker if (is_idle_task(current))
80614faf6fcSFrederic Weisbecker vtime->state = VTIME_IDLE;
807e6d5bf3eSFrederic Weisbecker else if (current->flags & PF_VCPU)
808e6d5bf3eSFrederic Weisbecker vtime->state = VTIME_GUEST;
80914faf6fcSFrederic Weisbecker else
810bac5b6b6SFrederic Weisbecker vtime->state = VTIME_SYS;
8110e4097c3SWanpeng Li vtime->starttime = sched_clock();
812802f4a82SFrederic Weisbecker vtime->cpu = smp_processor_id();
813bac5b6b6SFrederic Weisbecker write_seqcount_end(&vtime->seqcount);
8146a61671bSFrederic Weisbecker }
8156a61671bSFrederic Weisbecker
vtime_init_idle(struct task_struct * t,int cpu)81645eacc69SFrederic Weisbecker void vtime_init_idle(struct task_struct *t, int cpu)
8176a61671bSFrederic Weisbecker {
818bac5b6b6SFrederic Weisbecker struct vtime *vtime = &t->vtime;
8196a61671bSFrederic Weisbecker unsigned long flags;
8206a61671bSFrederic Weisbecker
821b7ce2277SFrederic Weisbecker local_irq_save(flags);
822bac5b6b6SFrederic Weisbecker write_seqcount_begin(&vtime->seqcount);
82314faf6fcSFrederic Weisbecker vtime->state = VTIME_IDLE;
8240e4097c3SWanpeng Li vtime->starttime = sched_clock();
825802f4a82SFrederic Weisbecker vtime->cpu = cpu;
826bac5b6b6SFrederic Weisbecker write_seqcount_end(&vtime->seqcount);
827b7ce2277SFrederic Weisbecker local_irq_restore(flags);
8286a61671bSFrederic Weisbecker }
8296a61671bSFrederic Weisbecker
task_gtime(struct task_struct * t)83016a6d9beSFrederic Weisbecker u64 task_gtime(struct task_struct *t)
8316a61671bSFrederic Weisbecker {
832bac5b6b6SFrederic Weisbecker struct vtime *vtime = &t->vtime;
8336a61671bSFrederic Weisbecker unsigned int seq;
83416a6d9beSFrederic Weisbecker u64 gtime;
8356a61671bSFrederic Weisbecker
836e5925394SFrederic Weisbecker if (!vtime_accounting_enabled())
8372541117bSHiroshi Shimamoto return t->gtime;
8382541117bSHiroshi Shimamoto
8396a61671bSFrederic Weisbecker do {
840bac5b6b6SFrederic Weisbecker seq = read_seqcount_begin(&vtime->seqcount);
8416a61671bSFrederic Weisbecker
8426a61671bSFrederic Weisbecker gtime = t->gtime;
843e6d5bf3eSFrederic Weisbecker if (vtime->state == VTIME_GUEST)
8442a42eb95SWanpeng Li gtime += vtime->gtime + vtime_delta(vtime);
8456a61671bSFrederic Weisbecker
846bac5b6b6SFrederic Weisbecker } while (read_seqcount_retry(&vtime->seqcount, seq));
8476a61671bSFrederic Weisbecker
8486a61671bSFrederic Weisbecker return gtime;
8496a61671bSFrederic Weisbecker }
8506a61671bSFrederic Weisbecker
8516a61671bSFrederic Weisbecker /*
8526a61671bSFrederic Weisbecker * Fetch cputime raw values from fields of task_struct and
8536a61671bSFrederic Weisbecker * add up the pending nohz execution time since the last
8546a61671bSFrederic Weisbecker * cputime snapshot.
8556a61671bSFrederic Weisbecker */
task_cputime(struct task_struct * t,u64 * utime,u64 * stime)856e7f2be11SFrederic Weisbecker bool task_cputime(struct task_struct *t, u64 *utime, u64 *stime)
8576a61671bSFrederic Weisbecker {
858bac5b6b6SFrederic Weisbecker struct vtime *vtime = &t->vtime;
8596a61671bSFrederic Weisbecker unsigned int seq;
860bac5b6b6SFrederic Weisbecker u64 delta;
861e7f2be11SFrederic Weisbecker int ret;
862353c50ebSStanislaw Gruszka
863353c50ebSStanislaw Gruszka if (!vtime_accounting_enabled()) {
864353c50ebSStanislaw Gruszka *utime = t->utime;
865353c50ebSStanislaw Gruszka *stime = t->stime;
866e7f2be11SFrederic Weisbecker return false;
867353c50ebSStanislaw Gruszka }
8686a61671bSFrederic Weisbecker
8696a61671bSFrederic Weisbecker do {
870e7f2be11SFrederic Weisbecker ret = false;
871bac5b6b6SFrederic Weisbecker seq = read_seqcount_begin(&vtime->seqcount);
8726a61671bSFrederic Weisbecker
873353c50ebSStanislaw Gruszka *utime = t->utime;
874353c50ebSStanislaw Gruszka *stime = t->stime;
8756a61671bSFrederic Weisbecker
87614faf6fcSFrederic Weisbecker /* Task is sleeping or idle, nothing to add */
87714faf6fcSFrederic Weisbecker if (vtime->state < VTIME_SYS)
8786a61671bSFrederic Weisbecker continue;
8796a61671bSFrederic Weisbecker
880e7f2be11SFrederic Weisbecker ret = true;
881bac5b6b6SFrederic Weisbecker delta = vtime_delta(vtime);
8826a61671bSFrederic Weisbecker
8836a61671bSFrederic Weisbecker /*
884e6d5bf3eSFrederic Weisbecker * Task runs either in user (including guest) or kernel space,
885e6d5bf3eSFrederic Weisbecker * add pending nohz time to the right place.
8866a61671bSFrederic Weisbecker */
887e6d5bf3eSFrederic Weisbecker if (vtime->state == VTIME_SYS)
8882a42eb95SWanpeng Li *stime += vtime->stime + delta;
889e6d5bf3eSFrederic Weisbecker else
890e6d5bf3eSFrederic Weisbecker *utime += vtime->utime + delta;
891bac5b6b6SFrederic Weisbecker } while (read_seqcount_retry(&vtime->seqcount, seq));
892e7f2be11SFrederic Weisbecker
893e7f2be11SFrederic Weisbecker return ret;
8946a61671bSFrederic Weisbecker }
89564eea63cSFrederic Weisbecker
vtime_state_fetch(struct vtime * vtime,int cpu)896f1dfdab6SChris Wilson static int vtime_state_fetch(struct vtime *vtime, int cpu)
89774722bb2SFrederic Weisbecker {
898f1dfdab6SChris Wilson int state = READ_ONCE(vtime->state);
899f1dfdab6SChris Wilson
90074722bb2SFrederic Weisbecker /*
90174722bb2SFrederic Weisbecker * We raced against a context switch, fetch the
90274722bb2SFrederic Weisbecker * kcpustat task again.
90374722bb2SFrederic Weisbecker */
90474722bb2SFrederic Weisbecker if (vtime->cpu != cpu && vtime->cpu != -1)
90574722bb2SFrederic Weisbecker return -EAGAIN;
90674722bb2SFrederic Weisbecker
90774722bb2SFrederic Weisbecker /*
90874722bb2SFrederic Weisbecker * Two possible things here:
90974722bb2SFrederic Weisbecker * 1) We are seeing the scheduling out task (prev) or any past one.
91074722bb2SFrederic Weisbecker * 2) We are seeing the scheduling in task (next) but it hasn't
91174722bb2SFrederic Weisbecker * passed though vtime_task_switch() yet so the pending
91274722bb2SFrederic Weisbecker * cputime of the prev task may not be flushed yet.
91374722bb2SFrederic Weisbecker *
91474722bb2SFrederic Weisbecker * Case 1) is ok but 2) is not. So wait for a safe VTIME state.
91574722bb2SFrederic Weisbecker */
916f1dfdab6SChris Wilson if (state == VTIME_INACTIVE)
91774722bb2SFrederic Weisbecker return -EAGAIN;
91874722bb2SFrederic Weisbecker
919f1dfdab6SChris Wilson return state;
92074722bb2SFrederic Weisbecker }
92174722bb2SFrederic Weisbecker
kcpustat_user_vtime(struct vtime * vtime)9225a1c9558SFrederic Weisbecker static u64 kcpustat_user_vtime(struct vtime *vtime)
9235a1c9558SFrederic Weisbecker {
9245a1c9558SFrederic Weisbecker if (vtime->state == VTIME_USER)
9255a1c9558SFrederic Weisbecker return vtime->utime + vtime_delta(vtime);
9265a1c9558SFrederic Weisbecker else if (vtime->state == VTIME_GUEST)
9275a1c9558SFrederic Weisbecker return vtime->gtime + vtime_delta(vtime);
9285a1c9558SFrederic Weisbecker return 0;
9295a1c9558SFrederic Weisbecker }
9305a1c9558SFrederic Weisbecker
kcpustat_field_vtime(u64 * cpustat,struct task_struct * tsk,enum cpu_usage_stat usage,int cpu,u64 * val)93164eea63cSFrederic Weisbecker static int kcpustat_field_vtime(u64 *cpustat,
9325a1c9558SFrederic Weisbecker struct task_struct *tsk,
93364eea63cSFrederic Weisbecker enum cpu_usage_stat usage,
93464eea63cSFrederic Weisbecker int cpu, u64 *val)
93564eea63cSFrederic Weisbecker {
9365a1c9558SFrederic Weisbecker struct vtime *vtime = &tsk->vtime;
93764eea63cSFrederic Weisbecker unsigned int seq;
93864eea63cSFrederic Weisbecker
93964eea63cSFrederic Weisbecker do {
940f1dfdab6SChris Wilson int state;
941f1dfdab6SChris Wilson
94264eea63cSFrederic Weisbecker seq = read_seqcount_begin(&vtime->seqcount);
94364eea63cSFrederic Weisbecker
944f1dfdab6SChris Wilson state = vtime_state_fetch(vtime, cpu);
945f1dfdab6SChris Wilson if (state < 0)
946f1dfdab6SChris Wilson return state;
94764eea63cSFrederic Weisbecker
94864eea63cSFrederic Weisbecker *val = cpustat[usage];
94964eea63cSFrederic Weisbecker
9505a1c9558SFrederic Weisbecker /*
9515a1c9558SFrederic Weisbecker * Nice VS unnice cputime accounting may be inaccurate if
9525a1c9558SFrederic Weisbecker * the nice value has changed since the last vtime update.
9535a1c9558SFrederic Weisbecker * But proper fix would involve interrupting target on nice
9545a1c9558SFrederic Weisbecker * updates which is a no go on nohz_full (although the scheduler
9555a1c9558SFrederic Weisbecker * may still interrupt the target if rescheduling is needed...)
9565a1c9558SFrederic Weisbecker */
9575a1c9558SFrederic Weisbecker switch (usage) {
9585a1c9558SFrederic Weisbecker case CPUTIME_SYSTEM:
959f1dfdab6SChris Wilson if (state == VTIME_SYS)
96064eea63cSFrederic Weisbecker *val += vtime->stime + vtime_delta(vtime);
9615a1c9558SFrederic Weisbecker break;
9625a1c9558SFrederic Weisbecker case CPUTIME_USER:
9635a1c9558SFrederic Weisbecker if (task_nice(tsk) <= 0)
9645a1c9558SFrederic Weisbecker *val += kcpustat_user_vtime(vtime);
9655a1c9558SFrederic Weisbecker break;
9665a1c9558SFrederic Weisbecker case CPUTIME_NICE:
9675a1c9558SFrederic Weisbecker if (task_nice(tsk) > 0)
9685a1c9558SFrederic Weisbecker *val += kcpustat_user_vtime(vtime);
9695a1c9558SFrederic Weisbecker break;
9705a1c9558SFrederic Weisbecker case CPUTIME_GUEST:
971f1dfdab6SChris Wilson if (state == VTIME_GUEST && task_nice(tsk) <= 0)
9725a1c9558SFrederic Weisbecker *val += vtime->gtime + vtime_delta(vtime);
9735a1c9558SFrederic Weisbecker break;
9745a1c9558SFrederic Weisbecker case CPUTIME_GUEST_NICE:
975f1dfdab6SChris Wilson if (state == VTIME_GUEST && task_nice(tsk) > 0)
9765a1c9558SFrederic Weisbecker *val += vtime->gtime + vtime_delta(vtime);
9775a1c9558SFrederic Weisbecker break;
9785a1c9558SFrederic Weisbecker default:
9795a1c9558SFrederic Weisbecker break;
9805a1c9558SFrederic Weisbecker }
98164eea63cSFrederic Weisbecker } while (read_seqcount_retry(&vtime->seqcount, seq));
98264eea63cSFrederic Weisbecker
98364eea63cSFrederic Weisbecker return 0;
98464eea63cSFrederic Weisbecker }
98564eea63cSFrederic Weisbecker
kcpustat_field(struct kernel_cpustat * kcpustat,enum cpu_usage_stat usage,int cpu)98664eea63cSFrederic Weisbecker u64 kcpustat_field(struct kernel_cpustat *kcpustat,
98764eea63cSFrederic Weisbecker enum cpu_usage_stat usage, int cpu)
98864eea63cSFrederic Weisbecker {
98964eea63cSFrederic Weisbecker u64 *cpustat = kcpustat->cpustat;
990e0d648f9SBorislav Petkov u64 val = cpustat[usage];
99164eea63cSFrederic Weisbecker struct rq *rq;
99264eea63cSFrederic Weisbecker int err;
99364eea63cSFrederic Weisbecker
99464eea63cSFrederic Weisbecker if (!vtime_accounting_enabled_cpu(cpu))
995e0d648f9SBorislav Petkov return val;
99664eea63cSFrederic Weisbecker
99764eea63cSFrederic Weisbecker rq = cpu_rq(cpu);
99864eea63cSFrederic Weisbecker
99964eea63cSFrederic Weisbecker for (;;) {
100064eea63cSFrederic Weisbecker struct task_struct *curr;
100164eea63cSFrederic Weisbecker
100264eea63cSFrederic Weisbecker rcu_read_lock();
100364eea63cSFrederic Weisbecker curr = rcu_dereference(rq->curr);
100464eea63cSFrederic Weisbecker if (WARN_ON_ONCE(!curr)) {
100564eea63cSFrederic Weisbecker rcu_read_unlock();
100664eea63cSFrederic Weisbecker return cpustat[usage];
100764eea63cSFrederic Weisbecker }
100864eea63cSFrederic Weisbecker
10095a1c9558SFrederic Weisbecker err = kcpustat_field_vtime(cpustat, curr, usage, cpu, &val);
101064eea63cSFrederic Weisbecker rcu_read_unlock();
101164eea63cSFrederic Weisbecker
101264eea63cSFrederic Weisbecker if (!err)
101364eea63cSFrederic Weisbecker return val;
101464eea63cSFrederic Weisbecker
101564eea63cSFrederic Weisbecker cpu_relax();
101664eea63cSFrederic Weisbecker }
101764eea63cSFrederic Weisbecker }
101864eea63cSFrederic Weisbecker EXPORT_SYMBOL_GPL(kcpustat_field);
101974722bb2SFrederic Weisbecker
kcpustat_cpu_fetch_vtime(struct kernel_cpustat * dst,const struct kernel_cpustat * src,struct task_struct * tsk,int cpu)102074722bb2SFrederic Weisbecker static int kcpustat_cpu_fetch_vtime(struct kernel_cpustat *dst,
102174722bb2SFrederic Weisbecker const struct kernel_cpustat *src,
102274722bb2SFrederic Weisbecker struct task_struct *tsk, int cpu)
102374722bb2SFrederic Weisbecker {
102474722bb2SFrederic Weisbecker struct vtime *vtime = &tsk->vtime;
102574722bb2SFrederic Weisbecker unsigned int seq;
102674722bb2SFrederic Weisbecker
102774722bb2SFrederic Weisbecker do {
102874722bb2SFrederic Weisbecker u64 *cpustat;
102974722bb2SFrederic Weisbecker u64 delta;
1030f1dfdab6SChris Wilson int state;
103174722bb2SFrederic Weisbecker
103274722bb2SFrederic Weisbecker seq = read_seqcount_begin(&vtime->seqcount);
103374722bb2SFrederic Weisbecker
1034f1dfdab6SChris Wilson state = vtime_state_fetch(vtime, cpu);
1035f1dfdab6SChris Wilson if (state < 0)
1036f1dfdab6SChris Wilson return state;
103774722bb2SFrederic Weisbecker
103874722bb2SFrederic Weisbecker *dst = *src;
103974722bb2SFrederic Weisbecker cpustat = dst->cpustat;
104074722bb2SFrederic Weisbecker
104174722bb2SFrederic Weisbecker /* Task is sleeping, dead or idle, nothing to add */
1042f1dfdab6SChris Wilson if (state < VTIME_SYS)
104374722bb2SFrederic Weisbecker continue;
104474722bb2SFrederic Weisbecker
104574722bb2SFrederic Weisbecker delta = vtime_delta(vtime);
104674722bb2SFrederic Weisbecker
104774722bb2SFrederic Weisbecker /*
104874722bb2SFrederic Weisbecker * Task runs either in user (including guest) or kernel space,
104974722bb2SFrederic Weisbecker * add pending nohz time to the right place.
105074722bb2SFrederic Weisbecker */
1051f1dfdab6SChris Wilson if (state == VTIME_SYS) {
105274722bb2SFrederic Weisbecker cpustat[CPUTIME_SYSTEM] += vtime->stime + delta;
1053f1dfdab6SChris Wilson } else if (state == VTIME_USER) {
105474722bb2SFrederic Weisbecker if (task_nice(tsk) > 0)
105574722bb2SFrederic Weisbecker cpustat[CPUTIME_NICE] += vtime->utime + delta;
105674722bb2SFrederic Weisbecker else
105774722bb2SFrederic Weisbecker cpustat[CPUTIME_USER] += vtime->utime + delta;
105874722bb2SFrederic Weisbecker } else {
1059f1dfdab6SChris Wilson WARN_ON_ONCE(state != VTIME_GUEST);
106074722bb2SFrederic Weisbecker if (task_nice(tsk) > 0) {
106174722bb2SFrederic Weisbecker cpustat[CPUTIME_GUEST_NICE] += vtime->gtime + delta;
106274722bb2SFrederic Weisbecker cpustat[CPUTIME_NICE] += vtime->gtime + delta;
106374722bb2SFrederic Weisbecker } else {
106474722bb2SFrederic Weisbecker cpustat[CPUTIME_GUEST] += vtime->gtime + delta;
106574722bb2SFrederic Weisbecker cpustat[CPUTIME_USER] += vtime->gtime + delta;
106674722bb2SFrederic Weisbecker }
106774722bb2SFrederic Weisbecker }
106874722bb2SFrederic Weisbecker } while (read_seqcount_retry(&vtime->seqcount, seq));
106974722bb2SFrederic Weisbecker
1070f1dfdab6SChris Wilson return 0;
107174722bb2SFrederic Weisbecker }
107274722bb2SFrederic Weisbecker
kcpustat_cpu_fetch(struct kernel_cpustat * dst,int cpu)107374722bb2SFrederic Weisbecker void kcpustat_cpu_fetch(struct kernel_cpustat *dst, int cpu)
107474722bb2SFrederic Weisbecker {
107574722bb2SFrederic Weisbecker const struct kernel_cpustat *src = &kcpustat_cpu(cpu);
107674722bb2SFrederic Weisbecker struct rq *rq;
107774722bb2SFrederic Weisbecker int err;
107874722bb2SFrederic Weisbecker
107974722bb2SFrederic Weisbecker if (!vtime_accounting_enabled_cpu(cpu)) {
108074722bb2SFrederic Weisbecker *dst = *src;
108174722bb2SFrederic Weisbecker return;
108274722bb2SFrederic Weisbecker }
108374722bb2SFrederic Weisbecker
108474722bb2SFrederic Weisbecker rq = cpu_rq(cpu);
108574722bb2SFrederic Weisbecker
108674722bb2SFrederic Weisbecker for (;;) {
108774722bb2SFrederic Weisbecker struct task_struct *curr;
108874722bb2SFrederic Weisbecker
108974722bb2SFrederic Weisbecker rcu_read_lock();
109074722bb2SFrederic Weisbecker curr = rcu_dereference(rq->curr);
109174722bb2SFrederic Weisbecker if (WARN_ON_ONCE(!curr)) {
109274722bb2SFrederic Weisbecker rcu_read_unlock();
109374722bb2SFrederic Weisbecker *dst = *src;
109474722bb2SFrederic Weisbecker return;
109574722bb2SFrederic Weisbecker }
109674722bb2SFrederic Weisbecker
109774722bb2SFrederic Weisbecker err = kcpustat_cpu_fetch_vtime(dst, src, curr, cpu);
109874722bb2SFrederic Weisbecker rcu_read_unlock();
109974722bb2SFrederic Weisbecker
110074722bb2SFrederic Weisbecker if (!err)
110174722bb2SFrederic Weisbecker return;
110274722bb2SFrederic Weisbecker
110374722bb2SFrederic Weisbecker cpu_relax();
110474722bb2SFrederic Weisbecker }
110574722bb2SFrederic Weisbecker }
110674722bb2SFrederic Weisbecker EXPORT_SYMBOL_GPL(kcpustat_cpu_fetch);
110774722bb2SFrederic Weisbecker
1108abf917cdSFrederic Weisbecker #endif /* CONFIG_VIRT_CPU_ACCOUNTING_GEN */
1109