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