1 #ifndef _LINUX_CONTEXT_TRACKING_H 2 #define _LINUX_CONTEXT_TRACKING_H 3 4 #include <linux/sched.h> 5 #include <linux/percpu.h> 6 #include <linux/vtime.h> 7 #include <asm/ptrace.h> 8 9 struct context_tracking { 10 /* 11 * When active is false, probes are unset in order 12 * to minimize overhead: TIF flags are cleared 13 * and calls to user_enter/exit are ignored. This 14 * may be further optimized using static keys. 15 */ 16 bool active; 17 enum ctx_state { 18 IN_KERNEL = 0, 19 IN_USER, 20 } state; 21 }; 22 23 static inline void __guest_enter(void) 24 { 25 /* 26 * This is running in ioctl context so we can avoid 27 * the call to vtime_account() with its unnecessary idle check. 28 */ 29 vtime_account_system(current); 30 current->flags |= PF_VCPU; 31 } 32 33 static inline void __guest_exit(void) 34 { 35 /* 36 * This is running in ioctl context so we can avoid 37 * the call to vtime_account() with its unnecessary idle check. 38 */ 39 vtime_account_system(current); 40 current->flags &= ~PF_VCPU; 41 } 42 43 #ifdef CONFIG_CONTEXT_TRACKING 44 DECLARE_PER_CPU(struct context_tracking, context_tracking); 45 46 static inline bool context_tracking_in_user(void) 47 { 48 return __this_cpu_read(context_tracking.state) == IN_USER; 49 } 50 51 static inline bool context_tracking_active(void) 52 { 53 return __this_cpu_read(context_tracking.active); 54 } 55 56 extern void user_enter(void); 57 extern void user_exit(void); 58 59 extern void guest_enter(void); 60 extern void guest_exit(void); 61 62 static inline enum ctx_state exception_enter(void) 63 { 64 enum ctx_state prev_ctx; 65 66 prev_ctx = this_cpu_read(context_tracking.state); 67 user_exit(); 68 69 return prev_ctx; 70 } 71 72 static inline void exception_exit(enum ctx_state prev_ctx) 73 { 74 if (prev_ctx == IN_USER) 75 user_enter(); 76 } 77 78 extern void context_tracking_task_switch(struct task_struct *prev, 79 struct task_struct *next); 80 #else 81 static inline bool context_tracking_in_user(void) { return false; } 82 static inline void user_enter(void) { } 83 static inline void user_exit(void) { } 84 85 static inline void guest_enter(void) 86 { 87 __guest_enter(); 88 } 89 90 static inline void guest_exit(void) 91 { 92 __guest_exit(); 93 } 94 95 static inline enum ctx_state exception_enter(void) { return 0; } 96 static inline void exception_exit(enum ctx_state prev_ctx) { } 97 static inline void context_tracking_task_switch(struct task_struct *prev, 98 struct task_struct *next) { } 99 #endif /* !CONFIG_CONTEXT_TRACKING */ 100 101 #endif 102