Merge branch 'x86-cpu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 20 May 2011 00:55:12 +0000 (17:55 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 20 May 2011 00:55:12 +0000 (17:55 -0700)
* 'x86-cpu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  x86, cpu: Fix detection of Celeron Covington stepping A1 and B0
  Documentation, ABI: Update L3 cache index disable text
  x86, AMD, cacheinfo: Fix L3 cache index disable checks
  x86, AMD, cacheinfo: Fix fallout caused by max3 conversion
  x86, cpu: Change NOP selection for certain Intel CPUs
  x86, cpu: Clean up and unify the NOP selection infrastructure
  x86, percpu: Use ASM_NOP4 instead of hardcoding P6_NOP4
  x86, cpu: Move AMD Elan Kconfig under "Processor family"

Fix up trivial conflicts in alternative handling (commit dc326fca2b64
"x86, cpu: Clean up and unify the NOP selection infrastructure" removed
some hacky 5-byte instruction stuff, while commit d430d3d7e646 "jump
label: Introduce static_branch() interface" renamed HAVE_JUMP_LABEL to
CONFIG_JUMP_LABEL in the code that went away)

1  2 
arch/x86/Kconfig
arch/x86/include/asm/alternative.h
arch/x86/kernel/alternative.c
arch/x86/kernel/cpu/intel.c
arch/x86/kernel/setup.c
drivers/cpufreq/Kconfig.x86

diff --combined arch/x86/Kconfig
index 7a0ff52c73fa2c6389f81890c720f28c8abdb793,f00a3f377cc0a889ffb5725ab8cf6969727c0e48..38adb2dca1d5085e5574917f3903f20f86cbf0b0
@@@ -8,7 -8,6 +8,7 @@@ config 64BI
  
  config X86_32
        def_bool !64BIT
 +      select CLKSRC_I8253
  
  config X86_64
        def_bool 64BIT
@@@ -72,6 -71,7 +72,6 @@@ config X8
        select GENERIC_IRQ_SHOW
        select IRQ_FORCED_THREADING
        select USE_GENERIC_SMP_HELPERS if SMP
 -      select ARCH_NO_SYSDEV_OPS
  
  config INSTRUCTION_DECODER
        def_bool (KPROBES || PERF_EVENTS)
@@@ -365,17 -365,6 +365,6 @@@ config X86_U
  # Following is an alphabetically sorted list of 32 bit extended platforms
  # Please maintain the alphabetic order if and when there are additions
  
- config X86_ELAN
-       bool "AMD Elan"
-       depends on X86_32
-       depends on X86_EXTENDED_PLATFORM
-       ---help---
-         Select this for an AMD Elan processor.
-         Do not use this option for K6/Athlon/Opteron processors!
-         If unsure, choose "PC-compatible" instead.
  config X86_INTEL_CE
        bool "CE4100 TV platform"
        depends on PCI
@@@ -690,7 -679,6 +679,7 @@@ config AMD_IOMM
        bool "AMD IOMMU support"
        select SWIOTLB
        select PCI_MSI
 +      select PCI_IOV
        depends on X86_64 && PCI && ACPI
        ---help---
          With this option you can enable support for AMD IOMMU hardware in
@@@ -1849,7 -1837,7 +1838,7 @@@ config APM_ALLOW_INT
  
  endif # APM
  
 -source "arch/x86/kernel/cpu/cpufreq/Kconfig"
 +source "drivers/cpufreq/Kconfig"
  
  source "drivers/cpuidle/Kconfig"
  
index 8cdd1e2479752cf49ae9789bfc222b43bbfb8461,7da168225a9dc915dc12cc4b1db77ab45ff2b9e7..bf535f947e8c359d1ff482420ca5fca0a8e70f19
@@@ -4,6 -4,7 +4,6 @@@
  #include <linux/types.h>
  #include <linux/stddef.h>
  #include <linux/stringify.h>
 -#include <linux/jump_label.h>
  #include <asm/asm.h>
  
  /*
@@@ -190,12 -191,4 +190,4 @@@ extern void *text_poke(void *addr, cons
  extern void *text_poke_smp(void *addr, const void *opcode, size_t len);
  extern void text_poke_smp_batch(struct text_poke_param *params, int n);
  
- #if defined(CONFIG_DYNAMIC_FTRACE) || defined(CONFIG_JUMP_LABEL)
- #define IDEAL_NOP_SIZE_5 5
- extern unsigned char ideal_nop5[IDEAL_NOP_SIZE_5];
- extern void arch_init_ideal_nop5(void);
- #else
- static inline void arch_init_ideal_nop5(void) {}
- #endif
  #endif /* _ASM_X86_ALTERNATIVE_H */
