22; Pure64 -- a 64-bit OS/software loader written in Assembly for x86-64 systems
33; Copyright (C) 2008-2025 Return Infinity -- see LICENSE.TXT
44;
5- ; INIT HPET
5+ ; INIT TIMER
66; =============================================================================
77
88
9- init_hpet:
9+ init_timer:
10+ ; Check for hypervisor presence
11+ mov eax , 1
12+ cpuid
13+ bt ecx , 31 ; HV - hypervisor present
14+ jnc init_timer_phys ; If bit is clear then jump to phys init
15+
16+ ; Check for hypervisor type
17+ mov eax , 0x40000000
18+ cpuid
19+ cmp ebx , 0x4B4D564B ; KMVK - KVM
20+ je init_timer_virt ; KVM detected? Then init_virt
21+ ; If not, fall through to init_phys
22+
23+ init_timer_phys:
1024 ; Verify there is a valid HPET address
1125 mov rax , [ p_HPET_Address ]
1226 cmp rax , 0
13- jz os_hpet_init_error
27+ jz init_timer_error
28+ call init_timer_hpet
29+ jmp init_timer_done
30+
31+ init_timer_virt:
32+ call init_timer_kvm
1433
34+ init_timer_error:
35+
36+ init_timer_done:
37+ ret
38+
39+
40+ ; -----------------------------------------------------------------------------
41+ init_timer_hpet:
1542 ; Verify the capabilities of HPET
1643 mov ecx , HPET_GEN_CAP
1744 call os_hpet_read
@@ -24,9 +51,9 @@ init_hpet:
2451
2552 ; Verify the Counter Clock Period is valid
2653 cmp eax , 0x05F5E100 ; 100,000,000 femtoseconds is the maximum
27- ja os_hpet_init_error
54+ ja init_timer_hpet_error
2855 cmp eax , 0 ; The Period has to be greater than 1 femtosecond
29- je os_hpet_init_error
56+ je init_timer_hpet_error
3057
3158 ; Calculate the HPET frequency
3259 mov rbx , rax ; Move Counter Clock Period to RBX
@@ -58,8 +85,9 @@ os_hpet_init_disable_int:
5885 mov ecx , HPET_GEN_CONF
5986 call os_hpet_write
6087
61- os_hpet_init_error :
88+ init_timer_hpet_error :
6289 ret
90+ ; -----------------------------------------------------------------------------
6391
6492
6593; -----------------------------------------------------------------------------
@@ -129,6 +157,34 @@ os_hpet_delay_end:
129157; -----------------------------------------------------------------------------
130158
131159
160+ ; -----------------------------------------------------------------------------
161+ init_timer_kvm:
162+ ; Check hypervisor feature bits
163+ mov eax , 0x40000001
164+ cpuid
165+ bt eax , 3
166+ jc init_timer_kvm_clocksource2
167+ bt eax , 0
168+ jc init_timer_kvm_clocksource
169+ jmp init_timer_done
170+
171+ init_timer_kvm_clocksource2:
172+ mov ecx , MSR_KVM_SYSTEM_TIME_NEW
173+ jmp init_timer_kvm_configure
174+
175+ init_timer_kvm_clocksource:
176+ mov ecx , MSR_KVM_SYSTEM_TIME
177+
178+ init_timer_kvm_configure:
179+ xor edx , edx
180+ mov eax , p_timer
181+ bts eax , 0 ; Enable bit
182+ wrmsr
183+
184+ ret
185+ ; -----------------------------------------------------------------------------
186+
187+
132188; Register list (64-bits wide)
133189HPET_GEN_CAP equ 0x000 ; COUNTER_CLK_PERIOD (63:32), LEG_RT_CAP (15), COUNT_SIZE_CAP (13), NUM_TIM_CAP (12:8)
134190; 0x008 - 0x00F are Reserved
@@ -153,5 +209,10 @@ HPET_TIMER_2_INT equ 0x150
153209; 0x160 - 0x3FF are Reserved for Timers 3-31
154210
155211
212+ ; MSRs
213+ MSR_KVM_SYSTEM_TIME_NEW equ 0x4B564D01
214+ MSR_KVM_SYSTEM_TIME equ 0x00000012
215+
216+
156217; =============================================================================
157218; EOF
0 commit comments