Linus,

please pull the latest x86-urgent-for-linus git tree from:

   git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git 
x86-urgent-for-linus

A series of fixes for X86:

 - The final fix for the end-of-stack issue in the unwinder
 - Handle non PAT systems gracefully
 - Prevent access to uninitiliazed memory
 - Move early delay calaibration after basic init
 - Fix Kconfig help text
 - Fix a cross compile issue
 - Unbreak older make versions

Thanks,

        tglx

------------------>
Benjamin Peterson (1):
      x86/watchdog: Fix Kconfig help text file path reference to lockup 
watchdog documentation

Jan Kiszka (2):
      x86/build: Permit building with old make versions
      x86/timers: Move simple_udelay_calibration past init_hypervisor_platform

Josh Poimboeuf (2):
      Revert "x86/entry: Fix the end of the stack for newly forked tasks"
      x86/unwind: Add end-of-stack check for ftrace handlers

Mateusz Jurczyk (1):
      x86/alternatives: Prevent uninitialized stack byte read in 
apply_alternatives()

Mikulas Patocka (1):
      x86/PAT: Fix Xorg regression on CPUs that don't support PAT

Rob Landley (1):
      x86/boot: Use CROSS_COMPILE prefix for readelf


 arch/x86/Kconfig                  |  2 +-
 arch/x86/Makefile                 |  2 +-
 arch/x86/boot/compressed/Makefile |  2 +-
 arch/x86/entry/entry_32.S         | 30 +++++++++++++++---------
 arch/x86/entry/entry_64.S         | 11 ++++-----
 arch/x86/kernel/alternative.c     |  9 +++++--
 arch/x86/kernel/setup.c           |  4 ++--
 arch/x86/kernel/unwind_frame.c    | 49 ++++++++++++++++++++++++++++++++-------
 arch/x86/mm/pat.c                 |  9 ++++---
 9 files changed, 81 insertions(+), 37 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index cd18994a9555..4ccfacc7232a 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -360,7 +360,7 @@ config SMP
          Management" code will be disabled if you say Y here.
 
          See also <file:Documentation/x86/i386/IO-APIC.txt>,
-         <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
+         <file:Documentation/lockup-watchdogs.txt> and the SMP-HOWTO available 
at
          <http://www.tldp.org/docs.html#howto>.
 
          If you don't know what to do here, say N.
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 5851411e60fb..bf240b920473 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -159,7 +159,7 @@ ifdef CONFIG_FUNCTION_GRAPH_TRACER
        # If '-Os' is enabled, disable it and print a warning.
         ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
           undefine CONFIG_CC_OPTIMIZE_FOR_SIZE
-         $(warning Disabling CONFIG_CC_OPTIMIZE_FOR_SIZE.  Your compiler does 
not have -mfentry so you cannot optimize for size with 
CONFIG_FUNCTION_GRAPH_TRACER.)
+          $(warning Disabling CONFIG_CC_OPTIMIZE_FOR_SIZE.  Your compiler does 
not have -mfentry so you cannot optimize for size with 
CONFIG_FUNCTION_GRAPH_TRACER.)
         endif
 
     endif
diff --git a/arch/x86/boot/compressed/Makefile 
b/arch/x86/boot/compressed/Makefile
index 44163e8c3868..2c860ad4fe06 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -94,7 +94,7 @@ vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_thunk_$(BITS).o
 quiet_cmd_check_data_rel = DATAREL $@
 define cmd_check_data_rel
        for obj in $(filter %.o,$^); do \
