x86: mask simd exceptions for userspace

This commit is contained in:
Mark Poliakov 2024-11-01 14:03:23 +02:00
parent 98fe60bc12
commit 17dc8e9a4d
8 changed files with 94 additions and 11 deletions

2
Cargo.lock generated
View File

@ -898,7 +898,9 @@ name = "kernel-arch-x86"
version = "0.1.0"
dependencies = [
"bitflags 2.6.0",
"bytemuck",
"kernel-arch-interface",
"static_assertions",
"tock-registers",
]

View File

@ -123,7 +123,7 @@ impl<K: KernelTableManager, PA: PhysicalMemoryAllocator<Address = PhysicalAddres
Ok(Self {
inner: UnsafeCell::new(Inner { sp }),
fpu_context: UnsafeCell::new(FpuContext::new()),
fpu_context: UnsafeCell::new(FpuContext::new(true)),
stack_base_phys,
stack_size: USER_TASK_PAGES * 0x1000,
@ -159,7 +159,7 @@ impl<K: KernelTableManager, PA: PhysicalMemoryAllocator<Address = PhysicalAddres
Ok(Self {
inner: UnsafeCell::new(Inner { sp }),
fpu_context: UnsafeCell::new(FpuContext::new()),
fpu_context: UnsafeCell::new(FpuContext::new(false)),
stack_base_phys,
stack_size: KERNEL_TASK_PAGES * 0x1000,

View File

@ -6,8 +6,10 @@ edition = "2021"
[dependencies]
kernel-arch-interface = { path = "../interface" }
bytemuck = { version = "1.16.1", features = ["derive"] }
bitflags = "2.6.0"
tock-registers = "0.8.1"
static_assertions = "1.1.0"
[lints.rust]
unexpected_cfgs = { level = "allow", check-cfg = ['cfg(rust_analyzer)'] }

View File

@ -217,6 +217,9 @@ fn enable_features(ecx: EcxFeatures, edx: EdxFeatures) {
}
}
if edx.contains(EdxFeatures::SSE) && ecx.contains(EcxFeatures::XSAVE) {
assert!(edx.contains(EdxFeatures::FPU));
CR0.modify(CR0::MP::SET);
CR4.modify(CR4::OSXMMEXCPT::SET);
XCR0.modify(XCR0::SSE::SET);
}
if ecx.contains(EcxFeatures::AVX) {

View File

@ -183,6 +183,8 @@ mod cr4 {
OSXSAVE OFFSET(18) NUMBITS(1) [],
/// If set, PCID is enabled
PCIDE OFFSET(17) NUMBITS(1) [],
/// Indicates OS support for unmasked SIMD exceptions
OSXMMEXCPT OFFSET(10) NUMBITS(1) [],
/// Indicates OS support for FXSAVE and FXRSTOR instructions
OSFXSR OFFSET(9) NUMBITS(1) [],
/// Performance-Monitoring Counter enable
@ -424,21 +426,89 @@ pub use msr::ia32_sfmask::MSR_IA32_SFMASK;
pub use msr::ia32_star::MSR_IA32_STAR;
pub use xcr0::XCR0;
use bytemuck::{Pod, Zeroable};
use static_assertions::const_assert_eq;
#[cfg(any(target_arch = "x86", rust_analyzer))]
#[derive(Clone, Copy, Pod, Zeroable)]
#[repr(C, align(16))]
struct FpuContextInner {
fcw: u16,
fsw: u16,
ftw: u8,
_0: u8,
fop: u16,
fip: u32,
fcs: u16,
_1: u16,
fdp: u32,
fds: u16,
_2: u16,
mxcsr: u32,
mxcsr_mask: u32,
mm: [u128; 8],
xmm: [u128; 8],
_3: [u128; 14],
}
#[cfg(any(target_arch = "x86_64", rust_analyzer))]
#[derive(Clone, Copy, Pod, Zeroable)]
#[repr(C, align(16))]
struct FpuContextInner {
fcw: u16,
fsw: u16,
ftw: u8,
_0: u8,
fop: u16,
fip: u64,
fdp: u64,
mxcsr: u32,
mxcsr_mask: u32,
mm: [u128; 8],
xmm: [u128; 16],
_1: [u128; 6],
}
const_assert_eq!(size_of::<FpuContextInner>(), 512);
#[repr(C, align(16))]
pub struct FpuContext {
inner: [u8; 512],
inner: FpuContextInner,
}
impl FpuContext {
pub const fn new() -> Self {
Self { inner: [0; 512] }
pub fn new(mask_exceptions: bool) -> Self {
const ALL_EXCEPTIONS_MASK: u32 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8);
let mut inner = FpuContextInner::zeroed();
if mask_exceptions {
inner.mxcsr |= ALL_EXCEPTIONS_MASK;
}
Self { inner }
}
pub fn store(this: *mut Self) {
unsafe { core::arch::asm!("fxsave ({})", in(reg) this, options(att_syntax)) }
#[cfg(any(target_arch = "x86", rust_analyzer))]
unsafe {
core::arch::x86::_fxsave(this as _)
}
#[cfg(any(target_arch = "x86_64", rust_analyzer))]
unsafe {
core::arch::x86_64::_fxsave64(this as _)
}
}
pub fn restore(this: *const Self) {
unsafe { core::arch::asm!("fxrstor ({})", in(reg) this, options(att_syntax)) }
#[cfg(any(target_arch = "x86", rust_analyzer))]
unsafe {
core::arch::x86::_fxrstor(this as _)
}
#[cfg(any(target_arch = "x86_64", rust_analyzer))]
unsafe {
core::arch::x86_64::_fxrstor64(this as _)
}
}
}

View File

@ -388,7 +388,7 @@ impl<K: KernelTableManager, PA: PhysicalMemoryAllocator<Address = PhysicalAddres
Ok(Self {
inner: UnsafeCell::new(Inner { sp, tss_rsp0: rsp0 }),
fpu_context: UnsafeCell::new(FpuContext::new()),
fpu_context: UnsafeCell::new(FpuContext::new(true)),
stack_base_phys,
stack_size: USER_TASK_PAGES * 0x1000,
_alloc: PhantomData,
@ -434,7 +434,7 @@ impl<K: KernelTableManager, PA: PhysicalMemoryAllocator<Address = PhysicalAddres
Ok(Self {
inner: UnsafeCell::new(Inner { sp, tss_rsp0: 0 }),
fpu_context: UnsafeCell::new(FpuContext::new()),
fpu_context: UnsafeCell::new(FpuContext::new(false)),
stack_base_phys,
stack_size: KERNEL_TASK_PAGES * 0x1000,
@ -473,7 +473,7 @@ impl<K: KernelTableManager, PA: PhysicalMemoryAllocator<Address = PhysicalAddres
Ok(Self {
inner: UnsafeCell::new(Inner { sp, tss_rsp0: rsp0 }),
fpu_context: UnsafeCell::new(FpuContext::new()),
fpu_context: UnsafeCell::new(FpuContext::new(true)),
stack_base_phys,
stack_size: USER_TASK_PAGES * 0x1000,

View File

@ -1,6 +1,6 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
version = 4
[[package]]
name = "aarch64-cpu"
@ -284,7 +284,9 @@ name = "kernel-arch-x86"
version = "0.1.0"
dependencies = [
"bitflags",
"bytemuck",
"kernel-arch-interface",
"static_assertions",
"tock-registers",
]

View File

@ -156,6 +156,10 @@ fn user_exception_inner(kind: ExceptionKind, frame: &mut ExceptionFrame) {
ExceptionKind::Breakpoint => {
todo!()
}
ExceptionKind::SimdFpuException => {
thread.raise_signal(Signal::MemoryAccessViolation);
true
}
_ => todo!("No handler for exception: {:?}", kind),
};