Moved cpuid.S from src/kernel/libroot/os/arch/x86/. Fixed it so that it

actually fills a cpuid_info structure. Renamed cpuid() to get_current_cpuid().
Added syscall _user_get_cpuid().
Added a lot of other vendor brand strings. The cpu_type and cpu_revision
fields should now be correctly set.
get_cpuid() now returns B_BAD_VALUE if the cpuNum parameter is out of bounds
(ie. higher than the number of available CPUs in the system).


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@10321 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2004-12-01 03:48:28 +00:00
parent d86cadcdb3
commit e25fbc6849
3 changed files with 108 additions and 41 deletions
+1
View File
@@ -21,6 +21,7 @@ KernelStaticLibrary libx86 :
arch_interrupts.S
arch_system_info.c
bios.cpp
cpuid.S
:
-fno-pic -Wno-unused
;
+65 -41
View File
@@ -4,7 +4,11 @@
*/
#include <KernelExport.h>
#include <OS.h>
#include <kernel.h>
#include <smp.h>
#include <arch/system_info.h>
#include <boot/kernel_args.h>
@@ -15,36 +19,21 @@ extern void cpuid(uint32 selector, cpuid_info *info);
extern uint32 cv_factor;
cpu_type sCpuType;
uint32 sCpuType;
int32 sCpuRevision;
int64 sCpuClockSpeed;
status_t
get_cpuid(cpuid_info *info, uint32 eax_register, uint32 cpu_num)
get_cpuid(cpuid_info *info, uint32 eaxRegister, uint32 cpuNum)
{
if (cpuNum >= (uint32)smp_get_num_cpus())
return B_BAD_VALUE;
// ToDo: cpu_num is ignored, we should use the call_all_cpus() function
// to fix this.
cpuid(eax_register, info);
if (eax_register == 0) {
// fixups for this special case
char *vendor = info->eax_0.vendorid;
uint32 data[4];
memcpy(data, info, sizeof(uint32) * 4);
// the high-order word is non-zero on some Cyrix CPUs
info->eax_0.max_eax = data[0] & 0xffff;
// the vendor string bytes need a little re-ordering
*((uint32 *)&vendor[0]) = data[1];
*((uint32 *)&vendor[4]) = data[3];
*((uint32 *)&vendor[8]) = data[2];
}
return B_OK;
return get_current_cpuid(info, eaxRegister);
}
@@ -67,33 +56,68 @@ arch_get_system_info(system_info *info, size_t size)
status_t
arch_system_info_init(struct kernel_args *args)
{
cpuid_info cpuInfo;
if (get_cpuid(&cpuInfo, 0, 0) == B_OK) {
int32 base;
// This is what you get if the CPU vendor is not recognized
// or the CPU does not support cpuid with eax == 1.
uint32 base = B_CPU_x86;
uint32 model = 0;
cpuid_info cpuInfo;
if (get_current_cpuid(&cpuInfo, 0) == B_OK) {
// set CPU type and revision
if (!strncmp(cpuInfo.eax_0.vendorid, "GenuineIntel", 12))
base = B_CPU_INTEL_X86;
else if (!strncmp(cpuInfo.eax_0.vendorid, "AuthenticAMD", 12))
base = B_CPU_AMD_X86;
else {
// ToDo: fix me, add Transmeta, VIA, ...!
base = B_CPU_INTEL_X86;
if (!strncmp(cpuInfo.eax_0.vendor_id, "GenuineIntel", 12))
base = B_CPU_INTEL_x86;
else if (!strncmp(cpuInfo.eax_0.vendor_id, "AuthenticAMD", 12))
base = B_CPU_AMD_x86;
else if (!strncmp(cpuInfo.eax_0.vendor_id, "CyrixInstead", 12))
base = B_CPU_CYRIX_x86;
else if (!strncmp(cpuInfo.eax_0.vendor_id, "RiseRiseRise", 12))
base = B_CPU_RISE_x86;
else if (!strncmp(cpuInfo.eax_0.vendor_id, "CentaurHauls", 12))
base = B_CPU_IDT_x86;
else if (!strncmp(cpuInfo.eax_0.vendor_id, "NexGenDriven", 12))
// ToDo: add NexGen CPU types
base = B_CPU_x86;
else if (!strncmp(cpuInfo.eax_0.vendor_id, "GenuineTMx86", 12))
base = B_CPU_TRANSMETA_x86;
else if (!strncmp(cpuInfo.eax_0.vendor_id, "Geode by NSC", 12))
base = B_CPU_NATIONAL_x86;
if (cpuInfo.eax_0.max_eax >= 1) {
get_current_cpuid(&cpuInfo, 1);
if (base != B_CPU_x86)
model = (cpuInfo.eax_1.family << 4) + cpuInfo.eax_1.model;
sCpuRevision = (cpuInfo.eax_1.type << 12)
| (cpuInfo.eax_1.family << 8)
| (cpuInfo.eax_1.model << 4)
| cpuInfo.eax_1.stepping;
}
get_cpuid(&cpuInfo, 1, 0);
sCpuType = base + cpuInfo.eax_1.model + (cpuInfo.eax_1.family << 4);
sCpuRevision = (cpuInfo.eax_1.type << 12)
| (cpuInfo.eax_1.family << 8)
| (cpuInfo.eax_1.model << 4)
| cpuInfo.eax_1.stepping;
} else {
sCpuType = B_CPU_INTEL_X86;
}
sCpuType = base + model;
sCpuClockSpeed = args->arch_args.cpu_clock_speed;
return B_OK;
}
// #pragma mark -
status_t
_user_get_cpuid(cpuid_info *userInfo, uint32 eaxRegister, uint32 cpuNum)
{
cpuid_info info;
status_t status;
if (!IS_USER_ADDRESS(userInfo))
return B_BAD_ADDRESS;
status = get_cpuid(&info, eaxRegister, cpuNum);
if (status == B_OK
&& user_memcpy(userInfo, &info, sizeof(cpuid_info)) < B_OK)
return B_BAD_ADDRESS;
return status;
}
+42
View File
@@ -0,0 +1,42 @@
/*
* Copyright 2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Copyright 2001, Travis Geiselbrecht. All rights reserved.
* Distributed under the terms of the NewOS License.
*/
#define FUNCTION(x) .global x; .type x,@function; x
.text
/* void get_current_cpuid(cpuid_info *info, uint32 eaxRegister) */
FUNCTION(get_current_cpuid):
pushl %ebx
pushl %edi
movl 12(%esp),%edi /* first arg points to the cpuid_info structure */
movl 16(%esp),%eax /* second arg sets up eax */
cpuid
movl %eax,0(%edi) /* copy the regs into the cpuid_info structure */
movl %ebx,4(%edi)
movl %edx,8(%edi)
movl %ecx,12(%edi)
popl %edi
popl %ebx
xorl %eax, %eax /* return B_OK */
ret
/* unsigned int get_eflags(void) */
FUNCTION(get_eflags):
pushfl
popl %eax
ret
/* void set_eflags(unsigned int val) */
FUNCTION(set_eflags):
pushl 4(%esp)
popfl
ret