Skip to content

Commit 53e8661

Browse files
authored
Merge pull request #1934 from sayantn/fix-xsave
Fix xsave segfaults
2 parents fc5ac13 + aa8bd37 commit 53e8661

File tree

3 files changed

+33
-44
lines changed

3 files changed

+33
-44
lines changed

ci/docker/x86_64-unknown-linux-gnu/Dockerfile

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,3 @@ RUN tar -xJf sde.tar.xz --strip-components=1 -C intel-sde
1414
ENV CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="/intel-sde/sde64 \
1515
-cpuid-in /checkout/ci/docker/x86_64-unknown-linux-gnu/cpuid.def \
1616
-rtm-mode full -tsx --"
17-
# These tests fail with SDE as it doesn't support saving register data
18-
ENV STDARCH_TEST_SKIP_FUNCTION="xsave,xsaveopt,xsave64,xsaveopt64"

crates/core_arch/src/x86/xsave.rs

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -159,29 +159,39 @@ pub unsafe fn _xrstors(mem_addr: *const u8, rs_mask: u64) {
159159
xrstors(mem_addr, (rs_mask >> 32) as u32, rs_mask as u32);
160160
}
161161

162+
#[cfg(test)]
163+
pub(crate) use tests::XsaveArea;
164+
162165
#[cfg(test)]
163166
mod tests {
164-
use std::{fmt, prelude::v1::*};
167+
use std::boxed::Box;
165168

166169
use crate::core_arch::x86::*;
167170
use stdarch_test::simd_test;
168171

169-
#[repr(align(64))]
170172
#[derive(Debug)]
171-
struct XsaveArea {
172-
// max size for 256-bit registers is 800 bytes:
173-
// see https://software.intel.com/en-us/node/682996
174-
// max size for 512-bit registers is 2560 bytes:
175-
// FIXME: add source
176-
data: [u8; 2560],
173+
pub(crate) struct XsaveArea {
174+
data: Box<[AlignedArray]>,
177175
}
178176

177+
#[repr(align(64))]
178+
#[derive(Copy, Clone, Debug)]
179+
struct AlignedArray([u8; 64]);
180+
179181
impl XsaveArea {
180-
fn new() -> XsaveArea {
181-
XsaveArea { data: [0; 2560] }
182+
#[target_feature(enable = "xsave")]
183+
pub(crate) fn new() -> XsaveArea {
184+
// `CPUID.(EAX=0DH,ECX=0):ECX` contains the size required to hold all supported xsave
185+
// components. `EBX` contains the size required to hold all xsave components currently
186+
// enabled in `XCR0`. We are using `ECX` to ensure enough space in all scenarios
187+
let CpuidResult { ecx, .. } = unsafe { __cpuid(0x0d) };
188+
189+
XsaveArea {
190+
data: vec![AlignedArray([0; 64]); ecx.div_ceil(64) as usize].into_boxed_slice(),
191+
}
182192
}
183-
fn ptr(&mut self) -> *mut u8 {
184-
self.data.as_mut_ptr()
193+
pub(crate) fn ptr(&mut self) -> *mut u8 {
194+
self.data.as_mut_ptr().cast()
185195
}
186196
}
187197

crates/core_arch/src/x86_64/xsave.rs

Lines changed: 11 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -126,39 +126,20 @@ pub unsafe fn _xrstors64(mem_addr: *const u8, rs_mask: u64) {
126126

127127
#[cfg(test)]
128128
mod tests {
129-
use crate::core_arch::x86_64::xsave;
130-
use std::fmt;
129+
use crate::core_arch::x86::*;
130+
use crate::core_arch::x86_64::*;
131131
use stdarch_test::simd_test;
132132

133-
#[repr(align(64))]
134-
#[derive(Debug)]
135-
struct XsaveArea {
136-
// max size for 256-bit registers is 800 bytes:
137-
// see https://software.intel.com/en-us/node/682996
138-
// max size for 512-bit registers is 2560 bytes:
139-
// FIXME: add source
140-
data: [u8; 2560],
141-
}
142-
143-
impl XsaveArea {
144-
fn new() -> XsaveArea {
145-
XsaveArea { data: [0; 2560] }
146-
}
147-
fn ptr(&mut self) -> *mut u8 {
148-
self.data.as_mut_ptr()
149-
}
150-
}
151-
152133
#[simd_test(enable = "xsave")]
153134
#[cfg_attr(miri, ignore)] // Register saving/restoring is not supported in Miri
154135
unsafe fn test_xsave64() {
155136
let m = 0xFFFFFFFFFFFFFFFF_u64; //< all registers
156137
let mut a = XsaveArea::new();
157138
let mut b = XsaveArea::new();
158139

159-
xsave::_xsave64(a.ptr(), m);
160-
xsave::_xrstor64(a.ptr(), m);
161-
xsave::_xsave64(b.ptr(), m);
140+
_xsave64(a.ptr(), m);
141+
_xrstor64(a.ptr(), m);
142+
_xsave64(b.ptr(), m);
162143
}
163144

164145
#[simd_test(enable = "xsave,xsaveopt")]
@@ -168,9 +149,9 @@ mod tests {
168149
let mut a = XsaveArea::new();
169150
let mut b = XsaveArea::new();
170151

171-
xsave::_xsaveopt64(a.ptr(), m);
172-
xsave::_xrstor64(a.ptr(), m);
173-
xsave::_xsaveopt64(b.ptr(), m);
152+
_xsaveopt64(a.ptr(), m);
153+
_xrstor64(a.ptr(), m);
154+
_xsaveopt64(b.ptr(), m);
174155
}
175156

176157
#[simd_test(enable = "xsave,xsavec")]
@@ -180,8 +161,8 @@ mod tests {
180161
let mut a = XsaveArea::new();
181162
let mut b = XsaveArea::new();
182163

183-
xsave::_xsavec64(a.ptr(), m);
184-
xsave::_xrstor64(a.ptr(), m);
185-
xsave::_xsavec64(b.ptr(), m);
164+
_xsavec64(a.ptr(), m);
165+
_xrstor64(a.ptr(), m);
166+
_xsavec64(b.ptr(), m);
186167
}
187168
}

0 commit comments

Comments
 (0)