use core::arch::asm;
use bit_field::BitField;
#[cfg(doc)]
use crate::registers::control::Cr4Flags;
use crate::registers::rflags::{self, RFlags};
#[derive(Debug, Clone, Copy)]
pub struct Smap(());
impl Smap {
pub fn new() -> Option<Self> {
#[allow(unused_unsafe)]
let cpuid = unsafe { core::arch::x86_64::__cpuid(7) };
if cpuid.ebx.get_bit(20) {
Some(Self(()))
} else {
None
}
}
#[inline]
pub const unsafe fn new_unchecked() -> Self {
Self(())
}
#[inline]
pub fn is_enabled(self) -> bool {
!rflags::read().contains(RFlags::ALIGNMENT_CHECK)
}
#[doc(alias = "stac")]
#[inline]
pub fn disable(self) {
unsafe {
asm!("stac", options(nomem, nostack, preserves_flags));
}
}
#[doc(alias = "clac")]
#[inline]
pub fn enable(self) {
unsafe {
asm!("clac", options(nomem, nostack, preserves_flags));
}
}
pub fn without_smap<F, R>(self, f: F) -> R
where
F: FnOnce() -> R,
{
let was_enabled = self.is_enabled();
self.disable();
let result = f();
if was_enabled {
self.enable();
}
result
}
}