alternative.c (46938cc8ab91354e6d751dc0790ddb4244b6703a) alternative.c (e836673c9b4966bc78e38aeda25f7022c57f0e90)
1#define pr_fmt(fmt) "SMP alternatives: " fmt
2
3#include <linux/module.h>
4#include <linux/sched.h>
5#include <linux/mutex.h>
6#include <linux/list.h>
7#include <linux/stringify.h>
8#include <linux/mm.h>

--- 261 unchanged lines hidden (view full) ---

270 * Are we looking at a near JMP with a 1 or 4-byte displacement.
271 */
272static inline bool is_jmp(const u8 opcode)
273{
274 return opcode == 0xeb || opcode == 0xe9;
275}
276
277static void __init_or_module
1#define pr_fmt(fmt) "SMP alternatives: " fmt
2
3#include <linux/module.h>
4#include <linux/sched.h>
5#include <linux/mutex.h>
6#include <linux/list.h>
7#include <linux/stringify.h>
8#include <linux/mm.h>

--- 261 unchanged lines hidden (view full) ---

270 * Are we looking at a near JMP with a 1 or 4-byte displacement.
271 */
272static inline bool is_jmp(const u8 opcode)
273{
274 return opcode == 0xeb || opcode == 0xe9;
275}
276
277static void __init_or_module
278recompute_jump(struct alt_instr *a, u8 *orig_insn, u8 *repl_insn, u8 *insn_buff)
278recompute_jump(struct alt_instr *a, u8 *orig_insn, u8 *repl_insn, u8 *insnbuf)
279{
280 u8 *next_rip, *tgt_rip;
281 s32 n_dspl, o_dspl;
282 int repl_len;
283
284 if (a->replacementlen != 5)
285 return;
286
279{
280 u8 *next_rip, *tgt_rip;
281 s32 n_dspl, o_dspl;
282 int repl_len;
283
284 if (a->replacementlen != 5)
285 return;
286
287 o_dspl = *(s32 *)(insn_buff + 1);
287 o_dspl = *(s32 *)(insnbuf + 1);
288
289 /* next_rip of the replacement JMP */
290 next_rip = repl_insn + a->replacementlen;
291 /* target rip of the replacement JMP */
292 tgt_rip = next_rip + o_dspl;
293 n_dspl = tgt_rip - orig_insn;
294
295 DPRINTK("target RIP: %px, new_displ: 0x%x", tgt_rip, n_dspl);

--- 9 unchanged lines hidden (view full) ---

305 goto two_byte_jmp;
306 else
307 goto five_byte_jmp;
308 }
309
310two_byte_jmp:
311 n_dspl -= 2;
312
288
289 /* next_rip of the replacement JMP */
290 next_rip = repl_insn + a->replacementlen;
291 /* target rip of the replacement JMP */
292 tgt_rip = next_rip + o_dspl;
293 n_dspl = tgt_rip - orig_insn;
294
295 DPRINTK("target RIP: %px, new_displ: 0x%x", tgt_rip, n_dspl);

--- 9 unchanged lines hidden (view full) ---

305 goto two_byte_jmp;
306 else
307 goto five_byte_jmp;
308 }
309
310two_byte_jmp:
311 n_dspl -= 2;
312
313 insn_buff[0] = 0xeb;
314 insn_buff[1] = (s8)n_dspl;
315 add_nops(insn_buff + 2, 3);
313 insnbuf[0] = 0xeb;
314 insnbuf[1] = (s8)n_dspl;
315 add_nops(insnbuf + 2, 3);
316
317 repl_len = 2;
318 goto done;
319
320five_byte_jmp:
321 n_dspl -= 5;
322
316
317 repl_len = 2;
318 goto done;
319
320five_byte_jmp:
321 n_dspl -= 5;
322
323 insn_buff[0] = 0xe9;
324 *(s32 *)&insn_buff[1] = n_dspl;
323 insnbuf[0] = 0xe9;
324 *(s32 *)&insnbuf[1] = n_dspl;
325
326 repl_len = 5;
327
328done:
329
330 DPRINTK("final displ: 0x%08x, JMP 0x%lx",
331 n_dspl, (unsigned long)orig_insn + n_dspl + repl_len);
332}

--- 30 unchanged lines hidden (view full) ---

363 * Marked "noinline" to cause control flow change and thus insn cache
364 * to refetch changed I$ lines.
365 */
366void __init_or_module noinline apply_alternatives(struct alt_instr *start,
367 struct alt_instr *end)
368{
369 struct alt_instr *a;
370 u8 *instr, *replacement;
325
326 repl_len = 5;
327
328done:
329
330 DPRINTK("final displ: 0x%08x, JMP 0x%lx",
331 n_dspl, (unsigned long)orig_insn + n_dspl + repl_len);
332}

