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); }