1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef _LINUX_CONTEXT_TRACKING_STATE_H 3 #define _LINUX_CONTEXT_TRACKING_STATE_H 4 5 #include <linux/percpu.h> 6 #include <linux/static_key.h> 7 #include <linux/context_tracking_irq.h> 8 9 enum ctx_state { 10 CONTEXT_DISABLED = -1, /* returned by ct_state() if unknown */ 11 CONTEXT_KERNEL = 0, 12 CONTEXT_USER, 13 CONTEXT_GUEST, 14 }; 15 16 struct context_tracking { 17 #ifdef CONFIG_CONTEXT_TRACKING_USER 18 /* 19 * When active is false, probes are unset in order 20 * to minimize overhead: TIF flags are cleared 21 * and calls to user_enter/exit are ignored. This 22 * may be further optimized using static keys. 23 */ 24 bool active; 25 int recursion; 26 enum ctx_state state; 27 #endif 28 #ifdef CONFIG_CONTEXT_TRACKING_IDLE 29 atomic_t dynticks; /* Even value for idle, else odd. */ 30 long dynticks_nesting; /* Track process nesting level. */ 31 #endif 32 }; 33 34 #ifdef CONFIG_CONTEXT_TRACKING 35 DECLARE_PER_CPU(struct context_tracking, context_tracking); 36 #endif 37 38 #ifdef CONFIG_CONTEXT_TRACKING_IDLE 39 static __always_inline int ct_dynticks(void) 40 { 41 return atomic_read(this_cpu_ptr(&context_tracking.dynticks)); 42 } 43 44 static __always_inline int ct_dynticks_cpu(int cpu) 45 { 46 struct context_tracking *ct = per_cpu_ptr(&context_tracking, cpu); 47 48 return atomic_read(&ct->dynticks); 49 } 50 51 static __always_inline int ct_dynticks_cpu_acquire(int cpu) 52 { 53 struct context_tracking *ct = per_cpu_ptr(&context_tracking, cpu); 54 55 return atomic_read_acquire(&ct->dynticks); 56 } 57 58 static __always_inline long ct_dynticks_nesting(void) 59 { 60 return __this_cpu_read(context_tracking.dynticks_nesting); 61 } 62 63 static __always_inline long ct_dynticks_nesting_cpu(int cpu) 64 { 65 struct context_tracking *ct = per_cpu_ptr(&context_tracking, cpu); 66 67 return ct->dynticks_nesting; 68 } 69 #endif /* #ifdef CONFIG_CONTEXT_TRACKING_IDLE */ 70 71 #ifdef CONFIG_CONTEXT_TRACKING_USER 72 extern struct static_key_false context_tracking_key; 73 74 static __always_inline bool context_tracking_enabled(void) 75 { 76 return static_branch_unlikely(&context_tracking_key); 77 } 78 79 static __always_inline bool context_tracking_enabled_cpu(int cpu) 80 { 81 return context_tracking_enabled() && per_cpu(context_tracking.active, cpu); 82 } 83 84 static inline bool context_tracking_enabled_this_cpu(void) 85 { 86 return context_tracking_enabled() && __this_cpu_read(context_tracking.active); 87 } 88 89 #else 90 static __always_inline bool context_tracking_enabled(void) { return false; } 91 static __always_inline bool context_tracking_enabled_cpu(int cpu) { return false; } 92 static __always_inline bool context_tracking_enabled_this_cpu(void) { return false; } 93 #endif /* CONFIG_CONTEXT_TRACKING_USER */ 94 95 #endif 96