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