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