There are tests for all this in the feature flags for intel and
non-intel CPUs like AMD -- including MTRR settings. All of this could
be dynamic. Here's some code that does this, and it's similiar to
NetWare. It detexts CPU type, feature flags, special instructions,
etc. All of this on x86 could be dynamically detected.
:-)
;*************************************************************************
;
; check current processor type and state
;
;*************************************************************************
public DetectProcessorInformation
DetectProcessorInformation proc near
mov ax, cs
mov ds, ax
mov es, ax
pushf
call get_cpuid
call get_fpuid
call print
popf
ret
DetectProcessorInformation endp
get_cpuid proc near
check_8086:
pushf
pop ax
mov cx, ax
and ax, 0fffh
push ax
popf
pushf
pop ax
and ax, 0f000h
cmp ax, 0f000h ; flag bits 12-15 are always set on an 8086
mov CPU_TYPE, 0 ; 8086 detected
je end_get_cpuid
check_80286:
or cx, 0f000h
push cx
popf
pushf
pop ax
and ax, 0f000h ; flag bits 12-15 are always clear on 80286 in
real mode
mov CPU_TYPE, 2 ; 80286 processor
jz end_get_cpuid
check_80386:
mov bx, sp
and sp, not 3
OPND32
pushf
OPND32
pop ax
OPND32
mov cx, ax
OPND32 35h, 40000h
OPND32
push ax
OPND32
popf
OPND32
pushf
OPND32
pop ax
OPND32
xor ax, cx ; AC bit won't toggle, 80386 detected
mov sp, bx
mov CPU_TYPE, 3 ; 80386 detected
jz end_get_cpuid
and sp, not 3
OPND32
push cx
OPND32
popf
mov sp, bx ; restore stack
check_80486:
mov CPU_TYPE, 4 ; default to 80486
OPND32
mov ax, cx
OPND32 35h, 200000h ; xor ID bit
OPND32
push ax
OPND32
popf
OPND32
pushf
OPND32
pop ax
OPND32
xor ax, cx ; cant toggle ID bit
je end_get_cpuid
check_vendor:
mov ID_FLAG, 1
OPND32
xor ax, ax
CPUID
OPND32
mov word ptr VENDOR_ID, bx
OPND32
mov word ptr VENDOR_ID[+4], dx
OPND32
mov word ptr VENDOR_ID[+8], cx
mov si, offset VENDOR_ID
mov di, offset intel_id
mov cx, length intel_id
compare:
repe cmpsb
or cx, cx
jnz end_get_cpuid
intel_processor:
mov INTEL_PROC, 1
cpuid_data:
OPND32
cmp ax, 1
jl end_get_cpuid
OPND32
xor ax, ax
OPND32
inc ax
CPUID
mov byte ptr ds:STEPPING, al
and STEPPING, STEPPING_MASK
and al, MODEL_MASK
shr al, MODEL_SHIFT
mov byte ptr ds:CPU_MODEL, al
and ax, FAMILY_MASK
shr ax, FAMILY_SHIFT
mov byte ptr ds:CPU_TYPE, al
mov dword ptr FEATURE_FLAGS, edx
end_get_cpuid:
ret
get_cpuid endp
get_fpuid proc near
fninit
mov word ptr ds:FP_STATUS, 5a5ah
fnstsw word ptr ds:FP_STATUS
mov ax, word ptr ds:FP_STATUS
cmp al, 0
mov FPU_TYPE, 0
jne end_get_fpuid
check_control_word:
fnstcw word ptr ds:FP_STATUS
mov ax, word ptr ds:FP_STATUS
and ax, 103fh
cmp ax, 3fh
mov FPU_TYPE, 0
jne end_get_fpuid
mov FPU_TYPE, 1
check_infinity:
cmp CPU_TYPE, 3
jne end_get_fpuid
fld1
fldz
fdiv
fld st
fchs
fcompp
fstsw word ptr ds:FP_STATUS
mov ax, word ptr ds:FP_STATUS
mov FPU_TYPE, 2
sahf
jz end_get_fpuid
mov FPU_TYPE, 3
end_get_fpuid:
ret
get_fpuid endp
print proc near
cmp ID_FLAG, 1
je print_cpuid_data
if (VERBOSE)
mov dx, offset id_msg
call OutputMessage
endif
print_86:
cmp CPU_TYPE, 0
jne print_286
if (VERBOSE)
mov dx, offset c8086
call OutputMessage
endif
cmp FPU_TYPE, 0
je end_print
if (VERBOSE)
mov dx, offset fp_8087
call OutputMessage
endif
jmp end_print
print_286:
cmp CPU_TYPE, 2
jne print_386
if (VERBOSE)
mov dx, offset c286
call OutputMessage
endif
cmp FPU_TYPE, 0
je end_print
if (VERBOSE)
mov dx, offset fp_80287
call OutputMessage
endif
jmp end_print
print_386:
cmp CPU_TYPE, 3
jne print_486
if (VERBOSE)
mov dx, offset c386
call OutputMessage
endif
cmp FPU_TYPE, 0
je end_print
cmp FPU_TYPE, 2
jne print_387
if (VERBOSE)
mov dx, offset fp_80287
call OutputMessage
endif
jmp end_print
print_387:
if (VERBOSE)
mov dx, offset fp_80387
call OutputMessage
endif
jmp end_print
print_486:
cmp FPU_TYPE, 0
je print_Intel486sx
if (VERBOSE)
mov dx, offset c486
call OutputMessage
endif
jmp end_print
print_Intel486sx:
if (VERBOSE)
mov dx, offset c486nfp
call OutputMessage
endif
jmp end_print
print_cpuid_data:
cmp_vendor:
cmp INTEL_PROC, 1
jne not_GenuineIntel
cmp CPU_TYPE, 4
jne check_Pentium
if (VERBOSE)
mov dx, offset Intel486_msg
call OutputMessage
endif
jmp print_family
check_Pentium:
cmp CPU_TYPE, 5
jne check_PentiumPro
if (VERBOSE)
mov dx, offset Pentium_msg
call OutputMessage
endif
jmp print_family
check_PentiumPro:
cmp CPU_TYPE, 6
jne print_features
if (VERBOSE)
mov dx, offset PentiumPro_msg
call OutputMessage
endif
print_family:
IF VERBOSE
mov dx, offset family_msg
call OutputMessage
ENDIF
mov al, byte ptr ds:CPU_TYPE
mov byte ptr dataCR, al
add byte ptr dataCR, 30h
IF VERBOSE
mov dx, offset dataCR
call OutputMessage
ENDIF
print_model:
IF VERBOSE
mov dx, offset model_msg
call OutputMessage
ENDIF
mov al, byte ptr ds:CPU_MODEL
mov byte ptr dataCR, al
add byte ptr dataCR, 30h
IF VERBOSE
mov dx, offset dataCR
call OutputMessage
ENDIF
print_features:
mov ax, word ptr ds:FEATURE_FLAGS
and ax, FPU_FLAG
jz check_mce
if (VERBOSE)
mov dx, offset fpu_msg
call OutputMessage
ENDIF
check_mce:
mov ax, word ptr ds:FEATURE_FLAGS
and ax, MCE_FLAG
jz check_wc
IF VERBOSE
mov dx, offset mce_msg
call OutputMessage
ENDIF
check_CMPXCHG8B:
mov ax, word ptr ds:FEATURE_FLAGS
and ax, CMPXCHG8B_FLAG
jz check_4MB_paging
IF VERBOSE
mov dx, offset cmp_msg
call OutputMessage
ENDIF
chekc_io_break:
mov ax, word ptr ds:FEATURE_FLAGS
test ax, 4
jz check_4MB_paging
IF VERBOSE
mov dx, offset io_break_msg
call OutputMessage
ENDIF
; Enable Debugging Extensions bit in CR4
CR4_TO_ECX
or ecx, 08h
ECX_TO_CR4
if (VERBOSE)
mov dx, offset io_break_enable
call OutputMessage
endif
check_4MB_paging:
mov ax, word ptr ds:FEATURE_FLAGS
test ax, 08h
jz check_PageExtend
IF VERBOSE
mov dx, offset page_4MB_msg
call OutputMessage
ENDIF
; Enable page size extension bit in CR4
CR4_TO_ECX
or ecx, 10h
ECX_TO_CR4
if (VERBOSE)
mov dx, offset p4mb_enable
call OutputMessage
endif
check_PageExtend:
mov ax, word ptr ds:FEATURE_FLAGS
test ax, 40h
jz check_wc
;; DEBUG DEBUG DEBUG !!!
; Enable page address extension bit in CR4
;; CR4_TO_ECX
;; or ecx, 20h
;; ECX_TO_CR4
check_wc:
mov dx, word ptr ds:FEATURE_FLAGS
test dx, 1000h ; MTRR support flag
jz end_print
if (VERBOSE)
mov dx, offset wc_enable
call OutputMessage
endif
jmp end_print
not_GenuineIntel:
if (VERBOSE)
mov dx, offset not_Intel
call OutputMessage
endif
end_print:
ret
print endp
kernel@kvack.org wrote:
>
> On Tue, 7 Nov 2000, Jeff V. Merkey wrote:
>
> > So how come NetWare and NT can detect this at run time, and we have to
> > use a .config option to specifiy it? Come on guys.....
>
> Then run a kernel compiled for i386 and suffer the poorer code quality
> that comes with not using newer instructions and including the
> workarounds for ancient hardware.
>
> -ben
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> Please read the FAQ at http://www.tux.org/lkml/
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/
This archive was generated by hypermail 2b29 : Tue Nov 07 2000 - 21:00:23 EST