diff options
| -rw-r--r-- | include/linux/context_tracking_state.h | 1 | ||||
| -rw-r--r-- | kernel/context_tracking.c | 29 |
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 | ||
| 41 | static 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 | |||
| 55 | static 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(); | ||
| 131 | out_irq_restore: | ||
| 108 | local_irq_restore(flags); | 132 | local_irq_restore(flags); |
| 109 | } | 133 | } |
| 110 | NOKPROBE_SYMBOL(context_tracking_enter); | 134 | NOKPROBE_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(); | ||
| 184 | out_irq_restore: | ||
| 156 | local_irq_restore(flags); | 185 | local_irq_restore(flags); |
| 157 | } | 186 | } |
| 158 | NOKPROBE_SYMBOL(context_tracking_exit); | 187 | NOKPROBE_SYMBOL(context_tracking_exit); |
