blob: 74f68f4dc6c20ef9c660ae344f97497821208dfa [file] [log] [blame]
Frederic Weisbecker91d1aa432012-11-27 19:33:25 +01001#include <linux/context_tracking.h>
Frederic Weisbecker6a616712012-12-16 20:00:34 +01002#include <linux/kvm_host.h>
Frederic Weisbecker91d1aa432012-11-27 19:33:25 +01003#include <linux/rcupdate.h>
4#include <linux/sched.h>
Frederic Weisbecker91d1aa432012-11-27 19:33:25 +01005#include <linux/hardirq.h>
Frederic Weisbecker6a616712012-12-16 20:00:34 +01006#include <linux/export.h>
Frederic Weisbecker91d1aa432012-11-27 19:33:25 +01007
Frederic Weisbecker95a79fd2013-01-07 18:12:14 +01008DEFINE_PER_CPU(struct context_tracking, context_tracking) = {
Frederic Weisbecker91d1aa432012-11-27 19:33:25 +01009#ifdef CONFIG_CONTEXT_TRACKING_FORCE
10 .active = true,
11#endif
12};
13
14void user_enter(void)
15{
16 unsigned long flags;
17
18 /*
19 * Some contexts may involve an exception occuring in an irq,
20 * leading to that nesting:
21 * rcu_irq_enter() rcu_user_exit() rcu_user_exit() rcu_irq_exit()
22 * This would mess up the dyntick_nesting count though. And rcu_irq_*()
23 * helpers are enough to protect RCU uses inside the exception. So
24 * just return immediately if we detect we are in an IRQ.
25 */
26 if (in_interrupt())
27 return;
28
29 WARN_ON_ONCE(!current->mm);
30
31 local_irq_save(flags);
32 if (__this_cpu_read(context_tracking.active) &&
33 __this_cpu_read(context_tracking.state) != IN_USER) {
Frederic Weisbeckerabf917c2012-07-25 07:56:04 +020034 vtime_user_enter(current);
Frederic Weisbecker91d1aa432012-11-27 19:33:25 +010035 rcu_user_enter();
Frederic Weisbeckerabf917c2012-07-25 07:56:04 +020036 __this_cpu_write(context_tracking.state, IN_USER);
Frederic Weisbecker91d1aa432012-11-27 19:33:25 +010037 }
38 local_irq_restore(flags);
39}
40
41void user_exit(void)
42{
43 unsigned long flags;
44
45 /*
46 * Some contexts may involve an exception occuring in an irq,
47 * leading to that nesting:
48 * rcu_irq_enter() rcu_user_exit() rcu_user_exit() rcu_irq_exit()
49 * This would mess up the dyntick_nesting count though. And rcu_irq_*()
50 * helpers are enough to protect RCU uses inside the exception. So
51 * just return immediately if we detect we are in an IRQ.
52 */
53 if (in_interrupt())
54 return;
55
56 local_irq_save(flags);
57 if (__this_cpu_read(context_tracking.state) == IN_USER) {
Frederic Weisbecker91d1aa432012-11-27 19:33:25 +010058 rcu_user_exit();
Frederic Weisbeckerabf917c2012-07-25 07:56:04 +020059 vtime_user_exit(current);
60 __this_cpu_write(context_tracking.state, IN_KERNEL);
Frederic Weisbecker91d1aa432012-11-27 19:33:25 +010061 }
62 local_irq_restore(flags);
63}
64
Frederic Weisbecker6a616712012-12-16 20:00:34 +010065void guest_enter(void)
66{
67 if (vtime_accounting_enabled())
68 vtime_guest_enter(current);
69 else
70 __guest_enter();
71}
72EXPORT_SYMBOL_GPL(guest_enter);
73
74void guest_exit(void)
75{
76 if (vtime_accounting_enabled())
77 vtime_guest_exit(current);
78 else
79 __guest_exit();
80}
81EXPORT_SYMBOL_GPL(guest_exit);
82
Frederic Weisbecker91d1aa432012-11-27 19:33:25 +010083void context_tracking_task_switch(struct task_struct *prev,
84 struct task_struct *next)
85{
86 if (__this_cpu_read(context_tracking.active)) {
87 clear_tsk_thread_flag(prev, TIF_NOHZ);
88 set_tsk_thread_flag(next, TIF_NOHZ);
89 }
90}