xref: /openbmc/linux/kernel/sched/cputime.c (revision 60a9ce57e7c5ac1df3a39fb941022bbfa40c0862)
173fbec60SFrederic Weisbecker #include <linux/export.h>
273fbec60SFrederic Weisbecker #include <linux/sched.h>
373fbec60SFrederic Weisbecker #include <linux/tsacct_kern.h>
473fbec60SFrederic Weisbecker #include <linux/kernel_stat.h>
573fbec60SFrederic Weisbecker #include <linux/static_key.h>
6abf917cdSFrederic Weisbecker #include <linux/context_tracking.h>
732ef5517SIngo Molnar #include <linux/sched/cputime.h>
873fbec60SFrederic Weisbecker #include "sched.h"
973fbec60SFrederic Weisbecker 
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 
2773fbec60SFrederic Weisbecker void enable_sched_clock_irqtime(void)
2873fbec60SFrederic Weisbecker {
2973fbec60SFrederic Weisbecker 	sched_clock_irqtime = 1;
3073fbec60SFrederic Weisbecker }
3173fbec60SFrederic Weisbecker 
3273fbec60SFrederic Weisbecker void disable_sched_clock_irqtime(void)
3373fbec60SFrederic Weisbecker {
3473fbec60SFrederic Weisbecker 	sched_clock_irqtime = 0;
3573fbec60SFrederic Weisbecker }
3673fbec60SFrederic Weisbecker 
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 /*
5073fbec60SFrederic Weisbecker  * Called before incrementing preempt_count on {soft,}irq_enter
5173fbec60SFrederic Weisbecker  * and before decrementing preempt_count on {soft,}irq_exit.
5273fbec60SFrederic Weisbecker  */
533e1df4f5SFrederic Weisbecker void irqtime_account_irq(struct task_struct *curr)
5473fbec60SFrederic Weisbecker {
5519d23dbfSFrederic Weisbecker 	struct irqtime *irqtime = this_cpu_ptr(&cpu_irqtime);
5673fbec60SFrederic Weisbecker 	s64 delta;
5773fbec60SFrederic Weisbecker 	int cpu;
5873fbec60SFrederic Weisbecker 
5973fbec60SFrederic Weisbecker 	if (!sched_clock_irqtime)
6073fbec60SFrederic Weisbecker 		return;
6173fbec60SFrederic Weisbecker 
6273fbec60SFrederic Weisbecker 	cpu = smp_processor_id();
6319d23dbfSFrederic Weisbecker 	delta = sched_clock_cpu(cpu) - irqtime->irq_start_time;
6419d23dbfSFrederic Weisbecker 	irqtime->irq_start_time += delta;
6573fbec60SFrederic Weisbecker 
6673fbec60SFrederic Weisbecker 	/*
6773fbec60SFrederic Weisbecker 	 * We do not account for softirq time from ksoftirqd here.
6873fbec60SFrederic Weisbecker 	 * We want to continue accounting softirq time to ksoftirqd thread
6973fbec60SFrederic Weisbecker 	 * in that case, so as not to confuse scheduler with a special task
7073fbec60SFrederic Weisbecker 	 * that do not consume any time, but still wants to run.
7173fbec60SFrederic Weisbecker 	 */
7225e2d8c1SFrederic Weisbecker 	if (hardirq_count())
7325e2d8c1SFrederic Weisbecker 		irqtime_account_delta(irqtime, delta, CPUTIME_IRQ);
7425e2d8c1SFrederic Weisbecker 	else if (in_serving_softirq() && curr != this_cpu_ksoftirqd())
7525e2d8c1SFrederic Weisbecker 		irqtime_account_delta(irqtime, delta, CPUTIME_SOFTIRQ);
7673fbec60SFrederic Weisbecker }
773e1df4f5SFrederic Weisbecker EXPORT_SYMBOL_GPL(irqtime_account_irq);
7873fbec60SFrederic Weisbecker 
792b1f967dSFrederic Weisbecker static u64 irqtime_tick_accounted(u64 maxtime)
8073fbec60SFrederic Weisbecker {
81a499a5a1SFrederic Weisbecker 	struct irqtime *irqtime = this_cpu_ptr(&cpu_irqtime);
822b1f967dSFrederic Weisbecker 	u64 delta;
8373fbec60SFrederic Weisbecker 
842b1f967dSFrederic Weisbecker 	delta = min(irqtime->tick_delta, maxtime);
852b1f967dSFrederic Weisbecker 	irqtime->tick_delta -= delta;
862810f611SFrederic Weisbecker 
87a499a5a1SFrederic Weisbecker 	return delta;
8873fbec60SFrederic Weisbecker }
8973fbec60SFrederic Weisbecker 
9073fbec60SFrederic Weisbecker #else /* CONFIG_IRQ_TIME_ACCOUNTING */
9173fbec60SFrederic Weisbecker 
9273fbec60SFrederic Weisbecker #define sched_clock_irqtime	(0)
9373fbec60SFrederic Weisbecker 
942b1f967dSFrederic Weisbecker static u64 irqtime_tick_accounted(u64 dummy)
9557430218SRik van Riel {
9657430218SRik van Riel 	return 0;
9757430218SRik van Riel }
9857430218SRik van Riel 
9973fbec60SFrederic Weisbecker #endif /* !CONFIG_IRQ_TIME_ACCOUNTING */
10073fbec60SFrederic Weisbecker 
10173fbec60SFrederic Weisbecker static inline void task_group_account_field(struct task_struct *p, int index,
10273fbec60SFrederic Weisbecker 					    u64 tmp)
10373fbec60SFrederic Weisbecker {
10473fbec60SFrederic Weisbecker 	/*
10573fbec60SFrederic Weisbecker 	 * Since all updates are sure to touch the root cgroup, we
10673fbec60SFrederic Weisbecker 	 * get ourselves ahead and touch it first. If the root cgroup
10773fbec60SFrederic Weisbecker 	 * is the only cgroup, then nothing else should be necessary.
10873fbec60SFrederic Weisbecker 	 *
10973fbec60SFrederic Weisbecker 	 */
110a4f61cc0SChristoph Lameter 	__this_cpu_add(kernel_cpustat.cpustat[index], tmp);
11173fbec60SFrederic Weisbecker 
1121966aaf7SLi Zefan 	cpuacct_account_field(p, index, tmp);
11373fbec60SFrederic Weisbecker }
11473fbec60SFrederic Weisbecker 
11573fbec60SFrederic Weisbecker /*
11673fbec60SFrederic Weisbecker  * Account user cpu time to a process.
11773fbec60SFrederic Weisbecker  * @p: the process that the cpu time gets accounted to
11873fbec60SFrederic Weisbecker  * @cputime: the cpu time spent in user space since the last update
11973fbec60SFrederic Weisbecker  */
12023244a5cSFrederic Weisbecker void account_user_time(struct task_struct *p, u64 cputime)
12173fbec60SFrederic Weisbecker {
12273fbec60SFrederic Weisbecker 	int index;
12373fbec60SFrederic Weisbecker 
12473fbec60SFrederic Weisbecker 	/* Add user time to process. */
12523244a5cSFrederic Weisbecker 	p->utime += cputime;
12623244a5cSFrederic Weisbecker 	account_group_user_time(p, cputime);
12773fbec60SFrederic Weisbecker 
128d0ea0268SDongsheng Yang 	index = (task_nice(p) > 0) ? CPUTIME_NICE : CPUTIME_USER;
12973fbec60SFrederic Weisbecker 
13073fbec60SFrederic Weisbecker 	/* Add user time to cpustat. */
13123244a5cSFrederic Weisbecker 	task_group_account_field(p, index, cputime);
13273fbec60SFrederic Weisbecker 
13373fbec60SFrederic Weisbecker 	/* Account for user time used */
1346fac4829SFrederic Weisbecker 	acct_account_cputime(p);
13573fbec60SFrederic Weisbecker }
13673fbec60SFrederic Weisbecker 
13773fbec60SFrederic Weisbecker /*
13873fbec60SFrederic Weisbecker  * Account guest cpu time to a process.
13973fbec60SFrederic Weisbecker  * @p: the process that the cpu time gets accounted to
14073fbec60SFrederic Weisbecker  * @cputime: the cpu time spent in virtual machine since the last update
14173fbec60SFrederic Weisbecker  */
142fb8b049cSFrederic Weisbecker void account_guest_time(struct task_struct *p, u64 cputime)
14373fbec60SFrederic Weisbecker {
14473fbec60SFrederic Weisbecker 	u64 *cpustat = kcpustat_this_cpu->cpustat;
14573fbec60SFrederic Weisbecker 
14673fbec60SFrederic Weisbecker 	/* Add guest time to process. */
147fb8b049cSFrederic Weisbecker 	p->utime += cputime;
148fb8b049cSFrederic Weisbecker 	account_group_user_time(p, cputime);
149fb8b049cSFrederic Weisbecker 	p->gtime += cputime;
15073fbec60SFrederic Weisbecker 
15173fbec60SFrederic Weisbecker 	/* Add guest time to cpustat. */
152d0ea0268SDongsheng Yang 	if (task_nice(p) > 0) {
153fb8b049cSFrederic Weisbecker 		cpustat[CPUTIME_NICE] += cputime;
154fb8b049cSFrederic Weisbecker 		cpustat[CPUTIME_GUEST_NICE] += cputime;
15573fbec60SFrederic Weisbecker 	} else {
156fb8b049cSFrederic Weisbecker 		cpustat[CPUTIME_USER] += cputime;
157fb8b049cSFrederic Weisbecker 		cpustat[CPUTIME_GUEST] += cputime;
15873fbec60SFrederic Weisbecker 	}
15973fbec60SFrederic Weisbecker }
16073fbec60SFrederic Weisbecker 
16173fbec60SFrederic Weisbecker /*
16273fbec60SFrederic Weisbecker  * Account system cpu time to a process and desired cpustat field
16373fbec60SFrederic Weisbecker  * @p: the process that the cpu time gets accounted to
16473fbec60SFrederic Weisbecker  * @cputime: the cpu time spent in kernel space since the last update
16540565b5aSStanislaw Gruszka  * @index: pointer to cpustat field that has to be updated
16673fbec60SFrederic Weisbecker  */
167c31cc6a5SFrederic Weisbecker void account_system_index_time(struct task_struct *p,
168fb8b049cSFrederic Weisbecker 			       u64 cputime, enum cpu_usage_stat index)
16973fbec60SFrederic Weisbecker {
17073fbec60SFrederic Weisbecker 	/* Add system time to process. */
171fb8b049cSFrederic Weisbecker 	p->stime += cputime;
172fb8b049cSFrederic Weisbecker 	account_group_system_time(p, cputime);
17373fbec60SFrederic Weisbecker 
17473fbec60SFrederic Weisbecker 	/* Add system time to cpustat. */
175fb8b049cSFrederic Weisbecker 	task_group_account_field(p, index, cputime);
17673fbec60SFrederic Weisbecker 
17773fbec60SFrederic Weisbecker 	/* Account for system time used */
1786fac4829SFrederic Weisbecker 	acct_account_cputime(p);
17973fbec60SFrederic Weisbecker }
18073fbec60SFrederic Weisbecker 
18173fbec60SFrederic Weisbecker /*
18273fbec60SFrederic Weisbecker  * Account system cpu time to a process.
18373fbec60SFrederic Weisbecker  * @p: the process that the cpu time gets accounted to
18473fbec60SFrederic Weisbecker  * @hardirq_offset: the offset to subtract from hardirq_count()
18573fbec60SFrederic Weisbecker  * @cputime: the cpu time spent in kernel space since the last update
18673fbec60SFrederic Weisbecker  */
187fb8b049cSFrederic Weisbecker void account_system_time(struct task_struct *p, int hardirq_offset, u64 cputime)
18873fbec60SFrederic Weisbecker {
18973fbec60SFrederic Weisbecker 	int index;
19073fbec60SFrederic Weisbecker 
19173fbec60SFrederic Weisbecker 	if ((p->flags & PF_VCPU) && (irq_count() - hardirq_offset == 0)) {
19240565b5aSStanislaw Gruszka 		account_guest_time(p, cputime);
19373fbec60SFrederic Weisbecker 		return;
19473fbec60SFrederic Weisbecker 	}
19573fbec60SFrederic Weisbecker 
19673fbec60SFrederic Weisbecker 	if (hardirq_count() - hardirq_offset)
19773fbec60SFrederic Weisbecker 		index = CPUTIME_IRQ;
19873fbec60SFrederic Weisbecker 	else if (in_serving_softirq())
19973fbec60SFrederic Weisbecker 		index = CPUTIME_SOFTIRQ;
20073fbec60SFrederic Weisbecker 	else
20173fbec60SFrederic Weisbecker 		index = CPUTIME_SYSTEM;
20273fbec60SFrederic Weisbecker 
203c31cc6a5SFrederic Weisbecker 	account_system_index_time(p, cputime, index);
20473fbec60SFrederic Weisbecker }
20573fbec60SFrederic Weisbecker 
20673fbec60SFrederic Weisbecker /*
20773fbec60SFrederic Weisbecker  * Account for involuntary wait time.
20873fbec60SFrederic Weisbecker  * @cputime: the cpu time spent in involuntary wait
20973fbec60SFrederic Weisbecker  */
210be9095edSFrederic Weisbecker void account_steal_time(u64 cputime)
21173fbec60SFrederic Weisbecker {
21273fbec60SFrederic Weisbecker 	u64 *cpustat = kcpustat_this_cpu->cpustat;
21373fbec60SFrederic Weisbecker 
214be9095edSFrederic Weisbecker 	cpustat[CPUTIME_STEAL] += cputime;
21573fbec60SFrederic Weisbecker }
21673fbec60SFrederic Weisbecker 
21773fbec60SFrederic Weisbecker /*
21873fbec60SFrederic Weisbecker  * Account for idle time.
21973fbec60SFrederic Weisbecker  * @cputime: the cpu time spent in idle wait
22073fbec60SFrederic Weisbecker  */
22118b43a9bSFrederic Weisbecker void account_idle_time(u64 cputime)
22273fbec60SFrederic Weisbecker {
22373fbec60SFrederic Weisbecker 	u64 *cpustat = kcpustat_this_cpu->cpustat;
22473fbec60SFrederic Weisbecker 	struct rq *rq = this_rq();
22573fbec60SFrederic Weisbecker 
22673fbec60SFrederic Weisbecker 	if (atomic_read(&rq->nr_iowait) > 0)
22718b43a9bSFrederic Weisbecker 		cpustat[CPUTIME_IOWAIT] += cputime;
22873fbec60SFrederic Weisbecker 	else
22918b43a9bSFrederic Weisbecker 		cpustat[CPUTIME_IDLE] += cputime;
23073fbec60SFrederic Weisbecker }
23173fbec60SFrederic Weisbecker 
23203cbc732SWanpeng Li /*
23303cbc732SWanpeng Li  * When a guest is interrupted for a longer amount of time, missed clock
23403cbc732SWanpeng Li  * ticks are not redelivered later. Due to that, this function may on
23503cbc732SWanpeng Li  * occasion account more time than the calling functions think elapsed.
23603cbc732SWanpeng Li  */
2372b1f967dSFrederic Weisbecker static __always_inline u64 steal_account_process_time(u64 maxtime)
23873fbec60SFrederic Weisbecker {
23973fbec60SFrederic Weisbecker #ifdef CONFIG_PARAVIRT
24073fbec60SFrederic Weisbecker 	if (static_key_false(&paravirt_steal_enabled)) {
2412b1f967dSFrederic Weisbecker 		u64 steal;
24273fbec60SFrederic Weisbecker 
24373fbec60SFrederic Weisbecker 		steal = paravirt_steal_clock(smp_processor_id());
24473fbec60SFrederic Weisbecker 		steal -= this_rq()->prev_steal_time;
2452b1f967dSFrederic Weisbecker 		steal = min(steal, maxtime);
2462b1f967dSFrederic Weisbecker 		account_steal_time(steal);
2472b1f967dSFrederic Weisbecker 		this_rq()->prev_steal_time += steal;
24873fbec60SFrederic Weisbecker 
2492b1f967dSFrederic Weisbecker 		return steal;
25073fbec60SFrederic Weisbecker 	}
25173fbec60SFrederic Weisbecker #endif
252807e5b80SWanpeng Li 	return 0;
25373fbec60SFrederic Weisbecker }
25473fbec60SFrederic Weisbecker 
255a634f933SFrederic Weisbecker /*
25657430218SRik van Riel  * Account how much elapsed time was spent in steal, irq, or softirq time.
25757430218SRik van Riel  */
2582b1f967dSFrederic Weisbecker static inline u64 account_other_time(u64 max)
25957430218SRik van Riel {
2602b1f967dSFrederic Weisbecker 	u64 accounted;
26157430218SRik van Riel 
2622810f611SFrederic Weisbecker 	/* Shall be converted to a lockdep-enabled lightweight check */
2632810f611SFrederic Weisbecker 	WARN_ON_ONCE(!irqs_disabled());
2642810f611SFrederic Weisbecker 
26557430218SRik van Riel 	accounted = steal_account_process_time(max);
26657430218SRik van Riel 
26757430218SRik van Riel 	if (accounted < max)
268a499a5a1SFrederic Weisbecker 		accounted += irqtime_tick_accounted(max - accounted);
26957430218SRik van Riel 
27057430218SRik van Riel 	return accounted;
27157430218SRik van Riel }
27257430218SRik van Riel 
273a1eb1411SStanislaw Gruszka #ifdef CONFIG_64BIT
274a1eb1411SStanislaw Gruszka static inline u64 read_sum_exec_runtime(struct task_struct *t)
275a1eb1411SStanislaw Gruszka {
276a1eb1411SStanislaw Gruszka 	return t->se.sum_exec_runtime;
277a1eb1411SStanislaw Gruszka }
278a1eb1411SStanislaw Gruszka #else
279a1eb1411SStanislaw Gruszka static u64 read_sum_exec_runtime(struct task_struct *t)
280a1eb1411SStanislaw Gruszka {
281a1eb1411SStanislaw Gruszka 	u64 ns;
282a1eb1411SStanislaw Gruszka 	struct rq_flags rf;
283a1eb1411SStanislaw Gruszka 	struct rq *rq;
284a1eb1411SStanislaw Gruszka 
285a1eb1411SStanislaw Gruszka 	rq = task_rq_lock(t, &rf);
286a1eb1411SStanislaw Gruszka 	ns = t->se.sum_exec_runtime;
287a1eb1411SStanislaw Gruszka 	task_rq_unlock(rq, t, &rf);
288a1eb1411SStanislaw Gruszka 
289a1eb1411SStanislaw Gruszka 	return ns;
290a1eb1411SStanislaw Gruszka }
291a1eb1411SStanislaw Gruszka #endif
292a1eb1411SStanislaw Gruszka 
29357430218SRik van Riel /*
294a634f933SFrederic Weisbecker  * Accumulate raw cputime values of dead tasks (sig->[us]time) and live
295a634f933SFrederic Weisbecker  * tasks (sum on group iteration) belonging to @tsk's group.
296a634f933SFrederic Weisbecker  */
297a634f933SFrederic Weisbecker void thread_group_cputime(struct task_struct *tsk, struct task_cputime *times)
298a634f933SFrederic Weisbecker {
299a634f933SFrederic Weisbecker 	struct signal_struct *sig = tsk->signal;
3005613fda9SFrederic Weisbecker 	u64 utime, stime;
301a634f933SFrederic Weisbecker 	struct task_struct *t;
302e78c3496SRik van Riel 	unsigned int seq, nextseq;
3039c368b5bSRik van Riel 	unsigned long flags;
304a634f933SFrederic Weisbecker 
305a1eb1411SStanislaw Gruszka 	/*
306a1eb1411SStanislaw Gruszka 	 * Update current task runtime to account pending time since last
307a1eb1411SStanislaw Gruszka 	 * scheduler action or thread_group_cputime() call. This thread group
308a1eb1411SStanislaw Gruszka 	 * might have other running tasks on different CPUs, but updating
309a1eb1411SStanislaw Gruszka 	 * their runtime can affect syscall performance, so we skip account
310a1eb1411SStanislaw Gruszka 	 * those pending times and rely only on values updated on tick or
311a1eb1411SStanislaw Gruszka 	 * other scheduler action.
312a1eb1411SStanislaw Gruszka 	 */
313a1eb1411SStanislaw Gruszka 	if (same_thread_group(current, tsk))
314a1eb1411SStanislaw Gruszka 		(void) task_sched_runtime(current);
315a1eb1411SStanislaw Gruszka 
316e78c3496SRik van Riel 	rcu_read_lock();
317e78c3496SRik van Riel 	/* Attempt a lockless read on the first round. */
318e78c3496SRik van Riel 	nextseq = 0;
319e78c3496SRik van Riel 	do {
320e78c3496SRik van Riel 		seq = nextseq;
3219c368b5bSRik van Riel 		flags = read_seqbegin_or_lock_irqsave(&sig->stats_lock, &seq);
322a634f933SFrederic Weisbecker 		times->utime = sig->utime;
323a634f933SFrederic Weisbecker 		times->stime = sig->stime;
324a634f933SFrederic Weisbecker 		times->sum_exec_runtime = sig->sum_sched_runtime;
325a634f933SFrederic Weisbecker 
3261e4dda08SOleg Nesterov 		for_each_thread(tsk, t) {
327e614b333SStanislaw Gruszka 			task_cputime(t, &utime, &stime);
3286fac4829SFrederic Weisbecker 			times->utime += utime;
3296fac4829SFrederic Weisbecker 			times->stime += stime;
330a1eb1411SStanislaw Gruszka 			times->sum_exec_runtime += read_sum_exec_runtime(t);
3311e4dda08SOleg Nesterov 		}
332e78c3496SRik van Riel 		/* If lockless access failed, take the lock. */
333e78c3496SRik van Riel 		nextseq = 1;
334e78c3496SRik van Riel 	} while (need_seqretry(&sig->stats_lock, seq));
3359c368b5bSRik van Riel 	done_seqretry_irqrestore(&sig->stats_lock, seq, flags);
336a634f933SFrederic Weisbecker 	rcu_read_unlock();
337a634f933SFrederic Weisbecker }
338a634f933SFrederic Weisbecker 
33973fbec60SFrederic Weisbecker #ifdef CONFIG_IRQ_TIME_ACCOUNTING
34073fbec60SFrederic Weisbecker /*
34173fbec60SFrederic Weisbecker  * Account a tick to a process and cpustat
34273fbec60SFrederic Weisbecker  * @p: the process that the cpu time gets accounted to
34373fbec60SFrederic Weisbecker  * @user_tick: is the tick from userspace
34473fbec60SFrederic Weisbecker  * @rq: the pointer to rq
34573fbec60SFrederic Weisbecker  *
34673fbec60SFrederic Weisbecker  * Tick demultiplexing follows the order
34773fbec60SFrederic Weisbecker  * - pending hardirq update
34873fbec60SFrederic Weisbecker  * - pending softirq update
34973fbec60SFrederic Weisbecker  * - user_time
35073fbec60SFrederic Weisbecker  * - idle_time
35173fbec60SFrederic Weisbecker  * - system time
35273fbec60SFrederic Weisbecker  *   - check for guest_time
35373fbec60SFrederic Weisbecker  *   - else account as system_time
35473fbec60SFrederic Weisbecker  *
35573fbec60SFrederic Weisbecker  * Check for hardirq is done both for system and user time as there is
35673fbec60SFrederic Weisbecker  * no timer going off while we are on hardirq and hence we may never get an
35773fbec60SFrederic Weisbecker  * opportunity to update it solely in system time.
35873fbec60SFrederic Weisbecker  * p->stime and friends are only updated on system time and not on irq
35973fbec60SFrederic Weisbecker  * softirq as those do not count in task exec_runtime any more.
36073fbec60SFrederic Weisbecker  */
36173fbec60SFrederic Weisbecker static void irqtime_account_process_tick(struct task_struct *p, int user_tick,
3622d513868SThomas Gleixner 					 struct rq *rq, int ticks)
36373fbec60SFrederic Weisbecker {
3642b1f967dSFrederic Weisbecker 	u64 other, cputime = TICK_NSEC * ticks;
36573fbec60SFrederic Weisbecker 
36657430218SRik van Riel 	/*
36757430218SRik van Riel 	 * When returning from idle, many ticks can get accounted at
36857430218SRik van Riel 	 * once, including some ticks of steal, irq, and softirq time.
36957430218SRik van Riel 	 * Subtract those ticks from the amount of time accounted to
37057430218SRik van Riel 	 * idle, or potentially user or system time. Due to rounding,
37157430218SRik van Riel 	 * other time can exceed ticks occasionally.
37257430218SRik van Riel 	 */
37303cbc732SWanpeng Li 	other = account_other_time(ULONG_MAX);
3742b1f967dSFrederic Weisbecker 	if (other >= cputime)
37573fbec60SFrederic Weisbecker 		return;
37623244a5cSFrederic Weisbecker 
3772b1f967dSFrederic Weisbecker 	cputime -= other;
37873fbec60SFrederic Weisbecker 
37957430218SRik van Riel 	if (this_cpu_ksoftirqd() == p) {
38073fbec60SFrederic Weisbecker 		/*
38173fbec60SFrederic Weisbecker 		 * ksoftirqd time do not get accounted in cpu_softirq_time.
38273fbec60SFrederic Weisbecker 		 * So, we have to handle it separately here.
38373fbec60SFrederic Weisbecker 		 * Also, p->stime needs to be updated for ksoftirqd.
38473fbec60SFrederic Weisbecker 		 */
385fb8b049cSFrederic Weisbecker 		account_system_index_time(p, cputime, CPUTIME_SOFTIRQ);
38673fbec60SFrederic Weisbecker 	} else if (user_tick) {
38740565b5aSStanislaw Gruszka 		account_user_time(p, cputime);
38873fbec60SFrederic Weisbecker 	} else if (p == rq->idle) {
38918b43a9bSFrederic Weisbecker 		account_idle_time(cputime);
39073fbec60SFrederic Weisbecker 	} else if (p->flags & PF_VCPU) { /* System time or guest time */
391fb8b049cSFrederic Weisbecker 		account_guest_time(p, cputime);
39273fbec60SFrederic Weisbecker 	} else {
393fb8b049cSFrederic Weisbecker 		account_system_index_time(p, cputime, CPUTIME_SYSTEM);
39473fbec60SFrederic Weisbecker 	}
39573fbec60SFrederic Weisbecker }
39673fbec60SFrederic Weisbecker 
39773fbec60SFrederic Weisbecker static void irqtime_account_idle_ticks(int ticks)
39873fbec60SFrederic Weisbecker {
39973fbec60SFrederic Weisbecker 	struct rq *rq = this_rq();
40073fbec60SFrederic Weisbecker 
4012d513868SThomas Gleixner 	irqtime_account_process_tick(current, 0, rq, ticks);
40273fbec60SFrederic Weisbecker }
40373fbec60SFrederic Weisbecker #else /* CONFIG_IRQ_TIME_ACCOUNTING */
4043f4724eaSFrederic Weisbecker static inline void irqtime_account_idle_ticks(int ticks) {}
4053f4724eaSFrederic Weisbecker static inline void irqtime_account_process_tick(struct task_struct *p, int user_tick,
4062d513868SThomas Gleixner 						struct rq *rq, int nr_ticks) {}
40773fbec60SFrederic Weisbecker #endif /* CONFIG_IRQ_TIME_ACCOUNTING */
40873fbec60SFrederic Weisbecker 
40973fbec60SFrederic Weisbecker /*
41073fbec60SFrederic Weisbecker  * Use precise platform statistics if available:
41173fbec60SFrederic Weisbecker  */
41273fbec60SFrederic Weisbecker #ifdef CONFIG_VIRT_CPU_ACCOUNTING
413a7e1a9e3SFrederic Weisbecker 
414e3942ba0SFrederic Weisbecker #ifndef __ARCH_HAS_VTIME_TASK_SWITCH
415b0493406SFrederic Weisbecker void vtime_common_task_switch(struct task_struct *prev)
416e3942ba0SFrederic Weisbecker {
417e3942ba0SFrederic Weisbecker 	if (is_idle_task(prev))
418e3942ba0SFrederic Weisbecker 		vtime_account_idle(prev);
419e3942ba0SFrederic Weisbecker 	else
420e3942ba0SFrederic Weisbecker 		vtime_account_system(prev);
421e3942ba0SFrederic Weisbecker 
422c8d7dabfSFrederic Weisbecker 	vtime_flush(prev);
423e3942ba0SFrederic Weisbecker 	arch_vtime_task_switch(prev);
424e3942ba0SFrederic Weisbecker }
425e3942ba0SFrederic Weisbecker #endif
42611113334SFrederic Weisbecker 
4270cfdf9a1SFrederic Weisbecker #endif /* CONFIG_VIRT_CPU_ACCOUNTING */
4280cfdf9a1SFrederic Weisbecker 
4290cfdf9a1SFrederic Weisbecker 
4300cfdf9a1SFrederic Weisbecker #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
431a7e1a9e3SFrederic Weisbecker /*
432a7e1a9e3SFrederic Weisbecker  * Archs that account the whole time spent in the idle task
433a7e1a9e3SFrederic Weisbecker  * (outside irq) as idle time can rely on this and just implement
434fd25b4c2SFrederic Weisbecker  * vtime_account_system() and vtime_account_idle(). Archs that
435a7e1a9e3SFrederic Weisbecker  * have other meaning of the idle time (s390 only includes the
436a7e1a9e3SFrederic Weisbecker  * time spent by the CPU when it's in low power mode) must override
437a7e1a9e3SFrederic Weisbecker  * vtime_account().
438a7e1a9e3SFrederic Weisbecker  */
439a7e1a9e3SFrederic Weisbecker #ifndef __ARCH_HAS_VTIME_ACCOUNT
4400cfdf9a1SFrederic Weisbecker void vtime_account_irq_enter(struct task_struct *tsk)
441a7e1a9e3SFrederic Weisbecker {
4420cfdf9a1SFrederic Weisbecker 	if (!in_interrupt() && is_idle_task(tsk))
443fd25b4c2SFrederic Weisbecker 		vtime_account_idle(tsk);
4440cfdf9a1SFrederic Weisbecker 	else
445abf917cdSFrederic Weisbecker 		vtime_account_system(tsk);
446a7e1a9e3SFrederic Weisbecker }
4470cfdf9a1SFrederic Weisbecker EXPORT_SYMBOL_GPL(vtime_account_irq_enter);
448a7e1a9e3SFrederic Weisbecker #endif /* __ARCH_HAS_VTIME_ACCOUNT */
449a7e1a9e3SFrederic Weisbecker 
4505613fda9SFrederic Weisbecker void task_cputime_adjusted(struct task_struct *p, u64 *ut, u64 *st)
45173fbec60SFrederic Weisbecker {
4529fbc42eaSFrederic Weisbecker 	*ut = p->utime;
4539fbc42eaSFrederic Weisbecker 	*st = p->stime;
4549fbc42eaSFrederic Weisbecker }
4559eec50b8SAndrey Smetanin EXPORT_SYMBOL_GPL(task_cputime_adjusted);
45673fbec60SFrederic Weisbecker 
4575613fda9SFrederic Weisbecker void thread_group_cputime_adjusted(struct task_struct *p, u64 *ut, u64 *st)
4589fbc42eaSFrederic Weisbecker {
4599fbc42eaSFrederic Weisbecker 	struct task_cputime cputime;
46073fbec60SFrederic Weisbecker 
4619fbc42eaSFrederic Weisbecker 	thread_group_cputime(p, &cputime);
4629fbc42eaSFrederic Weisbecker 
4639fbc42eaSFrederic Weisbecker 	*ut = cputime.utime;
4649fbc42eaSFrederic Weisbecker 	*st = cputime.stime;
4659fbc42eaSFrederic Weisbecker }
4669fbc42eaSFrederic Weisbecker #else /* !CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
4679fbc42eaSFrederic Weisbecker /*
4689fbc42eaSFrederic Weisbecker  * Account a single tick of cpu time.
4699fbc42eaSFrederic Weisbecker  * @p: the process that the cpu time gets accounted to
4709fbc42eaSFrederic Weisbecker  * @user_tick: indicates if the tick is a user or a system tick
4719fbc42eaSFrederic Weisbecker  */
4729fbc42eaSFrederic Weisbecker void account_process_tick(struct task_struct *p, int user_tick)
4739fbc42eaSFrederic Weisbecker {
4742b1f967dSFrederic Weisbecker 	u64 cputime, steal;
4759fbc42eaSFrederic Weisbecker 	struct rq *rq = this_rq();
4769fbc42eaSFrederic Weisbecker 
47755dbdcfaSFrederic Weisbecker 	if (vtime_accounting_cpu_enabled())
4789fbc42eaSFrederic Weisbecker 		return;
4799fbc42eaSFrederic Weisbecker 
4809fbc42eaSFrederic Weisbecker 	if (sched_clock_irqtime) {
4812d513868SThomas Gleixner 		irqtime_account_process_tick(p, user_tick, rq, 1);
4829fbc42eaSFrederic Weisbecker 		return;
4839fbc42eaSFrederic Weisbecker 	}
4849fbc42eaSFrederic Weisbecker 
4852b1f967dSFrederic Weisbecker 	cputime = TICK_NSEC;
48603cbc732SWanpeng Li 	steal = steal_account_process_time(ULONG_MAX);
48757430218SRik van Riel 
4882b1f967dSFrederic Weisbecker 	if (steal >= cputime)
4899fbc42eaSFrederic Weisbecker 		return;
4909fbc42eaSFrederic Weisbecker 
4912b1f967dSFrederic Weisbecker 	cputime -= steal;
49257430218SRik van Riel 
4939fbc42eaSFrederic Weisbecker 	if (user_tick)
49440565b5aSStanislaw Gruszka 		account_user_time(p, cputime);
4959fbc42eaSFrederic Weisbecker 	else if ((p != rq->idle) || (irq_count() != HARDIRQ_OFFSET))
496fb8b049cSFrederic Weisbecker 		account_system_time(p, HARDIRQ_OFFSET, cputime);
49773fbec60SFrederic Weisbecker 	else
49818b43a9bSFrederic Weisbecker 		account_idle_time(cputime);
4999fbc42eaSFrederic Weisbecker }
50073fbec60SFrederic Weisbecker 
5019fbc42eaSFrederic Weisbecker /*
5029fbc42eaSFrederic Weisbecker  * Account multiple ticks of idle time.
5039fbc42eaSFrederic Weisbecker  * @ticks: number of stolen ticks
5049fbc42eaSFrederic Weisbecker  */
5059fbc42eaSFrederic Weisbecker void account_idle_ticks(unsigned long ticks)
5069fbc42eaSFrederic Weisbecker {
50718b43a9bSFrederic Weisbecker 	u64 cputime, steal;
50826f2c75cSFrederic Weisbecker 
5099fbc42eaSFrederic Weisbecker 	if (sched_clock_irqtime) {
5109fbc42eaSFrederic Weisbecker 		irqtime_account_idle_ticks(ticks);
5119fbc42eaSFrederic Weisbecker 		return;
5129fbc42eaSFrederic Weisbecker 	}
5139fbc42eaSFrederic Weisbecker 
51418b43a9bSFrederic Weisbecker 	cputime = ticks * TICK_NSEC;
5152b1f967dSFrederic Weisbecker 	steal = steal_account_process_time(ULONG_MAX);
516f9bcf1e0SWanpeng Li 
517f9bcf1e0SWanpeng Li 	if (steal >= cputime)
518f9bcf1e0SWanpeng Li 		return;
519f9bcf1e0SWanpeng Li 
520f9bcf1e0SWanpeng Li 	cputime -= steal;
521f9bcf1e0SWanpeng Li 	account_idle_time(cputime);
5229fbc42eaSFrederic Weisbecker }
52373fbec60SFrederic Weisbecker 
524d9a3c982SFrederic Weisbecker /*
52555eaa7c1SStanislaw Gruszka  * Perform (stime * rtime) / total, but avoid multiplication overflow by
52655eaa7c1SStanislaw Gruszka  * loosing precision when the numbers are big.
527d9a3c982SFrederic Weisbecker  */
5285613fda9SFrederic Weisbecker static u64 scale_stime(u64 stime, u64 rtime, u64 total)
52973fbec60SFrederic Weisbecker {
53055eaa7c1SStanislaw Gruszka 	u64 scaled;
53173fbec60SFrederic Weisbecker 
53255eaa7c1SStanislaw Gruszka 	for (;;) {
53355eaa7c1SStanislaw Gruszka 		/* Make sure "rtime" is the bigger of stime/rtime */
53484f9f3a1SStanislaw Gruszka 		if (stime > rtime)
53584f9f3a1SStanislaw Gruszka 			swap(rtime, stime);
53673fbec60SFrederic Weisbecker 
53755eaa7c1SStanislaw Gruszka 		/* Make sure 'total' fits in 32 bits */
53855eaa7c1SStanislaw Gruszka 		if (total >> 32)
53955eaa7c1SStanislaw Gruszka 			goto drop_precision;
54055eaa7c1SStanislaw Gruszka 
54155eaa7c1SStanislaw Gruszka 		/* Does rtime (and thus stime) fit in 32 bits? */
54255eaa7c1SStanislaw Gruszka 		if (!(rtime >> 32))
54355eaa7c1SStanislaw Gruszka 			break;
54455eaa7c1SStanislaw Gruszka 
54555eaa7c1SStanislaw Gruszka 		/* Can we just balance rtime/stime rather than dropping bits? */
54655eaa7c1SStanislaw Gruszka 		if (stime >> 31)
54755eaa7c1SStanislaw Gruszka 			goto drop_precision;
54855eaa7c1SStanislaw Gruszka 
54955eaa7c1SStanislaw Gruszka 		/* We can grow stime and shrink rtime and try to make them both fit */
55055eaa7c1SStanislaw Gruszka 		stime <<= 1;
55155eaa7c1SStanislaw Gruszka 		rtime >>= 1;
55255eaa7c1SStanislaw Gruszka 		continue;
55355eaa7c1SStanislaw Gruszka 
55455eaa7c1SStanislaw Gruszka drop_precision:
55555eaa7c1SStanislaw Gruszka 		/* We drop from rtime, it has more bits than stime */
55655eaa7c1SStanislaw Gruszka 		rtime >>= 1;
55755eaa7c1SStanislaw Gruszka 		total >>= 1;
55855eaa7c1SStanislaw Gruszka 	}
55955eaa7c1SStanislaw Gruszka 
56055eaa7c1SStanislaw Gruszka 	/*
56155eaa7c1SStanislaw Gruszka 	 * Make sure gcc understands that this is a 32x32->64 multiply,
56255eaa7c1SStanislaw Gruszka 	 * followed by a 64/32->64 divide.
56355eaa7c1SStanislaw Gruszka 	 */
56455eaa7c1SStanislaw Gruszka 	scaled = div_u64((u64) (u32) stime * (u64) (u32) rtime, (u32)total);
5655613fda9SFrederic Weisbecker 	return scaled;
56673fbec60SFrederic Weisbecker }
56773fbec60SFrederic Weisbecker 
568fa092057SFrederic Weisbecker /*
5699d7fb042SPeter Zijlstra  * Adjust tick based cputime random precision against scheduler runtime
5709d7fb042SPeter Zijlstra  * accounting.
571347abad9SRik van Riel  *
5729d7fb042SPeter Zijlstra  * Tick based cputime accounting depend on random scheduling timeslices of a
5739d7fb042SPeter Zijlstra  * task to be interrupted or not by the timer.  Depending on these
5749d7fb042SPeter Zijlstra  * circumstances, the number of these interrupts may be over or
5759d7fb042SPeter Zijlstra  * under-optimistic, matching the real user and system cputime with a variable
5769d7fb042SPeter Zijlstra  * precision.
5779d7fb042SPeter Zijlstra  *
5789d7fb042SPeter Zijlstra  * Fix this by scaling these tick based values against the total runtime
5799d7fb042SPeter Zijlstra  * accounted by the CFS scheduler.
5809d7fb042SPeter Zijlstra  *
5819d7fb042SPeter Zijlstra  * This code provides the following guarantees:
5829d7fb042SPeter Zijlstra  *
5839d7fb042SPeter Zijlstra  *   stime + utime == rtime
5849d7fb042SPeter Zijlstra  *   stime_i+1 >= stime_i, utime_i+1 >= utime_i
5859d7fb042SPeter Zijlstra  *
5869d7fb042SPeter Zijlstra  * Assuming that rtime_i+1 >= rtime_i.
587fa092057SFrederic Weisbecker  */
588d37f761dSFrederic Weisbecker static void cputime_adjust(struct task_cputime *curr,
5899d7fb042SPeter Zijlstra 			   struct prev_cputime *prev,
5905613fda9SFrederic Weisbecker 			   u64 *ut, u64 *st)
59173fbec60SFrederic Weisbecker {
5925613fda9SFrederic Weisbecker 	u64 rtime, stime, utime;
5939d7fb042SPeter Zijlstra 	unsigned long flags;
594fa092057SFrederic Weisbecker 
5959d7fb042SPeter Zijlstra 	/* Serialize concurrent callers such that we can honour our guarantees */
5969d7fb042SPeter Zijlstra 	raw_spin_lock_irqsave(&prev->lock, flags);
5975613fda9SFrederic Weisbecker 	rtime = curr->sum_exec_runtime;
59873fbec60SFrederic Weisbecker 
599772c808aSStanislaw Gruszka 	/*
6009d7fb042SPeter Zijlstra 	 * This is possible under two circumstances:
6019d7fb042SPeter Zijlstra 	 *  - rtime isn't monotonic after all (a bug);
6029d7fb042SPeter Zijlstra 	 *  - we got reordered by the lock.
6039d7fb042SPeter Zijlstra 	 *
6049d7fb042SPeter Zijlstra 	 * In both cases this acts as a filter such that the rest of the code
6059d7fb042SPeter Zijlstra 	 * can assume it is monotonic regardless of anything else.
606772c808aSStanislaw Gruszka 	 */
607772c808aSStanislaw Gruszka 	if (prev->stime + prev->utime >= rtime)
608772c808aSStanislaw Gruszka 		goto out;
609772c808aSStanislaw Gruszka 
6105a8e01f8SStanislaw Gruszka 	stime = curr->stime;
6115a8e01f8SStanislaw Gruszka 	utime = curr->utime;
6125a8e01f8SStanislaw Gruszka 
613173be9a1SPeter Zijlstra 	/*
6143b9c08aeSIngo Molnar 	 * If either stime or utime are 0, assume all runtime is userspace.
6153b9c08aeSIngo Molnar 	 * Once a task gets some ticks, the monotonicy code at 'update:'
6163b9c08aeSIngo Molnar 	 * will ensure things converge to the observed ratio.
617173be9a1SPeter Zijlstra 	 */
6183b9c08aeSIngo Molnar 	if (stime == 0) {
6193b9c08aeSIngo Molnar 		utime = rtime;
6203b9c08aeSIngo Molnar 		goto update;
6219d7fb042SPeter Zijlstra 	}
62273fbec60SFrederic Weisbecker 
6233b9c08aeSIngo Molnar 	if (utime == 0) {
6243b9c08aeSIngo Molnar 		stime = rtime;
6253b9c08aeSIngo Molnar 		goto update;
6263b9c08aeSIngo Molnar 	}
6273b9c08aeSIngo Molnar 
6283b9c08aeSIngo Molnar 	stime = scale_stime(stime, rtime, stime + utime);
6293b9c08aeSIngo Molnar 
6303b9c08aeSIngo Molnar update:
6319d7fb042SPeter Zijlstra 	/*
6329d7fb042SPeter Zijlstra 	 * Make sure stime doesn't go backwards; this preserves monotonicity
6339d7fb042SPeter Zijlstra 	 * for utime because rtime is monotonic.
6349d7fb042SPeter Zijlstra 	 *
6359d7fb042SPeter Zijlstra 	 *  utime_i+1 = rtime_i+1 - stime_i
6369d7fb042SPeter Zijlstra 	 *            = rtime_i+1 - (rtime_i - utime_i)
6379d7fb042SPeter Zijlstra 	 *            = (rtime_i+1 - rtime_i) + utime_i
6389d7fb042SPeter Zijlstra 	 *            >= utime_i
6399d7fb042SPeter Zijlstra 	 */
6409d7fb042SPeter Zijlstra 	if (stime < prev->stime)
6419d7fb042SPeter Zijlstra 		stime = prev->stime;
6429d7fb042SPeter Zijlstra 	utime = rtime - stime;
6439d7fb042SPeter Zijlstra 
6449d7fb042SPeter Zijlstra 	/*
6459d7fb042SPeter Zijlstra 	 * Make sure utime doesn't go backwards; this still preserves
6469d7fb042SPeter Zijlstra 	 * monotonicity for stime, analogous argument to above.
6479d7fb042SPeter Zijlstra 	 */
6489d7fb042SPeter Zijlstra 	if (utime < prev->utime) {
6499d7fb042SPeter Zijlstra 		utime = prev->utime;
6509d7fb042SPeter Zijlstra 		stime = rtime - utime;
6519d7fb042SPeter Zijlstra 	}
6529d7fb042SPeter Zijlstra 
6539d7fb042SPeter Zijlstra 	prev->stime = stime;
6549d7fb042SPeter Zijlstra 	prev->utime = utime;
655772c808aSStanislaw Gruszka out:
656d37f761dSFrederic Weisbecker 	*ut = prev->utime;
657d37f761dSFrederic Weisbecker 	*st = prev->stime;
6589d7fb042SPeter Zijlstra 	raw_spin_unlock_irqrestore(&prev->lock, flags);
659d37f761dSFrederic Weisbecker }
660d37f761dSFrederic Weisbecker 
6615613fda9SFrederic Weisbecker void task_cputime_adjusted(struct task_struct *p, u64 *ut, u64 *st)
662d37f761dSFrederic Weisbecker {
663d37f761dSFrederic Weisbecker 	struct task_cputime cputime = {
664d37f761dSFrederic Weisbecker 		.sum_exec_runtime = p->se.sum_exec_runtime,
665d37f761dSFrederic Weisbecker 	};
666d37f761dSFrederic Weisbecker 
6676fac4829SFrederic Weisbecker 	task_cputime(p, &cputime.utime, &cputime.stime);
668d37f761dSFrederic Weisbecker 	cputime_adjust(&cputime, &p->prev_cputime, ut, st);
66973fbec60SFrederic Weisbecker }
6709eec50b8SAndrey Smetanin EXPORT_SYMBOL_GPL(task_cputime_adjusted);
67173fbec60SFrederic Weisbecker 
6725613fda9SFrederic Weisbecker void thread_group_cputime_adjusted(struct task_struct *p, u64 *ut, u64 *st)
67373fbec60SFrederic Weisbecker {
67473fbec60SFrederic Weisbecker 	struct task_cputime cputime;
67573fbec60SFrederic Weisbecker 
67673fbec60SFrederic Weisbecker 	thread_group_cputime(p, &cputime);
677d37f761dSFrederic Weisbecker 	cputime_adjust(&cputime, &p->signal->prev_cputime, ut, st);
67873fbec60SFrederic Weisbecker }
6799fbc42eaSFrederic Weisbecker #endif /* !CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
680abf917cdSFrederic Weisbecker 
681abf917cdSFrederic Weisbecker #ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
682bfce1d60SFrederic Weisbecker static u64 vtime_delta(struct task_struct *tsk)
683abf917cdSFrederic Weisbecker {
684ff9a9b4cSRik van Riel 	unsigned long now = READ_ONCE(jiffies);
685abf917cdSFrederic Weisbecker 
686*60a9ce57SFrederic Weisbecker 	if (time_before(now, (unsigned long)tsk->vtime_starttime))
6876a61671bSFrederic Weisbecker 		return 0;
6886a61671bSFrederic Weisbecker 
689*60a9ce57SFrederic Weisbecker 	return jiffies_to_nsecs(now - tsk->vtime_starttime);
6906a61671bSFrederic Weisbecker }
6916a61671bSFrederic Weisbecker 
692bfce1d60SFrederic Weisbecker static u64 get_vtime_delta(struct task_struct *tsk)
6936a61671bSFrederic Weisbecker {
694ff9a9b4cSRik van Riel 	unsigned long now = READ_ONCE(jiffies);
695bfce1d60SFrederic Weisbecker 	u64 delta, other;
6966a61671bSFrederic Weisbecker 
69703cbc732SWanpeng Li 	/*
69803cbc732SWanpeng Li 	 * Unlike tick based timing, vtime based timing never has lost
69903cbc732SWanpeng Li 	 * ticks, and no need for steal time accounting to make up for
70003cbc732SWanpeng Li 	 * lost ticks. Vtime accounts a rounded version of actual
70103cbc732SWanpeng Li 	 * elapsed time. Limit account_other_time to prevent rounding
70203cbc732SWanpeng Li 	 * errors from causing elapsed vtime to go negative.
70303cbc732SWanpeng Li 	 */
704*60a9ce57SFrederic Weisbecker 	delta = jiffies_to_nsecs(now - tsk->vtime_starttime);
705b58c3584SRik van Riel 	other = account_other_time(delta);
706*60a9ce57SFrederic Weisbecker 	WARN_ON_ONCE(tsk->vtime_state == VTIME_INACTIVE);
707*60a9ce57SFrederic Weisbecker 	tsk->vtime_starttime = now;
708abf917cdSFrederic Weisbecker 
709b58c3584SRik van Riel 	return delta - other;
710abf917cdSFrederic Weisbecker }
711abf917cdSFrederic Weisbecker 
7126a61671bSFrederic Weisbecker static void __vtime_account_system(struct task_struct *tsk)
7136a61671bSFrederic Weisbecker {
714bfce1d60SFrederic Weisbecker 	account_system_time(tsk, irq_count(), get_vtime_delta(tsk));
7156a61671bSFrederic Weisbecker }
7166a61671bSFrederic Weisbecker 
717abf917cdSFrederic Weisbecker void vtime_account_system(struct task_struct *tsk)
718abf917cdSFrederic Weisbecker {
719ff9a9b4cSRik van Riel 	if (!vtime_delta(tsk))
720ff9a9b4cSRik van Riel 		return;
721ff9a9b4cSRik van Riel 
722b7ce2277SFrederic Weisbecker 	write_seqcount_begin(&tsk->vtime_seqcount);
7236a61671bSFrederic Weisbecker 	__vtime_account_system(tsk);
724b7ce2277SFrederic Weisbecker 	write_seqcount_end(&tsk->vtime_seqcount);
7256a61671bSFrederic Weisbecker }
7266a61671bSFrederic Weisbecker 
7276a61671bSFrederic Weisbecker void vtime_user_enter(struct task_struct *tsk)
7286a61671bSFrederic Weisbecker {
729b7ce2277SFrederic Weisbecker 	write_seqcount_begin(&tsk->vtime_seqcount);
730ff9a9b4cSRik van Riel 	if (vtime_delta(tsk))
7316a61671bSFrederic Weisbecker 		__vtime_account_system(tsk);
732af2350bdSFrederic Weisbecker 	tsk->vtime_snap_whence = VTIME_USER;
733b7ce2277SFrederic Weisbecker 	write_seqcount_end(&tsk->vtime_seqcount);
7346a61671bSFrederic Weisbecker }
7356a61671bSFrederic Weisbecker 
7361c3eda01SFrederic Weisbecker void vtime_user_exit(struct task_struct *tsk)
7371c3eda01SFrederic Weisbecker {
7381c3eda01SFrederic Weisbecker 	write_seqcount_begin(&tsk->vtime_seqcount);
7391c3eda01SFrederic Weisbecker 	if (vtime_delta(tsk))
7401c3eda01SFrederic Weisbecker 		account_user_time(tsk, get_vtime_delta(tsk));
7419fa57cf5SFrederic Weisbecker 	tsk->vtime_snap_whence = VTIME_SYS;
7421c3eda01SFrederic Weisbecker 	write_seqcount_end(&tsk->vtime_seqcount);
7431c3eda01SFrederic Weisbecker }
7441c3eda01SFrederic Weisbecker 
7456a61671bSFrederic Weisbecker void vtime_guest_enter(struct task_struct *tsk)
7466a61671bSFrederic Weisbecker {
7475b206d48SFrederic Weisbecker 	/*
7485b206d48SFrederic Weisbecker 	 * The flags must be updated under the lock with
749*60a9ce57SFrederic Weisbecker 	 * the vtime_starttime flush and update.
7505b206d48SFrederic Weisbecker 	 * That enforces a right ordering and update sequence
7515b206d48SFrederic Weisbecker 	 * synchronization against the reader (task_gtime())
7525b206d48SFrederic Weisbecker 	 * that can thus safely catch up with a tickless delta.
7535b206d48SFrederic Weisbecker 	 */
754b7ce2277SFrederic Weisbecker 	write_seqcount_begin(&tsk->vtime_seqcount);
755ff9a9b4cSRik van Riel 	if (vtime_delta(tsk))
7566a61671bSFrederic Weisbecker 		__vtime_account_system(tsk);
7576a61671bSFrederic Weisbecker 	current->flags |= PF_VCPU;
758b7ce2277SFrederic Weisbecker 	write_seqcount_end(&tsk->vtime_seqcount);
7596a61671bSFrederic Weisbecker }
76048d6a816SFrederic Weisbecker EXPORT_SYMBOL_GPL(vtime_guest_enter);
7616a61671bSFrederic Weisbecker 
7626a61671bSFrederic Weisbecker void vtime_guest_exit(struct task_struct *tsk)
7636a61671bSFrederic Weisbecker {
764b7ce2277SFrederic Weisbecker 	write_seqcount_begin(&tsk->vtime_seqcount);
7656a61671bSFrederic Weisbecker 	__vtime_account_system(tsk);
7666a61671bSFrederic Weisbecker 	current->flags &= ~PF_VCPU;
767b7ce2277SFrederic Weisbecker 	write_seqcount_end(&tsk->vtime_seqcount);
768abf917cdSFrederic Weisbecker }
76948d6a816SFrederic Weisbecker EXPORT_SYMBOL_GPL(vtime_guest_exit);
770abf917cdSFrederic Weisbecker 
771abf917cdSFrederic Weisbecker void vtime_account_idle(struct task_struct *tsk)
772abf917cdSFrederic Weisbecker {
773bfce1d60SFrederic Weisbecker 	account_idle_time(get_vtime_delta(tsk));
774abf917cdSFrederic Weisbecker }
7753f4724eaSFrederic Weisbecker 
7766a61671bSFrederic Weisbecker void arch_vtime_task_switch(struct task_struct *prev)
7776a61671bSFrederic Weisbecker {
778b7ce2277SFrederic Weisbecker 	write_seqcount_begin(&prev->vtime_seqcount);
779*60a9ce57SFrederic Weisbecker 	prev->vtime_state = VTIME_INACTIVE;
780b7ce2277SFrederic Weisbecker 	write_seqcount_end(&prev->vtime_seqcount);
7816a61671bSFrederic Weisbecker 
782b7ce2277SFrederic Weisbecker 	write_seqcount_begin(&current->vtime_seqcount);
783*60a9ce57SFrederic Weisbecker 	current->vtime_state = VTIME_SYS;
784*60a9ce57SFrederic Weisbecker 	current->vtime_starttime = jiffies;
785b7ce2277SFrederic Weisbecker 	write_seqcount_end(&current->vtime_seqcount);
7866a61671bSFrederic Weisbecker }
7876a61671bSFrederic Weisbecker 
78845eacc69SFrederic Weisbecker void vtime_init_idle(struct task_struct *t, int cpu)
7896a61671bSFrederic Weisbecker {
7906a61671bSFrederic Weisbecker 	unsigned long flags;
7916a61671bSFrederic Weisbecker 
792b7ce2277SFrederic Weisbecker 	local_irq_save(flags);
793b7ce2277SFrederic Weisbecker 	write_seqcount_begin(&t->vtime_seqcount);
794*60a9ce57SFrederic Weisbecker 	t->vtime_state = VTIME_SYS;
795*60a9ce57SFrederic Weisbecker 	t->vtime_starttime = jiffies;
796b7ce2277SFrederic Weisbecker 	write_seqcount_end(&t->vtime_seqcount);
797b7ce2277SFrederic Weisbecker 	local_irq_restore(flags);
7986a61671bSFrederic Weisbecker }
7996a61671bSFrederic Weisbecker 
80016a6d9beSFrederic Weisbecker u64 task_gtime(struct task_struct *t)
8016a61671bSFrederic Weisbecker {
8026a61671bSFrederic Weisbecker 	unsigned int seq;
80316a6d9beSFrederic Weisbecker 	u64 gtime;
8046a61671bSFrederic Weisbecker 
805e5925394SFrederic Weisbecker 	if (!vtime_accounting_enabled())
8062541117bSHiroshi Shimamoto 		return t->gtime;
8072541117bSHiroshi Shimamoto 
8086a61671bSFrederic Weisbecker 	do {
809b7ce2277SFrederic Weisbecker 		seq = read_seqcount_begin(&t->vtime_seqcount);
8106a61671bSFrederic Weisbecker 
8116a61671bSFrederic Weisbecker 		gtime = t->gtime;
812*60a9ce57SFrederic Weisbecker 		if (t->vtime_state == VTIME_SYS && t->flags & PF_VCPU)
813bfce1d60SFrederic Weisbecker 			gtime += vtime_delta(t);
8146a61671bSFrederic Weisbecker 
815b7ce2277SFrederic Weisbecker 	} while (read_seqcount_retry(&t->vtime_seqcount, seq));
8166a61671bSFrederic Weisbecker 
8176a61671bSFrederic Weisbecker 	return gtime;
8186a61671bSFrederic Weisbecker }
8196a61671bSFrederic Weisbecker 
8206a61671bSFrederic Weisbecker /*
8216a61671bSFrederic Weisbecker  * Fetch cputime raw values from fields of task_struct and
8226a61671bSFrederic Weisbecker  * add up the pending nohz execution time since the last
8236a61671bSFrederic Weisbecker  * cputime snapshot.
8246a61671bSFrederic Weisbecker  */
8255613fda9SFrederic Weisbecker void task_cputime(struct task_struct *t, u64 *utime, u64 *stime)
8266a61671bSFrederic Weisbecker {
8275613fda9SFrederic Weisbecker 	u64 delta;
8286a61671bSFrederic Weisbecker 	unsigned int seq;
829353c50ebSStanislaw Gruszka 
830353c50ebSStanislaw Gruszka 	if (!vtime_accounting_enabled()) {
831353c50ebSStanislaw Gruszka 		*utime = t->utime;
832353c50ebSStanislaw Gruszka 		*stime = t->stime;
833353c50ebSStanislaw Gruszka 		return;
834353c50ebSStanislaw Gruszka 	}
8356a61671bSFrederic Weisbecker 
8366a61671bSFrederic Weisbecker 	do {
837b7ce2277SFrederic Weisbecker 		seq = read_seqcount_begin(&t->vtime_seqcount);
8386a61671bSFrederic Weisbecker 
839353c50ebSStanislaw Gruszka 		*utime = t->utime;
840353c50ebSStanislaw Gruszka 		*stime = t->stime;
8416a61671bSFrederic Weisbecker 
8426a61671bSFrederic Weisbecker 		/* Task is sleeping, nothing to add */
843*60a9ce57SFrederic Weisbecker 		if (t->vtime_state == VTIME_INACTIVE || is_idle_task(t))
8446a61671bSFrederic Weisbecker 			continue;
8456a61671bSFrederic Weisbecker 
846bfce1d60SFrederic Weisbecker 		delta = vtime_delta(t);
8476a61671bSFrederic Weisbecker 
8486a61671bSFrederic Weisbecker 		/*
8496a61671bSFrederic Weisbecker 		 * Task runs either in user or kernel space, add pending nohz time to
8506a61671bSFrederic Weisbecker 		 * the right place.
8516a61671bSFrederic Weisbecker 		 */
852*60a9ce57SFrederic Weisbecker 		if (t->vtime_state == VTIME_USER || t->flags & PF_VCPU)
853353c50ebSStanislaw Gruszka 			*utime += delta;
854*60a9ce57SFrederic Weisbecker 		else if (t->vtime_state == VTIME_SYS)
855353c50ebSStanislaw Gruszka 			*stime += delta;
856b7ce2277SFrederic Weisbecker 	} while (read_seqcount_retry(&t->vtime_seqcount, seq));
8576a61671bSFrederic Weisbecker }
858abf917cdSFrederic Weisbecker #endif /* CONFIG_VIRT_CPU_ACCOUNTING_GEN */
859