]> bbs.cooldavid.org Git - net-next-2.6.git/blame - arch/x86/kernel/alternative.c
x86, alternatives: Fix one more open-coded 8-bit alternative number
[net-next-2.6.git] / arch / x86 / kernel / alternative.c
CommitLineData
9a0b5817 1#include <linux/module.h>
f6a57033 2#include <linux/sched.h>
2f1dafe5 3#include <linux/mutex.h>
9a0b5817 4#include <linux/list.h>
8b5a10fc 5#include <linux/stringify.h>
19d36ccd
AK
6#include <linux/kprobes.h>
7#include <linux/mm.h>
8#include <linux/vmalloc.h>
3945dab4 9#include <linux/memory.h>
3d55cc8a 10#include <linux/stop_machine.h>
5a0e3ad6 11#include <linux/slab.h>
9a0b5817
GH
12#include <asm/alternative.h>
13#include <asm/sections.h>
19d36ccd 14#include <asm/pgtable.h>
8f4e956b
AK
15#include <asm/mce.h>
16#include <asm/nmi.h>
b097976e 17#include <asm/vsyscall.h>
e587cadd 18#include <asm/cacheflush.h>
78ff7fae 19#include <asm/tlbflush.h>
e587cadd 20#include <asm/io.h>
78ff7fae 21#include <asm/fixmap.h>
9a0b5817 22
ab144f5e
AK
23#define MAX_PATCH_LEN (255-1)
24
09488165
JB
25#ifdef CONFIG_HOTPLUG_CPU
26static int smp_alt_once;
9a0b5817 27
d167a518
GH
28static int __init bootonly(char *str)
29{
30 smp_alt_once = 1;
31 return 1;
32}
b7fb4af0 33__setup("smp-alt-boot", bootonly);
09488165
JB
34#else
35#define smp_alt_once 1
36#endif
37
8b5a10fc 38static int __initdata_or_module debug_alternative;
b7fb4af0 39
d167a518
GH
40static int __init debug_alt(char *str)
41{
42 debug_alternative = 1;
43 return 1;
44}
d167a518
GH
45__setup("debug-alternative", debug_alt);
46
09488165
JB
47static int noreplace_smp;
48
b7fb4af0
JF
49static int __init setup_noreplace_smp(char *str)
50{
51 noreplace_smp = 1;
52 return 1;
53}
54__setup("noreplace-smp", setup_noreplace_smp);
55
959b4fdf 56#ifdef CONFIG_PARAVIRT
8b5a10fc 57static int __initdata_or_module noreplace_paravirt = 0;
959b4fdf
JF
58
59static int __init setup_noreplace_paravirt(char *str)
60{
61 noreplace_paravirt = 1;
62 return 1;
63}
64__setup("noreplace-paravirt", setup_noreplace_paravirt);
65#endif
b7fb4af0 66
d167a518
GH
67#define DPRINTK(fmt, args...) if (debug_alternative) \
68 printk(KERN_DEBUG fmt, args)
69
8b5a10fc 70#if defined(GENERIC_NOP1) && !defined(CONFIG_X86_64)
9a0b5817
GH
71/* Use inline assembly to define this because the nops are defined
72 as inline assembly strings in the include files and we cannot
73 get them easily into strings. */
8b5a10fc 74asm("\t" __stringify(__INITRODATA_OR_MODULE) "\nintelnops: "
9a0b5817 75 GENERIC_NOP1 GENERIC_NOP2 GENERIC_NOP3 GENERIC_NOP4 GENERIC_NOP5 GENERIC_NOP6
f4be31ec
SR
76 GENERIC_NOP7 GENERIC_NOP8
77 "\t.previous");
121d7bf5 78extern const unsigned char intelnops[];
8b5a10fc
JB
79static const unsigned char *const __initconst_or_module
80intel_nops[ASM_NOP_MAX+1] = {
9a0b5817
GH
81 NULL,
82 intelnops,
83 intelnops + 1,
84 intelnops + 1 + 2,
85 intelnops + 1 + 2 + 3,
86 intelnops + 1 + 2 + 3 + 4,
87 intelnops + 1 + 2 + 3 + 4 + 5,
88 intelnops + 1 + 2 + 3 + 4 + 5 + 6,
89 intelnops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
90};
d167a518
GH
91#endif
92
93#ifdef K8_NOP1
8b5a10fc 94asm("\t" __stringify(__INITRODATA_OR_MODULE) "\nk8nops: "
d167a518 95 K8_NOP1 K8_NOP2 K8_NOP3 K8_NOP4 K8_NOP5 K8_NOP6
f4be31ec
SR
96 K8_NOP7 K8_NOP8
97 "\t.previous");
121d7bf5 98extern const unsigned char k8nops[];
8b5a10fc
JB
99static const unsigned char *const __initconst_or_module
100k8_nops[ASM_NOP_MAX+1] = {
9a0b5817
GH
101 NULL,
102 k8nops,
103 k8nops + 1,
104 k8nops + 1 + 2,
105 k8nops + 1 + 2 + 3,
106 k8nops + 1 + 2 + 3 + 4,
107 k8nops + 1 + 2 + 3 + 4 + 5,
108 k8nops + 1 + 2 + 3 + 4 + 5 + 6,
109 k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
110};
d167a518
GH
111#endif
112
8b5a10fc
JB
113#if defined(K7_NOP1) && !defined(CONFIG_X86_64)
114asm("\t" __stringify(__INITRODATA_OR_MODULE) "\nk7nops: "
d167a518 115 K7_NOP1 K7_NOP2 K7_NOP3 K7_NOP4 K7_NOP5 K7_NOP6
f4be31ec
SR
116 K7_NOP7 K7_NOP8
117 "\t.previous");
121d7bf5 118extern const unsigned char k7nops[];
8b5a10fc
JB
119static const unsigned char *const __initconst_or_module
120k7_nops[ASM_NOP_MAX+1] = {
9a0b5817
GH
121 NULL,
122 k7nops,
123 k7nops + 1,
124 k7nops + 1 + 2,
125 k7nops + 1 + 2 + 3,
126 k7nops + 1 + 2 + 3 + 4,
127 k7nops + 1 + 2 + 3 + 4 + 5,
128 k7nops + 1 + 2 + 3 + 4 + 5 + 6,
129 k7nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
130};
d167a518
GH
131#endif
132
32c464f5 133#ifdef P6_NOP1
8b5a10fc 134asm("\t" __stringify(__INITRODATA_OR_MODULE) "\np6nops: "
32c464f5 135 P6_NOP1 P6_NOP2 P6_NOP3 P6_NOP4 P6_NOP5 P6_NOP6
f4be31ec
SR
136 P6_NOP7 P6_NOP8
137 "\t.previous");
32c464f5 138extern const unsigned char p6nops[];
8b5a10fc
JB
139static const unsigned char *const __initconst_or_module
140p6_nops[ASM_NOP_MAX+1] = {
32c464f5
JB
141 NULL,
142 p6nops,
143 p6nops + 1,
144 p6nops + 1 + 2,
145 p6nops + 1 + 2 + 3,
146 p6nops + 1 + 2 + 3 + 4,
147 p6nops + 1 + 2 + 3 + 4 + 5,
148 p6nops + 1 + 2 + 3 + 4 + 5 + 6,
149 p6nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
150};
151#endif
152
d167a518
GH
153#ifdef CONFIG_X86_64
154
155extern char __vsyscall_0;
8b5a10fc 156static const unsigned char *const *__init_or_module find_nop_table(void)
d167a518 157{
f31d731e
PA
158 if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
159 boot_cpu_has(X86_FEATURE_NOPL))
160 return p6_nops;
161 else
162 return k8_nops;
d167a518
GH
163}
164
165#else /* CONFIG_X86_64 */
166
8b5a10fc 167static const unsigned char *const *__init_or_module find_nop_table(void)
9a0b5817 168{
f31d731e
PA
169 if (boot_cpu_has(X86_FEATURE_K8))
170 return k8_nops;
171 else if (boot_cpu_has(X86_FEATURE_K7))
172 return k7_nops;
173 else if (boot_cpu_has(X86_FEATURE_NOPL))
174 return p6_nops;
175 else
176 return intel_nops;
9a0b5817
GH
177}
178
d167a518
GH
179#endif /* CONFIG_X86_64 */
180
ab144f5e 181/* Use this to add nops to a buffer, then text_poke the whole buffer. */
8b5a10fc 182static void __init_or_module add_nops(void *insns, unsigned int len)
139ec7c4 183{
121d7bf5 184 const unsigned char *const *noptable = find_nop_table();
139ec7c4
RR
185
186 while (len > 0) {
187 unsigned int noplen = len;
188 if (noplen > ASM_NOP_MAX)
189 noplen = ASM_NOP_MAX;
ab144f5e 190 memcpy(insns, noptable[noplen], noplen);
139ec7c4
RR
191 insns += noplen;
192 len -= noplen;
193 }
194}
195
d167a518 196extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
5967ed87 197extern s32 __smp_locks[], __smp_locks_end[];
8b5a10fc 198static void *text_poke_early(void *addr, const void *opcode, size_t len);
d167a518 199
9a0b5817
GH
200/* Replace instructions with better alternatives for this CPU type.
201 This runs before SMP is initialized to avoid SMP problems with
202 self modifying code. This implies that assymetric systems where
203 APs have less capabilities than the boot processor are not handled.
204 Tough. Make sure you disable such features by hand. */
205
8b5a10fc
JB
206void __init_or_module apply_alternatives(struct alt_instr *start,
207 struct alt_instr *end)
9a0b5817 208{
9a0b5817 209 struct alt_instr *a;
1b1d9258 210 u8 insnbuf[MAX_PATCH_LEN];
9a0b5817 211
77bf90ed 212 DPRINTK("%s: alt table %p -> %p\n", __func__, start, end);
9a0b5817 213 for (a = start; a < end; a++) {
ab144f5e 214 u8 *instr = a->instr;
9a0b5817 215 BUG_ON(a->replacementlen > a->instrlen);
ab144f5e 216 BUG_ON(a->instrlen > sizeof(insnbuf));
9a0b5817
GH
217 if (!boot_cpu_has(a->cpuid))
218 continue;
d167a518
GH
219#ifdef CONFIG_X86_64
220 /* vsyscall code is not mapped yet. resolve it manually. */
221 if (instr >= (u8 *)VSYSCALL_START && instr < (u8*)VSYSCALL_END) {
222 instr = __va(instr - (u8*)VSYSCALL_START + (u8*)__pa_symbol(&__vsyscall_0));
223 DPRINTK("%s: vsyscall fixup: %p => %p\n",
77bf90ed 224 __func__, a->instr, instr);
d167a518
GH
225 }
226#endif
ab144f5e 227 memcpy(insnbuf, a->replacement, a->replacementlen);
1b1d9258
JB
228 if (*insnbuf == 0xe8 && a->replacementlen == 5)
229 *(s32 *)(insnbuf + 1) += a->replacement - a->instr;
ab144f5e
AK
230 add_nops(insnbuf + a->replacementlen,
231 a->instrlen - a->replacementlen);
e587cadd 232 text_poke_early(instr, insnbuf, a->instrlen);
9a0b5817
GH
233 }
234}
235
8ec4d41f
GH
236#ifdef CONFIG_SMP
237
5967ed87
JB
238static void alternatives_smp_lock(const s32 *start, const s32 *end,
239 u8 *text, u8 *text_end)
9a0b5817 240{
5967ed87 241 const s32 *poff;
9a0b5817 242
3945dab4 243 mutex_lock(&text_mutex);
5967ed87
JB
244 for (poff = start; poff < end; poff++) {
245 u8 *ptr = (u8 *)poff + *poff;
246
247 if (!*poff || ptr < text || ptr >= text_end)
9a0b5817 248 continue;
f88f07e0 249 /* turn DS segment override prefix into lock prefix */
d9c5841e
PA
250 if (*ptr == 0x3e)
251 text_poke(ptr, ((unsigned char []){0xf0}), 1);
9a0b5817 252 };
3945dab4 253 mutex_unlock(&text_mutex);
9a0b5817
GH
254}
255
5967ed87
JB
256static void alternatives_smp_unlock(const s32 *start, const s32 *end,
257 u8 *text, u8 *text_end)
9a0b5817 258{
5967ed87 259 const s32 *poff;
9a0b5817 260
b7fb4af0
JF
261 if (noreplace_smp)
262 return;
263
3945dab4 264 mutex_lock(&text_mutex);
5967ed87
JB
265 for (poff = start; poff < end; poff++) {
266 u8 *ptr = (u8 *)poff + *poff;
267
268 if (!*poff || ptr < text || ptr >= text_end)
9a0b5817 269 continue;
f88f07e0 270 /* turn lock prefix into DS segment override prefix */
d9c5841e
PA
271 if (*ptr == 0xf0)
272 text_poke(ptr, ((unsigned char []){0x3E}), 1);
9a0b5817 273 };
3945dab4 274 mutex_unlock(&text_mutex);
9a0b5817
GH
275}
276
277struct smp_alt_module {
278 /* what is this ??? */
279 struct module *mod;
280 char *name;
281
282 /* ptrs to lock prefixes */
5967ed87
JB
283 const s32 *locks;
284 const s32 *locks_end;
9a0b5817
GH
285
286 /* .text segment, needed to avoid patching init code ;) */
287 u8 *text;
288 u8 *text_end;
289
290 struct list_head next;
291};
292static LIST_HEAD(smp_alt_modules);
2f1dafe5 293static DEFINE_MUTEX(smp_alt);
ca74a6f8 294static int smp_mode = 1; /* protected by smp_alt */
9a0b5817 295
8b5a10fc
JB
296void __init_or_module alternatives_smp_module_add(struct module *mod,
297 char *name,
298 void *locks, void *locks_end,
299 void *text, void *text_end)
9a0b5817
GH
300{
301 struct smp_alt_module *smp;
9a0b5817 302
b7fb4af0
JF
303 if (noreplace_smp)
304 return;
305
9a0b5817
GH
306 if (smp_alt_once) {
307 if (boot_cpu_has(X86_FEATURE_UP))
308 alternatives_smp_unlock(locks, locks_end,
309 text, text_end);
310 return;
311 }
312
313 smp = kzalloc(sizeof(*smp), GFP_KERNEL);
314 if (NULL == smp)
315 return; /* we'll run the (safe but slow) SMP code then ... */
316
317 smp->mod = mod;
318 smp->name = name;
319 smp->locks = locks;
320 smp->locks_end = locks_end;
321 smp->text = text;
322 smp->text_end = text_end;
323 DPRINTK("%s: locks %p -> %p, text %p -> %p, name %s\n",
77bf90ed 324 __func__, smp->locks, smp->locks_end,
9a0b5817
GH
325 smp->text, smp->text_end, smp->name);
326
2f1dafe5 327 mutex_lock(&smp_alt);
9a0b5817
GH
328 list_add_tail(&smp->next, &smp_alt_modules);
329 if (boot_cpu_has(X86_FEATURE_UP))
330 alternatives_smp_unlock(smp->locks, smp->locks_end,
331 smp->text, smp->text_end);
2f1dafe5 332 mutex_unlock(&smp_alt);
9a0b5817
GH
333}
334
8b5a10fc 335void __init_or_module alternatives_smp_module_del(struct module *mod)
9a0b5817
GH
336{
337 struct smp_alt_module *item;
9a0b5817 338
b7fb4af0 339 if (smp_alt_once || noreplace_smp)
9a0b5817
GH
340 return;
341
2f1dafe5 342 mutex_lock(&smp_alt);
9a0b5817
GH
343 list_for_each_entry(item, &smp_alt_modules, next) {
344 if (mod != item->mod)
345 continue;
346 list_del(&item->next);
2f1dafe5 347 mutex_unlock(&smp_alt);
77bf90ed 348 DPRINTK("%s: %s\n", __func__, item->name);
9a0b5817
GH
349 kfree(item);
350 return;
351 }
2f1dafe5 352 mutex_unlock(&smp_alt);
9a0b5817
GH
353}
354
355void alternatives_smp_switch(int smp)
356{
357 struct smp_alt_module *mod;
9a0b5817 358
3047e99e
IM
359#ifdef CONFIG_LOCKDEP
360 /*
17abecfe
IM
361 * Older binutils section handling bug prevented
362 * alternatives-replacement from working reliably.
363 *
364 * If this still occurs then you should see a hang
365 * or crash shortly after this line:
3047e99e 366 */
17abecfe 367 printk("lockdep: fixing up alternatives.\n");
3047e99e
IM
368#endif
369
b7fb4af0 370 if (noreplace_smp || smp_alt_once)
9a0b5817
GH
371 return;
372 BUG_ON(!smp && (num_online_cpus() > 1));
373
2f1dafe5 374 mutex_lock(&smp_alt);
ca74a6f8
AK
375
376 /*
377 * Avoid unnecessary switches because it forces JIT based VMs to
378 * throw away all cached translations, which can be quite costly.
379 */
380 if (smp == smp_mode) {
381 /* nothing */
382 } else if (smp) {
9a0b5817 383 printk(KERN_INFO "SMP alternatives: switching to SMP code\n");
53756d37
JF
384 clear_cpu_cap(&boot_cpu_data, X86_FEATURE_UP);
385 clear_cpu_cap(&cpu_data(0), X86_FEATURE_UP);
9a0b5817
GH
386 list_for_each_entry(mod, &smp_alt_modules, next)
387 alternatives_smp_lock(mod->locks, mod->locks_end,
388 mod->text, mod->text_end);
389 } else {
390 printk(KERN_INFO "SMP alternatives: switching to UP code\n");
53756d37
JF
391 set_cpu_cap(&boot_cpu_data, X86_FEATURE_UP);
392 set_cpu_cap(&cpu_data(0), X86_FEATURE_UP);
9a0b5817
GH
393 list_for_each_entry(mod, &smp_alt_modules, next)
394 alternatives_smp_unlock(mod->locks, mod->locks_end,
395 mod->text, mod->text_end);
396 }
ca74a6f8 397 smp_mode = smp;
2f1dafe5 398 mutex_unlock(&smp_alt);
9a0b5817
GH
399}
400
2cfa1978
MH
401/* Return 1 if the address range is reserved for smp-alternatives */
402int alternatives_text_reserved(void *start, void *end)
403{
404 struct smp_alt_module *mod;
5967ed87 405 const s32 *poff;
076dc4a6
MH
406 u8 *text_start = start;
407 u8 *text_end = end;
2cfa1978
MH
408
409 list_for_each_entry(mod, &smp_alt_modules, next) {
076dc4a6 410 if (mod->text > text_end || mod->text_end < text_start)
2cfa1978 411 continue;
5967ed87
JB
412 for (poff = mod->locks; poff < mod->locks_end; poff++) {
413 const u8 *ptr = (const u8 *)poff + *poff;
414
415 if (text_start <= ptr && text_end > ptr)
2cfa1978 416 return 1;
5967ed87 417 }
2cfa1978
MH
418 }
419
420 return 0;
421}
8ec4d41f
GH
422#endif
423
139ec7c4 424#ifdef CONFIG_PARAVIRT
8b5a10fc
JB
425void __init_or_module apply_paravirt(struct paravirt_patch_site *start,
426 struct paravirt_patch_site *end)
139ec7c4 427{
98de032b 428 struct paravirt_patch_site *p;
ab144f5e 429 char insnbuf[MAX_PATCH_LEN];
139ec7c4 430
959b4fdf
JF
431 if (noreplace_paravirt)
432 return;
433
139ec7c4
RR
434 for (p = start; p < end; p++) {
435 unsigned int used;
436
ab144f5e 437 BUG_ON(p->len > MAX_PATCH_LEN);
d34fda4a
CW
438 /* prep the buffer with the original instructions */
439 memcpy(insnbuf, p->instr, p->len);
93b1eab3
JF
440 used = pv_init_ops.patch(p->instrtype, p->clobbers, insnbuf,
441 (unsigned long)p->instr, p->len);
7f63c41c 442
63f70270
JF
443 BUG_ON(used > p->len);
444
139ec7c4 445 /* Pad the rest with nops */
ab144f5e 446 add_nops(insnbuf + used, p->len - used);
e587cadd 447 text_poke_early(p->instr, insnbuf, p->len);
139ec7c4 448 }
139ec7c4 449}
98de032b 450extern struct paravirt_patch_site __start_parainstructions[],
139ec7c4
RR
451 __stop_parainstructions[];
452#endif /* CONFIG_PARAVIRT */
453
9a0b5817
GH
454void __init alternative_instructions(void)
455{
8f4e956b
AK
456 /* The patching is not fully atomic, so try to avoid local interruptions
457 that might execute the to be patched code.
458 Other CPUs are not running. */
459 stop_nmi();
123aa76e
AK
460
461 /*
462 * Don't stop machine check exceptions while patching.
463 * MCEs only happen when something got corrupted and in this
464 * case we must do something about the corruption.
465 * Ignoring it is worse than a unlikely patching race.
466 * Also machine checks tend to be broadcast and if one CPU
467 * goes into machine check the others follow quickly, so we don't
468 * expect a machine check to cause undue problems during to code
469 * patching.
470 */
8f4e956b 471
9a0b5817
GH
472 apply_alternatives(__alt_instructions, __alt_instructions_end);
473
474 /* switch to patch-once-at-boottime-only mode and free the
475 * tables in case we know the number of CPUs will never ever
476 * change */
477#ifdef CONFIG_HOTPLUG_CPU
478 if (num_possible_cpus() < 2)
479 smp_alt_once = 1;
9a0b5817
GH
480#endif
481
8ec4d41f 482#ifdef CONFIG_SMP
9a0b5817
GH
483 if (smp_alt_once) {
484 if (1 == num_possible_cpus()) {
485 printk(KERN_INFO "SMP alternatives: switching to UP code\n");
53756d37
JF
486 set_cpu_cap(&boot_cpu_data, X86_FEATURE_UP);
487 set_cpu_cap(&cpu_data(0), X86_FEATURE_UP);
488
9a0b5817
GH
489 alternatives_smp_unlock(__smp_locks, __smp_locks_end,
490 _text, _etext);
491 }
9a0b5817 492 } else {
9a0b5817
GH
493 alternatives_smp_module_add(NULL, "core kernel",
494 __smp_locks, __smp_locks_end,
495 _text, _etext);
ca74a6f8
AK
496
497 /* Only switch to UP mode if we don't immediately boot others */
649c6653 498 if (num_present_cpus() == 1 || setup_max_cpus <= 1)
ca74a6f8 499 alternatives_smp_switch(0);
9a0b5817 500 }
8ec4d41f 501#endif
441d40dc 502 apply_paravirt(__parainstructions, __parainstructions_end);
8f4e956b 503
f68fd5f4
FW
504 if (smp_alt_once)
505 free_init_pages("SMP alternatives",
506 (unsigned long)__smp_locks,
507 (unsigned long)__smp_locks_end);
508
8f4e956b 509 restart_nmi();
9a0b5817 510}
19d36ccd 511
e587cadd
MD
512/**
513 * text_poke_early - Update instructions on a live kernel at boot time
514 * @addr: address to modify
515 * @opcode: source of the copy
516 * @len: length to copy
517 *
19d36ccd
AK
518 * When you use this code to patch more than one byte of an instruction
519 * you need to make sure that other CPUs cannot execute this code in parallel.
e587cadd
MD
520 * Also no thread must be currently preempted in the middle of these
521 * instructions. And on the local CPU you need to be protected again NMI or MCE
522 * handlers seeing an inconsistent instruction while you patch.
19d36ccd 523 */
8b5a10fc
JB
524static void *__init_or_module text_poke_early(void *addr, const void *opcode,
525 size_t len)
19d36ccd 526{
e587cadd
MD
527 unsigned long flags;
528 local_irq_save(flags);
19d36ccd 529 memcpy(addr, opcode, len);
e587cadd 530 sync_core();
5367b688 531 local_irq_restore(flags);
e587cadd
MD
532 /* Could also do a CLFLUSH here to speed up CPU recovery; but
533 that causes hangs on some VIA CPUs. */
534 return addr;
535}
536
537/**
538 * text_poke - Update instructions on a live kernel
539 * @addr: address to modify
540 * @opcode: source of the copy
541 * @len: length to copy
542 *
543 * Only atomic text poke/set should be allowed when not doing early patching.
544 * It means the size must be writable atomically and the address must be aligned
545 * in a way that permits an atomic write. It also makes sure we fit on a single
546 * page.
78ff7fae
MH
547 *
548 * Note: Must be called under text_mutex.
e587cadd
MD
549 */
550void *__kprobes text_poke(void *addr, const void *opcode, size_t len)
551{
78ff7fae 552 unsigned long flags;
e587cadd 553 char *vaddr;
b7b66baa
MD
554 struct page *pages[2];
555 int i;
e587cadd 556
b7b66baa
MD
557 if (!core_kernel_text((unsigned long)addr)) {
558 pages[0] = vmalloc_to_page(addr);
559 pages[1] = vmalloc_to_page(addr + PAGE_SIZE);
15a601eb 560 } else {
b7b66baa 561 pages[0] = virt_to_page(addr);
00c6b2d5 562 WARN_ON(!PageReserved(pages[0]));
b7b66baa 563 pages[1] = virt_to_page(addr + PAGE_SIZE);
e587cadd 564 }
b7b66baa 565 BUG_ON(!pages[0]);
7cf49427 566 local_irq_save(flags);
78ff7fae
MH
567 set_fixmap(FIX_TEXT_POKE0, page_to_phys(pages[0]));
568 if (pages[1])
569 set_fixmap(FIX_TEXT_POKE1, page_to_phys(pages[1]));
570 vaddr = (char *)fix_to_virt(FIX_TEXT_POKE0);
b7b66baa 571 memcpy(&vaddr[(unsigned long)addr & ~PAGE_MASK], opcode, len);
78ff7fae
MH
572 clear_fixmap(FIX_TEXT_POKE0);
573 if (pages[1])
574 clear_fixmap(FIX_TEXT_POKE1);
575 local_flush_tlb();
19d36ccd 576 sync_core();
a534b679
AK
577 /* Could also do a CLFLUSH here to speed up CPU recovery; but
578 that causes hangs on some VIA CPUs. */
b7b66baa
MD
579 for (i = 0; i < len; i++)
580 BUG_ON(((char *)addr)[i] != ((char *)opcode)[i]);
7cf49427 581 local_irq_restore(flags);
e587cadd 582 return addr;
19d36ccd 583}
3d55cc8a
MH
584
585/*
586 * Cross-modifying kernel text with stop_machine().
587 * This code originally comes from immediate value.
588 */
589static atomic_t stop_machine_first;
590static int wrote_text;
591
592struct text_poke_params {
593 void *addr;
594 const void *opcode;
595 size_t len;
596};
597
598static int __kprobes stop_machine_text_poke(void *data)
599{
600 struct text_poke_params *tpp = data;
601
602 if (atomic_dec_and_test(&stop_machine_first)) {
603 text_poke(tpp->addr, tpp->opcode, tpp->len);
604 smp_wmb(); /* Make sure other cpus see that this has run */
605 wrote_text = 1;
606 } else {
607 while (!wrote_text)
e5a11016
MH
608 cpu_relax();
609 smp_mb(); /* Load wrote_text before following execution */
3d55cc8a
MH
610 }
611
612 flush_icache_range((unsigned long)tpp->addr,
613 (unsigned long)tpp->addr + tpp->len);
614 return 0;
615}
616
617/**
618 * text_poke_smp - Update instructions on a live kernel on SMP
619 * @addr: address to modify
620 * @opcode: source of the copy
621 * @len: length to copy
622 *
623 * Modify multi-byte instruction by using stop_machine() on SMP. This allows
624 * user to poke/set multi-byte text on SMP. Only non-NMI/MCE code modifying
625 * should be allowed, since stop_machine() does _not_ protect code against
626 * NMI and MCE.
627 *
628 * Note: Must be called under get_online_cpus() and text_mutex.
629 */
630void *__kprobes text_poke_smp(void *addr, const void *opcode, size_t len)
631{
632 struct text_poke_params tpp;
633
634 tpp.addr = addr;
635 tpp.opcode = opcode;
636 tpp.len = len;
637 atomic_set(&stop_machine_first, 1);
638 wrote_text = 0;
639 stop_machine(stop_machine_text_poke, (void *)&tpp, NULL);
640 return addr;
641}
642