110 lines
2.6 KiB
Rust
110 lines
2.6 KiB
Rust
#[inline]
|
|
pub fn hlt() {
|
|
unsafe {
|
|
core::arch::asm!("hlt", options(nomem, nostack, preserves_flags));
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub unsafe fn lidt(idt: &super::idt::IdtRegister) {
|
|
unsafe {
|
|
core::arch::asm!(
|
|
"lidt [{}]",
|
|
in(reg) idt,
|
|
options(readonly, nostack, preserves_flags)
|
|
);
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn int3() {
|
|
unsafe {
|
|
core::arch::asm!("int3", options(nomem, nostack, preserves_flags));
|
|
}
|
|
}
|
|
|
|
macro_rules! read_segment {
|
|
($segment:literal) => {
|
|
{
|
|
let value: u16;
|
|
unsafe {
|
|
core::arch::asm!(
|
|
concat!("mov {0:x}, ", $segment),
|
|
out(reg) value,
|
|
options(nomem, nostack, preserves_flags)
|
|
);
|
|
}
|
|
value
|
|
}
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub unsafe fn get_cs() -> u16 {
|
|
read_segment!("cs")
|
|
}
|
|
|
|
pub mod msr {
|
|
use core::arch::asm;
|
|
|
|
pub const MSR_STAR: u32 = 0xC000_0081;
|
|
pub const MSR_LSTAR: u32 = 0xC000_0082;
|
|
pub const MSR_CSTAR: u32 = 0xC000_0083;
|
|
pub const MSR_SFMASK: u32 = 0xC000_0084;
|
|
pub const MSR_FS_BASE: u32 = 0xC000_0100;
|
|
pub const MSR_GS_BASE: u32 = 0xC000_0101;
|
|
pub const MSR_KERNEL_GS_BASE: u32 = 0xC000_0102;
|
|
|
|
/// Reads the value of the specified Model-Specific Register (MSR).
|
|
/// # Safety
|
|
/// This operation is inherently unsafe.
|
|
#[inline]
|
|
pub unsafe fn read_msr(msr: u32) -> u64 {
|
|
unsafe {
|
|
let eax: u32;
|
|
let edx: u32;
|
|
asm!(
|
|
"rdmsr",
|
|
in("ecx") msr,
|
|
out("eax") eax,
|
|
out("edx") edx,
|
|
options(nomem, nostack, preserves_flags)
|
|
);
|
|
((edx as u64) << 32) | (eax as u64)
|
|
}
|
|
}
|
|
|
|
/// Writes the value to the specified Model-Specific Register (MSR).
|
|
/// # Safety
|
|
/// This operation is inherently unsafe.
|
|
#[inline]
|
|
pub unsafe fn write_msr(msr: u32, value: u64) {
|
|
unsafe {
|
|
let eax = value as u32;
|
|
let edx = (value >> 32) as u32;
|
|
asm!(
|
|
"wrmsr",
|
|
in("ecx") msr,
|
|
in("eax") eax,
|
|
in("edx") edx,
|
|
options(nomem, nostack, preserves_flags)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn rdtsc() -> u64 {
|
|
let low: u32;
|
|
let high: u32;
|
|
unsafe {
|
|
core::arch::asm!(
|
|
"rdtsc",
|
|
out("eax") low,
|
|
out("edx") high,
|
|
options(nomem, nostack, preserves_flags)
|
|
);
|
|
}
|
|
((high as u64) << 32) | (low as u64)
|
|
}
|