diff options
Diffstat (limited to 'kernel/jump_label.c')
-rw-r--r-- | kernel/jump_label.c | 54 |
1 files changed, 46 insertions, 8 deletions
diff --git a/kernel/jump_label.c b/kernel/jump_label.c index bbdfe2a462a0..01d3b70fc98a 100644 --- a/kernel/jump_label.c +++ b/kernel/jump_label.c | |||
@@ -66,19 +66,53 @@ void jump_label_inc(struct jump_label_key *key) | |||
66 | return; | 66 | return; |
67 | 67 | ||
68 | jump_label_lock(); | 68 | jump_label_lock(); |
69 | if (atomic_add_return(1, &key->enabled) == 1) | 69 | if (atomic_read(&key->enabled) == 0) |
70 | jump_label_update(key, JUMP_LABEL_ENABLE); | 70 | jump_label_update(key, JUMP_LABEL_ENABLE); |
71 | atomic_inc(&key->enabled); | ||
71 | jump_label_unlock(); | 72 | jump_label_unlock(); |
72 | } | 73 | } |
74 | EXPORT_SYMBOL_GPL(jump_label_inc); | ||
73 | 75 | ||
74 | void jump_label_dec(struct jump_label_key *key) | 76 | static void __jump_label_dec(struct jump_label_key *key, |
77 | unsigned long rate_limit, struct delayed_work *work) | ||
75 | { | 78 | { |
76 | if (!atomic_dec_and_mutex_lock(&key->enabled, &jump_label_mutex)) | 79 | if (!atomic_dec_and_mutex_lock(&key->enabled, &jump_label_mutex)) |
77 | return; | 80 | return; |
78 | 81 | ||
79 | jump_label_update(key, JUMP_LABEL_DISABLE); | 82 | if (rate_limit) { |
83 | atomic_inc(&key->enabled); | ||
84 | schedule_delayed_work(work, rate_limit); | ||
85 | } else | ||
86 | jump_label_update(key, JUMP_LABEL_DISABLE); | ||
87 | |||
80 | jump_label_unlock(); | 88 | jump_label_unlock(); |
81 | } | 89 | } |
90 | EXPORT_SYMBOL_GPL(jump_label_dec); | ||
91 | |||
92 | static void jump_label_update_timeout(struct work_struct *work) | ||
93 | { | ||
94 | struct jump_label_key_deferred *key = | ||
95 | container_of(work, struct jump_label_key_deferred, work.work); | ||
96 | __jump_label_dec(&key->key, 0, NULL); | ||
97 | } | ||
98 | |||
99 | void jump_label_dec(struct jump_label_key *key) | ||
100 | { | ||
101 | __jump_label_dec(key, 0, NULL); | ||
102 | } | ||
103 | |||
104 | void jump_label_dec_deferred(struct jump_label_key_deferred *key) | ||
105 | { | ||
106 | __jump_label_dec(&key->key, key->timeout, &key->work); | ||
107 | } | ||
108 | |||
109 | |||
110 | void jump_label_rate_limit(struct jump_label_key_deferred *key, | ||
111 | unsigned long rl) | ||
112 | { | ||
113 | key->timeout = rl; | ||
114 | INIT_DELAYED_WORK(&key->work, jump_label_update_timeout); | ||
115 | } | ||
82 | 116 | ||
83 | static int addr_conflict(struct jump_entry *entry, void *start, void *end) | 117 | static int addr_conflict(struct jump_entry *entry, void *start, void *end) |
84 | { | 118 | { |
@@ -110,7 +144,7 @@ static int __jump_label_text_reserved(struct jump_entry *iter_start, | |||
110 | * running code can override this to make the non-live update case | 144 | * running code can override this to make the non-live update case |
111 | * cheaper. | 145 | * cheaper. |
112 | */ | 146 | */ |
113 | void __weak arch_jump_label_transform_static(struct jump_entry *entry, | 147 | void __weak __init_or_module arch_jump_label_transform_static(struct jump_entry *entry, |
114 | enum jump_label_type type) | 148 | enum jump_label_type type) |
115 | { | 149 | { |
116 | arch_jump_label_transform(entry, type); | 150 | arch_jump_label_transform(entry, type); |
@@ -216,8 +250,13 @@ void jump_label_apply_nops(struct module *mod) | |||
216 | if (iter_start == iter_stop) | 250 | if (iter_start == iter_stop) |
217 | return; | 251 | return; |
218 | 252 | ||
219 | for (iter = iter_start; iter < iter_stop; iter++) | 253 | for (iter = iter_start; iter < iter_stop; iter++) { |
220 | arch_jump_label_transform_static(iter, JUMP_LABEL_DISABLE); | 254 | struct jump_label_key *iterk; |
255 | |||
256 | iterk = (struct jump_label_key *)(unsigned long)iter->key; | ||
257 | arch_jump_label_transform_static(iter, jump_label_enabled(iterk) ? | ||
258 | JUMP_LABEL_ENABLE : JUMP_LABEL_DISABLE); | ||
259 | } | ||
221 | } | 260 | } |
222 | 261 | ||
223 | static int jump_label_add_module(struct module *mod) | 262 | static int jump_label_add_module(struct module *mod) |
@@ -257,8 +296,7 @@ static int jump_label_add_module(struct module *mod) | |||
257 | key->next = jlm; | 296 | key->next = jlm; |
258 | 297 | ||
259 | if (jump_label_enabled(key)) | 298 | if (jump_label_enabled(key)) |
260 | __jump_label_update(key, iter, iter_stop, | 299 | __jump_label_update(key, iter, iter_stop, JUMP_LABEL_ENABLE); |
261 | JUMP_LABEL_ENABLE); | ||
262 | } | 300 | } |
263 | 301 | ||
264 | return 0; | 302 | return 0; |