Merge branch 'x86-asm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 5 Dec 2009 23:32:03 +0000 (15:32 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 5 Dec 2009 23:32:03 +0000 (15:32 -0800)
* 'x86-asm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  include/linux/compiler-gcc4.h: Fix build bug - gcc-4.0.2 doesn't understand __builtin_object_size
  x86/alternatives: No need for alternatives-asm.h to re-invent stuff already in asm.h
  x86/alternatives: Check replacementlen <= instrlen at build time
  x86, 64-bit: Set data segments to null after switching to 64-bit mode
  x86: Clean up the loadsegment() macro
  x86: Optimize loadsegment()
  x86: Add missing might_fault() checks to copy_{to,from}_user()
  x86-64: __copy_from_user_inatomic() adjustments
  x86: Remove unused thread_return label from switch_to()
  x86, 64-bit: Fix bstep_iret jump
  x86: Don't use the strict copy checks when branch profiling is in use
  x86, 64-bit: Move K8 B step iret fixup to fault entry asm
  x86: Generate cmpxchg build failures
  x86: Add a Kconfig option to turn the copy_from_user warnings into errors
  x86: Turn the copy_from_user check into an (optional) compile time warning
  x86: Use __builtin_memset and __builtin_memcpy for memset/memcpy
  x86: Use __builtin_object_size() to validate the buffer size for copy_from_user()

1  2 
arch/x86/Kconfig.debug
arch/x86/include/asm/cmpxchg_32.h
arch/x86/kernel/entry_64.S
arch/x86/kernel/head_64.S
include/linux/compiler-gcc4.h
include/linux/compiler.h

diff --combined arch/x86/Kconfig.debug
@@@ -186,15 -186,6 +186,15 @@@ config X86_DS_SELFTES
  config HAVE_MMIOTRACE_SUPPORT
        def_bool y
  
 +config X86_DECODER_SELFTEST
 +     bool "x86 instruction decoder selftest"
 +     depends on DEBUG_KERNEL
 +      ---help---
 +       Perform x86 instruction decoder selftests at build time.
 +       This option is useful for checking the sanity of x86 instruction
 +       decoder code.
 +       If unsure, say "N".
 +
  #
  # IO delay types:
  #
@@@ -296,4 -287,18 +296,18 @@@ config OPTIMIZE_INLININ
  
          If unsure, say N.
  
+ config DEBUG_STRICT_USER_COPY_CHECKS
+       bool "Strict copy size checks"
+       depends on DEBUG_KERNEL && !TRACE_BRANCH_PROFILING
+       ---help---
+         Enabling this option turns a certain set of sanity checks for user
+         copy operations into compile time failures.
+         The copy_from_user() etc checks are there to help test if there
+         are sufficient security checks on the length argument of
+         the copy operation, by having gcc prove that the argument is
+         within bounds.
+         If unsure, or if you run an older (pre 4.4) gcc, say N.
  endmenu
@@@ -8,14 -8,50 +8,50 @@@
   *       you need to test for the feature in boot_cpu_data.
   */
  
- #define xchg(ptr, v)                                                  \
-       ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), sizeof(*(ptr))))
+ extern void __xchg_wrong_size(void);
+ /*
+  * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
+  * Note 2: xchg has side effect, so that attribute volatile is necessary,
+  *      but generally the primitive is invalid, *ptr is output argument. --ANK
+  */
  
  struct __xchg_dummy {
        unsigned long a[100];
  };
  #define __xg(x) ((struct __xchg_dummy *)(x))
  
