pub use super::model_specific::{Efer, EferFlags};
use bitflags::bitflags;
#[derive(Debug)]
pub struct Cr0;
bitflags! {
pub struct Cr0Flags: u64 {
const PROTECTED_MODE_ENABLE = 1 << 0;
const MONITOR_COPROCESSOR = 1 << 1;
const EMULATE_COPROCESSOR = 1 << 2;
const TASK_SWITCHED = 1 << 3;
const NUMERIC_ERROR = 1 << 5;
const WRITE_PROTECT = 1 << 16;
const ALIGNMENT_MASK = 1 << 18;
const NOT_WRITE_THROUGH = 1 << 29;
const CACHE_DISABLE = 1 << 30;
const PAGING = 1 << 31;
}
}
#[derive(Debug)]
pub struct Cr2;
#[derive(Debug)]
pub struct Cr3;
bitflags! {
pub struct Cr3Flags: u64 {
const PAGE_LEVEL_WRITETHROUGH = 1 << 3;
const PAGE_LEVEL_CACHE_DISABLE = 1 << 4;
}
}
#[cfg(target_arch = "x86_64")]
mod x86_64 {
use super::*;
use crate::structures::paging::PhysFrame;
use crate::{PhysAddr, VirtAddr};
impl Cr0 {
pub fn read() -> Cr0Flags {
Cr0Flags::from_bits_truncate(Self::read_raw())
}
pub fn read_raw() -> u64 {
let value: u64;
unsafe {
asm!("mov %cr0, $0" : "=r" (value));
}
value
}
pub unsafe fn write(flags: Cr0Flags) {
let old_value = Self::read_raw();
let reserved = old_value & !(Cr0Flags::all().bits());
let new_value = reserved | flags.bits();
Self::write_raw(new_value);
}
pub unsafe fn write_raw(value: u64) {
asm!("mov $0, %cr0" :: "r" (value) : "memory")
}
pub unsafe fn update<F>(f: F)
where
F: FnOnce(&mut Cr0Flags),
{
let mut flags = Self::read();
f(&mut flags);
Self::write(flags);
}
}
impl Cr2 {
pub fn read() -> VirtAddr {
let value: u64;
unsafe {
asm!("mov %cr2, $0" : "=r" (value));
}
VirtAddr::new(value)
}
}
impl Cr3 {
pub fn read() -> (PhysFrame, Cr3Flags) {
let value: u64;
unsafe {
asm!("mov %cr3, $0" : "=r" (value));
}
let flags = Cr3Flags::from_bits_truncate(value);
let addr = PhysAddr::new(value & 0x_000f_ffff_ffff_f000);
let frame = PhysFrame::containing_address(addr);
(frame, flags)
}
pub unsafe fn write(frame: PhysFrame, flags: Cr3Flags) {
let addr = frame.start_address();
let value = addr.as_u64() | flags.bits();
asm!("mov $0, %cr3" :: "r" (value) : "memory")
}
}
}