Skip to content

Commit 80e5437

Browse files
authored
Merge pull request #192 from Freax13/feature/xf
implement #XF handler
2 parents a354d7d + 83d75f0 commit 80e5437

File tree

3 files changed

+115
-9
lines changed

3 files changed

+115
-9
lines changed

tee/kernel/src/exception.rs

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use x86_64::{
2525
},
2626
structures::{
2727
gdt::{Descriptor, DescriptorFlags, GlobalDescriptorTable, SegmentSelector},
28-
idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode},
28+
idt::{ExceptionVector, InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode},
2929
paging::Page,
3030
tss::TaskStateSegment,
3131
},
@@ -154,6 +154,8 @@ pub fn load_idt() {
154154
idt.general_protection_fault
155155
.set_handler_fn(general_protection_fault_handler);
156156
idt.page_fault.set_handler_fn(page_fault_handler);
157+
idt.simd_floating_point
158+
.set_handler_fn(simd_floating_point_handler);
157159
idt[TLB_VECTOR].set_handler_fn(tlb_shootdown_handler);
158160
idt[TIMER_VECTOR].set_handler_fn(timer_handler);
159161

@@ -178,12 +180,13 @@ extern "x86-interrupt" fn divide_error_handler(frame: InterruptStackFrame) {
178180
// Userspace code path:
179181
"swapgs",
180182
// Store the error code.
181-
"mov byte ptr gs:[{VECTOR_OFFSET}], 0x0",
183+
"mov byte ptr gs:[{VECTOR_OFFSET}], {VECTOR}",
182184
// Jump to the userspace exit point.
183185
"jmp {exception_entry}",
184186

185187
kernel_divide_error_handler = sym kernel_divide_error_handler,
186188
VECTOR_OFFSET = const offset_of!(PerCpu, vector),
189+
VECTOR = const ExceptionVector::Division as u8,
187190
exception_entry = sym exception_entry,
188191
);
189192
}
@@ -206,7 +209,7 @@ extern "x86-interrupt" fn page_fault_handler(
206209
// Userspace code path:
207210
"swapgs",
208211
// Store the error code.
209-
"mov byte ptr gs:[{VECTOR_OFFSET}], 0xe",
212+
"mov byte ptr gs:[{VECTOR_OFFSET}], {VECTOR}",
210213
"pop qword ptr gs:[{ERROR_CODE_OFFSET}]",
211214
// Jump to the userspace exit point.
212215
"jmp {exception_entry}",
@@ -257,6 +260,7 @@ extern "x86-interrupt" fn page_fault_handler(
257260

258261
kernel_page_fault_handler = sym kernel_page_fault_handler,
259262
VECTOR_OFFSET = const offset_of!(PerCpu, vector),
263+
VECTOR = const ExceptionVector::Page as u8,
260264
ERROR_CODE_OFFSET = const offset_of!(PerCpu, error_code),
261265
exception_entry = sym exception_entry,
262266
);
@@ -309,13 +313,14 @@ extern "x86-interrupt" fn general_protection_fault_handler(
309313
// Userspace code path:
310314
"swapgs",
311315
// Store the error code.
312-
"mov byte ptr gs:[{VECTOR_OFFSET}], 0xd",
316+
"mov byte ptr gs:[{VECTOR_OFFSET}], {VECTOR}",
313317
"pop qword ptr gs:[{ERROR_CODE_OFFSET}]",
314318
// Jump to the userspace exit point.
315319
"jmp {exception_entry}",
316320

317321
kernel_general_protection_fault_handler = sym kernel_general_protection_fault_handler,
318322
VECTOR_OFFSET = const offset_of!(PerCpu, vector),
323+
VECTOR = const ExceptionVector::GeneralProtection as u8,
319324
ERROR_CODE_OFFSET = const offset_of!(PerCpu, error_code),
320325
exception_entry = sym exception_entry,
321326
);
@@ -328,23 +333,50 @@ extern "x86-interrupt" fn kernel_general_protection_fault_handler(
328333
panic!("general protection fault {frame:x?} {code:x?}");
329334
}
330335

336+
#[unsafe(naked)]
337+
extern "x86-interrupt" fn simd_floating_point_handler(frame: InterruptStackFrame) {
338+
naked_asm!(
339+
"cld",
340+
// Check whether the exception happened in userspace.
341+
"test word ptr [rsp+8], 3",
342+
"je {kernel_simd_floating_point_handler}",
343+
344+
// Userspace code path:
345+
"swapgs",
346+
// Store the error code.
347+
"mov byte ptr gs:[{VECTOR_OFFSET}], {VECTOR}",
348+
// Jump to the userspace exit point.
349+
"jmp {exception_entry}",
350+
351+
kernel_simd_floating_point_handler = sym kernel_simd_floating_point_handler,
352+
VECTOR_OFFSET = const offset_of!(PerCpu, vector),
353+
VECTOR = const ExceptionVector::SimdFloatingPoint as u8,
354+
exception_entry = sym exception_entry,
355+
);
356+
}
357+
358+
extern "x86-interrupt" fn kernel_simd_floating_point_handler(frame: InterruptStackFrame) {
359+
panic!("simd floating point exception {frame:x?}");
360+
}
361+
331362
#[unsafe(naked)]
332363
extern "x86-interrupt" fn invalid_opcode_handler(frame: InterruptStackFrame) {
333364
naked_asm!(
334365
"cld",
335366
// Check whether the exception happened in userspace.
336-
"test word ptr [rsp+16], 3",
367+
"test word ptr [rsp+8], 3",
337368
"je {kernel_invalid_opcode_handler}",
338369

339370
// Userspace code path:
340371
"swapgs",
341372
// Store the error code.
342-
"mov byte ptr gs:[{VECTOR_OFFSET}], 0x6",
373+
"mov byte ptr gs:[{VECTOR_OFFSET}], {VECTOR}",
343374
// Jump to the userspace exit point.
344375
"jmp {exception_entry}",
345376

346377
kernel_invalid_opcode_handler = sym kernel_invalid_opcode_handler,
347378
VECTOR_OFFSET = const offset_of!(PerCpu, vector),
379+
VECTOR = const ExceptionVector::InvalidOpcode as u8,
348380
exception_entry = sym exception_entry,
349381
);
350382
}
@@ -422,13 +454,13 @@ extern "x86-interrupt" fn timer_handler(frame: InterruptStackFrame) {
422454
// Userspace code path:
423455
"swapgs",
424456
// Store the error code.
425-
"mov byte ptr gs:[{VECTOR_OFFSET}], {TIMER_VECTOR}",
457+
"mov byte ptr gs:[{VECTOR_OFFSET}], {VECTOR}",
426458
// Jump to the userspace exit point.
427459
"jmp {interrupt_entry}",
428460

429461
kernel_timer_handler = sym kernel_timer_handler,
430462
VECTOR_OFFSET = const offset_of!(PerCpu, vector),
431-
TIMER_VECTOR = const TIMER_VECTOR,
463+
VECTOR = const TIMER_VECTOR,
432464
interrupt_entry = sym interrupt_entry,
433465
);
434466
}

