Merge tag 'for-linus-3.12-merge' of git://git.kernel.org/pub/scm/linux/kernel/git...
[pandora-kernel.git] / include / linux / context_tracking.h
index fc09d7b..1581587 100644 (file)
 #define _LINUX_CONTEXT_TRACKING_H
 
 #include <linux/sched.h>
-#include <linux/percpu.h>
 #include <linux/vtime.h>
+#include <linux/context_tracking_state.h>
 #include <asm/ptrace.h>
 
-struct context_tracking {
-       /*
-        * When active is false, probes are unset in order
-        * to minimize overhead: TIF flags are cleared
-        * and calls to user_enter/exit are ignored. This
-        * may be further optimized using static keys.
-        */
-       bool active;
-       enum ctx_state {
-               IN_KERNEL = 0,
-               IN_USER,
-       } state;
-};
-
-static inline void __guest_enter(void)
-{
-       /*
-        * This is running in ioctl context so we can avoid
-        * the call to vtime_account() with its unnecessary idle check.
-        */
-       vtime_account_system(current);
-       current->flags |= PF_VCPU;
-}
-
-static inline void __guest_exit(void)
-{
-       /*
-        * This is running in ioctl context so we can avoid
-        * the call to vtime_account() with its unnecessary idle check.
-        */
-       vtime_account_system(current);
-       current->flags &= ~PF_VCPU;
-}
 
 #ifdef CONFIG_CONTEXT_TRACKING
-DECLARE_PER_CPU(struct context_tracking, context_tracking);
+extern void context_tracking_cpu_set(int cpu);
 
-static inline bool context_tracking_in_user(void)
+extern void context_tracking_user_enter(void);
+extern void context_tracking_user_exit(void);
+extern void __context_tracking_task_switch(struct task_struct *prev,
+                                          struct task_struct *next);
+
+static inline void user_enter(void)
 {
-       return __this_cpu_read(context_tracking.state) == IN_USER;
-}
+       if (static_key_false(&context_tracking_enabled))
+               context_tracking_user_enter();
 
-static inline bool context_tracking_active(void)
+}
+static inline void user_exit(void)
 {
-       return __this_cpu_read(context_tracking.active);
+       if (static_key_false(&context_tracking_enabled))
+               context_tracking_user_exit();
 }
 
-extern void user_enter(void);
-extern void user_exit(void);
-
-extern void guest_enter(void);
-extern void guest_exit(void);
-
 static inline enum ctx_state exception_enter(void)
 {
        enum ctx_state prev_ctx;
 
+       if (!static_key_false(&context_tracking_enabled))
+               return 0;
+
        prev_ctx = this_cpu_read(context_tracking.state);
-       user_exit();
+       context_tracking_user_exit();
 
        return prev_ctx;
 }
 
 static inline void exception_exit(enum ctx_state prev_ctx)
 {
-       if (prev_ctx == IN_USER)
-               user_enter();
+       if (static_key_false(&context_tracking_enabled)) {
+               if (prev_ctx == IN_USER)
+                       context_tracking_user_enter();
+       }
 }
 
-extern void context_tracking_task_switch(struct task_struct *prev,
-                                        struct task_struct *next);
+static inline void context_tracking_task_switch(struct task_struct *prev,
+                                               struct task_struct *next)
+{
+       if (static_key_false(&context_tracking_enabled))
+               __context_tracking_task_switch(prev, next);
+}
 #else
-static inline bool context_tracking_in_user(void) { return false; }
 static inline void user_enter(void) { }
 static inline void user_exit(void) { }
+static inline enum ctx_state exception_enter(void) { return 0; }
+static inline void exception_exit(enum ctx_state prev_ctx) { }
+static inline void context_tracking_task_switch(struct task_struct *prev,
+                                               struct task_struct *next) { }
+#endif /* !CONFIG_CONTEXT_TRACKING */
+
+
+#ifdef CONFIG_CONTEXT_TRACKING_FORCE
+extern void context_tracking_init(void);
+#else
+static inline void context_tracking_init(void) { }
+#endif /* CONFIG_CONTEXT_TRACKING_FORCE */
+
 
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
 static inline void guest_enter(void)
 {
-       __guest_enter();
+       if (vtime_accounting_enabled())
+               vtime_guest_enter(current);
+       else
+               current->flags |= PF_VCPU;
 }
 
 static inline void guest_exit(void)
 {
-       __guest_exit();
+       if (vtime_accounting_enabled())
+               vtime_guest_exit(current);
+       else
+               current->flags &= ~PF_VCPU;
 }
 
-static inline enum ctx_state exception_enter(void) { return 0; }
-static inline void exception_exit(enum ctx_state prev_ctx) { }
-static inline void context_tracking_task_switch(struct task_struct *prev,
-                                               struct task_struct *next) { }
-#endif /* !CONFIG_CONTEXT_TRACKING */
+#else
+static inline void guest_enter(void)
+{
+       /*
+        * This is running in ioctl context so its safe
+        * to assume that it's the stime pending cputime
+        * to flush.
+        */
+       vtime_account_system(current);
+       current->flags |= PF_VCPU;
+}
+
+static inline void guest_exit(void)
+{
+       /* Flush the guest cputime we spent on the guest */
+       vtime_account_system(current);
+       current->flags &= ~PF_VCPU;
+}
+#endif /* CONFIG_VIRT_CPU_ACCOUNTING_GEN */
 
 #endif