index 1eeeafcb4410f06bb21850fb2cf77906b3848580,c0501ea6b634cd4b998ef7002b6ff8b93fc14d05..a81f2d52f869d842d9301d5f9aea5c23a74369a2
@@@ -67,17 -67,30 +67,30 @@@ __setup("noreplace-paravirt", setup_nor
  #define DPRINTK(fmt, args...) if (debug_alternative) \
        printk(KERN_DEBUG fmt, args)
  
+ /*
+  * Each GENERIC_NOPX is of X bytes, and defined as an array of bytes
+  * that correspond to that nop. Getting from one nop to the next, we
+  * add to the array the offset that is equal to the sum of all sizes of
+  * nops preceding the one we are after.
+  *
+  * Note: The GENERIC_NOP5_ATOMIC is at the end, as it breaks the
+  * nice symmetry of sizes of the previous nops.
+  */
  #if defined(GENERIC_NOP1) && !defined(CONFIG_X86_64)
- /* Use inline assembly to define this because the nops are defined
-    as inline assembly strings in the include files and we cannot
-    get them easily into strings. */
- asm("\t" __stringify(__INITRODATA_OR_MODULE) "\nintelnops: "
-       GENERIC_NOP1 GENERIC_NOP2 GENERIC_NOP3 GENERIC_NOP4 GENERIC_NOP5 GENERIC_NOP6
-       GENERIC_NOP7 GENERIC_NOP8
-     "\t.previous");
- extern const unsigned char intelnops[];
- static const unsigned char *const __initconst_or_module
- intel_nops[ASM_NOP_MAX+1] = {
+ static const unsigned char intelnops[] =
+ {
+       GENERIC_NOP1,
+       GENERIC_NOP2,
+       GENERIC_NOP3,
+       GENERIC_NOP4,
+       GENERIC_NOP5,
+       GENERIC_NOP6,
+       GENERIC_NOP7,
+       GENERIC_NOP8,
+       GENERIC_NOP5_ATOMIC
+ };
+ static const unsigned char * const intel_nops[ASM_NOP_MAX+2] =
+ {
        NULL,
        intelnops,
        intelnops + 1,
        intelnops + 1 + 2 + 3 + 4 + 5,
        intelnops + 1 + 2 + 3 + 4 + 5 + 6,
        intelnops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
+       intelnops + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8,
  };
  #endif
  
  #ifdef K8_NOP1
- asm("\t" __stringify(__INITRODATA_OR_MODULE) "\nk8nops: "
-       K8_NOP1 K8_NOP2 K8_NOP3 K8_NOP4 K8_NOP5 K8_NOP6
-       K8_NOP7 K8_NOP8
-     "\t.previous");
- extern const unsigned char k8nops[];
- static const unsigned char *const __initconst_or_module
- k8_nops[ASM_NOP_MAX+1] = {
+ static const unsigned char k8nops[] =
+ {
+       K8_NOP1,
+       K8_NOP2,
+       K8_NOP3,
+       K8_NOP4,
+       K8_NOP5,
+       K8_NOP6,
+       K8_NOP7,
+       K8_NOP8,
+       K8_NOP5_ATOMIC
+ };
+ static const unsigned char * const k8_nops[ASM_NOP_MAX+2] =
+ {
        NULL,
        k8nops,
        k8nops + 1,
        k8nops + 1 + 2 + 3 + 4 + 5,
        k8nops + 1 + 2 + 3 + 4 + 5 + 6,
        k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
+       k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8,
  };
  #endif
  
  #if defined(K7_NOP1) && !defined(CONFIG_X86_64)
- asm("\t" __stringify(__INITRODATA_OR_MODULE) "\nk7nops: "
-       K7_NOP1 K7_NOP2 K7_NOP3 K7_NOP4 K7_NOP5 K7_NOP6
-       K7_NOP7 K7_NOP8
-     "\t.previous");
- extern const unsigned char k7nops[];
- static const unsigned char *const __initconst_or_module
- k7_nops[ASM_NOP_MAX+1] = {
+ static const unsigned char k7nops[] =
+ {
+       K7_NOP1,
+       K7_NOP2,
+       K7_NOP3,
+       K7_NOP4,
+       K7_NOP5,
+       K7_NOP6,
+       K7_NOP7,
+       K7_NOP8,
+       K7_NOP5_ATOMIC
+ };
+ static const unsigned char * const k7_nops[ASM_NOP_MAX+2] =
+ {
        NULL,
        k7nops,
        k7nops + 1,
        k7nops + 1 + 2 + 3 + 4 + 5,
        k7nops + 1 + 2 + 3 + 4 + 5 + 6,
        k7nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
+       k7nops + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8,
  };
  #endif
  
  #ifdef P6_NOP1
- asm("\t" __stringify(__INITRODATA_OR_MODULE) "\np6nops: "
-       P6_NOP1 P6_NOP2 P6_NOP3 P6_NOP4 P6_NOP5 P6_NOP6
-       P6_NOP7 P6_NOP8
-     "\t.previous");
- extern const unsigned char p6nops[];
- static const unsigned char *const __initconst_or_module
- p6_nops[ASM_NOP_MAX+1] = {
+ static const unsigned char  __initconst_or_module p6nops[] =
+ {
+       P6_NOP1,
+       P6_NOP2,
+       P6_NOP3,
+       P6_NOP4,
+       P6_NOP5,
+       P6_NOP6,
+       P6_NOP7,
+       P6_NOP8,
+       P6_NOP5_ATOMIC
+ };
+ static const unsigned char * const p6_nops[ASM_NOP_MAX+2] =
+ {
        NULL,
        p6nops,
        p6nops + 1,
        p6nops + 1 + 2 + 3 + 4 + 5,
        p6nops + 1 + 2 + 3 + 4 + 5 + 6,
        p6nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
+       p6nops + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8,
  };
  #endif
  
+ /* Initialize these to a safe default */
  #ifdef CONFIG_X86_64
+ const unsigned char * const *ideal_nops = p6_nops;
+ #else
+ const unsigned char * const *ideal_nops = intel_nops;
+ #endif
  
- extern char __vsyscall_0;
- static const unsigned char *const *__init_or_module find_nop_table(void)
+ void __init arch_init_ideal_nops(void)
  {
-       if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
-           boot_cpu_has(X86_FEATURE_NOPL))
-               return p6_nops;
-       else
-               return k8_nops;
- }
- #else /* CONFIG_X86_64 */
+       switch (boot_cpu_data.x86_vendor) {
+       case X86_VENDOR_INTEL:
+               /*
+                * Due to a decoder implementation quirk, some
+                * specific Intel CPUs actually perform better with
+                * the "k8_nops" than with the SDM-recommended NOPs.
+                */
+               if (boot_cpu_data.x86 == 6 &&
+                   boot_cpu_data.x86_model >= 0x0f &&
+                   boot_cpu_data.x86_model != 0x1c &&
+                   boot_cpu_data.x86_model != 0x26 &&
+                   boot_cpu_data.x86_model != 0x27 &&
+                   boot_cpu_data.x86_model < 0x30) {
+                       ideal_nops = k8_nops;
+               } else if (boot_cpu_has(X86_FEATURE_NOPL)) {
+                          ideal_nops = p6_nops;
+               } else {
+ #ifdef CONFIG_X86_64
+                       ideal_nops = k8_nops;
+ #else
+                       ideal_nops = intel_nops;
+ #endif
+               }
  
- static const unsigned char *const *__init_or_module find_nop_table(void)
- {
-       if (boot_cpu_has(X86_FEATURE_K8))
-               return k8_nops;
-       else if (boot_cpu_has(X86_FEATURE_K7))
-               return k7_nops;
-       else if (boot_cpu_has(X86_FEATURE_NOPL))
-               return p6_nops;
-       else
-               return intel_nops;
+       default:
+ #ifdef CONFIG_X86_64
+               ideal_nops = k8_nops;
+ #else
+               if (boot_cpu_has(X86_FEATURE_K8))
+                       ideal_nops = k8_nops;
+               else if (boot_cpu_has(X86_FEATURE_K7))
+                       ideal_nops = k7_nops;
+               else
+                       ideal_nops = intel_nops;
+ #endif
+       }
  }
  
- #endif /* CONFIG_X86_64 */
  /* Use this to add nops to a buffer, then text_poke the whole buffer. */
  static void __init_or_module add_nops(void *insns, unsigned int len)
  {
-       const unsigned char *const *noptable = find_nop_table();
        while (len > 0) {
                unsigned int noplen = len;
                if (noplen > ASM_NOP_MAX)
                        noplen = ASM_NOP_MAX;
-               memcpy(insns, noptable[noplen], noplen);
+               memcpy(insns, ideal_nops[noplen], noplen);
                insns += noplen;
                len -= noplen;
        }
  
  extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
  extern s32 __smp_locks[], __smp_locks_end[];
+ extern char __vsyscall_0;
  void *text_poke_early(void *addr, const void *opcode, size_t len);
  
  /* Replace instructions with better alternatives for this CPU type.
@@@ -210,15 -266,6 +266,15 @@@ void __init_or_module apply_alternative
        u8 insnbuf[MAX_PATCH_LEN];
  
        DPRINTK("%s: alt table %p -> %p\n", __func__, start, end);
 +      /*
 +       * The scan order should be from start to end. A later scanned
 +       * alternative code can overwrite a previous scanned alternative code.
 +       * Some kernel functions (e.g. memcpy, memset, etc) use this order to
 +       * patch code.
 +       *
 +       * So be careful if you want to change the scan order to any other
 +       * order.
 +       */
        for (a = start; a < end; a++) {
                u8 *instr = a->instr;
                BUG_ON(a->replacementlen > a->instrlen);
@@@ -687,29 -734,3 +743,3 @@@ void __kprobes text_poke_smp_batch(stru
        wrote_text = 0;
        __stop_machine(stop_machine_text_poke, (void *)&tpp, NULL);
  }
- #if defined(CONFIG_DYNAMIC_FTRACE) || defined(CONFIG_JUMP_LABEL)
- #ifdef CONFIG_X86_64
- unsigned char ideal_nop5[5] = { 0x66, 0x66, 0x66, 0x66, 0x90 };
- #else
- unsigned char ideal_nop5[5] = { 0x3e, 0x8d, 0x74, 0x26, 0x00 };
- #endif
- void __init arch_init_ideal_nop5(void)
- {
-       /*
-        * There is no good nop for all x86 archs.  This selection
-        * algorithm should be unified with the one in find_nop_table(),
-        * but this should be good enough for now.
-        *
-        * For cases other than the ones below, use the safe (as in
-        * always functional) defaults above.
-        */
- #ifdef CONFIG_X86_64
-       /* Don't use these on 32 bits due to broken virtualizers */
-       if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
-               memcpy(ideal_nop5, p6_nops[5], 5);
- #endif
- }
- #endif
index fc73a34ba8c9c1cb93c1086845090d03782381b5,32e86aa52743c54928b9d5feeea28bf129307e05..1edf5ba4fb2b76076f448db70d01587c71a96d3d
  
  static void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
  {
 +      u64 misc_enable;
 +
        /* Unmask CPUID levels if masked: */
        if (c->x86 > 6 || (c->x86 == 6 && c->x86_model >= 0xd)) {
 -              u64 misc_enable;
 -
                rdmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
  
                if (misc_enable & MSR_IA32_MISC_ENABLE_LIMIT_CPUID) {
         * (model 2) with the same problem.
         */
        if (c->x86 == 15) {
 -              u64 misc_enable;
 -
                rdmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
  
                if (misc_enable & MSR_IA32_MISC_ENABLE_FAST_STRING) {
                }
        }
  #endif
 +
 +      /*
 +       * If fast string is not enabled in IA32_MISC_ENABLE for any reason,
 +       * clear the fast string and enhanced fast string CPU capabilities.
 +       */
 +      if (c->x86 > 6 || (c->x86 == 6 && c->x86_model >= 0xd)) {
 +              rdmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
 +              if (!(misc_enable & MSR_IA32_MISC_ENABLE_FAST_STRING)) {
 +                      printk(KERN_INFO "Disabled fast string operations\n");
 +                      setup_clear_cpu_cap(X86_FEATURE_REP_GOOD);
 +                      setup_clear_cpu_cap(X86_FEATURE_ERMS);
 +              }
 +      }
  }
  
  #ifdef CONFIG_X86_32
@@@ -411,12 -400,10 +411,10 @@@ static void __cpuinit init_intel(struc
  
                switch (c->x86_model) {
                case 5:
-                       if (c->x86_mask == 0) {
-                               if (l2 == 0)
-                                       p = "Celeron (Covington)";
-                               else if (l2 == 256)
-                                       p = "Mobile Pentium II (Dixon)";
-                       }
+                       if (l2 == 0)
+                               p = "Celeron (Covington)";
+                       else if (l2 == 256)
+                               p = "Mobile Pentium II (Dixon)";
                        break;
  
                case 6:
diff --combined arch/x86/kernel/setup.c
index 4be9b398470ea7ed399fcd72d39c67681ae98e3f,390a663894d840f81c7224ec308cca2c1f094797..c3050af9306d2337e19d06d6841f5c1af422902c
@@@ -691,8 -691,6 +691,6 @@@ early_param("reservelow", parse_reserve
  
  void __init setup_arch(char **cmdline_p)
  {
-       unsigned long flags;
  #ifdef CONFIG_X86_32
        memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));
        visws_early_detect();
        paging_init();
        x86_init.paging.pagetable_setup_done(swapper_pg_dir);
  
 +      if (boot_cpu_data.cpuid_level >= 0) {
 +              /* A CPU has %cr4 if and only if it has CPUID */
 +              mmu_cr4_features = read_cr4();
 +      }
 +
  #ifdef CONFIG_X86_32
        /* sync back kernel address range */
        clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY,
  
        mcheck_init();
  
-       local_irq_save(flags);
-       arch_init_ideal_nop5();
-       local_irq_restore(flags);
+       arch_init_ideal_nops();
  }
  
  #ifdef CONFIG_X86_32
index 343f84760487b9f5afbe6ea72ba565b69881f20f,0ab9b22557c463766c66ba177c623983caa05904..78ff7ee48951b6d6d488f0da4d40e47929608f24
@@@ -1,7 -1,15 +1,7 @@@
  #
 -# CPU Frequency scaling
 +# x86 CPU Frequency scaling drivers
  #
  
 -menu "CPU Frequency scaling"
 -
 -source "drivers/cpufreq/Kconfig"
 -
 -if CPU_FREQ
 -
 -comment "CPUFreq processor drivers"
 -
  config X86_PCC_CPUFREQ
        tristate "Processor Clocking Control interface driver"
        depends on ACPI && ACPI_PROCESSOR
@@@ -35,7 -43,7 +35,7 @@@ config X86_ACPI_CPUFRE
  config ELAN_CPUFREQ
        tristate "AMD Elan SC400 and SC410"
        select CPU_FREQ_TABLE
-       depends on X86_ELAN
+       depends on MELAN
        ---help---
          This adds the CPUFreq driver for AMD Elan SC400 and SC410
          processors.
@@@ -51,7 -59,7 +51,7 @@@
  config SC520_CPUFREQ
        tristate "AMD Elan SC520"
        select CPU_FREQ_TABLE
-       depends on X86_ELAN
+       depends on MELAN
        ---help---
          This adds the CPUFreq driver for AMD Elan SC520 processor.
  
@@@ -253,3 -261,6 +253,3 @@@ config X86_SPEEDSTEP_RELAXED_CAP_CHEC
          option lets the probing code bypass some of those checks if the
          parameter "relaxed_check=1" is passed to the module.
  
 -endif # CPU_FREQ
 -
 -endmenu