aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/jump_label.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/jump_label.c')
-rw-r--r--kernel/jump_label.c54
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}
74EXPORT_SYMBOL_GPL(jump_label_inc);
73 75
74void jump_label_dec(struct jump_label_key *key) 76static 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}
90EXPORT_SYMBOL_GPL(jump_label_dec);
91
92static 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
99void jump_label_dec(struct jump_label_key *key)
100{
101 __jump_label_dec(key, 0, NULL);
102}
103
104void jump_label_dec_deferred(struct jump_label_key_deferred *key)
105{
106 __jump_label_dec(&key->key, key->timeout, &key->work);
107}
108
109
110void 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
83static int addr_conflict(struct jump_entry *entry, void *start, void *end) 117static 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 */
113void __weak arch_jump_label_transform_static(struct jump_entry *entry, 147void __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
223static int jump_label_add_module(struct module *mod) 262static 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;