+ #define __xchg(x, ptr, size)                                          \
+ ({                                                                    \
+       __typeof(*(ptr)) __x = (x);                                     \
+       switch (size) {                                                 \
+       case 1:                                                         \
+               asm volatile("xchgb %b0,%1"                             \
+                            : "=q" (__x)                               \
+                            : "m" (*__xg(ptr)), "0" (__x)              \
+                            : "memory");                               \
+               break;                                                  \
+       case 2:                                                         \
+               asm volatile("xchgw %w0,%1"                             \
+                            : "=r" (__x)                               \
+                            : "m" (*__xg(ptr)), "0" (__x)              \
+                            : "memory");                               \
+               break;                                                  \
+       case 4:                                                         \
+               asm volatile("xchgl %0,%1"                              \
+                            : "=r" (__x)                               \
+                            : "m" (*__xg(ptr)), "0" (__x)              \
+                            : "memory");                               \
+               break;                                                  \
+       default:                                                        \
+               __xchg_wrong_size();                                    \
+       }                                                               \
+       __x;                                                            \
+ })
+ #define xchg(ptr, v)                                                  \
+       __xchg((v), (ptr), sizeof(*ptr))
  /*
   * The semantics of XCHGCMP8B are a bit strange, this is why
   * there is a loop and the loading of %%eax and %%edx has to
@@@ -71,57 -107,63 +107,63 @@@ static inline void __set_64bit_var(unsi
                       (unsigned int)((value) >> 32))                   \
         : __set_64bit(ptr, ll_low((value)), ll_high((value))))
  
- /*
-  * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
-  * Note 2: xchg has side effect, so that attribute volatile is necessary,
-  *      but generally the primitive is invalid, *ptr is output argument. --ANK
-  */
- static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
-                                  int size)
- {
-       switch (size) {
-       case 1:
-               asm volatile("xchgb %b0,%1"
-                            : "=q" (x)
-                            : "m" (*__xg(ptr)), "0" (x)
-                            : "memory");
-               break;
-       case 2:
-               asm volatile("xchgw %w0,%1"
-                            : "=r" (x)
-                            : "m" (*__xg(ptr)), "0" (x)
-                            : "memory");
-               break;
-       case 4:
-               asm volatile("xchgl %0,%1"
-                            : "=r" (x)
-                            : "m" (*__xg(ptr)), "0" (x)
-                            : "memory");
-               break;
-       }
-       return x;
- }
+ extern void __cmpxchg_wrong_size(void);
  
  /*
   * Atomic compare and exchange.  Compare OLD with MEM, if identical,
   * store NEW in MEM.  Return the initial value in MEM.  Success is
   * indicated by comparing RETURN with OLD.
   */
+ #define __raw_cmpxchg(ptr, old, new, size, lock)                      \
+ ({                                                                    \
+       __typeof__(*(ptr)) __ret;                                       \
+       __typeof__(*(ptr)) __old = (old);                               \
+       __typeof__(*(ptr)) __new = (new);                               \
+       switch (size) {                                                 \
+       case 1:                                                         \
+               asm volatile(lock "cmpxchgb %b1,%2"                     \
+                            : "=a"(__ret)                              \
+                            : "q"(__new), "m"(*__xg(ptr)), "0"(__old)  \
+                            : "memory");                               \
+               break;                                                  \
+       case 2:                                                         \
+               asm volatile(lock "cmpxchgw %w1,%2"                     \
+                            : "=a"(__ret)                              \
+                            : "r"(__new), "m"(*__xg(ptr)), "0"(__old)  \
+                            : "memory");                               \
+               break;                                                  \
+       case 4:                                                         \
+               asm volatile(lock "cmpxchgl %1,%2"                      \
+                            : "=a"(__ret)                              \
+                            : "r"(__new), "m"(*__xg(ptr)), "0"(__old)  \
+                            : "memory");                               \
+               break;                                                  \
+       default:                                                        \
+               __cmpxchg_wrong_size();                                 \
+       }                                                               \
+       __ret;                                                          \
+ })
+ #define __cmpxchg(ptr, old, new, size)                                        \
+       __raw_cmpxchg((ptr), (old), (new), (size), LOCK_PREFIX)
+ #define __sync_cmpxchg(ptr, old, new, size)                           \
+       __raw_cmpxchg((ptr), (old), (new), (size), "lock; ")
+ #define __cmpxchg_local(ptr, old, new, size)                          \
+       __raw_cmpxchg((ptr), (old), (new), (size), "")
  
  #ifdef CONFIG_X86_CMPXCHG
  #define __HAVE_ARCH_CMPXCHG 1
- #define cmpxchg(ptr, o, n)                                            \
-       ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o),       \
-                                      (unsigned long)(n),              \
-                                      sizeof(*(ptr))))
- #define sync_cmpxchg(ptr, o, n)                                               \
-       ((__typeof__(*(ptr)))__sync_cmpxchg((ptr), (unsigned long)(o),  \
-                                           (unsigned long)(n),         \
-                                           sizeof(*(ptr))))
- #define cmpxchg_local(ptr, o, n)                                      \
-       ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \
-                                            (unsigned long)(n),        \
-                                            sizeof(*(ptr))))
+ #define cmpxchg(ptr, old, new)                                                \
+       __cmpxchg((ptr), (old), (new), sizeof(*ptr))
+ #define sync_cmpxchg(ptr, old, new)                                   \
+       __sync_cmpxchg((ptr), (old), (new), sizeof(*ptr))
+ #define cmpxchg_local(ptr, old, new)                                  \
+       __cmpxchg_local((ptr), (old), (new), sizeof(*ptr))
  #endif
  
  #ifdef CONFIG_X86_CMPXCHG64
                                               (unsigned long long)(n)))
  #endif
  
