Skip to content

Commit 6cec736

Browse files
authored
Added XCR0 register (#239)
1 parent 1b3b082 commit 6cec736

File tree

2 files changed

+97
-0
lines changed

2 files changed

+97
-0
lines changed

src/registers/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
pub mod control;
44
pub mod model_specific;
55
pub mod rflags;
6+
pub mod xcontrol;
67

78
#[cfg(feature = "instructions")]
89
pub use crate::instructions::segmentation::{rdfsbase, rdgsbase, wrfsbase, wrgsbase};

src/registers/xcontrol.rs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
//! Access to various extended system registers
2+
use bitflags::bitflags;
3+
4+
/// Extended feature enable mask register
5+
#[derive(Debug)]
6+
pub struct XCr0;
7+
8+
bitflags! {
9+
/// Configuration flags of the XCr0 register.
10+
pub struct XCr0Flags: u64 {
11+
/// Enables x87 FPU
12+
const X87 = 1;
13+
/// Enables 128-bit (legacy) SSE
14+
/// Must be set to enable AVX and YMM
15+
const SSE = 1<<1;
16+
/// Enables 256-bit SSE
17+
/// Must be set to enable AVX
18+
const YMM = 1<<2;
19+
/// When set, PKRU state management is supported by
20+
/// ZSAVE/XRSTOR
21+
const MPK = 1<<9;
22+
/// When set the Lightweight Profiling extensions are enabled
23+
const LWP = 1<<62;
24+
}
25+
}
26+
27+
#[cfg(all(feature = "instructions", feature = "inline_asm"))]
28+
mod x86_64 {
29+
use super::*;
30+
impl XCr0 {
31+
/// Read the current set of XCR0 flags.
32+
#[inline]
33+
pub fn read() -> XCr0Flags {
34+
XCr0Flags::from_bits_truncate(Self::read_raw())
35+
}
36+
37+
/// Read the current raw XCR0 value.
38+
#[inline]
39+
pub fn read_raw() -> u64 {
40+
let low: u32;
41+
let high: u32;
42+
43+
unsafe {
44+
asm!("
45+
xor rcx, rcx
46+
xgetbv
47+
",
48+
lateout("rdx") high,
49+
lateout("rax") low,
50+
lateout("rcx") _,
51+
);
52+
}
53+
54+
(high as u64) << 32 | (low as u64)
55+
}
56+
57+
/// Write XCR0 flags.
58+
///
59+
/// Preserves the value of reserved fields.
60+
///
61+
/// ## Safety
62+
///
63+
/// This function is unsafe because it's possible to
64+
/// enable features that are not supported by the architecture
65+
#[inline]
66+
pub unsafe fn write(flags: XCr0Flags) {
67+
let old_value = Self::read_raw();
68+
let reserved = old_value & !(XCr0Flags::all().bits());
69+
let new_value = reserved | flags.bits();
70+
71+
Self::write_raw(new_value);
72+
}
73+
74+
/// Write raw XCR0 flags.
75+
///
76+
/// Does _not_ preserve any values, including reserved fields.
77+
///
78+
/// ## Safety
79+
///
80+
/// This function is unsafe because it's possible to
81+
/// enable features that are not supported by the architecture
82+
#[inline]
83+
pub unsafe fn write_raw(value: u64) {
84+
let high: u32 = (value >> 32) as u32;
85+
let low: u32 = (value) as u32;
86+
asm!("
87+
xor ecx, ecx
88+
xsetbv
89+
",
90+
in("edx") high,
91+
in("eax") low,
92+
lateout("ecx") _,
93+
);
94+
}
95+
}
96+
}

0 commit comments

Comments
 (0)