aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-06-30 14:42:14 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-06-30 14:42:14 -0400
commit0fbc4aeabc91f2e39e0dffebe8f81a0eb3648d97 (patch)
tree4ffb5ea64600b09df6331083a9c68ae589096f76 /tools
parentd7d5388679312b7a7b6377e38e2b8fb06a82d84e (diff)
parentd79d0d8ad0cb3d782b41631dfeac8eb05e414bcd (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.c59
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 }