tee/kernel/src/user/syscall/cpu_state.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use x86_64::{
1818
registers::{
1919
control::Cr2,
2020
model_specific::{LStar, SFMask},
21+
mxcsr::MxCsr,
2122
rflags::RFlags,
2223
xcontrol::{XCr0, XCr0Flags},
2324
},
@@ -157,6 +158,37 @@ impl CpuState {
157158
code,
158159
})
159160
}
161+
0x13 => {
162+
let mxcsr = self.xsave_area.mxcsr();
163+
let error = if mxcsr.contains(MxCsr::INVALID_OPERATION)
164+
&& !mxcsr.contains(MxCsr::INVALID_OPERATION_MASK)
165+
{
166+
SimdFloatingPointError::InvalidOperation
167+
} else if mxcsr.contains(MxCsr::DENORMAL)
168+
&& !mxcsr.contains(MxCsr::DENORMAL_MASK)
169+
{
170+
SimdFloatingPointError::Denormal
171+
} else if mxcsr.contains(MxCsr::DIVIDE_BY_ZERO)
172+
&& !mxcsr.contains(MxCsr::DIVIDE_BY_ZERO_MASK)
173+
{
174+
SimdFloatingPointError::DivideByZero
175+
} else if mxcsr.contains(MxCsr::OVERFLOW)
176+
&& !mxcsr.contains(MxCsr::OVERFLOW_MASK)
177+
{
178+
SimdFloatingPointError::Overflow
179+
} else if mxcsr.contains(MxCsr::UNDERFLOW)
180+
&& !mxcsr.contains(MxCsr::UNDERFLOW_MASK)
181+
{
182+
SimdFloatingPointError::Underflow
183+
} else if mxcsr.contains(MxCsr::PRECISION)
184+
&& !mxcsr.contains(MxCsr::PRECISION_MASK)
185+
{
186+
SimdFloatingPointError::Precision
187+
} else {
188+
unreachable!()
189+
};
190+
Exit::SimdFloatingPoint(error)
191+
}
160192
TIMER_VECTOR => Exit::Timer,
161193
0x80 => {
162194
let no = self.registers.rax as u32;
@@ -649,6 +681,7 @@ pub enum Exit {
649681
InvalidOpcode,
650682
GeneralProtectionFault,
651683
PageFault(PageFaultExit),
684+
SimdFloatingPoint(SimdFloatingPointError),
652685
Timer,
653686
}
654687

@@ -658,6 +691,16 @@ pub struct PageFaultExit {
658691
pub code: PageFaultErrorCode,
659692
}
660693

694+
#[derive(Debug, Clone, Copy)]
695+
pub enum SimdFloatingPointError {
696+
InvalidOperation,
697+
Denormal,
698+
DivideByZero,
699+
Overflow,
700+
Underflow,
701+
Precision,
702+
}
703+
661704
#[derive(Clone)]
662705
struct XSaveArea {
663706
data: Vec<u8>,
@@ -701,6 +744,11 @@ impl XSaveArea {
701744
_xrstor64(self.data.as_ptr(), rs_mask.bits());
702745
}
703746
}
747+
748+
fn mxcsr(&self) -> MxCsr {
749+
let fxsave = from_bytes::<FXSave>(&self.data[..512]);
750+
MxCsr::from_bits_retain(fxsave.mxcsr)
751+
}
704752
}
705753

