Merge branch 'x86-asm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 28 Feb 2010 18:35:09 +0000 (10:35 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 28 Feb 2010 18:35:09 +0000 (10:35 -0800)
* 'x86-asm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  x86: Mark atomic irq ops raw for 32bit legacy
  x86: Merge show_regs()
  x86: Macroise x86 cache descriptors
  x86-32: clean up rwsem inline asm statements
  x86: Merge asm/atomic_{32,64}.h
  x86: Sync asm/atomic_32.h and asm/atomic_64.h
  x86: Split atomic64_t functions into seperate headers
  x86-64: Modify memcpy()/memset() alternatives mechanism
  x86-64: Modify copy_user_generic() alternatives mechanism
  x86: Lift restriction on the location of FIX_BTMAP_*
  x86, core: Optimize hweight32()

1  2 
arch/x86/include/asm/alternative.h
arch/x86/include/asm/uaccess_64.h
arch/x86/kernel/alternative.c
arch/x86/kernel/process.c
arch/x86/kernel/process_32.c
arch/x86/kernel/process_64.c

index ac80b7d70014aded380536cf0e412fb741cd9634,3b5b828767b6233019d2ef755f06e22134885fcb..f1e253ceba4be4b4835bd78250bc6b19f3f8c23a
@@@ -65,17 -65,12 +65,17 @@@ extern void alternatives_smp_module_add
                                        void *text, void *text_end);
  extern void alternatives_smp_module_del(struct module *mod);
  extern void alternatives_smp_switch(int smp);
 +extern int alternatives_text_reserved(void *start, void *end);
  #else
  static inline void alternatives_smp_module_add(struct module *mod, char *name,
                                               void *locks, void *locks_end,
                                               void *text, void *text_end) {}
  static inline void alternatives_smp_module_del(struct module *mod) {}
  static inline void alternatives_smp_switch(int smp) {}
 +static inline int alternatives_text_reserved(void *start, void *end)
 +{
 +      return 0;
 +}
  #endif        /* CONFIG_SMP */
  
  /* alternative assembly primitive: */
        asm volatile (ALTERNATIVE(oldinstr, newinstr, feature)          \
                : output : "i" (0), ## input)
  
+ /* Like alternative_io, but for replacing a direct call with another one. */
+ #define alternative_call(oldfunc, newfunc, feature, output, input...) \
+       asm volatile (ALTERNATIVE("call %P[old]", "call %P[new]", feature) \
+               : output : [old] "i" (oldfunc), [new] "i" (newfunc), ## input)
  /*
   * use this macro(s) if you need more than one output parameter
   * in alternative_io
   */
- #define ASM_OUTPUT2(a, b) a, b
+ #define ASM_OUTPUT2(a...) a
  
  struct paravirt_patch_site;
  #ifdef CONFIG_PARAVIRT
index 535e421498f6148ed36adaf698f54a13c58393de,a78c40305447c7ae76194169f2f206a82c010396..316708d5af92d2c5ecd2f7e22e0bc1852b003d7d
@@@ -8,6 -8,8 +8,8 @@@
  #include <linux/errno.h>
  #include <linux/prefetch.h>
  #include <linux/lockdep.h>
+ #include <asm/alternative.h>
+ #include <asm/cpufeature.h>
  #include <asm/page.h>
  
  /*
  
  /* Handles exceptions in both to and from, but doesn't do access_ok */
  __must_check unsigned long
- copy_user_generic(void *to, const void *from, unsigned len);
+ copy_user_generic_string(void *to, const void *from, unsigned len);
+ __must_check unsigned long
+ copy_user_generic_unrolled(void *to, const void *from, unsigned len);
+ static __always_inline __must_check unsigned long
+ copy_user_generic(void *to, const void *from, unsigned len)
+ {
+       unsigned ret;
+       alternative_call(copy_user_generic_unrolled,
+                        copy_user_generic_string,
+                        X86_FEATURE_REP_GOOD,
+                        ASM_OUTPUT2("=a" (ret), "=D" (to), "=S" (from),
+                                    "=d" (len)),
+                        "1" (to), "2" (from), "3" (len)
+                        : "memory", "rcx", "r8", "r9", "r10", "r11");
+       return ret;
+ }
  
  __must_check unsigned long
  _copy_to_user(void __user *to, const void *from, unsigned len);
@@@ -30,15 -49,16 +49,15 @@@ static inline unsigned long __must_chec
                                          unsigned long n)
  {
        int sz = __compiletime_object_size(to);
 -      int ret = -EFAULT;
  
        might_fault();
        if (likely(sz == -1 || sz >= n))
 -              ret = _copy_from_user(to, from, n);
 +              n = _copy_from_user(to, from, n);
  #ifdef CONFIG_DEBUG_VM
        else
                WARN(1, "Buffer overflow detected!\n");
  #endif
 -      return ret;
 +      return n;
  }
  
  static __always_inline __must_check
index e63b80e5861c91d90c9a620df7f884fcc43fe1b0,2589ea4c60ce145bfadbb2b925e6f81f85957bd8..e6ea0342c8f86e424ae164a479c5b3ffd411e867
@@@ -205,7 -205,7 +205,7 @@@ void __init_or_module apply_alternative
                                         struct alt_instr *end)
  {
        struct alt_instr *a;
-       char insnbuf[MAX_PATCH_LEN];
+       u8 insnbuf[MAX_PATCH_LEN];
  
        DPRINTK("%s: alt table %p -> %p\n", __func__, start, end);
        for (a = start; a < end; a++) {
                }
  #endif
                memcpy(insnbuf, a->replacement, a->replacementlen);
+               if (*insnbuf == 0xe8 && a->replacementlen == 5)
+                   *(s32 *)(insnbuf + 1) += a->replacement - a->instr;
                add_nops(insnbuf + a->replacementlen,
                         a->instrlen - a->replacementlen);
                text_poke_early(instr, insnbuf, a->instrlen);
@@@ -390,24 -392,6 +392,24 @@@ void alternatives_smp_switch(int smp
        mutex_unlock(&smp_alt);
  }
  
 +/* Return 1 if the address range is reserved for smp-alternatives */
 +int alternatives_text_reserved(void *start, void *end)
 +{
 +      struct smp_alt_module *mod;
 +      u8 **ptr;
 +      u8 *text_start = start;
 +      u8 *text_end = end;
 +
 +      list_for_each_entry(mod, &smp_alt_modules, next) {
 +              if (mod->text > text_end || mod->text_end < text_start)
 +                      continue;
 +              for (ptr = mod->locks; ptr < mod->locks_end; ptr++)
 +                      if (text_start <= *ptr && text_end >= *ptr)
 +                              return 1;
 +      }
 +
 +      return 0;
 +}
  #endif
  
  #ifdef CONFIG_PARAVIRT
index c9b3522b6b46bd120fdb296906b035bcfa0c9ec6,cf1e04b2ad659b234ef0b364f56e3e5963f6c466..02d678065d7d1f8a9d43a7c6efd58b5e83c61604
@@@ -92,6 -92,13 +92,13 @@@ void exit_thread(void
        }
  }
  
