mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 00:14:32 -08:00
[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:
@@ -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) );
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user