From e25fbc6849f07e905fdeee81285a97e8a7258ed0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 1 Dec 2004 03:48:28 +0000 Subject: [PATCH] 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 --- src/kernel/core/arch/x86/Jamfile | 1 + src/kernel/core/arch/x86/arch_system_info.c | 106 ++++++++++++-------- src/kernel/core/arch/x86/cpuid.S | 42 ++++++++ 3 files changed, 108 insertions(+), 41 deletions(-) create mode 100644 src/kernel/core/arch/x86/cpuid.S diff --git a/src/kernel/core/arch/x86/Jamfile b/src/kernel/core/arch/x86/Jamfile index 6f259744ae..e6a9d077ac 100644 --- a/src/kernel/core/arch/x86/Jamfile +++ b/src/kernel/core/arch/x86/Jamfile @@ -21,6 +21,7 @@ KernelStaticLibrary libx86 : arch_interrupts.S arch_system_info.c bios.cpp + cpuid.S : -fno-pic -Wno-unused ; diff --git a/src/kernel/core/arch/x86/arch_system_info.c b/src/kernel/core/arch/x86/arch_system_info.c index 174f2ffcf6..387fb17616 100644 --- a/src/kernel/core/arch/x86/arch_system_info.c +++ b/src/kernel/core/arch/x86/arch_system_info.c @@ -4,7 +4,11 @@ */ +#include #include + +#include +#include #include #include @@ -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; +} diff --git a/src/kernel/core/arch/x86/cpuid.S b/src/kernel/core/arch/x86/cpuid.S new file mode 100644 index 0000000000..f7b71ffadd --- /dev/null +++ b/src/kernel/core/arch/x86/cpuid.S @@ -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