+ void show_regs(struct pt_regs *regs)
+ {
+       show_registers(regs);
+       show_trace(NULL, regs, (unsigned long *)kernel_stack_pointer(regs),
+                  regs->bp);
+ }
  void show_regs_common(void)
  {
        const char *board, *product;
        if (!product)
                product = "";
  
 -      printk("\n");
 -      printk(KERN_INFO "Pid: %d, comm: %.20s %s %s %.*s %s/%s\n",
 +      printk(KERN_CONT "\n");
 +      printk(KERN_DEFAULT "Pid: %d, comm: %.20s %s %s %.*s %s/%s\n",
                current->pid, current->comm, print_tainted(),
                init_utsname()->release,
                (int)strcspn(init_utsname()->version, " "),
@@@ -115,6 -122,18 +122,6 @@@ void flush_thread(void
  {
        struct task_struct *tsk = current;
  
 -#ifdef CONFIG_X86_64
 -      if (test_tsk_thread_flag(tsk, TIF_ABI_PENDING)) {
 -              clear_tsk_thread_flag(tsk, TIF_ABI_PENDING);
 -              if (test_tsk_thread_flag(tsk, TIF_IA32)) {
 -                      clear_tsk_thread_flag(tsk, TIF_IA32);
 -              } else {
 -                      set_tsk_thread_flag(tsk, TIF_IA32);
 -                      current_thread_info()->status |= TS_COMPAT;
 -              }
 -      }
 -#endif
 -
        flush_ptrace_hw_breakpoint(tsk);
        memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
        /*
@@@ -276,8 -295,6 +283,8 @@@ int kernel_thread(int (*fn)(void *), vo
        regs.es = __USER_DS;
        regs.fs = __KERNEL_PERCPU;
        regs.gs = __KERNEL_STACK_CANARY;
 +#else
 +      regs.ss = __KERNEL_DS;
  #endif
  
        regs.orig_ax = -1;
index 37ad1e046aae81a7ecdcb367078081adfb647065,fe6a34e42bdeb12678b2a8f6e0f096792207ddcb..f6c62667e30c89db95a8f2bc7054a6c12108f0dd
@@@ -139,16 -139,16 +139,16 @@@ void __show_regs(struct pt_regs *regs, 
  
        show_regs_common();
  
 -      printk("EIP: %04x:[<%08lx>] EFLAGS: %08lx CPU: %d\n",
 +      printk(KERN_DEFAULT "EIP: %04x:[<%08lx>] EFLAGS: %08lx CPU: %d\n",
                        (u16)regs->cs, regs->ip, regs->flags,
                        smp_processor_id());
        print_symbol("EIP is at %s\n", regs->ip);
  
 -      printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
 +      printk(KERN_DEFAULT "EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
                regs->ax, regs->bx, regs->cx, regs->dx);
 -      printk("ESI: %08lx EDI: %08lx EBP: %08lx ESP: %08lx\n",
 +      printk(KERN_DEFAULT "ESI: %08lx EDI: %08lx EBP: %08lx ESP: %08lx\n",
                regs->si, regs->di, regs->bp, sp);
 -      printk(" DS: %04x ES: %04x FS: %04x GS: %04x SS: %04x\n",
 +      printk(KERN_DEFAULT " DS: %04x ES: %04x FS: %04x GS: %04x SS: %04x\n",
               (u16)regs->ds, (u16)regs->es, (u16)regs->fs, gs, ss);
  
        if (!all)
        cr2 = read_cr2();
        cr3 = read_cr3();
        cr4 = read_cr4_safe();
 -      printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n",
 +      printk(KERN_DEFAULT "CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n",
                        cr0, cr2, cr3, cr4);
  
        get_debugreg(d0, 0);
        get_debugreg(d1, 1);
        get_debugreg(d2, 2);
        get_debugreg(d3, 3);
 -      printk("DR0: %08lx DR1: %08lx DR2: %08lx DR3: %08lx\n",
 +      printk(KERN_DEFAULT "DR0: %08lx DR1: %08lx DR2: %08lx DR3: %08lx\n",
                        d0, d1, d2, d3);
  
        get_debugreg(d6, 6);
        get_debugreg(d7, 7);
 -      printk("DR6: %08lx DR7: %08lx\n",
 +      printk(KERN_DEFAULT "DR6: %08lx DR7: %08lx\n",
                        d6, d7);
  }
  
- void show_regs(struct pt_regs *regs)
- {
-       show_registers(regs);
-       show_trace(NULL, regs, &regs->sp, regs->bp);
- }
  void release_thread(struct task_struct *dead_task)
  {
        BUG_ON(dead_task->mm);
index 126f0b493d049f0e0393d9c5c58d2ebb43fd25fd,418f860880a292cd165fe5e9139c956779afdda3..dc9690b4c4cccf5450a8f49c0aec3bbdb1a86f78
@@@ -161,19 -161,19 +161,19 @@@ void __show_regs(struct pt_regs *regs, 
        unsigned int ds, cs, es;
  
        show_regs_common();
 -      printk(KERN_INFO "RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip);
 +      printk(KERN_DEFAULT "RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip);
        printk_address(regs->ip, 1);
 -      printk(KERN_INFO "RSP: %04lx:%016lx  EFLAGS: %08lx\n", regs->ss,
 +      printk(KERN_DEFAULT "RSP: %04lx:%016lx  EFLAGS: %08lx\n", regs->ss,
                        regs->sp, regs->flags);
 -      printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n",
 +      printk(KERN_DEFAULT "RAX: %016lx RBX: %016lx RCX: %016lx\n",
               regs->ax, regs->bx, regs->cx);
 -      printk(KERN_INFO "RDX: %016lx RSI: %016lx RDI: %016lx\n",
 +      printk(KERN_DEFAULT "RDX: %016lx RSI: %016lx RDI: %016lx\n",
               regs->dx, regs->si, regs->di);
 -      printk(KERN_INFO "RBP: %016lx R08: %016lx R09: %016lx\n",
 +      printk(KERN_DEFAULT "RBP: %016lx R08: %016lx R09: %016lx\n",
               regs->bp, regs->r8, regs->r9);
 -      printk(KERN_INFO "R10: %016lx R11: %016lx R12: %016lx\n",
 +      printk(KERN_DEFAULT "R10: %016lx R11: %016lx R12: %016lx\n",
               regs->r10, regs->r11, regs->r12);
 -      printk(KERN_INFO "R13: %016lx R14: %016lx R15: %016lx\n",
 +      printk(KERN_DEFAULT "R13: %016lx R14: %016lx R15: %016lx\n",
               regs->r13, regs->r14, regs->r15);
  
        asm("movl %%ds,%0" : "=r" (ds));
        cr3 = read_cr3();
        cr4 = read_cr4();
  
 -      printk(KERN_INFO "FS:  %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n",
 +      printk(KERN_DEFAULT "FS:  %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n",
               fs, fsindex, gs, gsindex, shadowgs);
 -      printk(KERN_INFO "CS:  %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds,
 +      printk(KERN_DEFAULT "CS:  %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds,
                        es, cr0);
 -      printk(KERN_INFO "CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3,
 +      printk(KERN_DEFAULT "CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3,
                        cr4);
  
        get_debugreg(d0, 0);
        get_debugreg(d1, 1);
        get_debugreg(d2, 2);
 -      printk(KERN_INFO "DR0: %016lx DR1: %016lx DR2: %016lx\n", d0, d1, d2);
 +      printk(KERN_DEFAULT "DR0: %016lx DR1: %016lx DR2: %016lx\n", d0, d1, d2);
        get_debugreg(d3, 3);
        get_debugreg(d6, 6);
        get_debugreg(d7, 7);
 -      printk(KERN_INFO "DR3: %016lx DR6: %016lx DR7: %016lx\n", d3, d6, d7);
 +      printk(KERN_DEFAULT "DR3: %016lx DR6: %016lx DR7: %016lx\n", d3, d6, d7);
  }
  
- void show_regs(struct pt_regs *regs)
- {
-       show_registers(regs);
-       show_trace(NULL, regs, (void *)(regs + 1), regs->bp);
- }
  void release_thread(struct task_struct *dead_task)
  {
        if (dead_task->mm) {
@@@ -521,18 -515,6 +515,18 @@@ void set_personality_64bit(void
        current->personality &= ~READ_IMPLIES_EXEC;
  }
  
 +void set_personality_ia32(void)
 +{
 +      /* inherit personality from parent */
 +
 +      /* Make sure to be in 32bit mode */
 +      set_thread_flag(TIF_IA32);
 +      current->personality |= force_personality32;
 +
 +      /* Prepare the first "return" to user space */
 +      current_thread_info()->status |= TS_COMPAT;
 +}
 +
  unsigned long get_wchan(struct task_struct *p)
  {
        unsigned long stack;