-
Notifications
You must be signed in to change notification settings - Fork 133
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
96 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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") _, | ||
); | ||
} | ||
} | ||
} |