- static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
-                                     unsigned long new, int size)
- {
-       unsigned long prev;
-       switch (size) {
-       case 1:
-               asm volatile(LOCK_PREFIX "cmpxchgb %b1,%2"
-                            : "=a"(prev)
-                            : "q"(new), "m"(*__xg(ptr)), "0"(old)
-                            : "memory");
-               return prev;
-       case 2:
-               asm volatile(LOCK_PREFIX "cmpxchgw %w1,%2"
-                            : "=a"(prev)
-                            : "r"(new), "m"(*__xg(ptr)), "0"(old)
-                            : "memory");
-               return prev;
-       case 4:
-               asm volatile(LOCK_PREFIX "cmpxchgl %1,%2"
-                            : "=a"(prev)
-                            : "r"(new), "m"(*__xg(ptr)), "0"(old)
-                            : "memory");
-               return prev;
-       }
-       return old;
- }
- /*
-  * Always use locked operations when touching memory shared with a
-  * hypervisor, since the system may be SMP even if the guest kernel
-  * isn't.
-  */
- static inline unsigned long __sync_cmpxchg(volatile void *ptr,
-                                          unsigned long old,
-                                          unsigned long new, int size)
- {
-       unsigned long prev;
-       switch (size) {
-       case 1:
-               asm volatile("lock; cmpxchgb %b1,%2"
-                            : "=a"(prev)
-                            : "q"(new), "m"(*__xg(ptr)), "0"(old)
-                            : "memory");
-               return prev;
-       case 2:
-               asm volatile("lock; cmpxchgw %w1,%2"
-                            : "=a"(prev)
-                            : "r"(new), "m"(*__xg(ptr)), "0"(old)
-                            : "memory");
-               return prev;
-       case 4:
-               asm volatile("lock; cmpxchgl %1,%2"
-                            : "=a"(prev)
-                            : "r"(new), "m"(*__xg(ptr)), "0"(old)
-                            : "memory");
-               return prev;
-       }
-       return old;
- }
- static inline unsigned long __cmpxchg_local(volatile void *ptr,
-                                           unsigned long old,
-                                           unsigned long new, int size)
- {
-       unsigned long prev;
-       switch (size) {
-       case 1:
-               asm volatile("cmpxchgb %b1,%2"
-                            : "=a"(prev)
-                            : "q"(new), "m"(*__xg(ptr)), "0"(old)
-                            : "memory");
-               return prev;
-       case 2:
-               asm volatile("cmpxchgw %w1,%2"
-                            : "=a"(prev)
-                            : "r"(new), "m"(*__xg(ptr)), "0"(old)
-                            : "memory");
-               return prev;
-       case 4:
-               asm volatile("cmpxchgl %1,%2"
-                            : "=a"(prev)
-                            : "r"(new), "m"(*__xg(ptr)), "0"(old)
-                            : "memory");
-               return prev;
-       }
-       return old;
- }
  static inline unsigned long long __cmpxchg64(volatile void *ptr,
                                             unsigned long long old,
                                             unsigned long long new)
