73
58
sort(start, size, sizeof(struct jump_entry), jump_label_cmp, NULL);
76
static struct jump_label_entry *get_jump_label_entry(jump_label_t key)
78
struct hlist_head *head;
79
struct hlist_node *node;
80
struct jump_label_entry *e;
81
u32 hash = jhash((void *)&key, sizeof(jump_label_t), 0);
83
head = &jump_label_table[hash & (JUMP_LABEL_TABLE_SIZE - 1)];
84
hlist_for_each_entry(e, node, head, hlist) {
91
static struct jump_label_entry *
92
add_jump_label_entry(jump_label_t key, int nr_entries, struct jump_entry *table)
94
struct hlist_head *head;
95
struct jump_label_entry *e;
98
e = get_jump_label_entry(key);
100
return ERR_PTR(-EEXIST);
102
e = kmalloc(sizeof(struct jump_label_entry), GFP_KERNEL);
104
return ERR_PTR(-ENOMEM);
106
hash = jhash((void *)&key, sizeof(jump_label_t), 0);
107
head = &jump_label_table[hash & (JUMP_LABEL_TABLE_SIZE - 1)];
110
e->nr_entries = nr_entries;
111
INIT_HLIST_HEAD(&(e->modules));
112
hlist_add_head(&e->hlist, head);
117
build_jump_label_hashtable(struct jump_entry *start, struct jump_entry *stop)
119
struct jump_entry *iter, *iter_begin;
120
struct jump_label_entry *entry;
123
sort_jump_label_entries(start, stop);
125
while (iter < stop) {
126
entry = get_jump_label_entry(iter->key);
130
while ((iter < stop) &&
131
(iter->key == iter_begin->key)) {
135
entry = add_jump_label_entry(iter_begin->key,
138
return PTR_ERR(entry);
140
WARN_ONCE(1, KERN_ERR "build_jump_hashtable: unexpected entry!\n");
148
* jump_label_update - update jump label text
149
* @key - key value associated with a a jump label
150
* @type - enum set to JUMP_LABEL_ENABLE or JUMP_LABEL_DISABLE
152
* Will enable/disable the jump for jump label @key, depending on the
157
void jump_label_update(unsigned long key, enum jump_label_type type)
159
struct jump_entry *iter;
160
struct jump_label_entry *entry;
161
struct hlist_node *module_node;
162
struct jump_label_module_entry *e_module;
61
static void jump_label_update(struct jump_label_key *key, int enable);
63
void jump_label_inc(struct jump_label_key *key)
65
if (atomic_inc_not_zero(&key->enabled))
165
68
jump_label_lock();
166
entry = get_jump_label_entry((jump_label_t)key);
168
count = entry->nr_entries;
171
if (kernel_text_address(iter->code))
172
arch_jump_label_transform(iter, type);
175
/* eanble/disable jump labels in modules */
176
hlist_for_each_entry(e_module, module_node, &(entry->modules),
178
count = e_module->nr_entries;
179
iter = e_module->table;
182
kernel_text_address(iter->code))
183
arch_jump_label_transform(iter, type);
69
if (atomic_add_return(1, &key->enabled) == 1)
70
jump_label_update(key, JUMP_LABEL_ENABLE);
74
void jump_label_dec(struct jump_label_key *key)
76
if (!atomic_dec_and_mutex_lock(&key->enabled, &jump_label_mutex))
79
jump_label_update(key, JUMP_LABEL_DISABLE);
188
80
jump_label_unlock();
200
#ifdef CONFIG_MODULES
202
static int module_conflict(void *start, void *end)
204
struct hlist_head *head;
205
struct hlist_node *node, *node_next, *module_node, *module_node_next;
206
struct jump_label_entry *e;
207
struct jump_label_module_entry *e_module;
208
struct jump_entry *iter;
212
for (i = 0; i < JUMP_LABEL_TABLE_SIZE; i++) {
213
head = &jump_label_table[i];
214
hlist_for_each_entry_safe(e, node, node_next, head, hlist) {
215
hlist_for_each_entry_safe(e_module, module_node,
217
&(e->modules), hlist) {
218
count = e_module->nr_entries;
219
iter = e_module->table;
221
if (addr_conflict(iter, start, end)) {
237
* jump_label_text_reserved - check if addr range is reserved
238
* @start: start text addr
239
* @end: end text addr
241
* checks if the text addr located between @start and @end
242
* overlaps with any of the jump label patch addresses. Code
243
* that wants to modify kernel text should first verify that
244
* it does not overlap with any of the jump label addresses.
245
* Caller must hold jump_label_mutex.
247
* returns 1 if there is an overlap, 0 otherwise
249
int jump_label_text_reserved(void *start, void *end)
251
struct jump_entry *iter;
252
struct jump_entry *iter_start = __start___jump_table;
253
struct jump_entry *iter_stop = __start___jump_table;
92
static int __jump_label_text_reserved(struct jump_entry *iter_start,
93
struct jump_entry *iter_stop, void *start, void *end)
95
struct jump_entry *iter;
256
97
iter = iter_start;
257
98
while (iter < iter_stop) {
258
if (addr_conflict(iter, start, end)) {
99
if (addr_conflict(iter, start, end))
265
/* now check modules */
266
#ifdef CONFIG_MODULES
267
conflict = module_conflict(start, end);
107
static void __jump_label_update(struct jump_label_key *key,
108
struct jump_entry *entry,
109
struct jump_entry *stop, int enable)
111
for (; (entry < stop) &&
112
(entry->key == (jump_label_t)(unsigned long)key);
115
* entry->code set to 0 invalidates module init text sections
116
* kernel_text_address() verifies we are not in core kernel
117
* init code, see jump_label_invalidate_module_init().
119
if (entry->code && kernel_text_address(entry->code))
120
arch_jump_label_transform(entry, enable);
280
static __init int init_jump_label(void)
131
static __init int jump_label_init(void)
283
133
struct jump_entry *iter_start = __start___jump_table;
284
134
struct jump_entry *iter_stop = __stop___jump_table;
135
struct jump_label_key *key = NULL;
285
136
struct jump_entry *iter;
287
138
jump_label_lock();
288
ret = build_jump_label_hashtable(__start___jump_table,
289
__stop___jump_table);
291
while (iter < iter_stop) {
139
jump_label_sort_entries(iter_start, iter_stop);
141
for (iter = iter_start; iter < iter_stop; iter++) {
292
142
arch_jump_label_text_poke_early(iter->code);
143
if (iter->key == (jump_label_t)(unsigned long)key)
146
key = (struct jump_label_key *)(unsigned long)iter->key;
147
atomic_set(&key->enabled, 0);
149
#ifdef CONFIG_MODULES
295
153
jump_label_unlock();
298
early_initcall(init_jump_label);
157
early_initcall(jump_label_init);
300
159
#ifdef CONFIG_MODULES
302
static struct jump_label_module_entry *
303
add_jump_label_module_entry(struct jump_label_entry *entry,
304
struct jump_entry *iter_begin,
305
int count, struct module *mod)
307
struct jump_label_module_entry *e;
309
e = kmalloc(sizeof(struct jump_label_module_entry), GFP_KERNEL);
311
return ERR_PTR(-ENOMEM);
313
e->nr_entries = count;
314
e->table = iter_begin;
315
hlist_add_head(&e->hlist, &entry->modules);
319
static int add_jump_label_module(struct module *mod)
321
struct jump_entry *iter, *iter_begin;
322
struct jump_label_entry *entry;
323
struct jump_label_module_entry *module_entry;
326
/* if the module doesn't have jump label entries, just return */
327
if (!mod->num_jump_entries)
330
sort_jump_label_entries(mod->jump_entries,
331
mod->jump_entries + mod->num_jump_entries);
332
iter = mod->jump_entries;
333
while (iter < mod->jump_entries + mod->num_jump_entries) {
334
entry = get_jump_label_entry(iter->key);
337
while ((iter < mod->jump_entries + mod->num_jump_entries) &&
338
(iter->key == iter_begin->key)) {
343
entry = add_jump_label_entry(iter_begin->key, 0, NULL);
345
return PTR_ERR(entry);
347
module_entry = add_jump_label_module_entry(entry, iter_begin,
349
if (IS_ERR(module_entry))
350
return PTR_ERR(module_entry);
161
struct jump_label_mod {
162
struct jump_label_mod *next;
163
struct jump_entry *entries;
167
static int __jump_label_mod_text_reserved(void *start, void *end)
171
mod = __module_text_address((unsigned long)start);
175
WARN_ON_ONCE(__module_text_address((unsigned long)end) != mod);
177
return __jump_label_text_reserved(mod->jump_entries,
178
mod->jump_entries + mod->num_jump_entries,
182
static void __jump_label_mod_update(struct jump_label_key *key, int enable)
184
struct jump_label_mod *mod = key->next;
187
struct module *m = mod->mod;
189
__jump_label_update(key, mod->entries,
190
m->jump_entries + m->num_jump_entries,
197
* apply_jump_label_nops - patch module jump labels with arch_get_jump_label_nop()
198
* @mod: module to patch
200
* Allow for run-time selection of the optimal nops. Before the module
201
* loads patch these with arch_get_jump_label_nop(), which is specified by
202
* the arch specific jump label code.
204
void jump_label_apply_nops(struct module *mod)
206
struct jump_entry *iter_start = mod->jump_entries;
207
struct jump_entry *iter_stop = iter_start + mod->num_jump_entries;
208
struct jump_entry *iter;
210
/* if the module doesn't have jump label entries, just return */
211
if (iter_start == iter_stop)
214
for (iter = iter_start; iter < iter_stop; iter++)
215
arch_jump_label_text_poke_early(iter->code);
218
static int jump_label_add_module(struct module *mod)
220
struct jump_entry *iter_start = mod->jump_entries;
221
struct jump_entry *iter_stop = iter_start + mod->num_jump_entries;
222
struct jump_entry *iter;
223
struct jump_label_key *key = NULL;
224
struct jump_label_mod *jlm;
226
/* if the module doesn't have jump label entries, just return */
227
if (iter_start == iter_stop)
230
jump_label_sort_entries(iter_start, iter_stop);
232
for (iter = iter_start; iter < iter_stop; iter++) {
233
if (iter->key == (jump_label_t)(unsigned long)key)
236
key = (struct jump_label_key *)(unsigned long)iter->key;
238
if (__module_address(iter->key) == mod) {
239
atomic_set(&key->enabled, 0);
245
jlm = kzalloc(sizeof(struct jump_label_mod), GFP_KERNEL);
251
jlm->next = key->next;
254
if (jump_label_enabled(key))
255
__jump_label_update(key, iter, iter_stop,
355
static void remove_jump_label_module(struct module *mod)
262
static void jump_label_del_module(struct module *mod)
357
struct hlist_head *head;
358
struct hlist_node *node, *node_next, *module_node, *module_node_next;
359
struct jump_label_entry *e;
360
struct jump_label_module_entry *e_module;
363
/* if the module doesn't have jump label entries, just return */
364
if (!mod->num_jump_entries)
367
for (i = 0; i < JUMP_LABEL_TABLE_SIZE; i++) {
368
head = &jump_label_table[i];
369
hlist_for_each_entry_safe(e, node, node_next, head, hlist) {
370
hlist_for_each_entry_safe(e_module, module_node,
372
&(e->modules), hlist) {
373
if (e_module->mod == mod) {
374
hlist_del(&e_module->hlist);
378
if (hlist_empty(&e->modules) && (e->nr_entries == 0)) {
379
hlist_del(&e->hlist);
264
struct jump_entry *iter_start = mod->jump_entries;
265
struct jump_entry *iter_stop = iter_start + mod->num_jump_entries;
266
struct jump_entry *iter;
267
struct jump_label_key *key = NULL;
268
struct jump_label_mod *jlm, **prev;
270
for (iter = iter_start; iter < iter_stop; iter++) {
271
if (iter->key == (jump_label_t)(unsigned long)key)
274
key = (struct jump_label_key *)(unsigned long)iter->key;
276
if (__module_address(iter->key) == mod)
282
while (jlm && jlm->mod != mod) {
386
static void remove_jump_label_module_init(struct module *mod)
294
static void jump_label_invalidate_module_init(struct module *mod)
388
struct hlist_head *head;
389
struct hlist_node *node, *node_next, *module_node, *module_node_next;
390
struct jump_label_entry *e;
391
struct jump_label_module_entry *e_module;
296
struct jump_entry *iter_start = mod->jump_entries;
297
struct jump_entry *iter_stop = iter_start + mod->num_jump_entries;
392
298
struct jump_entry *iter;
395
/* if the module doesn't have jump label entries, just return */
396
if (!mod->num_jump_entries)
399
for (i = 0; i < JUMP_LABEL_TABLE_SIZE; i++) {
400
head = &jump_label_table[i];
401
hlist_for_each_entry_safe(e, node, node_next, head, hlist) {
402
hlist_for_each_entry_safe(e_module, module_node,
404
&(e->modules), hlist) {
405
if (e_module->mod != mod)
407
count = e_module->nr_entries;
408
iter = e_module->table;
410
if (within_module_init(iter->code, mod))
300
for (iter = iter_start; iter < iter_stop; iter++) {
301
if (within_module_init(iter->code, mod))
427
314
case MODULE_STATE_COMING:
428
315
jump_label_lock();
429
ret = add_jump_label_module(mod);
316
ret = jump_label_add_module(mod);
431
remove_jump_label_module(mod);
318
jump_label_del_module(mod);
432
319
jump_label_unlock();
434
321
case MODULE_STATE_GOING:
435
322
jump_label_lock();
436
remove_jump_label_module(mod);
323
jump_label_del_module(mod);
437
324
jump_label_unlock();
439
326
case MODULE_STATE_LIVE:
440
327
jump_label_lock();
441
remove_jump_label_module_init(mod);
328
jump_label_invalidate_module_init(mod);
442
329
jump_label_unlock();
449
* apply_jump_label_nops - patch module jump labels with arch_get_jump_label_nop()
450
* @mod: module to patch
452
* Allow for run-time selection of the optimal nops. Before the module
453
* loads patch these with arch_get_jump_label_nop(), which is specified by
454
* the arch specific jump label code.
456
void jump_label_apply_nops(struct module *mod)
458
struct jump_entry *iter;
460
/* if the module doesn't have jump label entries, just return */
461
if (!mod->num_jump_entries)
464
iter = mod->jump_entries;
465
while (iter < mod->jump_entries + mod->num_jump_entries) {
466
arch_jump_label_text_poke_early(iter->code);
333
return notifier_from_errno(ret);
471
336
struct notifier_block jump_label_module_nb = {
472
337
.notifier_call = jump_label_module_notify,
338
.priority = 1, /* higher than tracepoints */
476
static __init int init_jump_label_module(void)
341
static __init int jump_label_init_module(void)
478
343
return register_module_notifier(&jump_label_module_nb);
480
early_initcall(init_jump_label_module);
345
early_initcall(jump_label_init_module);
482
347
#endif /* CONFIG_MODULES */
350
* jump_label_text_reserved - check if addr range is reserved
351
* @start: start text addr
352
* @end: end text addr
354
* checks if the text addr located between @start and @end
355
* overlaps with any of the jump label patch addresses. Code
356
* that wants to modify kernel text should first verify that
357
* it does not overlap with any of the jump label addresses.
358
* Caller must hold jump_label_mutex.
360
* returns 1 if there is an overlap, 0 otherwise
362
int jump_label_text_reserved(void *start, void *end)
364
int ret = __jump_label_text_reserved(__start___jump_table,
365
__stop___jump_table, start, end);
370
#ifdef CONFIG_MODULES
371
ret = __jump_label_mod_text_reserved(start, end);
376
static void jump_label_update(struct jump_label_key *key, int enable)
378
struct jump_entry *entry = key->entries, *stop = __stop___jump_table;
380
#ifdef CONFIG_MODULES
381
struct module *mod = __module_address((jump_label_t)key);
383
__jump_label_mod_update(key, enable);
386
stop = mod->jump_entries + mod->num_jump_entries;
388
/* if there are no users, entry can be NULL */
390
__jump_label_update(key, entry, stop, enable);