xref: /haiku/src/system/kernel/arch/x86/arch_system_info.cpp (revision 11d3892d285a72e161f5b13365dcce6e05a32374)
1bd185b41SIngo Weinhold /*
2bd185b41SIngo Weinhold  * Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3bd185b41SIngo Weinhold  * Distributed under the terms of the MIT License.
4bd185b41SIngo Weinhold  */
5bd185b41SIngo Weinhold 
6bd185b41SIngo Weinhold 
7bd185b41SIngo Weinhold #include <arch/system_info.h>
8bd185b41SIngo Weinhold 
9bd185b41SIngo Weinhold #include <string.h>
10bd185b41SIngo Weinhold 
11bd185b41SIngo Weinhold #include <KernelExport.h>
12bd185b41SIngo Weinhold #include <OS.h>
13bd185b41SIngo Weinhold 
14bd185b41SIngo Weinhold #include <boot/kernel_args.h>
15bd185b41SIngo Weinhold #include <cpu.h>
16bd185b41SIngo Weinhold #include <kernel.h>
17bd185b41SIngo Weinhold #include <smp.h>
18bd185b41SIngo Weinhold 
19bd185b41SIngo Weinhold 
20bd185b41SIngo Weinhold uint32 sCpuType;
21bd185b41SIngo Weinhold int32 sCpuRevision;
22bd185b41SIngo Weinhold int64 sCpuClockSpeed;
23bd185b41SIngo Weinhold 
24bd185b41SIngo Weinhold 
25bd185b41SIngo Weinhold static bool
26bd185b41SIngo Weinhold get_cpuid_for(cpuid_info *info, uint32 currentCPU, uint32 eaxRegister,
27bd185b41SIngo Weinhold 	uint32 forCPU)
28bd185b41SIngo Weinhold {
29bd185b41SIngo Weinhold 	if (currentCPU != forCPU)
30bd185b41SIngo Weinhold 		return false;
31bd185b41SIngo Weinhold 
32bd185b41SIngo Weinhold 	get_current_cpuid(info, eaxRegister);
33bd185b41SIngo Weinhold 	return true;
34bd185b41SIngo Weinhold }
35bd185b41SIngo Weinhold 
36bd185b41SIngo Weinhold 
37bd185b41SIngo Weinhold status_t
38bd185b41SIngo Weinhold get_cpuid(cpuid_info *info, uint32 eaxRegister, uint32 forCPU)
39bd185b41SIngo Weinhold {
40bd185b41SIngo Weinhold 	uint32 numCPUs = (uint32)smp_get_num_cpus();
41bd185b41SIngo Weinhold 	cpu_status state;
42bd185b41SIngo Weinhold 
43bd185b41SIngo Weinhold 	if (forCPU >= numCPUs)
44bd185b41SIngo Weinhold 		return B_BAD_VALUE;
45bd185b41SIngo Weinhold 
46bd185b41SIngo Weinhold 	// prevent us from being rescheduled
47bd185b41SIngo Weinhold 	state = disable_interrupts();
48bd185b41SIngo Weinhold 
49bd185b41SIngo Weinhold 	// ToDo: as long as we only run on pentium-class systems, we can assume
50bd185b41SIngo Weinhold 	//	that the CPU supports cpuid.
51bd185b41SIngo Weinhold 
52bd185b41SIngo Weinhold 	if (!get_cpuid_for(info, smp_get_current_cpu(), eaxRegister, forCPU)) {
53*11d3892dSAlex Smith 		smp_send_broadcast_ici(SMP_MSG_CALL_FUNCTION, (addr_t)info,
54bd185b41SIngo Weinhold 			eaxRegister, forCPU, (void *)get_cpuid_for, SMP_MSG_FLAG_SYNC);
55bd185b41SIngo Weinhold 	}
56bd185b41SIngo Weinhold 
57bd185b41SIngo Weinhold 	restore_interrupts(state);
58bd185b41SIngo Weinhold 	return B_OK;
59bd185b41SIngo Weinhold }
60bd185b41SIngo Weinhold 
61bd185b41SIngo Weinhold 
62bd185b41SIngo Weinhold status_t
63bd185b41SIngo Weinhold arch_get_system_info(system_info *info, size_t size)
64bd185b41SIngo Weinhold {
65bd185b41SIngo Weinhold 	info->cpu_type = (cpu_types)sCpuType;
66bd185b41SIngo Weinhold 	info->cpu_revision = sCpuRevision;
67bd185b41SIngo Weinhold 
68bd185b41SIngo Weinhold 	// - various cpu_info
69bd185b41SIngo Weinhold 	info->cpu_clock_speed = sCpuClockSpeed;
70bd185b41SIngo Weinhold 	// - bus_clock_speed
71bd185b41SIngo Weinhold 	info->platform_type = B_AT_CLONE_PLATFORM;
72bd185b41SIngo Weinhold 
73bd185b41SIngo Weinhold 	// ToDo: clock speeds could be retrieved via SMBIOS/DMI
74bd185b41SIngo Weinhold 	return B_OK;
75bd185b41SIngo Weinhold }
76bd185b41SIngo Weinhold 
77bd185b41SIngo Weinhold 
78bd185b41SIngo Weinhold status_t
79bd185b41SIngo Weinhold arch_system_info_init(struct kernel_args *args)
80bd185b41SIngo Weinhold {
81bd185b41SIngo Weinhold 	// This is what you get if the CPU vendor is not recognized
82bd185b41SIngo Weinhold 	// or the CPU does not support cpuid with eax == 1.
83bd185b41SIngo Weinhold 	uint32 base;
84bd185b41SIngo Weinhold 	uint32 model = 0;
85bd185b41SIngo Weinhold 	cpu_ent *cpu = get_cpu_struct();
86bd185b41SIngo Weinhold 
87bd185b41SIngo Weinhold 	switch (cpu->arch.vendor) {
88bd185b41SIngo Weinhold 		case VENDOR_INTEL:
89bd185b41SIngo Weinhold 			base = B_CPU_INTEL_x86;
90bd185b41SIngo Weinhold 			break;
91bd185b41SIngo Weinhold 		case VENDOR_AMD:
92bd185b41SIngo Weinhold 			base = B_CPU_AMD_x86;
93bd185b41SIngo Weinhold 			break;
94bd185b41SIngo Weinhold 		case VENDOR_CYRIX:
95bd185b41SIngo Weinhold 			base = B_CPU_CYRIX_x86;
96bd185b41SIngo Weinhold 			break;
97bd185b41SIngo Weinhold 		case VENDOR_UMC:
98bd185b41SIngo Weinhold 			base = B_CPU_INTEL_x86; // XXX
99bd185b41SIngo Weinhold 			break;
100bd185b41SIngo Weinhold 		case VENDOR_NEXGEN:
101bd185b41SIngo Weinhold 			base = B_CPU_INTEL_x86; // XXX
102bd185b41SIngo Weinhold 			break;
103bd185b41SIngo Weinhold 		case VENDOR_CENTAUR:
104bd185b41SIngo Weinhold 			base = B_CPU_VIA_IDT_x86;
105bd185b41SIngo Weinhold 			break;
106bd185b41SIngo Weinhold 		case VENDOR_RISE:
107bd185b41SIngo Weinhold 			base = B_CPU_RISE_x86;
108bd185b41SIngo Weinhold 			break;
109bd185b41SIngo Weinhold 		case VENDOR_TRANSMETA:
110bd185b41SIngo Weinhold 			base = B_CPU_TRANSMETA_x86;
111bd185b41SIngo Weinhold 			break;
112bd185b41SIngo Weinhold 		case VENDOR_NSC:
113bd185b41SIngo Weinhold 			base = B_CPU_NATIONAL_x86;
114bd185b41SIngo Weinhold 			break;
115bd185b41SIngo Weinhold 		default:
116bd185b41SIngo Weinhold 			base = B_CPU_x86;
117bd185b41SIngo Weinhold 	}
118bd185b41SIngo Weinhold 
119bd185b41SIngo Weinhold 	if (base != B_CPU_x86) {
120548b1a49SAlexander von Gluck IV 		if (base == B_CPU_INTEL_x86
121548b1a49SAlexander von Gluck IV 			|| (base == B_CPU_AMD_x86 && cpu->arch.family == 0xF)) {
122bd185b41SIngo Weinhold 			model = (cpu->arch.extended_family << 20)
123bd185b41SIngo Weinhold 				+ (cpu->arch.extended_model << 16)
124bd185b41SIngo Weinhold 				+ (cpu->arch.family << 4) + cpu->arch.model;
125bd185b41SIngo Weinhold 		} else {
126548b1a49SAlexander von Gluck IV 			model = (cpu->arch.family << 4)
127548b1a49SAlexander von Gluck IV 				+ cpu->arch.model;
128548b1a49SAlexander von Gluck IV 			// Isn't much useful extended family and model information
129548b1a49SAlexander von Gluck IV 			// yet on other processors.
130bd185b41SIngo Weinhold 		}
131bd185b41SIngo Weinhold 	}
132bd185b41SIngo Weinhold 
133bd185b41SIngo Weinhold 	sCpuRevision = (cpu->arch.extended_family << 18)
134bd185b41SIngo Weinhold 		| (cpu->arch.extended_model << 14) | (cpu->arch.type << 12)
135bd185b41SIngo Weinhold 		| (cpu->arch.family << 8) | (cpu->arch.model << 4) | cpu->arch.stepping;
136bd185b41SIngo Weinhold 
137bd185b41SIngo Weinhold 	sCpuType = base + model;
138bd185b41SIngo Weinhold 	sCpuClockSpeed = args->arch_args.cpu_clock_speed;
139bd185b41SIngo Weinhold 	return B_OK;
140bd185b41SIngo Weinhold }
141bd185b41SIngo Weinhold 
142bd185b41SIngo Weinhold 
143bd185b41SIngo Weinhold //	#pragma mark -
144bd185b41SIngo Weinhold 
145bd185b41SIngo Weinhold 
146bd185b41SIngo Weinhold status_t
147bd185b41SIngo Weinhold _user_get_cpuid(cpuid_info *userInfo, uint32 eaxRegister, uint32 cpuNum)
148bd185b41SIngo Weinhold {
149bd185b41SIngo Weinhold 	cpuid_info info;
150bd185b41SIngo Weinhold 	status_t status;
151bd185b41SIngo Weinhold 
152bd185b41SIngo Weinhold 	if (!IS_USER_ADDRESS(userInfo))
153bd185b41SIngo Weinhold 		return B_BAD_ADDRESS;
154bd185b41SIngo Weinhold 
155bd185b41SIngo Weinhold 	status = get_cpuid(&info, eaxRegister, cpuNum);
156bd185b41SIngo Weinhold 
157bd185b41SIngo Weinhold 	if (status == B_OK
158bd185b41SIngo Weinhold 		&& user_memcpy(userInfo, &info, sizeof(cpuid_info)) < B_OK)
159bd185b41SIngo Weinhold 		return B_BAD_ADDRESS;
160bd185b41SIngo Weinhold 
161bd185b41SIngo Weinhold 	return status;
162bd185b41SIngo Weinhold }
163