Skip to content

Commit 8d467ea

Browse files
committed
XCr0: Update the asserts to check all conditions
This avoids getting a #GP when writing. Signed-off-by: Joe Richey <[email protected]>
1 parent d4cb7bf commit 8d467ea

File tree

1 file changed

+25
-5
lines changed

1 file changed

+25
-5
lines changed

src/registers/xcontrol.rs

+25-5
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ mod x86_64 {
8282
/// Write XCR0 flags.
8383
///
8484
/// Preserves the value of reserved fields.
85+
/// Panics if invalid combinations of [`XCr0Flags`] are set.
8586
///
8687
/// ## Safety
8788
///
@@ -92,13 +93,32 @@ mod x86_64 {
9293
let old_value = Self::read_raw();
9394
let reserved = old_value & !(XCr0Flags::all().bits());
9495
let new_value = reserved | flags.bits();
96+
9597
assert!(flags.contains(XCr0Flags::X87), "The X87 flag must be set");
96-
assert!((flags.contains(XCr0Flags::AVX) && flags.contains(XCr0Flags::OPMASK) && flags.contains(XCr0Flags::ZMM_HI256) && flags.contains(XCr0Flags::HI16_ZMM)) || !(flags.contains(XCr0Flags::AVX) && flags.contains(XCr0Flags::OPMASK) && flags.contains(XCr0Flags::ZMM_HI256) && flags.contains(XCr0Flags::HI16_ZMM)), "You must enable AVX to set or unset any of XCR0.opmask, XCR0.ZMM_Hi256, and XCR0.Hi16_ZMM");
97-
if !flags.contains(XCr0Flags::AVX) && (flags.contains(XCr0Flags::OPMASK) || flags.contains(XCr0Flags::ZMM_HI256) || flags.contains(XCr0Flags::HI16_ZMM)) {
98-
panic!("You must have AVX enabled to set XCR0.opmask, XCR0.ZMM_Hi256, or XCR0.Hi16_ZMM");
98+
if flags.contains(XCr0Flags::YMM) {
99+
assert!(
100+
flags.contains(XCr0Flags::SSE),
101+
"AVX/YMM cannot be enabled without enabling SSE"
102+
);
103+
}
104+
let mpx = XCr0Flags::BNDREG | XCr0Flags::BNDCSR;
105+
if flags.intersects(mpx) {
106+
assert!(
107+
flags.contains(mpx),
108+
"MPX flags XCr0.BNDREG and XCr0.BNDCSR must be set and unset together"
109+
);
110+
}
111+
let avx512 = XCr0Flags::OPMASK | XCr0Flags::ZMM_HI256 | XCr0Flags::HI16_ZMM;
112+
if flags.intersects(avx512) {
113+
assert!(
114+
flags.contains(XCr0Flags::YMM),
115+
"AVX-512 cannot be enabled without enabling AVX/YMM"
116+
);
117+
assert!(
118+
flags.contains(avx512),
119+
"AVX-512 flags XCR0.opmask, XCR0.ZMM_Hi256, and XCR0.Hi16_ZMM must be set and unset together"
120+
);
99121
}
100-
assert!((flags.contains(XCr0Flags::BNDREG) && flags.contains(XCr0Flags::BNDCSR)) || !(flags.contains(XCr0Flags::BNDREG) && flags.contains(XCr0Flags::BNDCSR)), "BNDREG and BNDCSR must be set and unset together");
101-
assert!((flags.contains(XCr0Flags::OPMASK) && flags.contains(XCr0Flags::ZMM_HI256) && flags.contains(XCr0Flags::HI16_ZMM)) || !(flags.contains(XCr0Flags::OPMASK) && flags.contains(XCr0Flags::ZMM_HI256) && flags.contains(XCr0Flags::HI16_ZMM)), "You must set or unset all of XCR0.opmask, XCR0.ZMM_Hi256, and XCR0.Hi16_ZMM");
102122

103123
Self::write_raw(new_value);
104124
}

0 commit comments

Comments
 (0)