Imported Upstream version 1.30
[platform/upstream/x86info.git] / Intel / topology.c
1 /*
2  *  (C) 2008 Dave Jones.
3  *
4  *  Licensed under the terms of the GNU GPL License version 2.
5  *
6  *  Intel multicore/multithread determination.
7  */
8
9 #include <stdio.h>
10 #include <string.h>
11 #include <strings.h>
12 #include "../x86info.h"
13 #include "Intel.h"
14
15 /**
16  * fls - find last (most-significant) bit set
17  * @x: the word to search
18  *
19  * This is defined the same way as ffs.
20  * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
21  */
22
23 static int fls(int x)
24 {
25         int r = 32;
26
27         if (!x)
28                 return 0;
29         if (!(x & 0xffff0000u)) {
30                 x <<= 16;
31                 r -= 16;
32         }
33         if (!(x & 0xff000000u)) {
34                 x <<= 8;
35                 r -= 8;
36         }
37         if (!(x & 0xf0000000u)) {
38                 x <<= 4;
39                 r -= 4;
40         }
41         if (!(x & 0xc0000000u)) {
42                 x <<= 2;
43                 r -= 2;
44         }
45         if (!(x & 0x80000000u)) {
46                 x <<= 1;
47                 r -= 1;
48         }
49         return r;
50 }
51
52 static int get_count_order(unsigned int count)
53 {
54         int order;
55
56         order = fls(count) - 1;
57         if (count & (count - 1))
58                 order++;
59         return order;
60 }
61
62 static int intel_num_cpu_cores(struct cpudata *cpu)
63 {
64         unsigned int eax, ebx, ecx, edx;
65
66         if (cpu->cpuid_level < 4)
67                 return 1;
68
69         /* Intel has a non-standard dependency on %ecx for this CPUID level. */
70         cpuid_count(cpu->number, 4, 0, &eax, &ebx, &ecx, &edx);
71         if (eax & 0x1f)
72                 return (eax >> 26) + 1;
73         else
74                 return 1;
75 }
76
77 static int phys_pkg_id(int cpuid_apic, int index_msb)
78 {
79         return cpuid_apic >> index_msb;
80 }
81
82 void get_intel_topology(struct cpudata *cpu)
83 {
84         unsigned int eax, ebx, ecx, edx;
85         unsigned int index_msb, core_bits;
86
87         if (!(cpu->flags_edx & X86_FEATURE_HT))
88                 return;
89 /*
90         if (cpu_has(cpu, X86_FEATURE_CMP_LEGACY))
91                 goto out;
92
93         if (cpu_has(cpu, X86_FEATURE_XTOPOLOGY))
94                 return;
95 */
96
97
98         cpuid(cpu->number, 1, &eax, &ebx, &ecx, &edx);
99         cpu->num_siblings = (ebx & 0xff0000) >> 16;
100
101         if (cpu->num_siblings == 1) {
102                 if (debug)
103                         printf("Hyper-Threading is disabled\n");
104                 goto out;
105         }
106
107         if (cpu->num_siblings <= 1)
108                 goto out;
109
110         index_msb = get_count_order(cpu->num_siblings);
111         cpu->initial_apicid = (cpuid_ebx(cpu->number, 1) >> 24) & 0xFF;
112         cpu->phys_proc_id = phys_pkg_id(cpu->initial_apicid, index_msb);
113
114         cpu->x86_max_cores = intel_num_cpu_cores(cpu);
115         cpu->num_siblings = cpu->num_siblings / cpu->x86_max_cores;
116
117         index_msb = get_count_order(cpu->num_siblings);
118
119         core_bits = get_count_order(cpu->x86_max_cores);
120
121         cpu->cpu_core_id = phys_pkg_id(cpu->apicid, index_msb) &
122                 ((1 << core_bits) - 1);
123
124         if (debug == 1) {
125                 if ((cpu->x86_max_cores * cpu->num_siblings) > 1) {
126                         printf("%s:\n", __func__);
127                         printf("\tSiblings: %d\n", cpu->num_siblings);
128                         printf("\tPhysical Processor ID: %d\n", cpu->phys_proc_id);
129                         printf("\tProcessor Core ID: %d\n", cpu->cpu_core_id);
130                 }
131         }
132 out:
133         return;
134 }