blob: e070ea5dadacf3bf90d48c53f0eeb95f63d16430 [file] [log] [blame]
Frederic Weisbecker91d1aa432012-11-27 19:33:25 +01001#ifndef _LINUX_CONTEXT_TRACKING_H
2#define _LINUX_CONTEXT_TRACKING_H
3
Frederic Weisbecker91d1aa432012-11-27 19:33:25 +01004#include <linux/sched.h>
Frederic Weisbecker95a79fd2013-01-07 18:12:14 +01005#include <linux/percpu.h>
Frederic Weisbecker521921b2013-05-16 01:21:38 +02006#include <linux/vtime.h>
Frederic Weisbecker65f382f2013-07-11 19:12:32 +02007#include <linux/static_key.h>
Frederic Weisbecker56dd9472013-02-24 00:23:25 +01008#include <asm/ptrace.h>
Frederic Weisbecker95a79fd2013-01-07 18:12:14 +01009
10struct context_tracking {
11 /*
12 * When active is false, probes are unset in order
13 * to minimize overhead: TIF flags are cleared
14 * and calls to user_enter/exit are ignored. This
15 * may be further optimized using static keys.
16 */
17 bool active;
Frederic Weisbecker6c1e0252013-02-24 01:19:14 +010018 enum ctx_state {
Frederic Weisbecker95a79fd2013-01-07 18:12:14 +010019 IN_KERNEL = 0,
20 IN_USER,
21 } state;
22};
23
Frederic Weisbecker521921b2013-05-16 01:21:38 +020024
Frederic Weisbecker6c1e0252013-02-24 01:19:14 +010025#ifdef CONFIG_CONTEXT_TRACKING
Frederic Weisbecker65f382f2013-07-11 19:12:32 +020026extern struct static_key context_tracking_enabled;
Frederic Weisbecker95a79fd2013-01-07 18:12:14 +010027DECLARE_PER_CPU(struct context_tracking, context_tracking);
28
29static inline bool context_tracking_in_user(void)
30{
31 return __this_cpu_read(context_tracking.state) == IN_USER;
32}
33
34static inline bool context_tracking_active(void)
35{
36 return __this_cpu_read(context_tracking.active);
37}
Frederic Weisbecker91d1aa432012-11-27 19:33:25 +010038
Frederic Weisbecker2e709332013-07-10 00:55:25 +020039extern void context_tracking_cpu_set(int cpu);
40
Frederic Weisbeckerad657822013-07-10 02:44:35 +020041extern void context_tracking_user_enter(void);
42extern void context_tracking_user_exit(void);
Frederic Weisbecker73d424f2013-07-11 19:42:13 +020043extern void __context_tracking_task_switch(struct task_struct *prev,
44 struct task_struct *next);
Frederic Weisbeckerad657822013-07-10 02:44:35 +020045
46static inline void user_enter(void)
47{
48 if (static_key_false(&context_tracking_enabled))
49 context_tracking_user_enter();
50
51}
52static inline void user_exit(void)
53{
54 if (static_key_false(&context_tracking_enabled))
55 context_tracking_user_exit();
56}
Frederic Weisbecker56dd9472013-02-24 00:23:25 +010057
Frederic Weisbecker6c1e0252013-02-24 01:19:14 +010058static inline enum ctx_state exception_enter(void)
Frederic Weisbecker56dd9472013-02-24 00:23:25 +010059{
Frederic Weisbecker6c1e0252013-02-24 01:19:14 +010060 enum ctx_state prev_ctx;
61
Frederic Weisbeckerad657822013-07-10 02:44:35 +020062 if (!static_key_false(&context_tracking_enabled))
63 return 0;
64
Frederic Weisbecker6c1e0252013-02-24 01:19:14 +010065 prev_ctx = this_cpu_read(context_tracking.state);
Frederic Weisbeckerad657822013-07-10 02:44:35 +020066 context_tracking_user_exit();
Frederic Weisbecker6c1e0252013-02-24 01:19:14 +010067
68 return prev_ctx;
Frederic Weisbecker56dd9472013-02-24 00:23:25 +010069}
70
Frederic Weisbecker6c1e0252013-02-24 01:19:14 +010071static inline void exception_exit(enum ctx_state prev_ctx)
Frederic Weisbecker56dd9472013-02-24 00:23:25 +010072{
Frederic Weisbeckerad657822013-07-10 02:44:35 +020073 if (static_key_false(&context_tracking_enabled)) {
74 if (prev_ctx == IN_USER)
75 context_tracking_user_enter();
76 }
Frederic Weisbecker56dd9472013-02-24 00:23:25 +010077}
78
Frederic Weisbecker73d424f2013-07-11 19:42:13 +020079static inline void context_tracking_task_switch(struct task_struct *prev,
80 struct task_struct *next)
81{
82 if (static_key_false(&context_tracking_enabled))
83 __context_tracking_task_switch(prev, next);
84}
Frederic Weisbecker91d1aa432012-11-27 19:33:25 +010085#else
Frederic Weisbecker95a79fd2013-01-07 18:12:14 +010086static inline bool context_tracking_in_user(void) { return false; }
Frederic Weisbecker91d1aa432012-11-27 19:33:25 +010087static inline void user_enter(void) { }
88static inline void user_exit(void) { }
Frederic Weisbecker6c1e0252013-02-24 01:19:14 +010089static inline enum ctx_state exception_enter(void) { return 0; }
90static inline void exception_exit(enum ctx_state prev_ctx) { }
Frederic Weisbecker91d1aa432012-11-27 19:33:25 +010091static inline void context_tracking_task_switch(struct task_struct *prev,
92 struct task_struct *next) { }
93#endif /* !CONFIG_CONTEXT_TRACKING */
94
Frederic Weisbecker65f382f2013-07-11 19:12:32 +020095
96#ifdef CONFIG_CONTEXT_TRACKING_FORCE
97extern void context_tracking_init(void);
98#else
99static inline void context_tracking_init(void) { }
100#endif /* CONFIG_CONTEXT_TRACKING_FORCE */
101
102
Frederic Weisbecker2d854e52013-07-12 19:02:30 +0200103#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
Frederic Weisbecker48d6a812013-07-10 02:44:35 +0200104static inline void guest_enter(void)
105{
106 if (static_key_false(&context_tracking_enabled) &&
107 vtime_accounting_enabled())
108 vtime_guest_enter(current);
109 else
110 current->flags |= PF_VCPU;
111}
112
113static inline void guest_exit(void)
114{
115 if (static_key_false(&context_tracking_enabled) &&
116 vtime_accounting_enabled())
117 vtime_guest_exit(current);
118 else
119 current->flags &= ~PF_VCPU;
120}
Frederic Weisbecker73d424f2013-07-11 19:42:13 +0200121
Frederic Weisbecker2d854e52013-07-12 19:02:30 +0200122#else
123static inline void guest_enter(void)
124{
125 /*
Frederic Weisbecker5b206d42013-07-12 19:05:14 +0200126 * This is running in ioctl context so its safe
127 * to assume that it's the stime pending cputime
128 * to flush.
Frederic Weisbecker2d854e52013-07-12 19:02:30 +0200129 */
130 vtime_account_system(current);
131 current->flags |= PF_VCPU;
132}
133
134static inline void guest_exit(void)
135{
Frederic Weisbecker5b206d42013-07-12 19:05:14 +0200136 /* Flush the guest cputime we spent on the guest */
Frederic Weisbecker2d854e52013-07-12 19:02:30 +0200137 vtime_account_system(current);
138 current->flags &= ~PF_VCPU;
139}
140#endif /* CONFIG_VIRT_CPU_ACCOUNTING_GEN */
141
Frederic Weisbecker91d1aa432012-11-27 19:33:25 +0100142#endif