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 msi;
17pub mod pci;
18pub mod percpu;
19pub mod pic;
20pub mod ring3_diag;
21pub mod serial;
22pub mod smp;
23pub mod speaker;
24pub mod syscall;
25pub mod timer;
26pub mod tlb;
27pub mod tss;
28pub mod vga;
29pub mod vgabuf;
30pub mod x2apic;
31
32use core::arch::asm;
33
34pub fn init_cpu_extensions() {
36 unsafe {
37 let mut cr4: u64;
38 asm!("mov {}, cr4", out(reg) cr4, options(nomem, nostack));
39 cr4 |= (1 << 9) | (1 << 10);
41
42 if cpuid::host_uses_xsave() {
43 cr4 |= 1 << 18;
45 }
46 asm!("mov cr4, {}", in(reg) cr4, options(nomem, nostack));
47
48 let mut cr0: u64;
49 asm!("mov {}, cr0", out(reg) cr0, options(nomem, nostack));
50 cr0 &= !(1 << 2); cr0 |= 1 << 1; asm!("mov cr0, {}", in(reg) cr0, options(nomem, nostack));
53
54 asm!("fninit", options(nomem, nostack));
55
56 if cpuid::host_uses_xsave() {
57 let xcr0 = cpuid::host_default_xcr0();
58 xsetbv(0, xcr0);
59 }
60 }
61}
62
63#[inline]
65pub fn xgetbv(xcr: u32) -> u64 {
66 let eax: u32;
67 let edx: u32;
68 unsafe {
69 asm!(
70 "xgetbv",
71 in("ecx") xcr,
72 out("eax") eax,
73 out("edx") edx,
74 options(nomem, nostack),
75 );
76 }
77 ((edx as u64) << 32) | eax as u64
78}
79
80#[inline]
85pub unsafe fn xsetbv(xcr: u32, value: u64) {
86 asm!(
87 "xsetbv",
88 in("ecx") xcr,
89 in("eax") value as u32,
90 in("edx") (value >> 32) as u32,
91 options(nomem, nostack),
92 );
93}
94
95#[inline]
97pub fn hlt() {
98 unsafe {
99 asm!("hlt", options(nomem, nostack, preserves_flags));
100 }
101}
102
103#[inline]
105pub fn cli() {
106 unsafe {
107 asm!("cli", options(nomem, nostack));
108 }
109}
110
111#[inline]
113pub fn sti() {
114 unsafe {
115 asm!("sti", options(nomem, nostack));
116 }
117}
118
119#[inline]
121pub fn interrupts_enabled() -> bool {
122 let rflags: u64;
123 unsafe {
124 asm!("pushfq; pop {}", out(reg) rflags, options(nomem));
125 }
126 rflags & 0x200 != 0
127}
128
129#[inline]
135pub fn save_flags_and_cli() -> u64 {
136 let flags: u64;
137 unsafe {
140 asm!("pushfq; pop {0}; cli", out(reg) flags);
141 }
142 flags
143}
144
145#[inline]
149pub fn restore_flags(flags: u64) {
150 unsafe {
152 asm!("push {0}; popfq", in(reg) flags);
153 }
154}
155
156#[inline]
158pub fn rdmsr(msr: u32) -> u64 {
159 let edx: u32;
160 let eax: u32;
161 unsafe {
162 asm!(
163 "rdmsr",
164 in("ecx") msr,
165 out("edx") edx,
166 out("eax") eax,
167 options(nostack)
168 );
169 }
170 ((edx as u64) << 32) | eax as u64
171}
172
173#[inline]
175pub fn wrmsr(msr: u32, val: u64) {
176 let edx = (val >> 32) as u32;
177 let eax = val as u32;
178 unsafe {
179 asm!(
180 "wrmsr",
181 in("ecx") msr,
182 in("edx") edx,
183 in("eax") eax,
184 options(nostack)
185 );
186 }
187}
188
189#[inline]
193pub fn cpuid(leaf: u32, sub_leaf: u32) -> (u32, u32, u32, u32) {
194 let eax: u32;
195 let ebx: u32;
196 let ecx: u32;
197 let edx: u32;
198 unsafe {
199 asm!(
200 "push rbx",
201 "cpuid",
202 "mov {ebx_out:e}, ebx",
203 "pop rbx",
204 inout("eax") leaf => eax,
205 inout("ecx") sub_leaf => ecx,
206 ebx_out = out(reg) ebx,
207 out("edx") edx,
208 );
209 }
210 (eax, ebx, ecx, edx)
211}
212
213#[inline]
219pub fn rdtsc() -> u64 {
220 let eax: u32;
221 let edx: u32;
222 unsafe {
223 asm!("rdtsc", out("eax") eax, out("edx") edx, options(nomem, nostack));
224 }
225 ((edx as u64) << 32) | eax as u64
226}