xref: /linux/include/linux/vtime.h (revision 670e057744e0cc8047bf96d15d18c46e16ae2e93)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _LINUX_KERNEL_VTIME_H
3 #define _LINUX_KERNEL_VTIME_H
4 
5 #include <linux/context_tracking_state.h>
6 #include <linux/sched.h>
7 
8 /*
9  * Common vtime APIs
10  */
11 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
12 extern void vtime_account_kernel(struct task_struct *tsk);
13 #endif /* !CONFIG_VIRT_CPU_ACCOUNTING */
14 
15 #ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
16 extern void vtime_user_enter(struct task_struct *tsk);
17 extern void vtime_user_exit(struct task_struct *tsk);
18 extern void vtime_guest_enter(struct task_struct *tsk);
19 extern void vtime_guest_exit(struct task_struct *tsk);
20 extern void vtime_init_idle(struct task_struct *tsk, int cpu);
21 #else /* !CONFIG_VIRT_CPU_ACCOUNTING_GEN  */
22 static inline void vtime_user_enter(struct task_struct *tsk) { }
23 static inline void vtime_user_exit(struct task_struct *tsk) { }
24 static inline void vtime_guest_enter(struct task_struct *tsk) { }
25 static inline void vtime_guest_exit(struct task_struct *tsk) { }
26 static inline void vtime_init_idle(struct task_struct *tsk, int cpu) { }
27 #endif
28 
29 static inline bool vtime_generic_enabled_cpu(int cpu)
30 {
31 	return context_tracking_enabled_cpu(cpu);
32 }
33 
34 static inline bool vtime_generic_enabled_this_cpu(void)
35 {
36 	return context_tracking_enabled_this_cpu();
37 }
38 
39 #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
40 extern void vtime_account_idle(struct task_struct *tsk);
41 extern void vtime_account_irq(struct task_struct *tsk, unsigned int offset);
42 extern void vtime_account_softirq(struct task_struct *tsk);
43 extern void vtime_account_hardirq(struct task_struct *tsk);
44 extern void vtime_flush(struct task_struct *tsk);
45 #ifdef CONFIG_HAVE_VIRT_CPU_ACCOUNTING_IDLE
46 static inline void vtime_reset(void) { }
47 static inline void vtime_dyntick_start(void) { }
48 static inline void vtime_dyntick_stop(void) { }
49 #else
50 extern void vtime_reset(void);
51 extern void vtime_dyntick_start(void);
52 extern void vtime_dyntick_stop(void);
53 #endif
54 #else /* !CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
55 static inline void vtime_account_irq(struct task_struct *tsk, unsigned int offset) { }
56 static inline void vtime_account_softirq(struct task_struct *tsk) { }
57 static inline void vtime_account_hardirq(struct task_struct *tsk) { }
58 static inline void vtime_flush(struct task_struct *tsk) { }
59 static inline void vtime_reset(void) { }
60 static inline void vtime_dyntick_start(void) { }
61 static inline void vtime_dyntick_stop(void) { }
62 #endif
63 
64 /*
65  * vtime_accounting_enabled_this_cpu() definitions/declarations
66  */
67 #if defined(CONFIG_VIRT_CPU_ACCOUNTING_NATIVE)
68 
69 static inline bool vtime_accounting_enabled_this_cpu(void) { return true; }
70 extern void vtime_task_switch(struct task_struct *prev);
71 
72 static __always_inline void vtime_account_guest_enter(void)
73 {
74 	vtime_account_kernel(current);
75 	current->flags |= PF_VCPU;
76 }
77 
78 static __always_inline void vtime_account_guest_exit(void)
79 {
80 	vtime_account_kernel(current);
81 	current->flags &= ~PF_VCPU;
82 }
83 
84 #elif defined(CONFIG_VIRT_CPU_ACCOUNTING_GEN)
85 
86 /*
87  * Checks if vtime is enabled on some CPU. Cputime readers want to be careful
88  * in that case and compute the tickless cputime.
89  * For now vtime state is tied to context tracking. We might want to decouple
90  * those later if necessary.
91  */
92 static inline bool vtime_accounting_enabled(void)
93 {
94 	return context_tracking_enabled();
95 }
96 
97 static inline bool vtime_accounting_enabled_cpu(int cpu)
98 {
99 	return vtime_generic_enabled_cpu(cpu);
100 }
101 
102 static inline bool vtime_accounting_enabled_this_cpu(void)
103 {
104 	return vtime_generic_enabled_this_cpu();
105 }
106 
107 extern void vtime_task_switch_generic(struct task_struct *prev);
108 
109 static inline void vtime_task_switch(struct task_struct *prev)
110 {
111 	if (vtime_accounting_enabled_this_cpu())
112 		vtime_task_switch_generic(prev);
113 }
114 
115 static __always_inline void vtime_account_guest_enter(void)
116 {
117 	if (vtime_accounting_enabled_this_cpu())
118 		vtime_guest_enter(current);
119 	else
120 		current->flags |= PF_VCPU;
121 }
122 
123 static __always_inline void vtime_account_guest_exit(void)
124 {
125 	if (vtime_accounting_enabled_this_cpu())
126 		vtime_guest_exit(current);
127 	else
128 		current->flags &= ~PF_VCPU;
129 }
130 
131 #else /* !CONFIG_VIRT_CPU_ACCOUNTING */
132 
133 static inline bool vtime_accounting_enabled_this_cpu(void) { return false; }
134 static inline void vtime_task_switch(struct task_struct *prev) { }
135 
136 static __always_inline void vtime_account_guest_enter(void)
137 {
138 	current->flags |= PF_VCPU;
139 }
140 
141 static __always_inline void vtime_account_guest_exit(void)
142 {
143 	current->flags &= ~PF_VCPU;
144 }
145 
146 #endif
147 
148 
149 #ifdef CONFIG_IRQ_TIME_ACCOUNTING
150 extern void irqtime_account_irq(struct task_struct *tsk, unsigned int offset);
151 #else
152 static inline void irqtime_account_irq(struct task_struct *tsk, unsigned int offset) { }
153 #endif
154 
155 static inline void account_softirq_enter(struct task_struct *tsk)
156 {
157 	vtime_account_irq(tsk, SOFTIRQ_OFFSET);
158 	irqtime_account_irq(tsk, SOFTIRQ_OFFSET);
159 }
160 
161 static inline void account_softirq_exit(struct task_struct *tsk)
162 {
163 	vtime_account_softirq(tsk);
164 	irqtime_account_irq(tsk, 0);
165 }
166 
167 static inline void account_hardirq_enter(struct task_struct *tsk)
168 {
169 	vtime_account_irq(tsk, HARDIRQ_OFFSET);
170 	irqtime_account_irq(tsk, HARDIRQ_OFFSET);
171 }
172 
173 static inline void account_hardirq_exit(struct task_struct *tsk)
174 {
175 	vtime_account_hardirq(tsk);
176 	irqtime_account_irq(tsk, 0);
177 }
178 
179 #endif /* _LINUX_KERNEL_VTIME_H */
180