diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-30 14:42:14 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-30 14:42:14 -0400 |
commit | 0fbc4aeabc91f2e39e0dffebe8f81a0eb3648d97 (patch) | |
tree | 4ffb5ea64600b09df6331083a9c68ae589096f76 /tools | |
parent | d7d5388679312b7a7b6377e38e2b8fb06a82d84e (diff) | |
parent | d79d0d8ad0cb3d782b41631dfeac8eb05e414bcd (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:
"The biggest diffstat comes from self-test updates, plus there's entry
code fixes, 5-level paging related fixes, console debug output fixes,
and misc fixes"
* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/mm: Clean up the printk()s in show_fault_oops()
x86/mm: Drop unneeded __always_inline for p4d page table helpers
x86/efi: Fix efi_call_phys_epilog() with CONFIG_X86_5LEVEL=y
selftests/x86/sigreturn: Do minor cleanups
selftests/x86/sigreturn/64: Fix spurious failures on AMD CPUs
x86/entry/64/compat: Fix "x86/entry/64/compat: Preserve r8-r11 in int $0x80"
x86/mm: Don't free P4D table when it is folded at runtime
x86/entry/32: Add explicit 'l' instruction suffix
x86/mm: Get rid of KERN_CONT in show_fault_oops()
Diffstat (limited to 'tools')
-rw-r--r-- | tools/testing/selftests/x86/sigreturn.c | 59 |
1 files changed, 36 insertions, 23 deletions
diff --git a/tools/testing/selftests/x86/sigreturn.c b/tools/testing/selftests/x86/sigreturn.c index 246145b84a12..4d9dc3f2fd70 100644 --- a/tools/testing/selftests/x86/sigreturn.c +++ b/tools/testing/selftests/x86/sigreturn.c | |||
@@ -610,21 +610,41 @@ static int test_valid_sigreturn(int cs_bits, bool use_16bit_ss, int force_ss) | |||
610 | */ | 610 | */ |
611 | for (int i = 0; i < NGREG; i++) { | 611 | for (int i = 0; i < NGREG; i++) { |
612 | greg_t req = requested_regs[i], res = resulting_regs[i]; | 612 | greg_t req = requested_regs[i], res = resulting_regs[i]; |
613 | |||
613 | if (i == REG_TRAPNO || i == REG_IP) | 614 | if (i == REG_TRAPNO || i == REG_IP) |
614 | continue; /* don't care */ | 615 | continue; /* don't care */ |
615 | if (i == REG_SP) { | ||
616 | printf("\tSP: %llx -> %llx\n", (unsigned long long)req, | ||
617 | (unsigned long long)res); | ||
618 | 616 | ||
617 | if (i == REG_SP) { | ||
619 | /* | 618 | /* |
620 | * In many circumstances, the high 32 bits of rsp | 619 | * If we were using a 16-bit stack segment, then |
621 | * are zeroed. For example, we could be a real | 620 | * the kernel is a bit stuck: IRET only restores |
622 | * 32-bit program, or we could hit any of a number | 621 | * the low 16 bits of ESP/RSP if SS is 16-bit. |
623 | * of poorly-documented IRET or segmented ESP | 622 | * The kernel uses a hack to restore bits 31:16, |
624 | * oddities. If this happens, it's okay. | 623 | * but that hack doesn't help with bits 63:32. |
624 | * On Intel CPUs, bits 63:32 end up zeroed, and, on | ||
625 | * AMD CPUs, they leak the high bits of the kernel | ||
626 | * espfix64 stack pointer. There's very little that | ||
627 | * the kernel can do about it. | ||
628 | * | ||
629 | * Similarly, if we are returning to a 32-bit context, | ||
630 | * the CPU will often lose the high 32 bits of RSP. | ||
625 | */ | 631 | */ |
626 | if (res == (req & 0xFFFFFFFF)) | 632 | |
627 | continue; /* OK; not expected to work */ | 633 | if (res == req) |
634 | continue; | ||
635 | |||
636 | if (cs_bits != 64 && ((res ^ req) & 0xFFFFFFFF) == 0) { | ||
637 | printf("[NOTE]\tSP: %llx -> %llx\n", | ||
638 | (unsigned long long)req, | ||
639 | (unsigned long long)res); | ||
640 | continue; | ||
641 | } | ||
642 | |||
643 | printf("[FAIL]\tSP mismatch: requested 0x%llx; got 0x%llx\n", | ||
644 | (unsigned long long)requested_regs[i], | ||
645 | (unsigned long long)resulting_regs[i]); | ||
646 | nerrs++; | ||
647 | continue; | ||
628 | } | 648 | } |
629 | 649 | ||
630 | bool ignore_reg = false; | 650 | bool ignore_reg = false; |
@@ -654,25 +674,18 @@ static int test_valid_sigreturn(int cs_bits, bool use_16bit_ss, int force_ss) | |||
654 | #endif | 674 | #endif |
655 | 675 | ||
656 | /* Sanity check on the kernel */ | 676 | /* Sanity check on the kernel */ |
657 | if (i == REG_CX && requested_regs[i] != resulting_regs[i]) { | 677 | if (i == REG_CX && req != res) { |
658 | printf("[FAIL]\tCX (saved SP) mismatch: requested 0x%llx; got 0x%llx\n", | 678 | printf("[FAIL]\tCX (saved SP) mismatch: requested 0x%llx; got 0x%llx\n", |
659 | (unsigned long long)requested_regs[i], | 679 | (unsigned long long)req, |
660 | (unsigned long long)resulting_regs[i]); | 680 | (unsigned long long)res); |
661 | nerrs++; | 681 | nerrs++; |
662 | continue; | 682 | continue; |
663 | } | 683 | } |
664 | 684 | ||
665 | if (requested_regs[i] != resulting_regs[i] && !ignore_reg) { | 685 | if (req != res && !ignore_reg) { |
666 | /* | ||
667 | * SP is particularly interesting here. The | ||
668 | * usual cause of failures is that we hit the | ||
669 | * nasty IRET case of returning to a 16-bit SS, | ||
670 | * in which case bits 16:31 of the *kernel* | ||
671 | * stack pointer persist in ESP. | ||
672 | */ | ||
673 | printf("[FAIL]\tReg %d mismatch: requested 0x%llx; got 0x%llx\n", | 686 | printf("[FAIL]\tReg %d mismatch: requested 0x%llx; got 0x%llx\n", |
674 | i, (unsigned long long)requested_regs[i], | 687 | i, (unsigned long long)req, |
675 | (unsigned long long)resulting_regs[i]); | 688 | (unsigned long long)res); |
676 | nerrs++; | 689 | nerrs++; |
677 | } | 690 | } |
678 | } | 691 | } |