aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-09-24 15:33:58 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-09-24 15:33:58 -0400
commita141fd55f26231b5a17f74e504c56d44c3e62e5d (patch)
tree5859552ca39fec7b0808794889d03dff2106c145 /tools
parent16528a3fed5de9228de0dd7a9a4de3f3eb4c982a (diff)
parentf5caf621ee357279e759c0911daf6d55c7d36f03 (diff)
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fixes from Ingo Molnar: "Another round of CR3/PCID related fixes (I think this addresses all but one of the known problems with PCID support), an objtool fix plus a Clang fix that (finally) solves all Clang quirks to build a bootable x86 kernel as-is" * 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/asm: Fix inline asm call constraints for Clang objtool: Handle another GCC stack pointer adjustment bug x86/mm/32: Load a sane CR3 before cpu_init() on secondary CPUs x86/mm/32: Move setup_clear_cpu_cap(X86_FEATURE_PCID) earlier x86/mm/64: Stop using CR3.PCID == 0 in ASID-aware code x86/mm: Factor out CR3-building code
Diffstat (limited to 'tools')
-rw-r--r--tools/objtool/Documentation/stack-validation.txt6
-rw-r--r--tools/objtool/arch/x86/decode.c6
-rw-r--r--tools/objtool/check.c43
3 files changed, 35 insertions, 20 deletions
diff --git a/tools/objtool/Documentation/stack-validation.txt b/tools/objtool/Documentation/stack-validation.txt
index 6a1af43862df..3995735a878f 100644
--- a/tools/objtool/Documentation/stack-validation.txt
+++ b/tools/objtool/Documentation/stack-validation.txt
@@ -194,10 +194,10 @@ they mean, and suggestions for how to fix them.
194 If it's a GCC-compiled .c file, the error may be because the function 194 If it's a GCC-compiled .c file, the error may be because the function
195 uses an inline asm() statement which has a "call" instruction. An 195 uses an inline asm() statement which has a "call" instruction. An
196 asm() statement with a call instruction must declare the use of the 196 asm() statement with a call instruction must declare the use of the
197 stack pointer in its output operand. For example, on x86_64: 197 stack pointer in its output operand. On x86_64, this means adding
198 the ASM_CALL_CONSTRAINT as an output constraint:
198 199
199 register void *__sp asm("rsp"); 200 asm volatile("call func" : ASM_CALL_CONSTRAINT);
200 asm volatile("call func" : "+r" (__sp));
201 201
202 Otherwise the stack frame may not get created before the call. 202 Otherwise the stack frame may not get created before the call.
203 203
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index 0e8c8ec4fd4e..0f22768c0d4d 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -208,14 +208,14 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
208 break; 208 break;
209 209
210 case 0x89: 210 case 0x89:
211 if (rex == 0x48 && modrm == 0xe5) { 211 if (rex_w && !rex_r && modrm_mod == 3 && modrm_reg == 4) {
212 212
213 /* mov %rsp, %rbp */ 213 /* mov %rsp, reg */
214 *type = INSN_STACK; 214 *type = INSN_STACK;
215 op->src.type = OP_SRC_REG; 215 op->src.type = OP_SRC_REG;
216 op->src.reg = CFI_SP; 216 op->src.reg = CFI_SP;
217 op->dest.type = OP_DEST_REG; 217 op->dest.type = OP_DEST_REG;
218 op->dest.reg = CFI_BP; 218 op->dest.reg = op_to_cfi_reg[modrm_rm][rex_b];
219 break; 219 break;
220 } 220 }
221 221
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index f744617c9946..a0c518ecf085 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1203,24 +1203,39 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state)
1203 switch (op->src.type) { 1203 switch (op->src.type) {
1204 1204
1205 case OP_SRC_REG: 1205 case OP_SRC_REG:
1206 if (op->src.reg == CFI_SP && op->dest.reg == CFI_BP) { 1206 if (op->src.reg == CFI_SP && op->dest.reg == CFI_BP &&
1207 cfa->base == CFI_SP &&
1208 regs[CFI_BP].base == CFI_CFA &&
1209 regs[CFI_BP].offset == -cfa->offset) {
1210
1211 /* mov %rsp, %rbp */
1212 cfa->base = op->dest.reg;
1213 state->bp_scratch = false;
1214 }
1207 1215
1208 if (cfa->base == CFI_SP && 1216 else if (op->src.reg == CFI_SP &&
1209 regs[CFI_BP].base == CFI_CFA && 1217 op->dest.reg == CFI_BP && state->drap) {
1210 regs[CFI_BP].offset == -cfa->offset) {
1211 1218
1212 /* mov %rsp, %rbp */ 1219 /* drap: mov %rsp, %rbp */
1213 cfa->base = op->dest.reg; 1220 regs[CFI_BP].base = CFI_BP;
1214 state->bp_scratch = false; 1221 regs[CFI_BP].offset = -state->stack_size;
1215 } 1222 state->bp_scratch = false;
1223 }
1216 1224
1217 else if (state->drap) { 1225 else if (op->src.reg == CFI_SP && cfa->base == CFI_SP) {
1218 1226
1219 /* drap: mov %rsp, %rbp */ 1227 /*
1220 regs[CFI_BP].base = CFI_BP; 1228 * mov %rsp, %reg
1221 regs[CFI_BP].offset = -state->stack_size; 1229 *
1222 state->bp_scratch = false; 1230 * This is needed for the rare case where GCC
1223 } 1231 * does:
1232 *
1233 * mov %rsp, %rax
1234 * ...
1235 * mov %rax, %rsp
1236 */
1237 state->vals[op->dest.reg].base = CFI_CFA;
1238 state->vals[op->dest.reg].offset = -state->stack_size;
1224 } 1239 }
1225 1240
1226 else if (op->dest.reg == cfa->base) { 1241 else if (op->dest.reg == cfa->base) {