20 #include "pedigree/kernel/processor/NMFaultHandler.h" 21 #include "pedigree/kernel/Log.h" 22 #include "pedigree/kernel/debugger/Debugger.h" 23 #include "pedigree/kernel/process/Scheduler.h" 24 #include "pedigree/kernel/processor/PhysicalMemoryManager.h" 28 #define NM_FAULT_EXCEPTION 0x07 29 #define CR0_NE (1 << 5) 31 #define CR0_TS (1 << 3) 32 #define CR0_EM (1 << 2) 33 #define CR0_MP (1 << 1) 34 #define CR4_OSFXSR (1 << 9) 35 #define CR4_OSXMMEXCPT (1 << 10) 36 #define CPUID_FEAT_EDX_FXSR (1 << 24) 37 #define CPUID_FEAT_EDX_FPU (1 << 0) 38 #define CPUID_FEAT_EDX_SSE (1 << 25) 40 #define MXCSR_PM (1 << 12) 41 #define MXCSR_UM (1 << 11) 42 #define MXCSR_OM (1 << 10) 43 #define MXCSR_ZM (1 << 9) 44 #define MXCSR_DM (1 << 8) 45 #define MXCSR_IM (1 << 7) 49 #define MXCSR_RC_NEAREST 0 50 #define MXCSR_RC_DOWN 1 52 #define MXCSR_RC_TRUNCATE 3 56 static bool FXSR_Support, FPU_Support;
58 static inline void _SetFPUControlWord(uint16_t cw)
61 asm volatile(
" fldcw %0; " ::
"m"(cw));
67 uint32_t eax, ebx, ecx, edx, cr0, cr4, mxcsr = 0;
69 asm volatile(
"mov %%cr0, %0" :
"=r"(cr0));
70 asm volatile(
"mov %%cr4, %0" :
"=r"(cr4));
73 if (edx & CPUID_FEAT_EDX_FPU)
77 cr0 = (cr0 | CR0_NE | CR0_MP) & ~(CR0_EM | CR0_TS);
78 asm volatile(
"mov %0, %%cr0" ::
"r"(cr0));
81 asm volatile(
"finit");
84 _SetFPUControlWord(0x33F);
86 asm volatile(
"mov %0, %%cr0" ::
"r"(cr0));
91 if (edx & CPUID_FEAT_EDX_FXSR)
99 if (edx & CPUID_FEAT_EDX_SSE)
101 cr4 |= CR4_OSXMMEXCPT;
103 asm volatile(
"mov %0, %%cr4;" ::
"r"(cr4));
107 (MXCSR_PM | MXCSR_UM | MXCSR_OM | MXCSR_ZM | MXCSR_DM | MXCSR_IM);
110 mxcsr |= (MXCSR_RC_TRUNCATE << MXCSR_RC);
113 asm volatile(
"ldmxcsr %0;" ::
"m"(mxcsr));
116 asm volatile(
"mov %0, %%cr4;" ::
"r"(cr4));
120 NM_FAULT_EXCEPTION,
this);
125 asm volatile(
"mov %0, %%cr0" ::
"r"(cr0));
130 static X86SchedulerState *x87FPU_MMX_XMM_MXCSR_StateOwner = 0;
131 static X86SchedulerState x87FPU_MMX_XMM_MXCSR_StateBlank;
139 X86SchedulerState *pCurrentState = &pCurrentThread->
state();
141 asm volatile(
"mov %%cr0, %0" :
"=r"(cr0));
145 asm volatile(
"mov %0, %%cr0" ::
"r"(cr0));
149 FATAL_NOLOCK(
"NM: TS already disabled");
158 if (!(pCurrentState->flags & (1 << 1)))
160 if ((
size_t) x87FPU_MMX_XMM_MXCSR_StateOwner != 0)
161 asm volatile(
"fxrstor (%0);" ::
"r"(
162 ((((size_t) x87FPU_MMX_XMM_MXCSR_StateBlank
163 .x87FPU_MMX_XMM_MXCSR_State +
168 asm volatile(
"fxsave (%0);" ::
"r"(
169 ((((size_t) pCurrentState->x87FPU_MMX_XMM_MXCSR_State + 32) &
173 pCurrentState->flags |= (1 << 1);
177 if ((
size_t) x87FPU_MMX_XMM_MXCSR_StateOwner == (size_t) pCurrentState)
181 if ((
size_t) x87FPU_MMX_XMM_MXCSR_StateOwner != 0)
184 asm volatile(
"fxsave (%0);" ::
"r"(
185 ((((size_t) x87FPU_MMX_XMM_MXCSR_StateOwner
186 ->x87FPU_MMX_XMM_MXCSR_State +
191 if ((
size_t) pCurrentState != 0)
194 asm volatile(
"fxrstor (%0);" ::
"r"((
195 (((size_t) pCurrentState->x87FPU_MMX_XMM_MXCSR_State + 32) &
204 asm volatile(
"fxsave (%0);" ::
"r"(
205 ((((size_t) pCurrentState->x87FPU_MMX_XMM_MXCSR_State + 32) &
208 asm volatile(
"fxsave (%0);" ::
"r"(
209 ((((size_t) x87FPU_MMX_XMM_MXCSR_StateBlank
210 .x87FPU_MMX_XMM_MXCSR_State +
216 else if (FPU_Support)
218 if (!(pCurrentState->flags & (1 << 1)))
220 if ((
size_t) x87FPU_MMX_XMM_MXCSR_StateOwner != 0)
221 asm volatile(
"frstor (%0);" ::
"r"(
222 ((((
size_t) x87FPU_MMX_XMM_MXCSR_StateBlank
223 .x87FPU_MMX_XMM_MXCSR_State +
228 asm volatile(
"fsave (%0);" ::
"r"(
229 ((((size_t) pCurrentState->x87FPU_MMX_XMM_MXCSR_State + 32) &
233 pCurrentState->flags |= (1 << 1);
237 if ((
size_t) x87FPU_MMX_XMM_MXCSR_StateOwner == (size_t) pCurrentState)
241 if ((
size_t) x87FPU_MMX_XMM_MXCSR_StateOwner != 0)
244 asm volatile(
"fsave (%0);" ::
"r"(
245 ((((size_t) x87FPU_MMX_XMM_MXCSR_StateOwner
246 ->x87FPU_MMX_XMM_MXCSR_State +
251 if ((
size_t) pCurrentState != 0)
254 asm volatile(
"frstor (%0);" ::
"r"((
255 (((size_t) pCurrentState->x87FPU_MMX_XMM_MXCSR_State + 32) &
264 asm volatile(
"fsave (%0);" ::
"r"(
265 ((((size_t) pCurrentState->x87FPU_MMX_XMM_MXCSR_State + 32) &
268 asm volatile(
"fsave (%0);" ::
"r"(
269 ((((size_t) x87FPU_MMX_XMM_MXCSR_StateBlank
270 .x87FPU_MMX_XMM_MXCSR_State +
278 ERROR(
"FXSAVE and FSAVE are not supported");
282 x87FPU_MMX_XMM_MXCSR_StateOwner = pCurrentState;
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()
static NMFaultHandler m_Instance
static InterruptManager & instance()
NMFaultHandler() INITIALISATION_ONLY