-
Notifications
You must be signed in to change notification settings - Fork 18
/
detect_lm.asm
62 lines (49 loc) · 1.47 KB
/
detect_lm.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
;; Implemenation for detecting if CPU supports x64 Long Mode
;; In case, if CPU is not support this, leave CPU in x32 Protected Mode
;; http://wiki.osdev.org/Setting_Up_Long_Mode#Detecting_the_Presence_of_Long_Mode
[bits 32]
;; Check if CPUID is supported by attempting to flip the ID bit
;; If we can flip it, CPUID is available
detect_lm:
;; Copy FLAGS in to EAX via stack
pushfd
pop eax
;; Copy to ECX as well for comparing later on
mov ecx, eax
;; Flip the ID bit
xor eax, 1 << 21
;; Copy EAX to FLAGS via the stack
push eax
popfd
;; Copy FLAGS back to EAX
pushfd
pop eax
;; Restore FLAGS from the old version stored in ECX
push ecx
popfd
;; Compare EAX and ECX
;; If they are equal then that means the bit wasn't flipped
;; so that, CPUID isn't supported
xor eax, ecx
jz detect_lm_no_cpuid
;; Otherwise, we have to check whether long mode can be used or not
mov eax, 0x80000000
cpuid
cmp eax, 0x80000001
jb detect_lm_no_long_mode
;; We can use extended function for detecting long mode now
mov eax, 0x80000001
cpuid
test edx, 1 << 29
jz detect_lm_no_long_mode
;; In case, if all check are successful, we can actually switch to Long Mode
call switch_to_lm
ret
detect_lm_no_cpuid:
;; In case, if CPUID isn't supported execute kernel in x32 Protected Mode
call execute_kernel
jmp $
detect_lm_no_long_mode:
;; In case, if Long Mode is not supported execute kernel in x32 Protected Mode
call execute_kernel
jmp $