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