51e7ff401b
Port identifycpu() to userspace. The kernel lies and reports on cpuN while actually using the values from cpu0, but this attempts to bind itself to the requested CPU if running as root. That doesn't work properly yet due to kern/38588, but will do once that's fixed.
161 lines
3.9 KiB
ArmAsm
161 lines
3.9 KiB
ArmAsm
/* $NetBSD: i386-asm.S,v 1.1 2008/05/05 17:54:14 ad Exp $ */
|
|
|
|
/*-
|
|
* Copyright (c) 1998, 2000, 2004, 2006, 2007 The NetBSD Foundation, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include <machine/asm.h>
|
|
#include <machine/cputypes.h>
|
|
#include <machine/psl.h>
|
|
|
|
.data
|
|
|
|
_C_LABEL(cpu):
|
|
.long 0
|
|
.globl _C_LABEL(cpu)
|
|
_C_LABEL(cpu_info_level):
|
|
.long -1
|
|
.globl _C_LABEL(cpu_info_level)
|
|
|
|
.text
|
|
|
|
ENTRY(x86_cpuid2)
|
|
pushl %ebx
|
|
pushl %edi
|
|
movl 12(%esp), %eax
|
|
movl 16(%esp), %ecx
|
|
movl 20(%esp), %edi
|
|
cpuid
|
|
movl %eax, 0(%edi)
|
|
movl %ebx, 4(%edi)
|
|
movl %ecx, 8(%edi)
|
|
movl %edx, 12(%edi)
|
|
popl %edi
|
|
popl %ebx
|
|
ret
|
|
END(x86_cpuid2)
|
|
|
|
ENTRY(x86_identify)
|
|
pushl %ebx
|
|
/* Try to toggle alignment check flag; does not exist on 386. */
|
|
pushfl
|
|
popl %eax
|
|
movl %eax,%ecx
|
|
orl $PSL_AC,%eax
|
|
pushl %eax
|
|
popfl
|
|
pushfl
|
|
popl %eax
|
|
xorl %ecx,%eax
|
|
andl $PSL_AC,%eax
|
|
pushl %ecx
|
|
popfl
|
|
testl %eax,%eax
|
|
jnz try486
|
|
|
|
/*
|
|
* Try the test of a NexGen CPU -- ZF will not change on a DIV
|
|
* instruction on a NexGen, it will on an i386. Documented in
|
|
* Nx586 Processor Recognition Application Note, NexGen, Inc.
|
|
*/
|
|
movl $0x5555,%eax
|
|
xorl %edx,%edx
|
|
movl $2,%ecx
|
|
divl %ecx
|
|
jnz is386
|
|
|
|
isnx586:
|
|
/*
|
|
* Don't try cpuid, as Nx586s reportedly don't support the
|
|
* PSL_ID bit.
|
|
*/
|
|
movl $CPU_NX586,_C_LABEL(cpu)
|
|
jmp 2f
|
|
is386:
|
|
movl $CPU_386,_C_LABEL(cpu)
|
|
jmp 2f
|
|
|
|
try486: /* Try to toggle identification flag; does not exist on early 486s. */
|
|
pushfl
|
|
popl %eax
|
|
movl %eax,%ecx
|
|
xorl $PSL_ID,%eax
|
|
pushl %eax
|
|
popfl
|
|
pushfl
|
|
popl %eax
|
|
xorl %ecx,%eax
|
|
andl $PSL_ID,%eax
|
|
pushl %ecx
|
|
popfl
|
|
|
|
testl %eax,%eax
|
|
jnz try586
|
|
is486: movl $CPU_486,_C_LABEL(cpu)
|
|
/*
|
|
* Check Cyrix CPU
|
|
* Cyrix CPUs do not change the undefined flags following
|
|
* execution of the divide instruction which divides 5 by 2.
|
|
*
|
|
* Note: CPUID is enabled on M2, so it passes another way.
|
|
*/
|
|
pushfl
|
|
movl $0x5555, %eax
|
|
xorl %edx, %edx
|
|
movl $2, %ecx
|
|
clc
|
|
divl %ecx
|
|
jnc trycyrix486
|
|
popfl
|
|
jmp 2f
|
|
trycyrix486:
|
|
movl $CPU_6x86,_C_LABEL(cpu) # set CPU type
|
|
/*
|
|
* Check for Cyrix 486 CPU by seeing if the flags change during a
|
|
* divide. This is documented in the Cx486SLC/e SMM Programmer's
|
|
* Guide.
|
|
*/
|
|
xorl %edx,%edx
|
|
cmpl %edx,%edx # set flags to known state
|
|
pushfl
|
|
popl %ecx # store flags in ecx
|
|
movl $-1,%eax
|
|
movl $4,%ebx
|
|
divl %ebx # do a long division
|
|
pushfl
|
|
popl %eax
|
|
xorl %ecx,%eax # are the flags different?
|
|
testl $0x8d5,%eax # only check C|PF|AF|Z|N|V
|
|
jne 2f # yes; must be Cyrix 6x86 CPU
|
|
movl $CPU_486DLC,_C_LABEL(cpu)# set CPU type
|
|
jmp 2f
|
|
try586: /* Use the `cpuid' instruction. */
|
|
xorl %eax,%eax
|
|
cpuid
|
|
movl %eax,_C_LABEL(cpu_info_level)
|
|
2:
|
|
popl %ebx
|
|
ret
|