From da14fd123ee5cbb5e98587ce85bf3ceff860564b Mon Sep 17 00:00:00 2001 From: "Justin C. Miller" Date: Sun, 21 May 2023 14:48:27 -0700 Subject: [PATCH] [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. --- src/kernel/cpu.cpp | 23 +++++++++++++++++++++++ src/kernel/cpu.h | 2 ++ src/kernel/interrupts.cpp | 24 ++++++++++++++++++++++++ src/kernel/objects/thread.cpp | 9 +++++++++ src/kernel/objects/thread.h | 4 +++- src/kernel/syscall.s | 11 +++++++---- src/libraries/util/util/bitset.h | 4 ---- 7 files changed, 68 insertions(+), 9 deletions(-) diff --git a/src/kernel/cpu.cpp b/src/kernel/cpu.cpp index 71fc366..7033b65 100644 --- a/src/kernel/cpu.cpp +++ b/src/kernel/cpu.cpp @@ -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(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) ); +} diff --git a/src/kernel/cpu.h b/src/kernel/cpu.h index 8912bb1..8168d84 100644 --- a/src/kernel/cpu.h +++ b/src/kernel/cpu.h @@ -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. diff --git a/src/kernel/interrupts.cpp b/src/kernel/interrupts.cpp index 2752dbb..7de3710 100644 --- a/src/kernel/interrupts.cpp +++ b/src/kernel/interrupts.cpp @@ -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; diff --git a/src/kernel/objects/thread.cpp b/src/kernel/objects/thread.cpp index 1a58f2f..9475092 100644 --- a/src/kernel/objects/thread.cpp +++ b/src/kernel/objects/thread.cpp @@ -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() diff --git a/src/kernel/objects/thread.h b/src/kernel/objects/thread.h index 52c685a..150afa9 100644 --- a/src/kernel/objects/thread.h +++ b/src/kernel/objects/thread.h @@ -7,10 +7,10 @@ #include #include +#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; diff --git a/src/kernel/syscall.s b/src/kernel/syscall.s index f27eea3..47d1dab 100644 --- a/src/kernel/syscall.s +++ b/src/kernel/syscall.s @@ -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 diff --git a/src/libraries/util/util/bitset.h b/src/libraries/util/util/bitset.h index 685dfaa..27a2d34 100644 --- a/src/libraries/util/util/bitset.h +++ b/src/libraries/util/util/bitset.h @@ -66,8 +66,6 @@ namespace { template <> class bitset<64> { - static constexpr unsigned num_elems = 1; - template static constexpr uint64_t bit_or(T b) { return 1ull << uint64_t(b); } @@ -127,8 +125,6 @@ private: template <> class bitset<32> { - static constexpr unsigned num_elems = 1; - template static constexpr uint32_t bit_or(T b) { return 1u << uint32_t(b); }