--- 30 unchanged lines hidden (view full) ---

363 * Marked "noinline" to cause control flow change and thus insn cache
364 * to refetch changed I$ lines.
365 */
366void __init_or_module noinline apply_alternatives(struct alt_instr *start,
367 struct alt_instr *end)
368{
369 struct alt_instr *a;
370 u8 *instr, *replacement;
371 u8 insn_buff[MAX_PATCH_LEN];
371 u8 insnbuf[MAX_PATCH_LEN];
372
373 DPRINTK("alt table %px, -> %px", start, end);
374 /*
375 * The scan order should be from start to end. A later scanned
376 * alternative code can overwrite previously scanned alternative code.
377 * Some kernel functions (e.g. memcpy, memset, etc) use this order to
378 * patch code.
379 *
380 * So be careful if you want to change the scan order to any other
381 * order.
382 */
383 for (a = start; a < end; a++) {
372
373 DPRINTK("alt table %px, -> %px", start, end);
374 /*
375 * The scan order should be from start to end. A later scanned
376 * alternative code can overwrite previously scanned alternative code.
377 * Some kernel functions (e.g. memcpy, memset, etc) use this order to
378 * patch code.
379 *
380 * So be careful if you want to change the scan order to any other
381 * order.
382 */
383 for (a = start; a < end; a++) {
384 int insn_buff_sz = 0;
384 int insnbuf_sz = 0;
385
386 instr = (u8 *)&a->instr_offset + a->instr_offset;
387 replacement = (u8 *)&a->repl_offset + a->repl_offset;
385
386 instr = (u8 *)&a->instr_offset + a->instr_offset;
387 replacement = (u8 *)&a->repl_offset + a->repl_offset;
388 BUG_ON(a->instrlen > sizeof(insn_buff));
388 BUG_ON(a->instrlen > sizeof(insnbuf));
389 BUG_ON(a->cpuid >= (NCAPINTS + NBUGINTS) * 32);
390 if (!boot_cpu_has(a->cpuid)) {
391 if (a->padlen > 1)
392 optimize_nops(a, instr);
393
394 continue;
395 }
396
397 DPRINTK("feat: %d*32+%d, old: (%pS (%px) len: %d), repl: (%px, len: %d), pad: %d",
398 a->cpuid >> 5,
399 a->cpuid & 0x1f,
400 instr, instr, a->instrlen,
401 replacement, a->replacementlen, a->padlen);
402
403 DUMP_BYTES(instr, a->instrlen, "%px: old_insn: ", instr);
404 DUMP_BYTES(replacement, a->replacementlen, "%px: rpl_insn: ", replacement);
405
389 BUG_ON(a->cpuid >= (NCAPINTS + NBUGINTS) * 32);
390 if (!boot_cpu_has(a->cpuid)) {
391 if (a->padlen > 1)
392 optimize_nops(a, instr);
393
394 continue;
395 }
396
397 DPRINTK("feat: %d*32+%d, old: (%pS (%px) len: %d), repl: (%px, len: %d), pad: %d",
398 a->cpuid >> 5,
399 a->cpuid & 0x1f,
400 instr, instr, a->instrlen,
401 replacement, a->replacementlen, a->padlen);
402
403 DUMP_BYTES(instr, a->instrlen, "%px: old_insn: ", instr);
404 DUMP_BYTES(replacement, a->replacementlen, "%px: rpl_insn: ", replacement);
405
406 memcpy(insn_buff, replacement, a->replacementlen);
407 insn_buff_sz = a->replacementlen;
406 memcpy(insnbuf, replacement, a->replacementlen);
407 insnbuf_sz = a->replacementlen;
408
409 /*
410 * 0xe8 is a relative jump; fix the offset.
411 *
412 * Instruction length is checked before the opcode to avoid
413 * accessing uninitialized bytes for zero-length replacements.
414 */
408
409 /*
410 * 0xe8 is a relative jump; fix the offset.
411 *
412 * Instruction length is checked before the opcode to avoid
413 * accessing uninitialized bytes for zero-length replacements.
414 */
415 if (a->replacementlen == 5 && *insn_buff == 0xe8) {
416 *(s32 *)(insn_buff + 1) += replacement - instr;
415 if (a->replacementlen == 5 && *insnbuf == 0xe8) {
416 *(s32 *)(insnbuf + 1) += replacement - instr;
417 DPRINTK("Fix CALL offset: 0x%x, CALL 0x%lx",
417 DPRINTK("Fix CALL offset: 0x%x, CALL 0x%lx",
418 *(s32 *)(insn_buff + 1),
419 (unsigned long)instr + *(s32 *)(insn_buff + 1) + 5);
418 *(s32 *)(insnbuf + 1),
419 (unsigned long)instr + *(s32 *)(insnbuf + 1) + 5);
420 }
421
422 if (a->replacementlen && is_jmp(replacement[0]))
420 }
421
422 if (a->replacementlen && is_jmp(replacement[0]))
423 recompute_jump(a, instr, replacement, insn_buff);
423 recompute_jump(a, instr, replacement, insnbuf);
424
425 if (a->instrlen > a->replacementlen) {
424
425 if (a->instrlen > a->replacementlen) {
426 add_nops(insn_buff + a->replacementlen,
426 add_nops(insnbuf + a->replacementlen,
427 a->instrlen - a->replacementlen);
427 a->instrlen - a->replacementlen);
428 insn_buff_sz += a->instrlen - a->replacementlen;
428 insnbuf_sz += a->instrlen - a->replacementlen;
429 }
429 }
430 DUMP_BYTES(insn_buff, insn_buff_sz, "%px: final_insn: ", instr);
430 DUMP_BYTES(insnbuf, insnbuf_sz, "%px: final_insn: ", instr);
431
431
432 text_poke_early(instr, insn_buff, insn_buff_sz);
432 text_poke_early(instr, insnbuf, insnbuf_sz);
433 }
434}
435
436#ifdef CONFIG_SMP
437static void alternatives_smp_lock(const s32 *start, const s32 *end,
438 u8 *text, u8 *text_end)
439{
440 const s32 *poff;

--- 145 unchanged lines hidden (view full) ---

586}
587#endif /* CONFIG_SMP */
588
589#ifdef CONFIG_PARAVIRT
590void __init_or_module apply_paravirt(struct paravirt_patch_site *start,
591 struct paravirt_patch_site *end)
592{
593 struct paravirt_patch_site *p;
433 }
434}
435
436#ifdef CONFIG_SMP
437static void alternatives_smp_lock(const s32 *start, const s32 *end,
438 u8 *text, u8 *text_end)
439{
440 const s32 *poff;

--- 145 unchanged lines hidden (view full) ---

586}
587#endif /* CONFIG_SMP */
588
589#ifdef CONFIG_PARAVIRT
590void __init_or_module apply_paravirt(struct paravirt_patch_site *start,
591 struct paravirt_patch_site *end)
592{
593 struct paravirt_patch_site *p;
594 char insn_buff[MAX_PATCH_LEN];
594 char insnbuf[MAX_PATCH_LEN];
595
596 for (p = start; p < end; p++) {
597 unsigned int used;
598
599 BUG_ON(p->len > MAX_PATCH_LEN);
600 /* prep the buffer with the original instructions */
595
596 for (p = start; p < end; p++) {
597 unsigned int used;
598
599 BUG_ON(p->len > MAX_PATCH_LEN);
600 /* prep the buffer with the original instructions */
601 memcpy(insn_buff, p->instr, p->len);
602 used = pv_ops.init.patch(p->type, insn_buff, (unsigned long)p->instr, p->len);
601 memcpy(insnbuf, p->instr, p->len);
602 used = pv_ops.init.patch(p->instrtype, insnbuf,
603 (unsigned long)p->instr, p->len);
603
604 BUG_ON(used > p->len);
605
606 /* Pad the rest with nops */
604
605 BUG_ON(used > p->len);
606
607 /* Pad the rest with nops */
607 add_nops(insn_buff + used, p->len - used);
608 text_poke_early(p->instr, insn_buff, p->len);
608 add_nops(insnbuf + used, p->len - used);
609 text_poke_early(p->instr, insnbuf, p->len);
609 }
610}
611extern struct paravirt_patch_site __start_parainstructions[],
612 __stop_parainstructions[];
613#endif /* CONFIG_PARAVIRT */
614
615void __init alternative_instructions(void)
616{

--- 56 unchanged lines hidden (view full) ---

673 memcpy(addr, opcode, len);
674 local_irq_restore(flags);
675 sync_core();
676 /* Could also do a CLFLUSH here to speed up CPU recovery; but
677 that causes hangs on some VIA CPUs. */
678 return addr;
679}
680
610 }
611}
612extern struct paravirt_patch_site __start_parainstructions[],
613 __stop_parainstructions[];
614#endif /* CONFIG_PARAVIRT */
615
616void __init alternative_instructions(void)
617{

--- 56 unchanged lines hidden (view full) ---

674 memcpy(addr, opcode, len);
675 local_irq_restore(flags);
676 sync_core();
677 /* Could also do a CLFLUSH here to speed up CPU recovery; but
678 that causes hangs on some VIA CPUs. */
679 return addr;
680}
681
681/**
682 * text_poke - Update instructions on a live kernel
683 * @addr: address to modify
684 * @opcode: source of the copy
685 * @len: length to copy
686 *
687 * Only atomic text poke/set should be allowed when not doing early patching.
688 * It means the size must be writable atomically and the address must be aligned
689 * in a way that permits an atomic write. It also makes sure we fit on a single
690 * page.
691 */
692void *text_poke(void *addr, const void *opcode, size_t len)
682static void *__text_poke(void *addr, const void *opcode, size_t len)
693{
694 unsigned long flags;
695 char *vaddr;
696 struct page *pages[2];
697 int i;
698
699 /*
700 * While boot memory allocator is runnig we cannot use struct
701 * pages as they are not yet initialized.
702 */
703 BUG_ON(!after_bootmem);
704
683{
684 unsigned long flags;
685 char *vaddr;
686 struct page *pages[2];
687 int i;
688
689 /*
690 * While boot memory allocator is runnig we cannot use struct
691 * pages as they are not yet initialized.
692 */
693 BUG_ON(!after_bootmem);
694
705 lockdep_assert_held(&text_mutex);
706
707 if (!core_kernel_text((unsigned long)addr)) {
708 pages[0] = vmalloc_to_page(addr);
709 pages[1] = vmalloc_to_page(addr + PAGE_SIZE);
710 } else {
711 pages[0] = virt_to_page(addr);
712 WARN_ON(!PageReserved(pages[0]));
713 pages[1] = virt_to_page(addr + PAGE_SIZE);
714 }

--- 12 unchanged lines hidden (view full) ---

727 /* Could also do a CLFLUSH here to speed up CPU recovery; but
728 that causes hangs on some VIA CPUs. */
729 for (i = 0; i < len; i++)
730 BUG_ON(((char *)addr)[i] != ((char *)opcode)[i]);
731 local_irq_restore(flags);
732 return addr;
733}
734
695 if (!core_kernel_text((unsigned long)addr)) {
696 pages[0] = vmalloc_to_page(addr);
697 pages[1] = vmalloc_to_page(addr + PAGE_SIZE);
698 } else {
699 pages[0] = virt_to_page(addr);
700 WARN_ON(!PageReserved(pages[0]));
701 pages[1] = virt_to_page(addr + PAGE_SIZE);
702 }

--- 12 unchanged lines hidden (view full) ---

715 /* Could also do a CLFLUSH here to speed up CPU recovery; but
716 that causes hangs on some VIA CPUs. */
717 for (i = 0; i < len; i++)
718 BUG_ON(((char *)addr)[i] != ((char *)opcode)[i]);
719 local_irq_restore(flags);
720 return addr;
721}
722
723/**
724 * text_poke - Update instructions on a live kernel
725 * @addr: address to modify
726 * @opcode: source of the copy
727 * @len: length to copy
728 *
729 * Only atomic text poke/set should be allowed when not doing early patching.
730 * It means the size must be writable atomically and the address must be aligned
731 * in a way that permits an atomic write. It also makes sure we fit on a single
732 * page.
733 */
734void *text_poke(void *addr, const void *opcode, size_t len)
735{
736 lockdep_assert_held(&text_mutex);
737
738 return __text_poke(addr, opcode, len);
739}
740
741/**
742 * text_poke_kgdb - Update instructions on a live kernel by kgdb
743 * @addr: address to modify
744 * @opcode: source of the copy
745 * @len: length to copy
746 *
747 * Only atomic text poke/set should be allowed when not doing early patching.
748 * It means the size must be writable atomically and the address must be aligned
749 * in a way that permits an atomic write. It also makes sure we fit on a single
750 * page.
751 *
752 * Context: should only be used by kgdb, which ensures no other core is running,
753 * despite the fact it does not hold the text_mutex.
754 */
755void *text_poke_kgdb(void *addr, const void *opcode, size_t len)
756{
757 return __text_poke(addr, opcode, len);
758}
759
735static void do_sync_core(void *info)
736{
737 sync_core();
738}
739
740static bool bp_patching_in_progress;
741static void *bp_int3_handler, *bp_int3_addr;
742

--- 93 unchanged lines hidden ---
760static void do_sync_core(void *info)
761{
762 sync_core();
763}
764
765static bool bp_patching_in_progress;
766static void *bp_int3_handler, *bp_int3_addr;
767

--- 93 unchanged lines hidden ---