706754
/// The first 512 bytes used by the xsave instructions.

tee/kernel/src/user/thread.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ use crate::{
4949
FileMode, Nice, Pointer, PtraceEvent, Rusage, Signal, TimerId, Timespec, UserDesc,
5050
WStatus,
5151
},
52-
cpu_state::{CpuState, Exit, PageFaultExit},
52+
cpu_state::{CpuState, Exit, PageFaultExit, SimdFloatingPointError},
5353
},
5454
},
5555
};
@@ -297,6 +297,26 @@ impl Thread {
297297
self.queue_signal_or_die(sig_info);
298298
}
299299
Exit::PageFault(page_fault) => self.handle_page_fault(page_fault),
300+
Exit::SimdFloatingPoint(error) => {
301+
let code = match error {
302+
SimdFloatingPointError::InvalidOperation => {
303+
SigInfoCode::FPE_FLTINV
304+
}
305+
SimdFloatingPointError::Denormal => SigInfoCode::FPE_FLTUND,
306+
SimdFloatingPointError::DivideByZero => SigInfoCode::FPE_FLTDIV,
307+
SimdFloatingPointError::Overflow => SigInfoCode::FPE_FLTOVF,
308+
SimdFloatingPointError::Underflow => SigInfoCode::FPE_FLTUND,
309+
SimdFloatingPointError::Precision => SigInfoCode::FPE_FLTRES,
310+
};
311+
let sig_info = SigInfo {
312+
signal: Signal::FPE,
313+
code,
314+
fields: SigFields::SigFault(SigFault {
315+
addr: self.cpu_state.lock().faulting_instruction(),
316+
}),
317+
};
318+
self.queue_signal_or_die(sig_info);
319+
}
300320
Exit::Timer => {
301321
// Handle the timer interrupt.
302322
time::expire_timers();
@@ -567,6 +587,7 @@ impl Thread {
567587
| Exit::InvalidOpcode
568588
| Exit::GeneralProtectionFault
569589
| Exit::PageFault(_)
590+
| Exit::SimdFloatingPoint(_)
570591
| Exit::Timer => writeln!(write, "{:indent$}{exit:?}", "")?,
571592
}
572593
} else {
@@ -1305,6 +1326,11 @@ impl SigInfoCode {
13051326
pub const SEGV_ACCERR: Self = Self(2);
13061327
pub const ILL_ILLOPN: Self = Self(2);
13071328
pub const BUS_ADRERR: Self = Self(2);
1329+
pub const FPE_FLTDIV: Self = Self(3);
1330+
pub const FPE_FLTOVF: Self = Self(4);
1331+
pub const FPE_FLTUND: Self = Self(5);
1332+
pub const FPE_FLTRES: Self = Self(6);
1333+
pub const FPE_FLTINV: Self = Self(7);
13081334
pub const KERNEL: Self = Self(0x80);
13091335
pub const TIMER: Self = Self(-2);
13101336
pub const TKILL: Self = Self(-6);

0 commit comments

Comments
 (0)