@@@ -312,23 -266,19 +266,23 @@@ static inline unsigned long cmpxchg_386
  
  extern unsigned long long cmpxchg_486_u64(volatile void *, u64, u64);
  
 -#define cmpxchg64(ptr, o, n)                                          \
 -({                                                                    \
 -      __typeof__(*(ptr)) __ret;                                       \
 -      if (likely(boot_cpu_data.x86 > 4))                              \
 -              __ret = (__typeof__(*(ptr)))__cmpxchg64((ptr),          \
 -                              (unsigned long long)(o),                \
 -                              (unsigned long long)(n));               \
 -      else                                                            \
 -              __ret = (__typeof__(*(ptr)))cmpxchg_486_u64((ptr),      \
 -                              (unsigned long long)(o),                \
 -                              (unsigned long long)(n));               \
 -      __ret;                                                          \
 -})
 +#define cmpxchg64(ptr, o, n)                                  \
 +({                                                            \
 +      __typeof__(*(ptr)) __ret;                               \
 +      __typeof__(*(ptr)) __old = (o);                         \
 +      __typeof__(*(ptr)) __new = (n);                         \
 +      alternative_io("call cmpxchg8b_emu",                    \
 +                      "lock; cmpxchg8b (%%esi)" ,             \
 +                     X86_FEATURE_CX8,                         \
 +                     "=A" (__ret),                            \
 +                     "S" ((ptr)), "0" (__old),                \
 +                     "b" ((unsigned int)__new),               \
 +                     "c" ((unsigned int)(__new>>32))          \
 +                     : "memory");                             \
 +      __ret; })
 +
 +
 +
  #define cmpxchg64_local(ptr, o, n)                                    \
  ({                                                                    \
        __typeof__(*(ptr)) __ret;                                       \
@@@ -155,11 -155,11 +155,11 @@@ GLOBAL(return_to_handler
  
        call ftrace_return_to_handler
  
 -      movq %rax, 16(%rsp)
 +      movq %rax, %rdi
        movq 8(%rsp), %rdx
        movq (%rsp), %rax
 -      addq $16, %rsp
 -      retq
 +      addq $24, %rsp
 +      jmp *%rdi
  #endif
  
  
@@@ -803,10 -803,6 +803,10 @@@ END(interrupt
        call \func
        .endm
  
 +/*
 + * Interrupt entry/exit should be protected against kprobes
 + */
 +      .pushsection .kprobes.text, "ax"
        /*
         * The interrupt stubs push (~vector+0x80) onto the stack and
         * then jump to common_interrupt.
@@@ -945,10 -941,6 +945,10 @@@ ENTRY(retint_kernel
  
        CFI_ENDPROC
  END(common_interrupt)
 +/*
 + * End of kprobes section
 + */
 +       .popsection
  
  /*
   * APIC interrupts.
@@@ -1499,12 -1491,17 +1499,17 @@@ error_kernelspace
        leaq irq_return(%rip),%rcx
        cmpq %rcx,RIP+8(%rsp)
        je error_swapgs
-       movl %ecx,%ecx  /* zero extend */
-       cmpq %rcx,RIP+8(%rsp)
-       je error_swapgs
+       movl %ecx,%eax  /* zero extend */
+       cmpq %rax,RIP+8(%rsp)
+       je bstep_iret
        cmpq $gs_change,RIP+8(%rsp)
        je error_swapgs
        jmp error_sti
+ bstep_iret:
+       /* Fix truncated RIP */
+       movq %rcx,RIP+8(%rsp)
+       jmp error_swapgs
  END(error_entry)
  
  
@@@ -212,8 -212,8 +212,8 @@@ ENTRY(secondary_startup_64
         */
        lgdt    early_gdt_descr(%rip)
  
-       /* set up data segments. actually 0 would do too */
-       movl $__KERNEL_DS,%eax
+       /* set up data segments */
+       xorl %eax,%eax
        movl %eax,%ds
        movl %eax,%ss
        movl %eax,%es
@@@ -418,7 -418,7 +418,7 @@@ ENTRY(phys_base
  ENTRY(idt_table)
        .skip IDT_ENTRIES * 16
  
 -      .section .bss.page_aligned, "aw", @nobits
 +      __PAGE_ALIGNED_BSS
        .align PAGE_SIZE
  ENTRY(empty_zero_page)
        .skip PAGE_SIZE
     the kernel context */
  #define __cold                        __attribute__((__cold__))
  
 +
 +#if __GNUC_MINOR__ >= 5
 +/*
 + * Mark a position in code as unreachable.  This can be used to
 + * suppress control flow warnings after asm blocks that transfer
 + * control elsewhere.
 + *
 + * Early snapshots of gcc 4.5 don't support this and we can't detect
 + * this in the preprocessor, but we can live with this because they're
 + * unreleased.  Really, we need to have autoconf for the kernel.
 + */
 +#define unreachable() __builtin_unreachable()
 +#endif
 +
  #endif
+ #if __GNUC_MINOR__ > 0
+ #define __compiletime_object_size(obj) __builtin_object_size(obj, 0)
+ #endif
+ #if __GNUC_MINOR__ >= 4
+ #define __compiletime_warning(message) __attribute__((warning(message)))
+ #define __compiletime_error(message) __attribute__((error(message)))
+ #endif
diff --combined include/linux/compiler.h
@@@ -144,11 -144,6 +144,11 @@@ void ftrace_likely_update(struct ftrace
  # define barrier() __memory_barrier()
  #endif
  
 +/* Unreachable code */
 +#ifndef unreachable
 +# define unreachable() do { } while (1)
 +#endif
 +
  #ifndef RELOC_HIDE
  # define RELOC_HIDE(ptr, off)                                 \
    ({ unsigned long __ptr;                                     \
  # define __maybe_unused               /* unimplemented */
  #endif
  
 +#ifndef __always_unused
 +# define __always_unused      /* unimplemented */
 +#endif
 +
  #ifndef noinline
  #define noinline
  #endif
  # define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
  #endif
  
+ /* Compile time object size, -1 for unknown */
+ #ifndef __compiletime_object_size
+ # define __compiletime_object_size(obj) -1
+ #endif
+ #ifndef __compiletime_warning
+ # define __compiletime_warning(message)
+ #endif
+ #ifndef __compiletime_error
+ # define __compiletime_error(message)
+ #endif
  /*
   * Prevent the compiler from merging or refetching accesses.  The compiler
   * is also forbidden from reordering successive instances of ACCESS_ONCE(),