]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - kernel/context_tracking.c
kvm: Prepare to add generic guest entry/exit callbacks
[mirror_ubuntu-zesty-kernel.git] / kernel / context_tracking.c
CommitLineData
91d1aa43
FW
1#include <linux/context_tracking.h>
2#include <linux/rcupdate.h>
3#include <linux/sched.h>
91d1aa43
FW
4#include <linux/hardirq.h>
5
91d1aa43 6
95a79fd4 7DEFINE_PER_CPU(struct context_tracking, context_tracking) = {
91d1aa43
FW
8#ifdef CONFIG_CONTEXT_TRACKING_FORCE
9 .active = true,
10#endif
11};
12
13void user_enter(void)
14{
15 unsigned long flags;
16
17 /*
18 * Some contexts may involve an exception occuring in an irq,
19 * leading to that nesting:
20 * rcu_irq_enter() rcu_user_exit() rcu_user_exit() rcu_irq_exit()
21 * This would mess up the dyntick_nesting count though. And rcu_irq_*()
22 * helpers are enough to protect RCU uses inside the exception. So
23 * just return immediately if we detect we are in an IRQ.
24 */
25 if (in_interrupt())
26 return;
27
28 WARN_ON_ONCE(!current->mm);
29
30 local_irq_save(flags);
31 if (__this_cpu_read(context_tracking.active) &&
32 __this_cpu_read(context_tracking.state) != IN_USER) {
abf917cd 33 vtime_user_enter(current);
91d1aa43 34 rcu_user_enter();
abf917cd 35 __this_cpu_write(context_tracking.state, IN_USER);
91d1aa43
FW
36 }
37 local_irq_restore(flags);
38}
39
40void user_exit(void)
41{
42 unsigned long flags;
43
44 /*
45 * Some contexts may involve an exception occuring in an irq,
46 * leading to that nesting:
47 * rcu_irq_enter() rcu_user_exit() rcu_user_exit() rcu_irq_exit()
48 * This would mess up the dyntick_nesting count though. And rcu_irq_*()
49 * helpers are enough to protect RCU uses inside the exception. So
50 * just return immediately if we detect we are in an IRQ.
51 */
52 if (in_interrupt())
53 return;
54
55 local_irq_save(flags);
56 if (__this_cpu_read(context_tracking.state) == IN_USER) {
91d1aa43 57 rcu_user_exit();
abf917cd
FW
58 vtime_user_exit(current);
59 __this_cpu_write(context_tracking.state, IN_KERNEL);
91d1aa43
FW
60 }
61 local_irq_restore(flags);
62}
63
64void context_tracking_task_switch(struct task_struct *prev,
65 struct task_struct *next)
66{
67 if (__this_cpu_read(context_tracking.active)) {
68 clear_tsk_thread_flag(prev, TIF_NOHZ);
69 set_tsk_thread_flag(next, TIF_NOHZ);
70 }
71}