-               readelf -S $$obj | grep -qF .rel.local && { \
+               ${CROSS_COMPILE}readelf -S $$obj | grep -qF .rel.local && { \
                        echo "error: $$obj has data relocations!" >&2; \
                        exit 1; \
                } || true; \
diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S
index 50bc26949e9e..48ef7bb32c42 100644
--- a/arch/x86/entry/entry_32.S
+++ b/arch/x86/entry/entry_32.S
@@ -252,6 +252,23 @@ ENTRY(__switch_to_asm)
 END(__switch_to_asm)
 
 /*
+ * The unwinder expects the last frame on the stack to always be at the same
+ * offset from the end of the page, which allows it to validate the stack.
+ * Calling schedule_tail() directly would break that convention because its an
+ * asmlinkage function so its argument has to be pushed on the stack.  This
+ * wrapper creates a proper "end of stack" frame header before the call.
+ */
+ENTRY(schedule_tail_wrapper)
+       FRAME_BEGIN
+
+       pushl   %eax
+       call    schedule_tail
+       popl    %eax
+
+       FRAME_END
+       ret
+ENDPROC(schedule_tail_wrapper)
+/*
  * A newly forked process directly context switches into this address.
  *
  * eax: prev task we switched from
@@ -259,24 +276,15 @@ END(__switch_to_asm)
  * edi: kernel thread arg
  */
 ENTRY(ret_from_fork)
-       FRAME_BEGIN             /* help unwinder find end of stack */
-
-       /*
-        * schedule_tail() is asmlinkage so we have to put its 'prev' argument
-        * on the stack.
-        */
-       pushl   %eax
-       call    schedule_tail
-       popl    %eax
+       call    schedule_tail_wrapper
 
        testl   %ebx, %ebx
        jnz     1f              /* kernel threads are uncommon */
 
 2:
        /* When we fork, we trace the syscall return in the child, too. */
-       leal    FRAME_OFFSET(%esp), %eax
+       movl    %esp, %eax
        call    syscall_return_slowpath
-       FRAME_END
        jmp     restore_all
 
        /* kernel thread */
diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
index 607d72c4a485..4a4c0834f965 100644
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -36,7 +36,6 @@
 #include <asm/smap.h>
 #include <asm/pgtable_types.h>
 #include <asm/export.h>
-#include <asm/frame.h>
 #include <linux/err.h>
 
 .code64
@@ -406,19 +405,17 @@ END(__switch_to_asm)
  * r12: kernel thread arg
  */
 ENTRY(ret_from_fork)
-       FRAME_BEGIN                     /* help unwinder find end of stack */
        movq    %rax, %rdi
-       call    schedule_tail           /* rdi: 'prev' task parameter */
+       call    schedule_tail                   /* rdi: 'prev' task parameter */
 
-       testq   %rbx, %rbx              /* from kernel_thread? */
-       jnz     1f                      /* kernel threads are uncommon */
+       testq   %rbx, %rbx                      /* from kernel_thread? */
+       jnz     1f                              /* kernel threads are uncommon 
*/
 
 2:
-       leaq    FRAME_OFFSET(%rsp),%rdi /* pt_regs pointer */
+       movq    %rsp, %rdi
        call    syscall_return_slowpath /* returns with IRQs disabled */
        TRACE_IRQS_ON                   /* user mode is traced as IRQS on */
        SWAPGS
-       FRAME_END
        jmp     restore_regs_and_iret
 
 1:
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index c5b8f760473c..32e14d137416 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -409,8 +409,13 @@ void __init_or_module noinline apply_alternatives(struct 
alt_instr *start,
                memcpy(insnbuf, replacement, a->replacementlen);
                insnbuf_sz = a->replacementlen;
 
-               /* 0xe8 is a relative jump; fix the offset. */
-               if (*insnbuf == 0xe8 && a->replacementlen == 5) {
+               /*
+                * 0xe8 is a relative jump; fix the offset.
+                *
+                * Instruction length is checked before the opcode to avoid
+                * accessing uninitialized bytes for zero-length replacements.
+                */
+               if (a->replacementlen == 5 && *insnbuf == 0xe8) {
                        *(s32 *)(insnbuf + 1) += replacement - instr;
                        DPRINTK("Fix CALL offset: 0x%x, CALL 0x%lx",
                                *(s32 *)(insnbuf + 1),
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 0b4d3c686b1e..f81823695014 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -980,8 +980,6 @@ void __init setup_arch(char **cmdline_p)
         */
        x86_configure_nx();
 
-       simple_udelay_calibration();
-
        parse_early_param();
 
 #ifdef CONFIG_MEMORY_HOTPLUG
@@ -1041,6 +1039,8 @@ void __init setup_arch(char **cmdline_p)
         */
        init_hypervisor_platform();
 
+       simple_udelay_calibration();
+
        x86_init.resources.probe_roms();
 
        /* after parse_early_param, so could debug it */
diff --git a/arch/x86/kernel/unwind_frame.c b/arch/x86/kernel/unwind_frame.c
index 82c6d7f1fd73..b9389d72b2f7 100644
--- a/arch/x86/kernel/unwind_frame.c
+++ b/arch/x86/kernel/unwind_frame.c
@@ -104,6 +104,11 @@ static inline unsigned long *last_frame(struct 
unwind_state *state)
        return (unsigned long *)task_pt_regs(state->task) - 2;
 }
 
+static bool is_last_frame(struct unwind_state *state)
+{
+       return state->bp == last_frame(state);
+}
+
 #ifdef CONFIG_X86_32
 #define GCC_REALIGN_WORDS 3
 #else
@@ -115,16 +120,15 @@ static inline unsigned long *last_aligned_frame(struct 
unwind_state *state)
        return last_frame(state) - GCC_REALIGN_WORDS;
 }
 
-static bool is_last_task_frame(struct unwind_state *state)
+static bool is_last_aligned_frame(struct unwind_state *state)
 {
        unsigned long *last_bp = last_frame(state);
        unsigned long *aligned_bp = last_aligned_frame(state);
 
        /*
-        * We have to check for the last task frame at two different locations
-        * because gcc can occasionally decide to realign the stack pointer and
-        * change the offset of the stack frame in the prologue of a function
-        * called by head/entry code.  Examples:
+        * GCC can occasionally decide to realign the stack pointer and change
+        * the offset of the stack frame in the prologue of a function called
+        * by head/entry code.  Examples:
         *
         * <start_secondary>:
         *      push   %edi
@@ -141,11 +145,38 @@ static bool is_last_task_frame(struct unwind_state *state)
         *      push   %rbp
         *      mov    %rsp,%rbp
         *
-        * Note that after aligning the stack, it pushes a duplicate copy of
-        * the return address before pushing the frame pointer.
+        * After aligning the stack, it pushes a duplicate copy of the return
+        * address before pushing the frame pointer.
+        */
+       return (state->bp == aligned_bp && *(aligned_bp + 1) == *(last_bp + 1));
+}
+
+static bool is_last_ftrace_frame(struct unwind_state *state)
+{
+       unsigned long *last_bp = last_frame(state);
+       unsigned long *last_ftrace_bp = last_bp - 3;
+
+       /*
+        * When unwinding from an ftrace handler of a function called by entry
+        * code, the stack layout of the last frame is:
+        *
+        *   bp
+        *   parent ret addr
+        *   bp
+        *   function ret addr
+        *   parent ret addr
+        *   pt_regs
+        *   -----------------
         */
-       return (state->bp == last_bp ||
-               (state->bp == aligned_bp && *(aligned_bp+1) == *(last_bp+1)));
+       return (state->bp == last_ftrace_bp &&
+               *state->bp == *(state->bp + 2) &&
+               *(state->bp + 1) == *(state->bp + 4));
+}
+
+static bool is_last_task_frame(struct unwind_state *state)
+{
+       return is_last_frame(state) || is_last_aligned_frame(state) ||
+              is_last_ftrace_frame(state);
 }
 
 /*
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index 9b78685b66e6..83a59a67757a 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -65,9 +65,11 @@ static int __init nopat(char *str)
 }
 early_param("nopat", nopat);
 
+static bool __read_mostly __pat_initialized = false;
+
 bool pat_enabled(void)
 {
-       return !!__pat_enabled;
+       return __pat_initialized;
 }
 EXPORT_SYMBOL_GPL(pat_enabled);
 
@@ -225,13 +227,14 @@ static void pat_bsp_init(u64 pat)
        }
 
        wrmsrl(MSR_IA32_CR_PAT, pat);
+       __pat_initialized = true;
 
        __init_cache_modes(pat);
 }
 
 static void pat_ap_init(u64 pat)
 {
-       if (!boot_cpu_has(X86_FEATURE_PAT)) {
+       if (!this_cpu_has(X86_FEATURE_PAT)) {
                /*
                 * If this happens we are on a secondary CPU, but switched to
                 * PAT on the boot CPU. We have no way to undo PAT.
@@ -306,7 +309,7 @@ void pat_init(void)
        u64 pat;
        struct cpuinfo_x86 *c = &boot_cpu_data;
 
-       if (!pat_enabled()) {
+       if (!__pat_enabled) {
                init_cache_modes();
                return;
        }

Reply via email to