alternative.c (1260ed77798502de9c98020040d2995008de10cc) | alternative.c (8754e67ad4ac692c67ff1f99c0d07156f04ae40c) |
---|---|
1// SPDX-License-Identifier: GPL-2.0-only 2#define pr_fmt(fmt) "SMP alternatives: " fmt 3 4#include <linux/module.h> 5#include <linux/sched.h> 6#include <linux/perf_event.h> 7#include <linux/mutex.h> 8#include <linux/list.h> --- 567 unchanged lines hidden (view full) --- 576 modrm += reg; 577 578 bytes[i++] = 0xff; /* opcode */ 579 bytes[i++] = modrm; 580 581 return i; 582} 583 | 1// SPDX-License-Identifier: GPL-2.0-only 2#define pr_fmt(fmt) "SMP alternatives: " fmt 3 4#include <linux/module.h> 5#include <linux/sched.h> 6#include <linux/perf_event.h> 7#include <linux/mutex.h> 8#include <linux/list.h> --- 567 unchanged lines hidden (view full) --- 576 modrm += reg; 577 578 bytes[i++] = 0xff; /* opcode */ 579 bytes[i++] = modrm; 580 581 return i; 582} 583 |
584static int emit_call_track_retpoline(void *addr, struct insn *insn, int reg, u8 *bytes) | 584static int __emit_trampoline(void *addr, struct insn *insn, u8 *bytes, 585 void *call_dest, void *jmp_dest) |
585{ 586 u8 op = insn->opcode.bytes[0]; 587 int i = 0; 588 589 /* 590 * Clang does 'weird' Jcc __x86_indirect_thunk_r11 conditional 591 * tail-calls. Deal with them. 592 */ --- 4 unchanged lines hidden (view full) --- 597 } 598 599 if (insn->length == 6) 600 bytes[i++] = 0x2e; /* CS-prefix */ 601 602 switch (op) { 603 case CALL_INSN_OPCODE: 604 __text_gen_insn(bytes+i, op, addr+i, | 586{ 587 u8 op = insn->opcode.bytes[0]; 588 int i = 0; 589 590 /* 591 * Clang does 'weird' Jcc __x86_indirect_thunk_r11 conditional 592 * tail-calls. Deal with them. 593 */ --- 4 unchanged lines hidden (view full) --- 598 } 599 600 if (insn->length == 6) 601 bytes[i++] = 0x2e; /* CS-prefix */ 602 603 switch (op) { 604 case CALL_INSN_OPCODE: 605 __text_gen_insn(bytes+i, op, addr+i, |
605 __x86_indirect_call_thunk_array[reg], | 606 call_dest, |
606 CALL_INSN_SIZE); 607 i += CALL_INSN_SIZE; 608 break; 609 610 case JMP32_INSN_OPCODE: 611clang_jcc: 612 __text_gen_insn(bytes+i, op, addr+i, | 607 CALL_INSN_SIZE); 608 i += CALL_INSN_SIZE; 609 break; 610 611 case JMP32_INSN_OPCODE: 612clang_jcc: 613 __text_gen_insn(bytes+i, op, addr+i, |
613 __x86_indirect_jump_thunk_array[reg], | 614 jmp_dest, |
614 JMP32_INSN_SIZE); 615 i += JMP32_INSN_SIZE; 616 break; 617 618 default: 619 WARN(1, "%pS %px %*ph\n", addr, addr, 6, addr); 620 return -1; 621 } 622 623 WARN_ON_ONCE(i != insn->length); 624 625 return i; 626} 627 | 615 JMP32_INSN_SIZE); 616 i += JMP32_INSN_SIZE; 617 break; 618 619 default: 620 WARN(1, "%pS %px %*ph\n", addr, addr, 6, addr); 621 return -1; 622 } 623 624 WARN_ON_ONCE(i != insn->length); 625 626 return i; 627} 628 |
629static int emit_call_track_retpoline(void *addr, struct insn *insn, int reg, u8 *bytes) 630{ 631 return __emit_trampoline(addr, insn, bytes, 632 __x86_indirect_call_thunk_array[reg], 633 __x86_indirect_jump_thunk_array[reg]); 634} 635 636#ifdef CONFIG_MITIGATION_ITS 637static int emit_its_trampoline(void *addr, struct insn *insn, int reg, u8 *bytes) 638{ 639 return __emit_trampoline(addr, insn, bytes, 640 __x86_indirect_its_thunk_array[reg], 641 __x86_indirect_its_thunk_array[reg]); 642} 643 644/* Check if an indirect branch is at ITS-unsafe address */ 645static bool cpu_wants_indirect_its_thunk_at(unsigned long addr, int reg) 646{ 647 if (!cpu_feature_enabled(X86_FEATURE_INDIRECT_THUNK_ITS)) 648 return false; 649 650 /* Indirect branch opcode is 2 or 3 bytes depending on reg */ 651 addr += 1 + reg / 8; 652 653 /* Lower-half of the cacheline? */ 654 return !(addr & 0x20); 655} 656#endif 657 |
|
628/* 629 * Rewrite the compiler generated retpoline thunk calls. 630 * 631 * For spectre_v2=off (!X86_FEATURE_RETPOLINE), rewrite them into immediate 632 * indirect instructions, avoiding the extra indirection. 633 * 634 * For example, convert: 635 * --- 58 unchanged lines hidden (view full) --- 694 * For RETPOLINE_LFENCE: prepend the indirect CALL/JMP with an LFENCE. 695 */ 696 if (cpu_feature_enabled(X86_FEATURE_RETPOLINE_LFENCE)) { 697 bytes[i++] = 0x0f; 698 bytes[i++] = 0xae; 699 bytes[i++] = 0xe8; /* LFENCE */ 700 } 701 | 658/* 659 * Rewrite the compiler generated retpoline thunk calls. 660 * 661 * For spectre_v2=off (!X86_FEATURE_RETPOLINE), rewrite them into immediate 662 * indirect instructions, avoiding the extra indirection. 663 * 664 * For example, convert: 665 * --- 58 unchanged lines hidden (view full) --- 724 * For RETPOLINE_LFENCE: prepend the indirect CALL/JMP with an LFENCE. 725 */ 726 if (cpu_feature_enabled(X86_FEATURE_RETPOLINE_LFENCE)) { 727 bytes[i++] = 0x0f; 728 bytes[i++] = 0xae; 729 bytes[i++] = 0xe8; /* LFENCE */ 730 } 731 |
732#ifdef CONFIG_MITIGATION_ITS 733 /* 734 * Check if the address of last byte of emitted-indirect is in 735 * lower-half of the cacheline. Such branches need ITS mitigation. 736 */ 737 if (cpu_wants_indirect_its_thunk_at((unsigned long)addr + i, reg)) 738 return emit_its_trampoline(addr, insn, reg, bytes); 739#endif 740 |
|
702 ret = emit_indirect(op, reg, bytes + i); 703 if (ret < 0) 704 return ret; 705 i += ret; 706 707 /* 708 * The compiler is supposed to EMIT an INT3 after every unconditional 709 * JMP instruction due to AMD BTC. However, if the compiler is too old --- 2184 unchanged lines hidden --- | 741 ret = emit_indirect(op, reg, bytes + i); 742 if (ret < 0) 743 return ret; 744 i += ret; 745 746 /* 747 * The compiler is supposed to EMIT an INT3 after every unconditional 748 * JMP instruction due to AMD BTC. However, if the compiler is too old --- 2184 unchanged lines hidden --- |