[kernel] Add MXCSR handling, mask SIMD exceptions

Now threads inherit their MXCSR (sans exception state bits) SIMD
settings from their creator. By default, all exceptions are masked, and
both "to zero" flags are set.
This commit is contained in:
Justin C. Miller
2023-05-21 14:48:27 -07:00
parent f215b98f74
commit da14fd123e
7 changed files with 68 additions and 9 deletions

View File

@@ -118,6 +118,19 @@ cpu_early_init(cpu_data *cpu)
.set(xcr0::SSE);
set_xcr0(xcr0_val);
// Set initial floating point state
const util::bitset32 mxcsr_val {
mxcsr::DAZ,
mxcsr::IM,
mxcsr::DM,
mxcsr::ZM,
mxcsr::OM,
mxcsr::UM,
mxcsr::PM,
mxcsr::FTZ,
};
asm ( "ldmxcsr %0" :: "m"(mxcsr_val) );
// Install the GS base pointint to the cpu_data
wrmsr(msr::ia32_gs_base, reinterpret_cast<uintptr_t>(cpu));
}
@@ -234,3 +247,13 @@ cpu_init(cpu_data *cpu, bool bsp)
xsave_enable();
}
/// Set up initial per-thread CPU state. Called once from initialize_user_cpu in
/// syscall.s, the first code run after a thread comes out of task_switch for the
/// very first time.
extern "C" void
cpu_initialize_thread_state()
{
const util::bitset32 &mxcsr_val = obj::thread::current().m_mxcsr;
asm ( "ldmxcsr %0" :: "m"(mxcsr_val) );
}

View File

@@ -142,6 +142,8 @@ extern "C" {
uint64_t set_xcr0(uint64_t val);
cpu_data * _current_gsbase();
void cpu_initialize_thread_state();
}
/// Do early initialization of the BSP CPU.

View File

@@ -145,6 +145,30 @@ isr_handler(cpu_state *regs)
}
break;
case isr::isrSIMDFPE: {
uint32_t mxcsr = 0;
asm volatile ("stmxcsr %0" : "=m"(mxcsr));
util::format({message, sizeof(message)},
"SIMD Exception; MXCSR[%s%s%s%s%s%s%s%s%s%s%s%s%s%s rc:%d]",
(mxcsr & 0x0001) ? " IE" : "",
(mxcsr & 0x0002) ? " DE" : "",
(mxcsr & 0x0004) ? " ZE" : "",
(mxcsr & 0x0008) ? " OE" : "",
(mxcsr & 0x0010) ? " UE" : "",
(mxcsr & 0x0020) ? " PE" : "",
(mxcsr & 0x0040) ? " DAZ" : "",
(mxcsr & 0x0080) ? " IM" : "",
(mxcsr & 0x0100) ? " DM" : "",
(mxcsr & 0x0200) ? " ZM" : "",
(mxcsr & 0x0400) ? " OM" : "",
(mxcsr & 0x0800) ? " UM" : "",
(mxcsr & 0x1000) ? " PM" : "",
(mxcsr & 0x8000) ? " FTZ" : "",
((mxcsr >> 13) & 0x3));
kassert(false, message, regs);
}
break;
case isr::isrSpurious:
// No EOI for the spurious interrupt
return;

View File

@@ -34,6 +34,15 @@ thread::thread(process &parent, uint8_t pri, uintptr_t rsp0) :
m_tcb.rsp0 = rsp0;
m_creator = current_cpu().thread;
asm volatile ( "stmxcsr %0" : "=m"(m_mxcsr) );
m_mxcsr
.clear(mxcsr::IE)
.clear(mxcsr::DE)
.clear(mxcsr::ZE)
.clear(mxcsr::OE)
.clear(mxcsr::UE)
.clear(mxcsr::PE);
}
thread::~thread()

View File

@@ -7,10 +7,10 @@
#include <util/linked_list.h>
#include <util/spinlock.h>
#include "cpu.h"
#include "objects/kobject.h"
#include "wait_queue.h"
struct cpu_data;
struct page_table;
namespace obj {
@@ -176,6 +176,7 @@ private:
thread(const thread &other) = delete;
thread(const thread &&other) = delete;
friend class process;
friend void ::cpu_initialize_thread_state();
/// Constructor. Used when a kernel stack already exists.
/// \arg parent The process which owns this thread
@@ -195,6 +196,7 @@ private:
thread *m_creator;
state m_state;
util::bitset32 m_mxcsr;
uint64_t m_wake_value;
uint64_t m_wake_timeout;

View File

@@ -16,10 +16,11 @@ STAR_HIGH equ \
; IA32_FMASK - Mask off interrupts in syscalls
FMASK_VAL equ 0x200
extern __counter_syscall_enter
extern __counter_syscall_sysret
extern syscall_registry
extern syscall_invalid
extern __counter_syscall_enter ; syscall.cpp.cog
extern __counter_syscall_sysret ;
extern syscall_registry ;
extern syscall_invalid ;
extern cpu_initialize_thread_state ; cpu.cpp
global syscall_handler_prelude: function hidden (syscall_handler_prelude.end - syscall_handler_prelude)
@@ -79,6 +80,8 @@ syscall_handler_prelude:
global initialize_user_cpu: function hidden (initialize_user_cpu.end - initialize_user_cpu)
initialize_user_cpu:
call cpu_initialize_thread_state
mov rax, 0xaaaaaaaa
mov rdx, 0xdddddddd
mov r8, 0x08080808