20 #include "pedigree/kernel/processor/NMFaultHandler.h" 21 #include "pedigree/kernel/Log.h" 22 #include "pedigree/kernel/process/Thread.h" 23 #include "pedigree/kernel/processor/InterruptManager.h" 24 #include "pedigree/kernel/processor/Processor.h" 25 #include "pedigree/kernel/processor/ProcessorInformation.h" 26 #include "pedigree/kernel/processor/state.h" 30 #define NM_FAULT_EXCEPTION 0x07 31 #define CR0_NE (1 << 5) 33 #define CR0_TS (1 << 3) 34 #define CR0_EM (1 << 2) 35 #define CR0_MP (1 << 1) 36 #define CR4_OSFXSR (1 << 9) 37 #define CR4_OSXMMEXCPT (1 << 10) 38 #define CPUID_FEAT_EDX_FXSR (1 << 24) 39 #define CPUID_FEAT_EDX_FPU (1 << 0) 40 #define CPUID_FEAT_EDX_SSE (1 << 25) 42 #define MXCSR_PM (1 << 12) 43 #define MXCSR_UM (1 << 11) 44 #define MXCSR_OM (1 << 10) 45 #define MXCSR_ZM (1 << 9) 46 #define MXCSR_DM (1 << 8) 47 #define MXCSR_IM (1 << 7) 51 #define MXCSR_RC_NEAREST 0 52 #define MXCSR_RC_DOWN 1 54 #define MXCSR_RC_TRUNCATE 3 58 static bool FXSR_Support, FPU_Support;
60 static inline void _SetFPUControlWord(uint16_t cw)
63 asm volatile(
" fldcw %0; " ::
"m"(cw));
74 NM_FAULT_EXCEPTION,
this);
81 uint32_t eax, ebx, ecx, edx, mxcsr = 0;
84 asm volatile(
"mov %%cr0, %0" :
"=r"(cr0));
85 asm volatile(
"mov %%cr4, %0" :
"=r"(cr4));
88 if (edx & CPUID_FEAT_EDX_FPU)
92 cr0 = (cr0 | CR0_NE | CR0_MP) & ~(CR0_EM | CR0_TS);
93 asm volatile(
"mov %0, %%cr0" ::
"r"(cr0));
96 asm volatile(
"finit");
99 _SetFPUControlWord(0x33F);
101 asm volatile(
"mov %0, %%cr0" ::
"r"(cr0));
106 if (edx & CPUID_FEAT_EDX_FXSR)
112 FXSR_Support =
false;
114 if (edx & CPUID_FEAT_EDX_SSE)
116 cr4 |= CR4_OSXMMEXCPT;
118 asm volatile(
"mov %0, %%cr4;" ::
"r"(cr4));
122 (MXCSR_PM | MXCSR_UM | MXCSR_OM | MXCSR_ZM | MXCSR_DM | MXCSR_IM);
125 mxcsr |= (MXCSR_RC_TRUNCATE << MXCSR_RC);
128 asm volatile(
"ldmxcsr %0;" ::
"m"(mxcsr));
131 asm volatile(
"mov %0, %%cr4;" ::
"r"(cr4));
136 asm volatile(
"mov %0, %%cr0" ::
"r"(cr0));
153 asm volatile(
"mov %%cr0, %0" :
"=r"(cr0));
157 asm volatile(
"mov %0, %%cr0" ::
"r"(cr0));
161 FATAL_NOLOCK(
"NM: TS already disabled");
170 if (!(pCurrentState->flags & (1 << 1)))
172 if (x87FPU_MMX_XMM_MXCSR_StateOwner)
173 asm volatile(
"fxrstor (%0);" ::
"r"(
174 (((
reinterpret_cast<uintptr_t
>(
175 x87FPU_MMX_XMM_MXCSR_StateBlank
176 .x87FPU_MMX_XMM_MXCSR_State) +
181 asm volatile(
"fxsave (%0);" ::
"r"(
182 (((
reinterpret_cast<uintptr_t
>(
183 pCurrentState->x87FPU_MMX_XMM_MXCSR_State) +
188 pCurrentState->flags |= (1 << 1);
192 if (x87FPU_MMX_XMM_MXCSR_StateOwner == pCurrentState)
196 if (x87FPU_MMX_XMM_MXCSR_StateOwner)
199 asm volatile(
"fxsave (%0);" ::
"r"(
200 (((
reinterpret_cast<uintptr_t
>(
201 x87FPU_MMX_XMM_MXCSR_StateOwner
202 ->x87FPU_MMX_XMM_MXCSR_State) +
210 asm volatile(
"fxrstor (%0);" ::
"r"(
211 (((
reinterpret_cast<uintptr_t
>(
212 pCurrentState->x87FPU_MMX_XMM_MXCSR_State) +
222 asm volatile(
"fxsave (%0);" ::
"r"(
223 (((
reinterpret_cast<uintptr_t
>(
224 pCurrentState->x87FPU_MMX_XMM_MXCSR_State) +
228 asm volatile(
"fxsave (%0);" ::
"r"((
229 ((
reinterpret_cast<uintptr_t
>(x87FPU_MMX_XMM_MXCSR_StateBlank
230 .x87FPU_MMX_XMM_MXCSR_State) +
236 else if (FPU_Support)
238 if (!(pCurrentState->flags & (1 << 1)))
240 if (x87FPU_MMX_XMM_MXCSR_StateOwner)
241 asm volatile(
"frstor (%0);" ::
"r"(
242 (((
reinterpret_cast<uintptr_t
>(
243 x87FPU_MMX_XMM_MXCSR_StateBlank
244 .x87FPU_MMX_XMM_MXCSR_State) +
249 asm volatile(
"fsave (%0);" ::
"r"(
250 (((
reinterpret_cast<uintptr_t
>(
251 pCurrentState->x87FPU_MMX_XMM_MXCSR_State) +
256 pCurrentState->flags |= (1 << 1);
260 if (x87FPU_MMX_XMM_MXCSR_StateOwner == pCurrentState)
264 if (x87FPU_MMX_XMM_MXCSR_StateOwner)
267 asm volatile(
"fsave (%0);" ::
"r"(
268 (((
reinterpret_cast<uintptr_t
>(
269 x87FPU_MMX_XMM_MXCSR_StateOwner
270 ->x87FPU_MMX_XMM_MXCSR_State) +
278 asm volatile(
"frstor (%0);" ::
"r"(
279 (((
reinterpret_cast<uintptr_t
>(
280 pCurrentState->x87FPU_MMX_XMM_MXCSR_State) +
290 asm volatile(
"fsave (%0);" ::
"r"(
291 (((
reinterpret_cast<uintptr_t
>(
292 pCurrentState->x87FPU_MMX_XMM_MXCSR_State) +
296 asm volatile(
"fsave (%0);" ::
"r"((
297 ((
reinterpret_cast<uintptr_t
>(x87FPU_MMX_XMM_MXCSR_StateBlank
298 .x87FPU_MMX_XMM_MXCSR_State) +
306 ERROR(
"FXSAVE and FSAVE are not supported");
310 x87FPU_MMX_XMM_MXCSR_StateOwner = pCurrentState;
317 void NMFaultHandler::threadTerminated(
Thread *pThread)
322 if (x87FPU_MMX_XMM_MXCSR_StateOwner == state)
324 x87FPU_MMX_XMM_MXCSR_StateOwner =
nullptr;
virtual bool registerInterruptHandler(size_t nInterruptNumber, InterruptHandler *pHandler)=0
static void cpuid(uint32_t inEax, uint32_t inEcx, uint32_t &eax, uint32_t &ebx, uint32_t &ecx, uint32_t &edx)
virtual void interrupt(size_t interruptNumber, InterruptState &state)
static ProcessorInformation & information()
bool initialiseProcessor()
static NMFaultHandler m_Instance
static InterruptManager & instance()
NMFaultHandler() INITIALISATION_ONLY