diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-24 15:33:58 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-24 15:33:58 -0400 |
commit | a141fd55f26231b5a17f74e504c56d44c3e62e5d (patch) | |
tree | 5859552ca39fec7b0808794889d03dff2106c145 /tools | |
parent | 16528a3fed5de9228de0dd7a9a4de3f3eb4c982a (diff) | |
parent | f5caf621ee357279e759c0911daf6d55c7d36f03 (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.txt | 6 | ||||
-rw-r--r-- | tools/objtool/arch/x86/decode.c | 6 | ||||
-rw-r--r-- | tools/objtool/check.c | 43 |
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) { |