aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/context_tracking_state.h1
-rw-r--r--kernel/context_tracking.c29
2 files changed, 30 insertions, 0 deletions
diff --git a/include/linux/context_tracking_state.h b/include/linux/context_tracking_state.h
index 6b7b96a32b75..678ecdf90cf6 100644
--- a/include/linux/context_tracking_state.h
+++ b/include/linux/context_tracking_state.h
@@ -12,6 +12,7 @@ struct context_tracking {
12 * may be further optimized using static keys. 12 * may be further optimized using static keys.
13 */ 13 */
14 bool active; 14 bool active;
15 int recursion;
15 enum ctx_state { 16 enum ctx_state {
16 CONTEXT_KERNEL = 0, 17 CONTEXT_KERNEL = 0,
17 CONTEXT_USER, 18 CONTEXT_USER,
diff --git a/kernel/context_tracking.c b/kernel/context_tracking.c
index 72d59a1a6eb6..5b11a10e196a 100644
--- a/kernel/context_tracking.c
+++ b/kernel/context_tracking.c
@@ -38,6 +38,25 @@ void context_tracking_cpu_set(int cpu)
38 } 38 }
39} 39}
40 40
41static bool context_tracking_recursion_enter(void)
42{
43 int recursion;
44
45 recursion = __this_cpu_inc_return(context_tracking.recursion);
46 if (recursion == 1)
47 return true;
48
49 WARN_ONCE((recursion < 1), "Invalid context tracking recursion value %d\n", recursion);
50 __this_cpu_dec(context_tracking.recursion);
51
52 return false;
53}
54
55static void context_tracking_recursion_exit(void)
56{
57 __this_cpu_dec(context_tracking.recursion);
58}
59
41/** 60/**
42 * context_tracking_enter - Inform the context tracking that the CPU is going 61 * context_tracking_enter - Inform the context tracking that the CPU is going
43 * enter user or guest space mode. 62 * enter user or guest space mode.
@@ -75,6 +94,9 @@ void context_tracking_enter(enum ctx_state state)
75 WARN_ON_ONCE(!current->mm); 94 WARN_ON_ONCE(!current->mm);
76 95
77 local_irq_save(flags); 96 local_irq_save(flags);
97 if (!context_tracking_recursion_enter())
98 goto out_irq_restore;
99
78 if ( __this_cpu_read(context_tracking.state) != state) { 100 if ( __this_cpu_read(context_tracking.state) != state) {
79 if (__this_cpu_read(context_tracking.active)) { 101 if (__this_cpu_read(context_tracking.active)) {
80 /* 102 /*
@@ -105,6 +127,8 @@ void context_tracking_enter(enum ctx_state state)
105 */ 127 */
106 __this_cpu_write(context_tracking.state, state); 128 __this_cpu_write(context_tracking.state, state);
107 } 129 }
130 context_tracking_recursion_exit();
131out_irq_restore:
108 local_irq_restore(flags); 132 local_irq_restore(flags);
109} 133}
110NOKPROBE_SYMBOL(context_tracking_enter); 134NOKPROBE_SYMBOL(context_tracking_enter);
@@ -139,6 +163,9 @@ void context_tracking_exit(enum ctx_state state)
139 return; 163 return;
140 164
141 local_irq_save(flags); 165 local_irq_save(flags);
166 if (!context_tracking_recursion_enter())
167 goto out_irq_restore;
168
142 if (__this_cpu_read(context_tracking.state) == state) { 169 if (__this_cpu_read(context_tracking.state) == state) {
143 if (__this_cpu_read(context_tracking.active)) { 170 if (__this_cpu_read(context_tracking.active)) {
144 /* 171 /*
@@ -153,6 +180,8 @@ void context_tracking_exit(enum ctx_state state)
153 } 180 }
154 __this_cpu_write(context_tracking.state, CONTEXT_KERNEL); 181 __this_cpu_write(context_tracking.state, CONTEXT_KERNEL);
155 } 182 }
183 context_tracking_recursion_exit();
184out_irq_restore:
156 local_irq_restore(flags); 185 local_irq_restore(flags);
157} 186}
158NOKPROBE_SYMBOL(context_tracking_exit); 187NOKPROBE_SYMBOL(context_tracking_exit);