linux/arch/x86/kernel/cpu/addon_cpuid_features.c
<<
>>
Prefs
   1/*
   2 *      Routines to indentify additional cpu features that are scattered in
   3 *      cpuid space.
   4 */
   5#include <linux/cpu.h>
   6
   7#include <asm/pat.h>
   8#include <asm/processor.h>
   9
  10#include <asm/apic.h>
  11
  12struct cpuid_bit {
  13        u16 feature;
  14        u8 reg;
  15        u8 bit;
  16        u32 level;
  17};
  18
  19enum cpuid_regs {
  20        CR_EAX = 0,
  21        CR_ECX,
  22        CR_EDX,
  23        CR_EBX
  24};
  25
  26void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c)
  27{
  28        u32 max_level;
  29        u32 regs[4];
  30        const struct cpuid_bit *cb;
  31
  32        static const struct cpuid_bit __cpuinitconst cpuid_bits[] = {
  33                { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006 },
  34                { X86_FEATURE_ARAT, CR_EAX, 2, 0x00000006 },
  35                { 0, 0, 0, 0 }
  36        };
  37
  38        for (cb = cpuid_bits; cb->feature; cb++) {
  39
  40                /* Verify that the level is valid */
  41                max_level = cpuid_eax(cb->level & 0xffff0000);
  42                if (max_level < cb->level ||
  43                    max_level > (cb->level | 0xffff))
  44                        continue;
  45
  46                cpuid(cb->level, &regs[CR_EAX], &regs[CR_EBX],
  47                        &regs[CR_ECX], &regs[CR_EDX]);
  48
  49                if (regs[cb->reg] & (1 << cb->bit))
  50                        set_cpu_cap(c, cb->feature);
  51        }
  52}
  53
  54/* leaf 0xb SMT level */
  55#define SMT_LEVEL       0
  56
  57/* leaf 0xb sub-leaf types */
  58#define INVALID_TYPE    0
  59#define SMT_TYPE        1
  60#define CORE_TYPE       2
  61
  62#define LEAFB_SUBTYPE(ecx)              (((ecx) >> 8) & 0xff)
  63#define BITS_SHIFT_NEXT_LEVEL(eax)      ((eax) & 0x1f)
  64#define LEVEL_MAX_SIBLINGS(ebx)         ((ebx) & 0xffff)
  65
  66/*
  67 * Check for extended topology enumeration cpuid leaf 0xb and if it
  68 * exists, use it for populating initial_apicid and cpu topology
  69 * detection.
  70 */
  71void __cpuinit detect_extended_topology(struct cpuinfo_x86 *c)
  72{
  73#ifdef CONFIG_SMP
  74        unsigned int eax, ebx, ecx, edx, sub_index;
  75        unsigned int ht_mask_width, core_plus_mask_width;
  76        unsigned int core_select_mask, core_level_siblings;
  77
  78        if (c->cpuid_level < 0xb)
  79                return;
  80
  81        cpuid_count(0xb, SMT_LEVEL, &eax, &ebx, &ecx, &edx);
  82
  83        /*
  84         * check if the cpuid leaf 0xb is actually implemented.
  85         */
  86        if (ebx == 0 || (LEAFB_SUBTYPE(ecx) != SMT_TYPE))
  87                return;
  88
  89        set_cpu_cap(c, X86_FEATURE_XTOPOLOGY);
  90
  91        /*
  92         * initial apic id, which also represents 32-bit extended x2apic id.
  93         */
  94        c->initial_apicid = edx;
  95
  96        /*
  97         * Populate HT related information from sub-leaf level 0.
  98         */
  99        core_level_siblings = smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx);
 100        core_plus_mask_width = ht_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
 101
 102        sub_index = 1;
 103        do {
 104                cpuid_count(0xb, sub_index, &eax, &ebx, &ecx, &edx);
 105
 106                /*
 107                 * Check for the Core type in the implemented sub leaves.
 108                 */
 109                if (LEAFB_SUBTYPE(ecx) == CORE_TYPE) {
 110                        core_level_siblings = LEVEL_MAX_SIBLINGS(ebx);
 111                        core_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
 112                        break;
 113                }
 114
 115                sub_index++;
 116        } while (LEAFB_SUBTYPE(ecx) != INVALID_TYPE);
 117
 118        core_select_mask = (~(-1 << core_plus_mask_width)) >> ht_mask_width;
 119
 120        c->cpu_core_id = apic->phys_pkg_id(c->initial_apicid, ht_mask_width)
 121                                                 & core_select_mask;
 122        c->phys_proc_id = apic->phys_pkg_id(c->initial_apicid, core_plus_mask_width);
 123        /*
 124         * Reinit the apicid, now that we have extended initial_apicid.
 125         */
 126        c->apicid = apic->phys_pkg_id(c->initial_apicid, 0);
 127
 128        c->x86_max_cores = (core_level_siblings / smp_num_siblings);
 129
 130
 131        printk(KERN_INFO  "CPU: Physical Processor ID: %d\n",
 132               c->phys_proc_id);
 133        if (c->x86_max_cores > 1)
 134                printk(KERN_INFO  "CPU: Processor Core ID: %d\n",
 135                       c->cpu_core_id);
 136        return;
 137#endif
 138}
 139