xref: /haiku/src/system/kernel/arch/x86/arch_system_info.cpp (revision 1bc7045fdfb85e6151d01c73669be19627c4783b)
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 
20*1bc7045fSPawel Dziepak enum cpu_vendor sCPUVendor;
21*1bc7045fSPawel Dziepak uint32 sCPUModel;
22*1bc7045fSPawel Dziepak 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 
324110b730SPawel Dziepak 	get_current_cpuid(info, eaxRegister, 0);
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)) {
5311d3892dSAlex 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_system_info_init(struct kernel_args *args)
64bd185b41SIngo Weinhold {
65*1bc7045fSPawel Dziepak 	// So far we don't have to care about heterogeneous x86 platforms.
66bd185b41SIngo Weinhold 	cpu_ent* cpu = get_cpu_struct();
67bd185b41SIngo Weinhold 
68bd185b41SIngo Weinhold 	switch (cpu->arch.vendor) {
69bd185b41SIngo Weinhold 		case VENDOR_AMD:
70*1bc7045fSPawel Dziepak 			sCPUVendor = B_CPU_VENDOR_AMD;
71bd185b41SIngo Weinhold 			break;
72bd185b41SIngo Weinhold 		case VENDOR_CENTAUR:
73*1bc7045fSPawel Dziepak 			sCPUVendor = B_CPU_VENDOR_VIA;
74bd185b41SIngo Weinhold 			break;
75*1bc7045fSPawel Dziepak 		case VENDOR_CYRIX:
76*1bc7045fSPawel Dziepak 			sCPUVendor = B_CPU_VENDOR_CYRIX;
77bd185b41SIngo Weinhold 			break;
78*1bc7045fSPawel Dziepak 		case VENDOR_INTEL:
79*1bc7045fSPawel Dziepak 			sCPUVendor = B_CPU_VENDOR_INTEL;
80bd185b41SIngo Weinhold 			break;
81bd185b41SIngo Weinhold 		case VENDOR_NSC:
82*1bc7045fSPawel Dziepak 			sCPUVendor = B_CPU_VENDOR_NATIONAL_SEMICONDUCTOR;
83*1bc7045fSPawel Dziepak 			break;
84*1bc7045fSPawel Dziepak 		case VENDOR_RISE:
85*1bc7045fSPawel Dziepak 			sCPUVendor = B_CPU_VENDOR_RISE;
86*1bc7045fSPawel Dziepak 			break;
87*1bc7045fSPawel Dziepak 		case VENDOR_TRANSMETA:
88*1bc7045fSPawel Dziepak 			sCPUVendor = B_CPU_VENDOR_TRANSMETA;
89bd185b41SIngo Weinhold 			break;
90bd185b41SIngo Weinhold 		default:
91*1bc7045fSPawel Dziepak 			sCPUVendor = B_CPU_VENDOR_UNKNOWN;
92*1bc7045fSPawel Dziepak 			break;
93bd185b41SIngo Weinhold 	}
94bd185b41SIngo Weinhold 
95*1bc7045fSPawel Dziepak 	sCPUModel = (cpu->arch.extended_family << 20)
96*1bc7045fSPawel Dziepak 		| (cpu->arch.extended_model << 16) | (cpu->arch.type << 12)
97bd185b41SIngo Weinhold 		| (cpu->arch.family << 8) | (cpu->arch.model << 4) | cpu->arch.stepping;
98bd185b41SIngo Weinhold 
99*1bc7045fSPawel Dziepak 	sCPUClockSpeed = args->arch_args.cpu_clock_speed;
100bd185b41SIngo Weinhold 	return B_OK;
101bd185b41SIngo Weinhold }
102bd185b41SIngo Weinhold 
103bd185b41SIngo Weinhold 
104*1bc7045fSPawel Dziepak void
105*1bc7045fSPawel Dziepak arch_fill_topology_node(cpu_topology_node_info* node, int32 cpu)
106*1bc7045fSPawel Dziepak {
107*1bc7045fSPawel Dziepak 	switch (node->type) {
108*1bc7045fSPawel Dziepak 		case B_TOPOLOGY_ROOT:
109*1bc7045fSPawel Dziepak #if __INTEL__
110*1bc7045fSPawel Dziepak 			node->data.root.platform = B_CPU_x86;
111*1bc7045fSPawel Dziepak #elif __x86_64__
112*1bc7045fSPawel Dziepak 			node->data.root.platform = B_CPU_x86_64;
113*1bc7045fSPawel Dziepak #else
114*1bc7045fSPawel Dziepak 			node->data.root.platform = B_CPU_UNKNOWN;
115*1bc7045fSPawel Dziepak #endif
116*1bc7045fSPawel Dziepak 			break;
117*1bc7045fSPawel Dziepak 
118*1bc7045fSPawel Dziepak 		case B_TOPOLOGY_PACKAGE:
119*1bc7045fSPawel Dziepak 			node->data.package.vendor = sCPUVendor;
120*1bc7045fSPawel Dziepak 			node->data.package.cache_line_size = CACHE_LINE_SIZE;
121*1bc7045fSPawel Dziepak 			break;
122*1bc7045fSPawel Dziepak 
123*1bc7045fSPawel Dziepak 		case B_TOPOLOGY_CORE:
124*1bc7045fSPawel Dziepak 			node->data.core.model = sCPUModel;
125*1bc7045fSPawel Dziepak 			node->data.core.default_frequency = sCPUClockSpeed;
126*1bc7045fSPawel Dziepak 			break;
127*1bc7045fSPawel Dziepak 
128*1bc7045fSPawel Dziepak 		default:
129*1bc7045fSPawel Dziepak 			break;
130*1bc7045fSPawel Dziepak 	}
131*1bc7045fSPawel Dziepak }
132*1bc7045fSPawel Dziepak 
133*1bc7045fSPawel Dziepak 
134bd185b41SIngo Weinhold //	#pragma mark -
135bd185b41SIngo Weinhold 
136bd185b41SIngo Weinhold 
137bd185b41SIngo Weinhold status_t
138bd185b41SIngo Weinhold _user_get_cpuid(cpuid_info *userInfo, uint32 eaxRegister, uint32 cpuNum)
139bd185b41SIngo Weinhold {
140bd185b41SIngo Weinhold 	cpuid_info info;
141bd185b41SIngo Weinhold 	status_t status;
142bd185b41SIngo Weinhold 
143bd185b41SIngo Weinhold 	if (!IS_USER_ADDRESS(userInfo))
144bd185b41SIngo Weinhold 		return B_BAD_ADDRESS;
145bd185b41SIngo Weinhold 
146bd185b41SIngo Weinhold 	status = get_cpuid(&info, eaxRegister, cpuNum);
147bd185b41SIngo Weinhold 
148bd185b41SIngo Weinhold 	if (status == B_OK
149bd185b41SIngo Weinhold 		&& user_memcpy(userInfo, &info, sizeof(cpuid_info)) < B_OK)
150bd185b41SIngo Weinhold 		return B_BAD_ADDRESS;
151bd185b41SIngo Weinhold 
152bd185b41SIngo Weinhold 	return status;
153bd185b41SIngo Weinhold }
154*1bc7045fSPawel Dziepak 
155