strat9_kernel/arch/x86_64/
mod.rs1pub mod apic;
6pub mod boot_timestamp;
7pub mod cpuid;
8pub mod gdt;
9pub mod idt;
10pub mod io;
11pub mod ioapic;
12pub mod keyboard;
13pub mod keyboard_layout;
14pub mod keyboard_us;
15pub mod mouse;
16pub mod pci;
17pub mod percpu;
18pub mod pic;
19pub mod ring3_diag;
20pub mod serial;
21pub mod smp;
22pub mod syscall;
23pub mod timer;
24pub mod tlb;
25pub mod tss;
26pub mod vga;
27pub mod x2apic;
28
29use core::arch::asm;
30
31pub fn init_cpu_extensions() {
33 unsafe {
34 let mut cr4: u64;
35 asm!("mov {}, cr4", out(reg) cr4, options(nomem, nostack));
36 cr4 |= (1 << 9) | (1 << 10);
38
39 if cpuid::host_uses_xsave() {
40 cr4 |= 1 << 18;
42 }
43 asm!("mov cr4, {}", in(reg) cr4, options(nomem, nostack));
44
45 let mut cr0: u64;
46 asm!("mov {}, cr0", out(reg) cr0, options(nomem, nostack));
47 cr0 &= !(1 << 2); cr0 |= 1 << 1; asm!("mov cr0, {}", in(reg) cr0, options(nomem, nostack));
50
51 asm!("fninit", options(nomem, nostack));
52
53 if cpuid::host_uses_xsave() {
54 let xcr0 = cpuid::host_default_xcr0();
55 xsetbv(0, xcr0);
56 }
57 }
58}
59
60#[inline]
62pub fn xgetbv(xcr: u32) -> u64 {
63 let eax: u32;
64 let edx: u32;
65 unsafe {
66 asm!(
67 "xgetbv",
68 in("ecx") xcr,
69 out("eax") eax,
70 out("edx") edx,
71 options(nomem, nostack),
72 );
73 }
74 ((edx as u64) << 32) | eax as u64
75}
76
77#[inline]
82pub unsafe fn xsetbv(xcr: u32, value: u64) {
83 asm!(
84 "xsetbv",
85 in("ecx") xcr,
86 in("eax") value as u32,
87 in("edx") (value >> 32) as u32,
88 options(nomem, nostack),
89 );
90}
91
92#[inline]
94pub fn hlt() {
95 unsafe {
96 asm!("hlt", options(nomem, nostack, preserves_flags));
97 }
98}
99
100#[inline]
102pub fn cli() {
103 unsafe {
104 asm!("cli", options(nomem, nostack));
105 }
106}
107
108#[inline]
110pub fn sti() {
111 unsafe {
112 asm!("sti", options(nomem, nostack));
113 }
114}
115
116#[inline]
118pub fn interrupts_enabled() -> bool {
119 let rflags: u64;
120 unsafe {
121 asm!("pushfq; pop {}", out(reg) rflags, options(nomem));
122 }
123 rflags & 0x200 != 0
124}
125
126#[inline]
132pub fn save_flags_and_cli() -> u64 {
133 let flags: u64;
134 unsafe {
137 asm!("pushfq; pop {0}; cli", out(reg) flags);
138 }
139 flags
140}
141
142#[inline]
146pub fn restore_flags(flags: u64) {
147 unsafe {
149 asm!("push {0}; popfq", in(reg) flags);
150 }
151}
152
153#[inline]
155pub fn rdmsr(msr: u32) -> u64 {
156 let edx: u32;
157 let eax: u32;
158 unsafe {
159 asm!(
160 "rdmsr",
161 in("ecx") msr,
162 out("edx") edx,
163 out("eax") eax,
164 options(nostack)
165 );
166 }
167 ((edx as u64) << 32) | eax as u64
168}
169
170#[inline]
172pub fn wrmsr(msr: u32, val: u64) {
173 let edx = (val >> 32) as u32;
174 let eax = val as u32;
175 unsafe {
176 asm!(
177 "wrmsr",
178 in("ecx") msr,
179 in("edx") edx,
180 in("eax") eax,
181 options(nostack)
182 );
183 }
184}
185
186#[inline]
190pub fn cpuid(leaf: u32, sub_leaf: u32) -> (u32, u32, u32, u32) {
191 let eax: u32;
192 let ebx: u32;
193 let ecx: u32;
194 let edx: u32;
195 unsafe {
196 asm!(
197 "push rbx",
198 "cpuid",
199 "mov {ebx_out:e}, ebx",
200 "pop rbx",
201 inout("eax") leaf => eax,
202 inout("ecx") sub_leaf => ecx,
203 ebx_out = out(reg) ebx,
204 out("edx") edx,
205 );
206 }
207 (eax, ebx, ecx, edx)
208}
209
210#[inline]
216pub fn rdtsc() -> u64 {
217 let eax: u32;
218 let edx: u32;
219 unsafe {
220 asm!("rdtsc", out("eax") eax, out("edx") edx, options(nomem, nostack));
221 }
222 ((edx as u64) << 32) | eax as u64
223}