Skip to content

Commit

Permalink
Added XCR0 register
Browse files Browse the repository at this point in the history
  • Loading branch information
Qubasa committed Apr 1, 2021
1 parent 1b3b082 commit faf8617
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/registers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
pub mod control;
pub mod model_specific;
pub mod rflags;
pub mod xcontrol;

#[cfg(feature = "instructions")]
pub use crate::instructions::segmentation::{rdfsbase, rdgsbase, wrfsbase, wrgsbase};
Expand Down
95 changes: 95 additions & 0 deletions src/registers/xcontrol.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
//! Access to various extended system registers
use bitflags::bitflags;

/// Extended feature enable mask register
#[derive(Debug)]
pub struct XCr0;

bitflags! {
/// Configuration flags of the XCr0 register.
pub struct XCr0Flags: u64 {
/// Enables x87 FPU
const X87 = 1;
/// Enables 128-bit (legacy) SSE
/// Must be set to enable AVX and YMM
const SSE = 1<<1;
/// Enables 256-bit SSE
/// Must be set to enable AVX
const YMM = 1<<2;
/// When set, PKRU state management is supported by
/// ZSAVE/XRSTOR
const MPK = 1<<9;
/// When set the Lightweight Profiling extensions are enabled
const LWP = 1<<62;
}
}

mod x86_64 {
use super::*;
impl XCr0 {
/// Read the current set of XCR0 flags.
#[inline]
pub fn read() -> XCr0Flags {
XCr0Flags::from_bits_truncate(Self::read_raw())
}

/// Read the current raw XCR0 value.
#[inline]
pub fn read_raw() -> u64 {
let low: u32;
let high: u32;

unsafe {
asm!("
xor rcx, rcx
xgetbv
",
lateout("rdx") high,
lateout("rax") low,
lateout("rcx") _,
);
}

return (high as u64) << 32 | (low as u64);
}

/// Write XCR0 flags.
///
/// Preserves the value of reserved fields.
///
/// ## Safety
///
/// This function is unsafe because it's possible to
/// enable features that are not supported by the architecture
#[inline]
pub unsafe fn write(flags: XCr0Flags) {
let old_value = Self::read_raw();
let reserved = old_value & !(XCr0Flags::all().bits());
let new_value = reserved | flags.bits();

Self::write_raw(new_value);
}

/// Write raw XCR0 flags.
///
/// Does _not_ preserve any values, including reserved fields.
///
/// ## Safety
///
/// This function is unsafe because it's possible to
/// enable features that are not supported by the architecture
#[inline]
pub unsafe fn write_raw(value: u64) {
let high: u32 = (value >> 32) as u32;
let low: u32 = (value) as u32;
asm!("
xor ecx, ecx
xsetbv
",
in("edx") high,
in("eax") low,
lateout("ecx") _,
);
}
}
}

0 comments on commit faf8617

Please sign in to comment.