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