diff --git a/Cargo.toml b/Cargo.toml index f07ed6f3..24b6a17b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ name = "x86_64" readme = "README.md" repository = "https://github.com/rust-osdev/x86_64" version = "0.14.10" -edition = "2018" +edition = "2021" rust-version = "1.57" # Needed to support panic! in const fns [dependencies] @@ -33,6 +33,7 @@ abi_x86_interrupt = [] const_fn = [] step_trait = [] doc_cfg = [] +binary = [] # These features are no longer used and only there for backwards compatibility. external_asm = [] diff --git a/src/lib.rs b/src/lib.rs index 3dc74b2b..b9944583 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,7 +8,8 @@ #![cfg_attr(feature = "doc_cfg", feature(doc_cfg))] #![warn(missing_docs)] #![deny(missing_debug_implementations)] -#![deny(unsafe_op_in_unsafe_fn)] +#![allow(unsafe_op_in_unsafe_fn)] +#![allow(clippy::derive_partial_eq_without_eq)] pub use crate::addr::{align_down, align_up, PhysAddr, VirtAddr}; diff --git a/src/registers/control.rs b/src/registers/control.rs index 56fb987a..9b1ddbbd 100644 --- a/src/registers/control.rs +++ b/src/registers/control.rs @@ -3,6 +3,20 @@ pub use super::model_specific::{Efer, EferFlags}; use bitflags::bitflags; +/// System software can use the TPR register to temporarily block low-priority interrupts from +/// interrupting a high-priority task. This is accomplished by loading TPR with a value corresponding to +/// the highest-priority interrupt that is to be blocked. +#[derive(Debug)] +pub struct Cr8; + +bitflags! { + /// Configuration flags of the [`Cr8`] register. + pub struct Cr8Flags: u64 { + /// A value corresponding to the highest-priority interrupt that is to be blocked + const TASK_PRIORITY = 0xf; + } +} + /// Various control flags modifying the basic operation of the CPU. #[derive(Debug)] pub struct Cr0; @@ -163,6 +177,57 @@ mod x86_64 { use crate::{instructions::tlb::Pcid, structures::paging::PhysFrame, PhysAddr, VirtAddr}; use core::arch::asm; + impl Cr8 { + /// Returns the task priority + #[inline] + pub fn read() -> Cr8Flags { + let value = Self::read_raw(); + Cr8Flags::from_bits_truncate(value) + } + + /// Read the current raw CR8 value. + #[inline] + pub fn read_raw() -> u64 { + let value: u64; + + unsafe { + asm!("mov {}, cr8", out(reg) value, options(nomem, nostack, preserves_flags)); + } + + value + } + + /// Write raw CR8 flags. + /// + /// Does _not_ preserve any values, including reserved fields. + /// + /// ## Safety + /// + /// Could mask important external interrupts + #[inline] + pub unsafe fn write_raw(value: u64) { + unsafe { + asm!("mov cr8, {}", in(reg) value, options(nostack, preserves_flags)); + } + } + + /// Write CR8 flags. + /// + /// Preserves the value of reserved fields. + /// + /// ## Safety + /// + /// Could mask important external interrupts + #[inline] + pub unsafe fn write(flags: Cr8Flags) { + let old_value = Self::read_raw(); + let reserved = old_value & !(Cr8Flags::all().bits()); + let new_value = reserved | flags.bits(); + + Self::write_raw(new_value); + } + } + impl Cr0 { /// Read the current set of CR0 flags. #[inline] diff --git a/src/registers/mod.rs b/src/registers/mod.rs index 73632c06..2890424f 100644 --- a/src/registers/mod.rs +++ b/src/registers/mod.rs @@ -3,6 +3,7 @@ pub mod control; pub mod debug; pub mod model_specific; +pub mod mtrr; pub mod mxcsr; pub mod rflags; pub mod segmentation; diff --git a/src/registers/model_specific.rs b/src/registers/model_specific.rs index 49590156..c163b91e 100644 --- a/src/registers/model_specific.rs +++ b/src/registers/model_specific.rs @@ -43,6 +43,10 @@ pub struct GsBase; #[derive(Debug)] pub struct KernelGsBase; +/// System Configuration Register. +#[derive(Debug)] +pub struct Syscfg; + /// Syscall Register: STAR #[derive(Debug)] pub struct Star; @@ -51,10 +55,18 @@ pub struct Star; #[derive(Debug)] pub struct LStar; +/// Syscall Register: CSTAR +#[derive(Debug)] +pub struct CStar; + /// Syscall Register: SFMASK #[derive(Debug)] pub struct SFMask; +impl Syscfg { + /// The underlying model specific register. + pub const MSR: Msr = Msr(0xC001_0010); +} /// IA32_U_CET: user mode CET configuration #[derive(Debug)] pub struct UCet; @@ -93,6 +105,11 @@ impl LStar { pub const MSR: Msr = Msr(0xC000_0082); } +impl CStar { + /// The underlying model specific register. + pub const MSR: Msr = Msr(0xC000_0083); +} + impl SFMask { /// The underlying model specific register. pub const MSR: Msr = Msr(0xC000_0084); @@ -108,6 +125,28 @@ impl SCet { pub const MSR: Msr = Msr(0x6A2); } +bitflags! { + /// Flags of the System Configuration Register. + pub struct SyscfgFlags: u32 { + /// MtrrFixDramEn + const MFDE = 1 << 18; + /// MtrrFixDramModEn + const MFDM = 1 << 19; + /// MtrrVarDramEn + const MVDM = 1 << 20; + /// MtrrTom2En + const TOM2 = 1 << 21; + /// Tom2ForceMemTypeWB + const FWB = 1 << 22; + /// MemEncryptionModeEn + const MEME = 1 << 23; + /// SecureNestPagingEn + const SNPE = 1 << 24; + /// VMPLEn + const VMPLE = 1 << 25; + } +} + bitflags! { /// Flags of the Extended Feature Enable Register. pub struct EferFlags: u64 { @@ -215,6 +254,69 @@ mod x86_64 { } } + impl Syscfg { + /// Read the current Syscfg flags. + #[inline] + pub fn read() -> SyscfgFlags { + SyscfgFlags::from_bits_truncate(Self::read_raw()) + } + + /// Read the current raw Syscfg flags. + #[inline] + pub fn read_raw() -> u32 { + unsafe { Self::MSR.read() as u32 } + } + + /// Write the Syscfg flags, preserving reserved values. + /// + /// Preserves the value of reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to break memory + /// safety with wrong flags, e.g. by disabling long mode. + #[inline] + pub unsafe fn write(flags: SyscfgFlags) { + let old_value = Self::read_raw(); + let reserved = old_value & !(SyscfgFlags::all().bits()); + let new_value = reserved | flags.bits(); + + Self::write_raw(new_value); + } + + /// Write the Syscfg flags. + /// + /// Does not preserve any bits, including reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to + /// break memory safety with wrong flags + #[inline] + pub unsafe fn write_raw(flags: u32) { + let mut msr = Self::MSR; + msr.write(flags as u64); + } + + /// Update Syscfg flags. + /// + /// Preserves the value of reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to break memory + /// safety with wrong flags, e.g. by disabling long mode. + #[inline] + pub unsafe fn update(f: F) + where + F: FnOnce(&mut SyscfgFlags), + { + let mut flags = Self::read(); + f(&mut flags); + Self::write(flags); + } + } + impl Efer { /// Read the current EFER flags. #[inline] @@ -462,6 +564,23 @@ mod x86_64 { } } + impl CStar { + /// Read the current CStar register. + /// This holds the target RIP of a syscall in compatibily mode. + #[inline] + pub fn read() -> VirtAddr { + VirtAddr::new(unsafe { Self::MSR.read() }) + } + + /// Write a given virtual address to the CStar register. + /// This holds the target RIP of a syscall in compatibily mode. + #[inline] + pub fn write(address: VirtAddr) { + let mut msr = Self::MSR; + unsafe { msr.write(address.as_u64()) }; + } + } + impl SFMask { /// Read to the SFMask register. /// The SFMASK register is used to specify which RFLAGS bits diff --git a/src/registers/mtrr.rs b/src/registers/mtrr.rs new file mode 100644 index 00000000..9bd88b1a --- /dev/null +++ b/src/registers/mtrr.rs @@ -0,0 +1,1908 @@ +//! Functions to read and write memory typing registers. + +use crate::addr::PhysAddr; +use crate::registers::model_specific::Msr; +use crate::structures::paging::frame::PhysFrame; +use crate::structures::paging::frame::PhysFrameRange; +use bitflags::bitflags; +use core::convert::TryFrom; +use core::convert::TryInto; + +/// Read only register describing the level of MTRR support +#[derive(Debug)] +pub struct MTRRcap; + +#[allow(dead_code)] +/// Fixed range MTRR address with memory type +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct FixMemRange { + /// Address range being mem typed + pub range: PhysFrameRange, + /// Memory type + pub memory_type: MTRRtype, +} + +impl FixMemRange { + /// Creates a new mem range struct describing memory typing + pub fn new(start: u64, end: u64, memory_type: MTRRtype) -> Self { + let start = PhysFrame::from_start_address(PhysAddr::new(start)).unwrap(); + let end = PhysFrame::from_start_address(PhysAddr::new(end + 1)).unwrap(); + Self { + memory_type, + range: PhysFrameRange { start, end }, + } + } +} + +/// Return type for reading a fixed memory range MTRR +pub type FixMemRangeReg = [FixMemRange; 8]; + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[repr(u8)] +/// Memory types +pub enum MTRRtype { + /// All accesses are uncacheable. Write combining is not allowed. Speculative accesses are not allowed. + Uncachable = 0x0, + /// All accesses are uncacheable. Write combining is allowed. Speculative reads are allowed. + WriteCombining = 0x1, + /// Reads allocate cache lines on a cache miss. + /// Cache lines are not allocated on a write miss. Write hits update the cache and main memory. + Writethrough = 0x4, + /// Reads allocate cache lines on a cache miss. + /// All writes update main memory. Cache lines are not allocated on a write miss. Write hits invalidate the cache and update main memory. + WriteProtect = 0x5, + /// Reads allocate cache lines on a cache miss, + /// and can allocate to either the shared, exclusive, or modified state. + /// Write allocate to the modified state on a cache miss. + WriteBack = 0x6, +} + +impl TryFrom for MTRRtype { + type Error = u8; + fn try_from(value: u8) -> Result { + match value { + 0x0 => Ok(MTRRtype::Uncachable), + 0x1 => Ok(MTRRtype::WriteCombining), + 0x4 => Ok(MTRRtype::Writethrough), + 0x5 => Ok(MTRRtype::WriteProtect), + 0x6 => Ok(MTRRtype::WriteBack), + _ => Err(value), + } + } +} + +impl TryFrom for MTRRtype { + type Error = u64; + fn try_from(value: u64) -> Result { + match value { + 0x0 => Ok(MTRRtype::Uncachable), + 0x1 => Ok(MTRRtype::WriteCombining), + 0x4 => Ok(MTRRtype::Writethrough), + 0x5 => Ok(MTRRtype::WriteProtect), + 0x6 => Ok(MTRRtype::WriteBack), + _ => Err(value), + } + } +} + +impl From for u8 { + fn from(val: MTRRtype) -> Self { + val as u8 + } +} + +bitflags! { + /// Flags for MTRR capabilities register + pub struct MTRRcapFlags: u64 { + /// Variable range register count + const VARIABLE_RANGE_REGISTER_COUNT = 0xff; + /// Fixed range registers + const FIXED_RANGE_REGISTERS = 1 << 8; + /// Write combining + const WRITE_COMBINING = 1 << 10; + } +} + +bitflags! { + /// Flags for default memory type register + pub struct MTRRdefTypeFlags: u64 { + /// Default memory type + const TYPE = 0xff; + /// Fixed range enable + const FIXED_ENABLE = 1 << 10; + /// MTRR enable bit if cleared the default memory type + /// of fixed and variable range registers is uncachable! + const MTRR_ENABLE = 1 << 11; + } +} + +bitflags! { + /// Flags for the MTRRphysMask register + pub struct MTRRphysMaskFlags: u64 { + /// Indicates that the MTRR pair is valid (enalbed) when set to 1 + const VALID = 1 << 11; + /// The mask value used to specify the memory range + const PHYS_MASK = 0xffff_ffff_ff << 12; + } +} + +bitflags! { + /// Flags for the MTRRphysBase[n] registers + pub struct MTRRphysBaseFlags: u64 { + /// The memory range base-address in physical-address space + const PHYS_BASE = 0xffff_ffff_ff << 12; + /// The memory type used to characterize the memory range + const TYPE = 0xff; + } +} + +/// Specifies the memory-range base address of a +/// variable range memory region. +#[derive(Debug)] +pub struct MTRRphysBase0; +/// Specifies the memory-range base address of a +/// variable range memory region. +#[derive(Debug)] +pub struct MTRRphysBase1; +/// Specifies the memory-range base address of a +/// variable range memory region. +#[derive(Debug)] +pub struct MTRRphysBase2; +/// Specifies the memory-range base address of a +/// variable range memory region. +#[derive(Debug)] +pub struct MTRRphysBase3; +/// Specifies the memory-range base address of a +/// variable range memory region. +#[derive(Debug)] +pub struct MTRRphysBase4; +/// Specifies the memory-range base address of a +/// variable range memory region. +#[derive(Debug)] +pub struct MTRRphysBase5; +/// Specifies the memory-range base address of a +/// variable range memory region. +#[derive(Debug)] +pub struct MTRRphysBase6; +/// Specifies the memory-range base address of a +/// variable range memory region. +#[derive(Debug)] +pub struct MTRRphysBase7; +/// Specifies the size of a variable range memory region. +#[derive(Debug)] +pub struct MTRRphysMask0; +/// Specifies the size of a variable range memory region. +#[derive(Debug)] +pub struct MTRRphysMask1; +/// Specifies the size of a variable range memory region. +#[derive(Debug)] +pub struct MTRRphysMask2; +/// Specifies the size of a variable range memory region. +#[derive(Debug)] +pub struct MTRRphysMask3; +/// Specifies the size of a variable range memory region. +#[derive(Debug)] +pub struct MTRRphysMask4; +/// Specifies the size of a variable range memory region. +#[derive(Debug)] +pub struct MTRRphysMask5; +/// Specifies the size of a variable range memory region. +#[derive(Debug)] +pub struct MTRRphysMask6; +/// Specifies the size of a variable range memory region. +#[derive(Debug)] +pub struct MTRRphysMask7; +/// Fixed range MTRR used to characterize the first 1MB of physical memory +#[derive(Debug)] +pub struct MTRRfix64K00000; +/// Fixed range MTRR used to characterize the first 1MB of physical memory +#[derive(Debug)] +pub struct MTRRfix16K80000; +/// Fixed range MTRR used to characterize the first 1MB of physical memory +#[derive(Debug)] +pub struct MTRRfix16KA0000; +/// Fixed range MTRR used to characterize the first 1MB of physical memory +#[derive(Debug)] +pub struct MTRRfix4KC0000; +/// Fixed range MTRR used to characterize the first 1MB of physical memory +#[derive(Debug)] +pub struct MTRRfix4KC8000; +/// Fixed range MTRR used to characterize the first 1MB of physical memory +#[derive(Debug)] +pub struct MTRRfix4KD0000; +/// Fixed range MTRR used to characterize the first 1MB of physical memory +#[derive(Debug)] +pub struct MTRRfix4KD8000; +/// Fixed range MTRR used to characterize the first 1MB of physical memory +#[derive(Debug)] +pub struct MTRRfix4KE0000; +/// Fixed range MTRR used to characterize the first 1MB of physical memory +#[derive(Debug)] +pub struct MTRRfix4KE8000; +/// Fixed range MTRR used to characterize the first 1MB of physical memory +#[derive(Debug)] +pub struct MTRRfix4KF0000; +/// Fixed range MTRR used to characterize the first 1MB of physical memory +#[derive(Debug)] +pub struct MTRRfix4KF8000; +/// Sets the default memory type for physical addresses not within +/// ranges established by fixed range and variable range MTRRs. +#[derive(Debug)] +pub struct MTRRdefType; + +impl MTRRdefType { + /// The underlying model specific register. + pub const MSR: Msr = Msr::new(0x02FF); +} + +impl MTRRcap { + /// The underlying model specific register. + pub const MSR: Msr = Msr::new(0x00FE); +} + +impl MTRRphysBase0 { + /// THe underlying model specific register. + pub const MSR: Msr = Msr::new(0x0200); +} + +impl MTRRphysBase1 { + /// The underlying model specific register + pub const MSR: Msr = Msr::new(0x0202); +} + +impl MTRRphysBase2 { + /// The underlying model specific register + pub const MSR: Msr = Msr::new(0x204); +} + +impl MTRRphysBase3 { + /// The underlying model specific register + pub const MSR: Msr = Msr::new(0x206); +} + +impl MTRRphysBase4 { + /// The underlying model specific register + pub const MSR: Msr = Msr::new(0x208); +} + +impl MTRRphysBase5 { + /// The underlying model specific register + pub const MSR: Msr = Msr::new(0x20A); +} +impl MTRRphysBase6 { + /// The underlying model specific register + pub const MSR: Msr = Msr::new(0x20C); +} + +impl MTRRphysBase7 { + /// The underlying model specific register + pub const MSR: Msr = Msr::new(0x20E); +} + +impl MTRRphysMask0 { + /// The underlying model specific register + pub const MSR: Msr = Msr::new(0x201); +} + +impl MTRRphysMask1 { + /// The underlying model specific register + pub const MSR: Msr = Msr::new(0x203); +} + +impl MTRRphysMask2 { + /// The underlying model specific register + pub const MSR: Msr = Msr::new(0x205); +} + +impl MTRRphysMask3 { + /// The underlying model specific register + pub const MSR: Msr = Msr::new(0x207); +} + +impl MTRRphysMask4 { + /// The underlying model specific register + pub const MSR: Msr = Msr::new(0x209); +} + +impl MTRRphysMask5 { + /// The underlying model specific register + pub const MSR: Msr = Msr::new(0x20B); +} + +impl MTRRphysMask6 { + /// The underlying model specific register + pub const MSR: Msr = Msr::new(0x20D); +} + +impl MTRRphysMask7 { + /// The underlying model specific register + pub const MSR: Msr = Msr::new(0x20F); +} + +impl MTRRfix64K00000 { + /// The underlying model specific register + pub const MSR: Msr = Msr::new(0x250); +} + +impl MTRRfix16K80000 { + /// The underlying model specific register + pub const MSR: Msr = Msr::new(0x258); +} + +impl MTRRfix16KA0000 { + /// The underlying model specific register + pub const MSR: Msr = Msr::new(0x259); +} + +impl MTRRfix4KC0000 { + /// The underlying model specific register + pub const MSR: Msr = Msr::new(0x268); +} + +impl MTRRfix4KC8000 { + /// The underlying model specific register + pub const MSR: Msr = Msr::new(0x269); +} + +impl MTRRfix4KD0000 { + /// The underlying model specific register + pub const MSR: Msr = Msr::new(0x26A); +} + +impl MTRRfix4KD8000 { + /// The underlying model specific register + pub const MSR: Msr = Msr::new(0x26B); +} + +impl MTRRfix4KE0000 { + /// The underlying model specific register + pub const MSR: Msr = Msr::new(0x26C); +} + +impl MTRRfix4KE8000 { + /// The underlying model specific register + pub const MSR: Msr = Msr::new(0x26D); +} + +impl MTRRfix4KF0000 { + /// The underlying model specific register + pub const MSR: Msr = Msr::new(0x26E); +} + +impl MTRRfix4KF8000 { + /// The underlying model specific register + pub const MSR: Msr = Msr::new(0x26F); +} + +#[cfg(feature = "instructions")] +mod x86_64 { + + use super::*; + impl MTRRcap { + /// Read the current raw MTRRcap flags. + #[inline] + pub fn read_raw() -> u64 { + unsafe { Self::MSR.read() } + } + + /// Write the MTRRcap flags. + /// + /// Does not preserve any bits, including reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to + /// break memory safety with wrong flags + #[inline] + pub unsafe fn write_raw(flags: u64) { + let mut msr = Self::MSR; + msr.write(flags); + } + + /// Write the MTRRcap flags, preserving reserved values. + /// + /// Preserves the value of reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to break memory + /// safety with wrong flags + #[inline] + pub unsafe fn write(flags: MTRRcapFlags) { + let old_value = Self::read_raw(); + let reserved = old_value & !(MTRRcapFlags::all().bits()); + let new_value = reserved | flags.bits(); + + Self::write_raw(new_value); + } + + /// Read the current MTRRcap flags. + #[inline] + pub fn read() -> MTRRcapFlags { + MTRRcapFlags::from_bits_truncate(Self::read_raw()) + } + } + + impl MTRRphysBase0 { + /// Read the current raw MTRRphysBase flags. + #[inline] + pub fn read_raw() -> u64 { + unsafe { Self::MSR.read() } + } + + /// Write the MTRRphysBase flags. + /// + /// Does not preserve any bits, including reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to + /// break memory safety with wrong flags + #[inline] + pub unsafe fn write_raw(flags: u64) { + let mut msr = Self::MSR; + msr.write(flags); + } + + /// Write the MTRRphysBase flags, preserving reserved values. + /// + /// Preserves the value of reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to break memory + /// safety with wrong flags + #[inline] + pub unsafe fn write(flags: MTRRphysBaseFlags) { + let old_value = Self::read_raw(); + let reserved = old_value & !(MTRRphysBaseFlags::all().bits()); + let new_value = reserved | flags.bits(); + + Self::write_raw(new_value); + } + + /// Read the current MTRRphysBase flags. + #[inline] + pub fn read() -> MTRRphysBaseFlags { + MTRRphysBaseFlags::from_bits_truncate(Self::read_raw()) + } + } + + impl MTRRphysBase1 { + /// Read the current raw MTRRphysBase flags. + #[inline] + pub fn read_raw() -> u64 { + unsafe { Self::MSR.read() } + } + + /// Write the MTRRphysBase flags. + /// + /// Does not preserve any bits, including reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to + /// break memory safety with wrong flags + #[inline] + pub unsafe fn write_raw(flags: u64) { + let mut msr = Self::MSR; + msr.write(flags); + } + + /// Write the MTRRphysBase flags, preserving reserved values. + /// + /// Preserves the value of reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to break memory + /// safety with wrong flags + #[inline] + pub unsafe fn write(flags: MTRRphysBaseFlags) { + let old_value = Self::read_raw(); + let reserved = old_value & !(MTRRphysBaseFlags::all().bits()); + let new_value = reserved | flags.bits(); + + Self::write_raw(new_value); + } + + /// Read the current MTRRphysBase flags. + #[inline] + pub fn read() -> MTRRphysBaseFlags { + MTRRphysBaseFlags::from_bits_truncate(Self::read_raw()) + } + } + + impl MTRRphysBase2 { + /// Read the current raw MTRRphysBase flags. + #[inline] + pub fn read_raw() -> u64 { + unsafe { Self::MSR.read() } + } + + /// Write the MTRRphysBase flags. + /// + /// Does not preserve any bits, including reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to + /// break memory safety with wrong flags + #[inline] + pub unsafe fn write_raw(flags: u64) { + let mut msr = Self::MSR; + msr.write(flags); + } + + /// Write the MTRRphysBase flags, preserving reserved values. + /// + /// Preserves the value of reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to break memory + /// safety with wrong flags + #[inline] + pub unsafe fn write(flags: MTRRphysBaseFlags) { + let old_value = Self::read_raw(); + let reserved = old_value & !(MTRRphysBaseFlags::all().bits()); + let new_value = reserved | flags.bits(); + + Self::write_raw(new_value); + } + + /// Read the current MTRRphysBase flags. + #[inline] + pub fn read() -> MTRRphysBaseFlags { + MTRRphysBaseFlags::from_bits_truncate(Self::read_raw()) + } + } + + impl MTRRphysBase3 { + /// Read the current raw MTRRphysBase flags. + #[inline] + pub fn read_raw() -> u64 { + unsafe { Self::MSR.read() } + } + + /// Write the MTRRphysBase flags. + /// + /// Does not preserve any bits, including reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to + /// break memory safety with wrong flags + #[inline] + pub unsafe fn write_raw(flags: u64) { + let mut msr = Self::MSR; + msr.write(flags); + } + + /// Write the MTRRphysBase flags, preserving reserved values. + /// + /// Preserves the value of reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to break memory + /// safety with wrong flags + #[inline] + pub unsafe fn write(flags: MTRRphysBaseFlags) { + let old_value = Self::read_raw(); + let reserved = old_value & !(MTRRphysBaseFlags::all().bits()); + let new_value = reserved | flags.bits(); + + Self::write_raw(new_value); + } + + /// Read the current MTRRphysBase flags. + #[inline] + pub fn read() -> MTRRphysBaseFlags { + MTRRphysBaseFlags::from_bits_truncate(Self::read_raw()) + } + } + + impl MTRRphysBase4 { + /// Read the current raw MTRRphysBase flags. + #[inline] + pub fn read_raw() -> u64 { + unsafe { Self::MSR.read() } + } + + /// Write the MTRRphysBase flags. + /// + /// Does not preserve any bits, including reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to + /// break memory safety with wrong flags + #[inline] + pub unsafe fn write_raw(flags: u64) { + let mut msr = Self::MSR; + msr.write(flags); + } + + /// Write the MTRRphysBase flags, preserving reserved values. + /// + /// Preserves the value of reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to break memory + /// safety with wrong flags + #[inline] + pub unsafe fn write(flags: MTRRphysBaseFlags) { + let old_value = Self::read_raw(); + let reserved = old_value & !(MTRRphysBaseFlags::all().bits()); + let new_value = reserved | flags.bits(); + + Self::write_raw(new_value); + } + + /// Read the current MTRRphysBase flags. + #[inline] + pub fn read() -> MTRRphysBaseFlags { + MTRRphysBaseFlags::from_bits_truncate(Self::read_raw()) + } + } + + impl MTRRphysBase5 { + /// Read the current raw MTRRphysBase flags. + #[inline] + pub fn read_raw() -> u64 { + unsafe { Self::MSR.read() } + } + + /// Write the MTRRphysBase flags. + /// + /// Does not preserve any bits, including reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to + /// break memory safety with wrong flags + #[inline] + pub unsafe fn write_raw(flags: u64) { + let mut msr = Self::MSR; + msr.write(flags); + } + + /// Write the MTRRphysBase flags, preserving reserved values. + /// + /// Preserves the value of reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to break memory + /// safety with wrong flags + #[inline] + pub unsafe fn write(flags: MTRRphysBaseFlags) { + let old_value = Self::read_raw(); + let reserved = old_value & !(MTRRphysBaseFlags::all().bits()); + let new_value = reserved | flags.bits(); + + Self::write_raw(new_value); + } + + /// Read the current MTRRphysBase flags. + #[inline] + pub fn read() -> MTRRphysBaseFlags { + MTRRphysBaseFlags::from_bits_truncate(Self::read_raw()) + } + } + + impl MTRRphysBase6 { + /// Read the current raw MTRRphysBase flags. + #[inline] + pub fn read_raw() -> u64 { + unsafe { Self::MSR.read() } + } + + /// Write the MTRRphysBase flags. + /// + /// Does not preserve any bits, including reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to + /// break memory safety with wrong flags + #[inline] + pub unsafe fn write_raw(flags: u64) { + let mut msr = Self::MSR; + msr.write(flags); + } + + /// Write the MTRRphysBase flags, preserving reserved values. + /// + /// Preserves the value of reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to break memory + /// safety with wrong flags + #[inline] + pub unsafe fn write(flags: MTRRphysBaseFlags) { + let old_value = Self::read_raw(); + let reserved = old_value & !(MTRRphysBaseFlags::all().bits()); + let new_value = reserved | flags.bits(); + + Self::write_raw(new_value); + } + + /// Read the current MTRRphysBase flags. + #[inline] + pub fn read() -> MTRRphysBaseFlags { + MTRRphysBaseFlags::from_bits_truncate(Self::read_raw()) + } + } + + impl MTRRphysBase7 { + /// Read the current raw MTRRphysBase flags. + #[inline] + pub fn read_raw() -> u64 { + unsafe { Self::MSR.read() } + } + + /// Write the MTRRphysBase flags. + /// + /// Does not preserve any bits, including reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to + /// break memory safety with wrong flags + #[inline] + pub unsafe fn write_raw(flags: u64) { + let mut msr = Self::MSR; + msr.write(flags); + } + + /// Write the MTRRphysBase flags, preserving reserved values. + /// + /// Preserves the value of reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to break memory + /// safety with wrong flags + #[inline] + pub unsafe fn write(flags: MTRRphysBaseFlags) { + let old_value = Self::read_raw(); + let reserved = old_value & !(MTRRphysBaseFlags::all().bits()); + let new_value = reserved | flags.bits(); + + Self::write_raw(new_value); + } + + /// Read the current MTRRphysBase flags. + #[inline] + pub fn read() -> MTRRphysBaseFlags { + MTRRphysBaseFlags::from_bits_truncate(Self::read_raw()) + } + } + + impl MTRRphysMask0 { + /// Read the current raw MTRRphysMask flags. + #[inline] + pub fn read_raw() -> u64 { + unsafe { Self::MSR.read() } + } + + /// Write the MTRRphysMask flags. + /// + /// Does not preserve any bits, including reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to + /// break memory safety with wrong flags + #[inline] + pub unsafe fn write_raw(flags: u64) { + let mut msr = Self::MSR; + msr.write(flags); + } + + /// Write the MTRRphysMask flags, preserving reserved values. + /// + /// Preserves the value of reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to break memory + /// safety with wrong flags + #[inline] + pub unsafe fn write(flags: MTRRphysMaskFlags) { + let old_value = Self::read_raw(); + let reserved = old_value & !(MTRRphysMaskFlags::all().bits()); + let new_value = reserved | flags.bits(); + + Self::write_raw(new_value); + } + + /// Read the current MTRRphysMask flags. + #[inline] + pub fn read() -> MTRRphysMaskFlags { + MTRRphysMaskFlags::from_bits_truncate(Self::read_raw()) + } + } + + impl MTRRphysMask1 { + /// Read the current raw MTRRphysMask flags. + #[inline] + pub fn read_raw() -> u64 { + unsafe { Self::MSR.read() } + } + + /// Write the MTRRphysMask flags. + /// + /// Does not preserve any bits, including reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to + /// break memory safety with wrong flags + #[inline] + pub unsafe fn write_raw(flags: u64) { + let mut msr = Self::MSR; + msr.write(flags); + } + + /// Write the MTRRphysMask flags, preserving reserved values. + /// + /// Preserves the value of reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to break memory + /// safety with wrong flags + #[inline] + pub unsafe fn write(flags: MTRRphysMaskFlags) { + let old_value = Self::read_raw(); + let reserved = old_value & !(MTRRphysMaskFlags::all().bits()); + let new_value = reserved | flags.bits(); + + Self::write_raw(new_value); + } + + /// Read the current MTRRphysMask flags. + #[inline] + pub fn read() -> MTRRphysMaskFlags { + MTRRphysMaskFlags::from_bits_truncate(Self::read_raw()) + } + } + + impl MTRRphysMask2 { + /// Read the current raw MTRRphysMask flags. + #[inline] + pub fn read_raw() -> u64 { + unsafe { Self::MSR.read() } + } + + /// Write the MTRRphysMask flags. + /// + /// Does not preserve any bits, including reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to + /// break memory safety with wrong flags + #[inline] + pub unsafe fn write_raw(flags: u64) { + let mut msr = Self::MSR; + msr.write(flags); + } + + /// Write the MTRRphysMask flags, preserving reserved values. + /// + /// Preserves the value of reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to break memory + /// safety with wrong flags + #[inline] + pub unsafe fn write(flags: MTRRphysMaskFlags) { + let old_value = Self::read_raw(); + let reserved = old_value & !(MTRRphysMaskFlags::all().bits()); + let new_value = reserved | flags.bits(); + + Self::write_raw(new_value); + } + + /// Read the current MTRRphysMask flags. + #[inline] + pub fn read() -> MTRRphysMaskFlags { + MTRRphysMaskFlags::from_bits_truncate(Self::read_raw()) + } + } + + impl MTRRphysMask3 { + /// Read the current raw MTRRphysMask flags. + #[inline] + pub fn read_raw() -> u64 { + unsafe { Self::MSR.read() } + } + + /// Write the MTRRphysMask flags. + /// + /// Does not preserve any bits, including reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to + /// break memory safety with wrong flags + #[inline] + pub unsafe fn write_raw(flags: u64) { + let mut msr = Self::MSR; + msr.write(flags); + } + + /// Write the MTRRphysMask flags, preserving reserved values. + /// + /// Preserves the value of reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to break memory + /// safety with wrong flags + #[inline] + pub unsafe fn write(flags: MTRRphysMaskFlags) { + let old_value = Self::read_raw(); + let reserved = old_value & !(MTRRphysMaskFlags::all().bits()); + let new_value = reserved | flags.bits(); + + Self::write_raw(new_value); + } + + /// Read the current MTRRphysMask flags. + #[inline] + pub fn read() -> MTRRphysMaskFlags { + MTRRphysMaskFlags::from_bits_truncate(Self::read_raw()) + } + } + + impl MTRRphysMask4 { + /// Read the current raw MTRRphysMask flags. + #[inline] + pub fn read_raw() -> u64 { + unsafe { Self::MSR.read() } + } + + /// Write the MTRRphysMask flags. + /// + /// Does not preserve any bits, including reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to + /// break memory safety with wrong flags + #[inline] + pub unsafe fn write_raw(flags: u64) { + let mut msr = Self::MSR; + msr.write(flags); + } + + /// Write the MTRRphysMask flags, preserving reserved values. + /// + /// Preserves the value of reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to break memory + /// safety with wrong flags + #[inline] + pub unsafe fn write(flags: MTRRphysMaskFlags) { + let old_value = Self::read_raw(); + let reserved = old_value & !(MTRRphysMaskFlags::all().bits()); + let new_value = reserved | flags.bits(); + + Self::write_raw(new_value); + } + + /// Read the current MTRRphysMask flags. + #[inline] + pub fn read() -> MTRRphysMaskFlags { + MTRRphysMaskFlags::from_bits_truncate(Self::read_raw()) + } + } + + impl MTRRphysMask5 { + /// Read the current raw MTRRphysMask flags. + #[inline] + pub fn read_raw() -> u64 { + unsafe { Self::MSR.read() } + } + + /// Write the MTRRphysMask flags. + /// + /// Does not preserve any bits, including reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to + /// break memory safety with wrong flags + #[inline] + pub unsafe fn write_raw(flags: u64) { + let mut msr = Self::MSR; + msr.write(flags); + } + + /// Write the MTRRphysMask flags, preserving reserved values. + /// + /// Preserves the value of reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to break memory + /// safety with wrong flags + #[inline] + pub unsafe fn write(flags: MTRRphysMaskFlags) { + let old_value = Self::read_raw(); + let reserved = old_value & !(MTRRphysMaskFlags::all().bits()); + let new_value = reserved | flags.bits(); + + Self::write_raw(new_value); + } + + /// Read the current MTRRphysMask flags. + #[inline] + pub fn read() -> MTRRphysMaskFlags { + MTRRphysMaskFlags::from_bits_truncate(Self::read_raw()) + } + } + + impl MTRRphysMask6 { + /// Read the current raw MTRRphysMask flags. + #[inline] + pub fn read_raw() -> u64 { + unsafe { Self::MSR.read() } + } + + /// Write the MTRRphysMask flags. + /// + /// Does not preserve any bits, including reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to + /// break memory safety with wrong flags + #[inline] + pub unsafe fn write_raw(flags: u64) { + let mut msr = Self::MSR; + msr.write(flags); + } + + /// Write the MTRRphysMask flags, preserving reserved values. + /// + /// Preserves the value of reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to break memory + /// safety with wrong flags + #[inline] + pub unsafe fn write(flags: MTRRphysMaskFlags) { + let old_value = Self::read_raw(); + let reserved = old_value & !(MTRRphysMaskFlags::all().bits()); + let new_value = reserved | flags.bits(); + + Self::write_raw(new_value); + } + + /// Read the current MTRRphysMask flags. + #[inline] + pub fn read() -> MTRRphysMaskFlags { + MTRRphysMaskFlags::from_bits_truncate(Self::read_raw()) + } + } + + impl MTRRphysMask7 { + /// Read the current raw MTRRphysMask flags. + #[inline] + pub fn read_raw() -> u64 { + unsafe { Self::MSR.read() } + } + + /// Write the MTRRphysMask flags. + /// + /// Does not preserve any bits, including reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to + /// break memory safety with wrong flags + #[inline] + pub unsafe fn write_raw(flags: u64) { + let mut msr = Self::MSR; + msr.write(flags); + } + + /// Write the MTRRphysMask flags, preserving reserved values. + /// + /// Preserves the value of reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to break memory + /// safety with wrong flags + #[inline] + pub unsafe fn write(flags: MTRRphysMaskFlags) { + let old_value = Self::read_raw(); + let reserved = old_value & !(MTRRphysMaskFlags::all().bits()); + let new_value = reserved | flags.bits(); + + Self::write_raw(new_value); + } + + /// Read the current MTRRphysMask flags. + #[inline] + pub fn read() -> MTRRphysMaskFlags { + MTRRphysMaskFlags::from_bits_truncate(Self::read_raw()) + } + } + + impl MTRRdefType { + /// Read the current raw MTRRdefType flags. + #[inline] + pub fn read_raw() -> u64 { + unsafe { Self::MSR.read() } + } + + /// Write the MTRRdefType flags. + /// + /// Does not preserve any bits, including reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to + /// break memory safety with wrong flags + #[inline] + pub unsafe fn write_raw(flags: u64) { + let mut msr = Self::MSR; + msr.write(flags); + } + + /// Write the MTRRdefType flags, preserving reserved values. + /// + /// Preserves the value of reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to break memory + /// safety with wrong flags + #[inline] + pub unsafe fn write(flags: MTRRdefTypeFlags) { + let old_value = Self::read_raw(); + let reserved = old_value & !(MTRRdefTypeFlags::all().bits()); + let new_value = reserved | flags.bits(); + + Self::write_raw(new_value); + } + + /// Read the current MTRRdefType flags. + #[inline] + pub fn read() -> MTRRdefTypeFlags { + MTRRdefTypeFlags::from_bits_truncate(Self::read_raw()) + } + } + + impl MTRRfix64K00000 { + /// Read the raw register + #[inline] + pub fn read_raw() -> u64 { + unsafe { Self::MSR.read() } + } + + /// Writes the MTRR fixed range memory types. + /// + /// Does not preserve any bits, including reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to + /// break memory safety with wrong flags + #[inline] + pub unsafe fn write_raw(flags: u64) { + let mut msr = Self::MSR; + msr.write(flags); + } + + /// Reads the MTRR fixed range memory types. + /// The 512 Kbytes of memory spanning addresses 00_0000h to 07_FFFFh are segmented into eight + /// 64-Kbyte ranges. A single MTRR is used to characterize this address space. + pub fn read() -> FixMemRangeReg { + let r = Self::read_raw(); + let one = FixMemRange::new(0x00000, 0x0FFFF, (r & 0xff).try_into().unwrap()); + let two = FixMemRange::new( + 0x10000, + 0x1FFFF, + ((r & (0xff << 8)) >> 8).try_into().unwrap(), + ); + let three = FixMemRange::new( + 0x20000, + 0x2FFFF, + ((r & (0xff << 16)) >> 16).try_into().unwrap(), + ); + let four = FixMemRange::new( + 0x30000, + 0x3FFFF, + ((r & (0xff << 24)) >> 24).try_into().unwrap(), + ); + let five = FixMemRange::new( + 0x40000, + 0x4FFFF, + ((r & (0xff << 32)) >> 32).try_into().unwrap(), + ); + let six = FixMemRange::new( + 0x50000, + 0x5FFFF, + ((r & (0xff << 40)) >> 40).try_into().unwrap(), + ); + let seven = FixMemRange::new( + 0x60000, + 0x6FFFF, + ((r & (0xff << 48)) >> 48).try_into().unwrap(), + ); + let eight = FixMemRange::new( + 0x70000, + 0x7FFFF, + ((r & (0xff << 56)) >> 56).try_into().unwrap(), + ); + [one, two, three, four, five, six, seven, eight] + } + } + + impl MTRRfix16K80000 { + /// Reads the raw register + #[inline] + pub fn read_raw() -> u64 { + unsafe { Self::MSR.read() } + } + + /// Writes the MTRR fixed range memory types. + /// + /// Does not preserve any bits, including reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to + /// break memory safety with wrong flags + #[inline] + pub unsafe fn write_raw(flags: u64) { + let mut msr = Self::MSR; + msr.write(flags); + } + + /// Reads the MTRR fixed range memory types. + /// The 256 Kbytes of memory spanning addresses 08_0000h to 0B_FFFFh are segmented into 16 16- + /// Kbyte ranges. Two MTRRs are used to characterize this address space. + pub fn read() -> FixMemRangeReg { + let r = Self::read_raw(); + let one = FixMemRange::new(0x80000, 0x83FFF, (r & 0xff).try_into().unwrap()); + let two = FixMemRange::new( + 0x84000, + 0x87FFF, + ((r & (0xff << 8)) >> 8).try_into().unwrap(), + ); + let three = FixMemRange::new( + 0x88000, + 0x8BFFF, + ((r & (0xff << 16)) >> 16).try_into().unwrap(), + ); + let four = FixMemRange::new( + 0x8C000, + 0x8FFFF, + ((r & (0xff << 24)) >> 24).try_into().unwrap(), + ); + let five = FixMemRange::new( + 0x90000, + 0x93FFF, + ((r & (0xff << 32)) >> 32).try_into().unwrap(), + ); + let six = FixMemRange::new( + 0x94000, + 0x97FFF, + ((r & (0xff << 40)) >> 40).try_into().unwrap(), + ); + let seven = FixMemRange::new( + 0x98000, + 0x9BFFF, + ((r & (0xff << 48)) >> 48).try_into().unwrap(), + ); + let eight = FixMemRange::new( + 0x9C000, + 0x9FFFF, + ((r & (0xff << 56)) >> 56).try_into().unwrap(), + ); + [one, two, three, four, five, six, seven, eight] + } + } + + impl MTRRfix16KA0000 { + /// Reads the raw register value + #[inline] + pub fn read_raw() -> u64 { + unsafe { Self::MSR.read() } + } + + /// Writes the MTRR fixed range memory types. + /// + /// Does not preserve any bits, including reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to + /// break memory safety with wrong flags + #[inline] + pub unsafe fn write_raw(flags: u64) { + let mut msr = Self::MSR; + msr.write(flags); + } + + /// Reads the MTRR fixed range memory types. + /// The 256 Kbytes of memory spanning addresses 08_0000h to 0B_FFFFh are segmented into 16 16- + /// Kbyte ranges. Two MTRRs are used to characterize this address space. + pub fn read() -> FixMemRangeReg { + let r = Self::read_raw(); + let one = FixMemRange::new(0xA0000, 0xA3FFF, (r & 0xff).try_into().unwrap()); + let two = FixMemRange::new( + 0xA4000, + 0xA7FFF, + ((r & (0xff << 8)) >> 8).try_into().unwrap(), + ); + let three = FixMemRange::new( + 0xA8000, + 0xABFFF, + ((r & (0xff << 16)) >> 16).try_into().unwrap(), + ); + let four = FixMemRange::new( + 0xAC000, + 0xAFFFF, + ((r & (0xff << 24)) >> 24).try_into().unwrap(), + ); + let five = FixMemRange::new( + 0xB0000, + 0xB3FFF, + ((r & (0xff << 32)) >> 32).try_into().unwrap(), + ); + let six = FixMemRange::new( + 0xB4000, + 0xB7FFF, + ((r & (0xff << 40)) >> 40).try_into().unwrap(), + ); + let seven = FixMemRange::new( + 0xB8000, + 0xBBFFF, + ((r & (0xff << 48)) >> 48).try_into().unwrap(), + ); + let eight = FixMemRange::new( + 0xBC000, + 0xBFFFF, + ((r & (0xff << 56)) >> 56).try_into().unwrap(), + ); + [one, two, three, four, five, six, seven, eight] + } + } + + impl MTRRfix4KC0000 { + /// Reads the MTRR fixed range memory types. + #[inline] + pub fn read_raw() -> u64 { + unsafe { Self::MSR.read() } + } + + /// Writes the MTRR fixed range memory types. + /// + /// Does not preserve any bits, including reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to + /// break memory safety with wrong flags + #[inline] + pub unsafe fn write_raw(flags: u64) { + let mut msr = Self::MSR; + msr.write(flags); + } + + /// The 256 Kbytes of memory spanning addresses 0C_0000h to 0F_FFFFh are segmented into 64 4- + /// Kbyte ranges. Eight MTRRs are used to characterize this address space. + pub fn read() -> FixMemRangeReg { + let r = Self::read_raw(); + let one = FixMemRange::new(0xC0000, 0xC0FFF, (r & 0xff).try_into().unwrap()); + let two = FixMemRange::new( + 0xC1000, + 0xC1FFF, + ((r & (0xff << 8)) >> 8).try_into().unwrap(), + ); + let three = FixMemRange::new( + 0xC2000, + 0xC2FFF, + ((r & (0xff << 16)) >> 16).try_into().unwrap(), + ); + let four = FixMemRange::new( + 0xC3000, + 0xC3FFF, + ((r & (0xff << 24)) >> 24).try_into().unwrap(), + ); + let five = FixMemRange::new( + 0xC4000, + 0xC4FFF, + ((r & (0xff << 32)) >> 32).try_into().unwrap(), + ); + let six = FixMemRange::new( + 0xC5000, + 0xC5FFF, + ((r & (0xff << 40)) >> 40).try_into().unwrap(), + ); + let seven = FixMemRange::new( + 0xC6000, + 0xCFFF, + ((r & (0xff << 48)) >> 48).try_into().unwrap(), + ); + let eight = FixMemRange::new( + 0xC7000, + 0xC7FFF, + ((r & (0xff << 56)) >> 56).try_into().unwrap(), + ); + [one, two, three, four, five, six, seven, eight] + } + } + + impl MTRRfix4KC8000 { + /// Reads the MTRR fixed range memory types. + #[inline] + pub fn read_raw() -> u64 { + unsafe { Self::MSR.read() } + } + + /// Writes the MTRR fixed range memory types. + /// + /// Does not preserve any bits, including reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to + /// break memory safety with wrong flags + #[inline] + pub unsafe fn write_raw(flags: u64) { + let mut msr = Self::MSR; + msr.write(flags); + } + + /// The 256 Kbytes of memory spanning addresses 0C_0000h to 0F_FFFFh are segmented into 64 4- + /// Kbyte ranges. Eight MTRRs are used to characterize this address space. + pub fn read() -> FixMemRangeReg { + let r = Self::read_raw(); + let one = FixMemRange::new(0xC8000, 0xC8FFF, (r & 0xff).try_into().unwrap()); + let two = FixMemRange::new( + 0xC9000, + 0xC9FFF, + ((r & (0xff << 8)) >> 8).try_into().unwrap(), + ); + let three = FixMemRange::new( + 0xCA000, + 0xCAFFF, + ((r & (0xff << 16)) >> 16).try_into().unwrap(), + ); + let four = FixMemRange::new( + 0xCB000, + 0xCBFFF, + ((r & (0xff << 24)) >> 24).try_into().unwrap(), + ); + let five = FixMemRange::new( + 0xCC000, + 0xCCFFF, + ((r & (0xff << 32)) >> 32).try_into().unwrap(), + ); + let six = FixMemRange::new( + 0xCD000, + 0xCDFFF, + ((r & (0xff << 40)) >> 40).try_into().unwrap(), + ); + let seven = FixMemRange::new( + 0xCE000, + 0xCEFFF, + ((r & (0xff << 48)) >> 48).try_into().unwrap(), + ); + let eight = FixMemRange::new( + 0xCF000, + 0xCFFFF, + ((r & (0xff << 56)) >> 56).try_into().unwrap(), + ); + [one, two, three, four, five, six, seven, eight] + } + } + + impl MTRRfix4KD0000 { + /// Reads the MTRR fixed range memory types. + #[inline] + pub fn read_raw() -> u64 { + unsafe { Self::MSR.read() } + } + + /// Writes the MTRR fixed range memory types. + /// + /// Does not preserve any bits, including reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to + /// break memory safety with wrong flags + #[inline] + pub unsafe fn write_raw(flags: u64) { + let mut msr = Self::MSR; + msr.write(flags); + } + + /// The 256 Kbytes of memory spanning addresses 0C_0000h to 0F_FFFFh are segmented into 64 4- + /// Kbyte ranges. Eight MTRRs are used to characterize this address space. + pub fn read() -> FixMemRangeReg { + let r = Self::read_raw(); + let one = FixMemRange::new(0xD0000, 0xD0FFF, (r & 0xff).try_into().unwrap()); + let two = FixMemRange::new( + 0xD1000, + 0xD1FFF, + ((r & (0xff << 8)) >> 8).try_into().unwrap(), + ); + let three = FixMemRange::new( + 0xD2000, + 0xD2FFF, + ((r & (0xff << 16)) >> 16).try_into().unwrap(), + ); + let four = FixMemRange::new( + 0xD3000, + 0xD3FFF, + ((r & (0xff << 24)) >> 24).try_into().unwrap(), + ); + let five = FixMemRange::new( + 0xD4000, + 0xD4FFF, + ((r & (0xff << 32)) >> 32).try_into().unwrap(), + ); + let six = FixMemRange::new( + 0xD5000, + 0xD5FFF, + ((r & (0xff << 40)) >> 40).try_into().unwrap(), + ); + let seven = FixMemRange::new( + 0xD6000, + 0xD6FFF, + ((r & (0xff << 48)) >> 48).try_into().unwrap(), + ); + let eight = FixMemRange::new( + 0xD7000, + 0xD7FFF, + ((r & (0xff << 56)) >> 56).try_into().unwrap(), + ); + [one, two, three, four, five, six, seven, eight] + } + } + + impl MTRRfix4KD8000 { + /// Reads the MTRR fixed range memory types. + #[inline] + pub fn read_raw() -> u64 { + unsafe { Self::MSR.read() } + } + + /// Writes the MTRR fixed range memory types. + /// + /// Does not preserve any bits, including reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to + /// break memory safety with wrong flags + #[inline] + pub unsafe fn write_raw(flags: u64) { + let mut msr = Self::MSR; + msr.write(flags); + } + + /// The 256 Kbytes of memory spanning addresses 0C_0000h to 0F_FFFFh are segmented into 64 4- + /// Kbyte ranges. Eight MTRRs are used to characterize this address space. + pub fn read() -> FixMemRangeReg { + let r = Self::read_raw(); + let one = FixMemRange::new(0xD8000, 0xD8FFF, (r & 0xff).try_into().unwrap()); + let two = FixMemRange::new( + 0xD9000, + 0xD9FFF, + ((r & (0xff << 8)) >> 8).try_into().unwrap(), + ); + let three = FixMemRange::new( + 0xDA000, + 0xDAFFF, + ((r & (0xff << 16)) >> 16).try_into().unwrap(), + ); + let four = FixMemRange::new( + 0xDB000, + 0xDBFFF, + ((r & (0xff << 24)) >> 24).try_into().unwrap(), + ); + let five = FixMemRange::new( + 0xDC000, + 0xDCFFF, + ((r & (0xff << 32)) >> 32).try_into().unwrap(), + ); + let six = FixMemRange::new( + 0xDD000, + 0xDDFFF, + ((r & (0xff << 40)) >> 40).try_into().unwrap(), + ); + let seven = FixMemRange::new( + 0xDE000, + 0xDEFFF, + ((r & (0xff << 48)) >> 48).try_into().unwrap(), + ); + let eight = FixMemRange::new( + 0xDF000, + 0xDFFFF, + ((r & (0xff << 56)) >> 56).try_into().unwrap(), + ); + [one, two, three, four, five, six, seven, eight] + } + } + + impl MTRRfix4KE0000 { + /// Reads the MTRR fixed range memory types. + #[inline] + pub fn read_raw() -> u64 { + unsafe { Self::MSR.read() } + } + + /// Writes the MTRR fixed range memory types. + /// + /// Does not preserve any bits, including reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to + /// break memory safety with wrong flags + #[inline] + pub unsafe fn write_raw(flags: u64) { + let mut msr = Self::MSR; + msr.write(flags); + } + + /// The 256 Kbytes of memory spanning addresses 0C_0000h to 0F_FFFFh are segmented into 64 4- + /// Kbyte ranges. Eight MTRRs are used to characterize this address space. + pub fn read() -> FixMemRangeReg { + let r = Self::read_raw(); + let one = FixMemRange::new(0xE0000, 0xE0FFF, (r & 0xff).try_into().unwrap()); + let two = FixMemRange::new( + 0xE1000, + 0xE1FFF, + ((r & (0xff << 8)) >> 8).try_into().unwrap(), + ); + let three = FixMemRange::new( + 0xE2000, + 0xE2FFF, + ((r & (0xff << 16)) >> 16).try_into().unwrap(), + ); + let four = FixMemRange::new( + 0xE3000, + 0xE3FFF, + ((r & (0xff << 24)) >> 24).try_into().unwrap(), + ); + let five = FixMemRange::new( + 0xE4000, + 0xE4FFF, + ((r & (0xff << 32)) >> 32).try_into().unwrap(), + ); + let six = FixMemRange::new( + 0xE5000, + 0xE5FFF, + ((r & (0xff << 40)) >> 40).try_into().unwrap(), + ); + let seven = FixMemRange::new( + 0xE6000, + 0xE6FFF, + ((r & (0xff << 48)) >> 48).try_into().unwrap(), + ); + let eight = FixMemRange::new( + 0xE7000, + 0xE7FFF, + ((r & (0xff << 56)) >> 56).try_into().unwrap(), + ); + [one, two, three, four, five, six, seven, eight] + } + } + + impl MTRRfix4KE8000 { + /// Reads the MTRR fixed range memory types. + #[inline] + pub fn read_raw() -> u64 { + unsafe { Self::MSR.read() } + } + + /// Writes the MTRR fixed range memory types. + /// + /// Does not preserve any bits, including reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to + /// break memory safety with wrong flags + #[inline] + pub unsafe fn write_raw(flags: u64) { + let mut msr = Self::MSR; + msr.write(flags); + } + + /// The 256 Kbytes of memory spanning addresses 0C_0000h to 0F_FFFFh are segmented into 64 4- + /// Kbyte ranges. Eight MTRRs are used to characterize this address space. + pub fn read() -> FixMemRangeReg { + let r = Self::read_raw(); + let one = FixMemRange::new(0xE8000, 0xE8FFF, (r & 0xff).try_into().unwrap()); + let two = FixMemRange::new( + 0xE9000, + 0xE9FFF, + ((r & (0xff << 8)) >> 8).try_into().unwrap(), + ); + let three = FixMemRange::new( + 0xEA000, + 0xEAFFF, + ((r & (0xff << 16)) >> 16).try_into().unwrap(), + ); + let four = FixMemRange::new( + 0xEA000, + 0xEAFFF, + ((r & (0xff << 24)) >> 24).try_into().unwrap(), + ); + let five = FixMemRange::new( + 0xEB000, + 0xEBFFF, + ((r & (0xff << 32)) >> 32).try_into().unwrap(), + ); + let six = FixMemRange::new( + 0xEC000, + 0xECFFF, + ((r & (0xff << 40)) >> 40).try_into().unwrap(), + ); + let seven = FixMemRange::new( + 0xED000, + 0xEDFFF, + ((r & (0xff << 48)) >> 48).try_into().unwrap(), + ); + let eight = FixMemRange::new( + 0xEE000, + 0xEEFFF, + ((r & (0xff << 56)) >> 56).try_into().unwrap(), + ); + [one, two, three, four, five, six, seven, eight] + } + } + + impl MTRRfix4KF0000 { + /// Reads the MTRR fixed range memory types. + #[inline] + pub fn read_raw() -> u64 { + unsafe { Self::MSR.read() } + } + + /// Writes the MTRR fixed range memory types. + /// + /// Does not preserve any bits, including reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to + /// break memory safety with wrong flags + #[inline] + pub unsafe fn write_raw(flags: u64) { + let mut msr = Self::MSR; + msr.write(flags); + } + + /// The 256 Kbytes of memory spanning addresses 0C_0000h to 0F_FFFFh are segmented into 64 4- + /// Kbyte ranges. Eight MTRRs are used to characterize this address space. + pub fn read() -> FixMemRangeReg { + let r = Self::read_raw(); + let one = FixMemRange::new(0xF0000, 0xF0FFF, (r & 0xff).try_into().unwrap()); + let two = FixMemRange::new( + 0xF1000, + 0xF1FFF, + ((r & (0xff << 8)) >> 8).try_into().unwrap(), + ); + let three = FixMemRange::new( + 0xF2000, + 0xF2FFF, + ((r & (0xff << 16)) >> 16).try_into().unwrap(), + ); + let four = FixMemRange::new( + 0xF3000, + 0xF3FFF, + ((r & (0xff << 24)) >> 24).try_into().unwrap(), + ); + let five = FixMemRange::new( + 0xF4000, + 0xF4FFF, + ((r & (0xff << 32)) >> 32).try_into().unwrap(), + ); + let six = FixMemRange::new( + 0xF5000, + 0xF5FFF, + ((r & (0xff << 40)) >> 40).try_into().unwrap(), + ); + let seven = FixMemRange::new( + 0xF6000, + 0xF6FFF, + ((r & (0xff << 48)) >> 48).try_into().unwrap(), + ); + let eight = FixMemRange::new( + 0xF7000, + 0xF7FFF, + ((r & (0xff << 56)) >> 56).try_into().unwrap(), + ); + [one, two, three, four, five, six, seven, eight] + } + } + + impl MTRRfix4KF8000 { + /// Reads the MTRR fixed range memory types. + #[inline] + pub fn read_raw() -> u64 { + unsafe { Self::MSR.read() } + } + + /// Writes the MTRR fixed range memory types. + /// + /// Does not preserve any bits, including reserved fields. + /// + /// ## Safety + /// + /// Unsafe because it's possible to + /// break memory safety with wrong flags + #[inline] + pub unsafe fn write_raw(flags: u64) { + let mut msr = Self::MSR; + msr.write(flags); + } + + /// The 256 Kbytes of memory spanning addresses 0C_0000h to 0F_FFFFh are segmented into 64 4- + /// Kbyte ranges. Eight MTRRs are used to characterize this address space. + pub fn read() -> FixMemRangeReg { + let r = Self::read_raw(); + let one = FixMemRange::new(0xF8000, 0xF8FFF, (r & 0xff).try_into().unwrap()); + let two = FixMemRange::new( + 0xF9000, + 0xF9FFF, + ((r & (0xff << 8)) >> 8).try_into().unwrap(), + ); + let three = FixMemRange::new( + 0xFA000, + 0xFAFFF, + ((r & (0xff << 16)) >> 16).try_into().unwrap(), + ); + let four = FixMemRange::new( + 0xFB000, + 0xFBFFF, + ((r & (0xff << 24)) >> 24).try_into().unwrap(), + ); + let five = FixMemRange::new( + 0xFC000, + 0xFCFFF, + ((r & (0xff << 32)) >> 32).try_into().unwrap(), + ); + let six = FixMemRange::new( + 0xFD000, + 0xFDFFF, + ((r & (0xff << 40)) >> 40).try_into().unwrap(), + ); + let seven = FixMemRange::new( + 0xFE000, + 0xFEFFF, + ((r & (0xff << 48)) >> 48).try_into().unwrap(), + ); + let eight = FixMemRange::new( + 0xFF000, + 0xFFFFF, + ((r & (0xff << 56)) >> 56).try_into().unwrap(), + ); + [one, two, three, four, five, six, seven, eight] + } + } +} diff --git a/src/structures/gdt.rs b/src/structures/gdt.rs index 5942030d..f6c93441 100644 --- a/src/structures/gdt.rs +++ b/src/structures/gdt.rs @@ -44,7 +44,7 @@ use crate::registers::segmentation::{Segment, CS, SS}; /// // Add entry for TSS, call gdt.load() then update segment registers /// ``` -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Copy)] pub struct GlobalDescriptorTable { table: [u64; 8], len: usize, diff --git a/src/structures/idt.rs b/src/structures/idt.rs index fe0d467a..9b5ebf9c 100644 --- a/src/structures/idt.rs +++ b/src/structures/idt.rs @@ -810,7 +810,7 @@ impl_set_handler_fn!(DivergingHandlerFuncWithErrCode); /// Represents the options field of an IDT entry. #[repr(transparent)] -#[derive(Clone, Copy, PartialEq)] +#[derive(Clone, Copy, PartialEq, Eq)] pub struct EntryOptions(u16); impl fmt::Debug for EntryOptions { @@ -1090,7 +1090,7 @@ pub enum DescriptorTable { /// * Intel Volume 3A: 6.3.1 #[repr(u8)] #[non_exhaustive] -#[derive(Copy, Clone, Debug, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum ExceptionVector { /// Error during Division Division = 0x00, @@ -1486,7 +1486,7 @@ mod test { unsafe { frame .as_mut() - .update(|f| f.instruction_pointer = f.instruction_pointer + 2u64); + .update(|f| f.instruction_pointer += 2u64); } } } diff --git a/src/structures/paging/mapper/mapped_page_table.rs b/src/structures/paging/mapper/mapped_page_table.rs index 5537fd02..a2b4c59a 100644 --- a/src/structures/paging/mapper/mapped_page_table.rs +++ b/src/structures/paging/mapper/mapped_page_table.rs @@ -39,7 +39,7 @@ impl<'a, P: PageTableFrameMapping> MappedPageTable<'a, P> { /// Returns a mutable reference to the wrapped level 4 `PageTable` instance. pub fn level_4_table(&mut self) -> &mut PageTable { - &mut self.level_4_table + self.level_4_table } /// Returns the `PageTableFrameMapping` used for converting virtual to physical addresses. diff --git a/src/structures/paging/mapper/recursive_page_table.rs b/src/structures/paging/mapper/recursive_page_table.rs index 7dc1f639..fb3f7a6a 100644 --- a/src/structures/paging/mapper/recursive_page_table.rs +++ b/src/structures/paging/mapper/recursive_page_table.rs @@ -85,7 +85,7 @@ impl<'a> RecursivePageTable<'a> { /// Returns a mutable reference to the wrapped level 4 `PageTable` instance. pub fn level_4_table(&mut self) -> &mut PageTable { - &mut self.p4 + self.p4 } /// Internal helper function to create the page table of the next level if needed.