Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

misc.c File Reference

#include "ki.h"

Go to the source code of this file.

Classes

struct  _CONTROL_WORD
struct  FLOAT_SAVE

Defines

#define FLOAT_SAVE_COMPLETE_CONTEXT   0x01
#define FLOAT_SAVE_FREE_CONTEXT_HEAP   0x02
#define FLOAT_SAVE_VALID   0x04
#define FLOAT_SAVE_RESERVED   0xF8

Typedefs

typedef _CONTROL_WORD CONTROL_WORD
typedef _CONTROL_WORDPCONTROL_WORD
typedef * PFLOAT_SAVE

Functions

__inline KIRQL Kix86FxSave (PULONG NpxFrame)
__inline KIRQL Kix86FnSave (PULONG NpxFrame)
__inline KIRQL Kix86LdMXCsr (PULONG MXCsr)
__inline KIRQL Kix86StMXCsr (PULONG MXCsr)
NTSTATUS KeSaveFloatingPointState (OUT PKFLOATING_SAVE PublicFloatSave)
NTSTATUS KeRestoreFloatingPointState (IN PKFLOATING_SAVE PublicFloatSave)
VOID __cdecl KeSaveStateForHibernate (IN PKPROCESSOR_STATE ProcessorState)

Variables

BOOLEAN KeI386FxsrPresent
BOOLEAN KeI386XMMIPresent


Define Documentation

#define FLOAT_SAVE_COMPLETE_CONTEXT   0x01
 

Definition at line 55 of file ke/i386/misc.c.

Referenced by KeRestoreFloatingPointState(), and KeSaveFloatingPointState().

#define FLOAT_SAVE_FREE_CONTEXT_HEAP   0x02
 

Definition at line 56 of file ke/i386/misc.c.

Referenced by KeRestoreFloatingPointState(), and KeSaveFloatingPointState().

#define FLOAT_SAVE_RESERVED   0xF8
 

Definition at line 58 of file ke/i386/misc.c.

Referenced by KeRestoreFloatingPointState().

#define FLOAT_SAVE_VALID   0x04
 

Definition at line 57 of file ke/i386/misc.c.

Referenced by KeRestoreFloatingPointState(), and KeSaveFloatingPointState().


Typedef Documentation

typedef struct _CONTROL_WORD CONTROL_WORD
 

typedef struct _CONTROL_WORD * PCONTROL_WORD
 

typedef * PFLOAT_SAVE
 

Referenced by KeRestoreFloatingPointState(), and KeSaveFloatingPointState().


Function Documentation

NTSTATUS KeRestoreFloatingPointState IN PKFLOATING_SAVE  PublicFloatSave  ) 
 

Definition at line 366 of file ke/i386/misc.c.

References ASSERT, DbgPrint, ExFreePool(), FLOAT_SAVE_COMPLETE_CONTEXT, FLOAT_SAVE_FREE_CONTEXT_HEAP, FLOAT_SAVE_RESERVED, FLOAT_SAVE_VALID, _KTHREAD::InitialStack, KeGetCurrentPrcb, KeGetCurrentThread, KeI386FxsrPresent, KeI386NpxPresent, KeI386XMMIPresent, Kix86LdMXCsr(), _KTHREAD::NpxIrql, _KTHREAD::NpxState, NULL, and PFLOAT_SAVE.

00371 : 00372 00373 This routine retores the thread's current non-volatile NPX state, 00374 to the passed in state. 00375 00376 Arguments: 00377 00378 FloatSave - the non-volatile npx state for the thread to restore 00379 00380 Return Value: 00381 00382 --*/ 00383 { 00384 PKTHREAD Thread; 00385 PFX_SAVE_AREA NpxFrame; 00386 ULONG Cr0State; 00387 PFLOAT_SAVE FloatSave; 00388 00389 ASSERT (KeI386NpxPresent); 00390 00391 FloatSave = (PFLOAT_SAVE) PublicFloatSave; 00392 Thread = FloatSave->Thread; 00393 00394 NpxFrame = (PFX_SAVE_AREA)(((ULONG)(Thread->InitialStack) - 00395 sizeof(FX_SAVE_AREA))); 00396 00397 00398 // 00399 // Verify float save looks like it's from the right context 00400 // 00401 00402 if ((FloatSave->Flags & (FLOAT_SAVE_VALID | FLOAT_SAVE_RESERVED)) != FLOAT_SAVE_VALID) { 00403 00404 // BUGBUG: need to pick a good bugcheck code 00405 // KeBugCheck (...); 00406 DbgPrint("KeRestoreFloatingPointState: Invalid float save area\n"); 00407 DbgBreakPoint(); 00408 } 00409 00410 if (FloatSave->Irql != KeGetCurrentIrql()) { 00411 // BUGBUG: need to pick a good bugcheck code 00412 // KeBugCheck (...); 00413 DbgPrint("KeRestoreFloatingPointState: Invalid IRQL\n"); 00414 DbgBreakPoint(); 00415 } 00416 00417 if (Thread != KeGetCurrentThread()) { 00418 // BUGBUG: need to pick a good bugcheck code 00419 // KeBugCheck (...); 00420 DbgPrint("KeRestoreFloatingPointState: Invalid thread\n"); 00421 DbgBreakPoint(); 00422 } 00423 00424 00425 // 00426 // Synchronize with context switches and the npx trap handlers 00427 // 00428 00429 _asm { 00430 cli 00431 } 00432 00433 // 00434 // Restore the required state 00435 // 00436 00437 if (FloatSave->Flags & FLOAT_SAVE_COMPLETE_CONTEXT) { 00438 00439 // 00440 // Restore the entire fp state to the threads save area 00441 // 00442 00443 if (Thread->NpxState == NPX_STATE_LOADED) { 00444 00445 // 00446 // This state in the fp unit is no longer needed, just disregard it 00447 // 00448 00449 Thread->NpxState = NPX_STATE_NOT_LOADED; 00450 KeGetCurrentPrcb()->NpxThread = NULL; 00451 } 00452 00453 // 00454 // Copy restored state to npx frame 00455 // 00456 00457 RtlCopyMemory (NpxFrame, FloatSave->u.Context, sizeof(FX_SAVE_AREA)); 00458 00459 } else { 00460 00461 // 00462 // Restore the non-volatile state 00463 // 00464 00465 if (Thread->NpxState == NPX_STATE_LOADED) { 00466 00467 // 00468 // Init fp state and restore control word 00469 // 00470 00471 _asm { 00472 fninit 00473 mov eax, FloatSave 00474 fldcw [eax] FLOAT_SAVE.u.Fcw.ControlWord 00475 } 00476 00477 00478 if ((KeI386FxsrPresent) && (KeI386XMMIPresent)) { 00479 Kix86LdMXCsr(&FloatSave->u.Fcw.MXCsr); 00480 } 00481 00482 00483 } else { 00484 00485 // 00486 // Fp state not loaded. Restore control word in npx frame 00487 // 00488 00489 if (KeI386FxsrPresent) { 00490 NpxFrame->U.FxArea.ControlWord = FloatSave->u.Fcw.ControlWord; 00491 NpxFrame->U.FxArea.StatusWord = 0; 00492 NpxFrame->U.FxArea.TagWord = 0; 00493 NpxFrame->NpxSavedCpu = 0; 00494 NpxFrame->U.FxArea.MXCsr = FloatSave->u.Fcw.MXCsr; 00495 00496 } else { 00497 NpxFrame->U.FnArea.ControlWord = FloatSave->u.Fcw.ControlWord; 00498 NpxFrame->U.FnArea.StatusWord = 0; 00499 NpxFrame->U.FnArea.TagWord = 0xffff; 00500 } 00501 00502 } 00503 00504 NpxFrame->Cr0NpxState = FloatSave->Cr0NpxState; 00505 } 00506 00507 // 00508 // Restore NpxIrql and Cr0 00509 // 00510 00511 Thread->NpxIrql = FloatSave->PreviousNpxIrql; 00512 Cr0State = Thread->NpxState | NpxFrame->Cr0NpxState; 00513 00514 _asm { 00515 mov eax, cr0 00516 mov ecx, eax 00517 and eax, not (CR0_MP|CR0_EM|CR0_TS) 00518 or eax, Cr0State 00519 cmp eax, ecx 00520 je short res10 00521 mov cr0, eax 00522 res10: 00523 sti 00524 } 00525 00526 // 00527 // Done 00528 // 00529 00530 if (FloatSave->Flags & FLOAT_SAVE_FREE_CONTEXT_HEAP) { 00531 ExFreePool (FloatSave->u.Context); 00532 } 00533 00534 FloatSave->Flags = 0; 00535 return STATUS_SUCCESS; 00536 }

NTSTATUS KeSaveFloatingPointState OUT PKFLOATING_SAVE  PublicFloatSave  ) 
 

Definition at line 133 of file ke/i386/misc.c.

References APC_LEVEL, ASSERT, DISPATCH_LEVEL, ExAllocatePoolWithTag, FLOAT_SAVE_COMPLETE_CONTEXT, FLOAT_SAVE_FREE_CONTEXT_HEAP, FLOAT_SAVE_VALID, _KTHREAD::InitialStack, KeGetCurrentPrcb, KeGetCurrentThread, KeI386FxsrPresent, KeI386NpxPresent, KeI386XMMIPresent, Kix86FnSave(), Kix86FxSave(), Kix86LdMXCsr(), Kix86StMXCsr(), NonPagedPool, _KTHREAD::NpxIrql, _KTHREAD::NpxState, PFLOAT_SAVE, and USHORT.

00138 : 00139 00140 This routine saves the thread's current non-volatile NPX state, 00141 and sets a new initial floating point state for the caller. 00142 00143 Arguments: 00144 00145 FloatSave - receives the current non-volatile npx state for the thread 00146 00147 Return Value: 00148 00149 --*/ 00150 { 00151 PKTHREAD Thread; 00152 PFX_SAVE_AREA NpxFrame; 00153 KIRQL Irql; 00154 USHORT ControlWord; 00155 ULONG MXCsr; 00156 PKPRCB Prcb; 00157 PFLOAT_SAVE FloatSave; 00158 00159 // 00160 // If the system is using floating point emulation, then 00161 // return an error 00162 // 00163 00164 if (!KeI386NpxPresent) { 00165 return STATUS_ILLEGAL_FLOAT_CONTEXT; 00166 } 00167 00168 // 00169 // Get the current irql and thread 00170 // 00171 00172 FloatSave = (PFLOAT_SAVE) PublicFloatSave; 00173 00174 Irql = KeGetCurrentIrql(); 00175 Thread = KeGetCurrentThread(); 00176 00177 ASSERT (Thread->NpxIrql <= Irql); 00178 00179 FloatSave->Flags = 0; 00180 FloatSave->Irql = Irql; 00181 FloatSave->PreviousNpxIrql = Thread->NpxIrql; 00182 FloatSave->Thread = Thread; 00183 00184 // 00185 // If the irql has changed we need to save the complete floating 00186 // state context as the prior level has been interrupted. 00187 // 00188 00189 if (Thread->NpxIrql != Irql) { 00190 00191 // 00192 // If this is apc level we don't have anyplace to hold this 00193 // context, allocate some heap. 00194 // 00195 00196 if (Irql == APC_LEVEL) { 00197 FloatSave->u.Context = ExAllocatePoolWithTag ( 00198 NonPagedPool, 00199 sizeof (FX_SAVE_AREA), 00200 ' XPN' 00201 ); 00202 00203 if (!FloatSave->u.Context) { 00204 return STATUS_INSUFFICIENT_RESOURCES; 00205 } 00206 00207 FloatSave->Flags |= FLOAT_SAVE_FREE_CONTEXT_HEAP; 00208 00209 } else { 00210 00211 ASSERT (Irql == DISPATCH_LEVEL); 00212 FloatSave->u.Context = &KeGetCurrentPrcb()->NpxSaveArea; 00213 00214 } 00215 00216 FloatSave->Flags |= FLOAT_SAVE_COMPLETE_CONTEXT; 00217 } 00218 00219 // 00220 // Stop context switching and allow access to the local fp unit 00221 // 00222 00223 _asm { 00224 cli 00225 mov eax, cr0 00226 mov ecx, eax 00227 and eax, not (CR0_MP|CR0_EM|CR0_TS) 00228 cmp eax, ecx 00229 je short sav10 00230 00231 mov cr0, eax 00232 sav10: 00233 } 00234 00235 Prcb = KeGetCurrentPrcb(); 00236 00237 // 00238 // Get ownership of npx register set for this context 00239 // 00240 00241 if (Prcb->NpxThread != Thread) { 00242 00243 // 00244 // If the other context is loaded in the npx registers, flush 00245 // it to that threads save area 00246 // 00247 if (Prcb->NpxThread) { 00248 00249 NpxFrame = (PFX_SAVE_AREA)(((ULONG)(Prcb->NpxThread->InitialStack) - 00250 sizeof(FX_SAVE_AREA))); 00251 00252 if (KeI386FxsrPresent) { 00253 Kix86FxSave((PULONG)NpxFrame); 00254 } else { 00255 Kix86FnSave((PULONG)NpxFrame); 00256 } 00257 00258 NpxFrame->NpxSavedCpu = 0; 00259 Prcb->NpxThread->NpxState = NPX_STATE_NOT_LOADED; 00260 00261 } 00262 00263 Prcb->NpxThread = Thread; 00264 } 00265 00266 NpxFrame = (PFX_SAVE_AREA)(((ULONG)(Thread->InitialStack) - 00267 sizeof(FX_SAVE_AREA))); 00268 00269 00270 // 00271 // Save the previous state as required 00272 // 00273 00274 if (FloatSave->Flags & FLOAT_SAVE_COMPLETE_CONTEXT) { 00275 00276 // 00277 // Need to save the entire context 00278 // 00279 00280 if (Thread->NpxState == NPX_STATE_LOADED) { 00281 if (KeI386FxsrPresent) { 00282 Kix86FxSave ((PULONG)(FloatSave->u.Context)); 00283 } else { 00284 Kix86FnSave ((PULONG)(FloatSave->u.Context)); 00285 } 00286 00287 FloatSave->u.Context->NpxSavedCpu = 0; 00288 FloatSave->u.Context->Cr0NpxState = NpxFrame->Cr0NpxState; 00289 00290 } else { 00291 RtlCopyMemory (FloatSave->u.Context, NpxFrame, sizeof(FX_SAVE_AREA)); 00292 FloatSave->u.Context->NpxSavedCpu = 0; 00293 00294 } 00295 00296 } else { 00297 00298 // 00299 // Save only the non-volatile state 00300 // 00301 00302 if (Thread->NpxState == NPX_STATE_LOADED) { 00303 00304 _asm { 00305 mov eax, FloatSave 00306 fnstcw [eax] FLOAT_SAVE.u.Fcw.ControlWord 00307 } 00308 00309 if ((KeI386FxsrPresent) && (KeI386XMMIPresent)) { 00310 Kix86StMXCsr(&FloatSave->u.Fcw.MXCsr); 00311 } 00312 00313 } else { 00314 // 00315 // Save the control word from the npx frame. 00316 // 00317 00318 if (KeI386FxsrPresent) { 00319 FloatSave->u.Fcw.ControlWord = (USHORT) NpxFrame->U.FxArea.ControlWord; 00320 FloatSave->u.Fcw.MXCsr = NpxFrame->U.FxArea.MXCsr; 00321 00322 } else { 00323 FloatSave->u.Fcw.ControlWord = (USHORT) NpxFrame->U.FnArea.ControlWord; 00324 } 00325 } 00326 00327 00328 // 00329 // Save Cr0NpxState, but clear CR0_TS as there's not non-volatile 00330 // pending fp exceptions 00331 // 00332 00333 FloatSave->Cr0NpxState = NpxFrame->Cr0NpxState & ~CR0_TS; 00334 } 00335 00336 // 00337 // The previous state is saved. Set an initial default 00338 // FP state for the caller 00339 // 00340 00341 NpxFrame->Cr0NpxState = 0; 00342 Thread->NpxState = NPX_STATE_LOADED; 00343 Thread->NpxIrql = Irql; 00344 ControlWord = 0x27f; // 64bit mode 00345 MXCsr = 0x1f80; 00346 00347 _asm { 00348 fninit 00349 fldcw ControlWord 00350 } 00351 00352 if ((KeI386FxsrPresent) && (KeI386XMMIPresent)) { 00353 Kix86LdMXCsr(&MXCsr); 00354 } 00355 00356 _asm { 00357 sti 00358 } 00359 00360 FloatSave->Flags |= FLOAT_SAVE_VALID; 00361 return STATUS_SUCCESS; 00362 }

VOID __cdecl KeSaveStateForHibernate IN PKPROCESSOR_STATE  ProcessorState  ) 
 

Definition at line 542 of file ke/i386/misc.c.

References KiSaveProcessorControlState().

00547 : 00548 00549 Saves all processor-specific state that must be preserved 00550 across an S4 state (hibernation). 00551 00552 N.B. #pragma surrounding this function is required in order 00553 to create the frame pointer than RtlCaptureContext relies 00554 on. 00555 N.B. _CRTAPI1 (__cdecl) decoration is also required so that 00556 RtlCaptureContext can compute the correct ESP. 00557 00558 Arguments: 00559 00560 ProcessorState - Supplies the KPROCESSOR_STATE where the 00561 current CPU's state is to be saved. 00562 00563 Return Value: 00564 00565 None. 00566 00567 --*/ 00568 00569 { 00570 RtlCaptureContext(&ProcessorState->ContextFrame); 00571 KiSaveProcessorControlState(ProcessorState); 00572 } #pragma optimize( "y", off ) // disable frame pointer omission (FPO)

__inline KIRQL Kix86FnSave PULONG  NpxFrame  ) 
 

Definition at line 84 of file ke/i386/misc.c.

Referenced by KeSaveFloatingPointState().

00087 { 00088 __asm { 00089 mov eax, NpxFrame 00090 fnsave [eax] 00091 } 00092 }

__inline KIRQL Kix86FxSave PULONG  NpxFrame  ) 
 

Definition at line 67 of file ke/i386/misc.c.

Referenced by KeSaveFloatingPointState().

00070 { 00071 _asm { 00072 mov eax, NpxFrame 00073 ;fxsave [eax] 00074 _emit 0fh 00075 _emit 0aeh 00076 _emit 0 00077 } 00078 }

__inline KIRQL Kix86LdMXCsr PULONG  MXCsr  ) 
 

Definition at line 99 of file ke/i386/misc.c.

Referenced by KeRestoreFloatingPointState(), and KeSaveFloatingPointState().

00102 { 00103 _asm { 00104 mov eax, MXCsr 00105 ;LDMXCSR [eax] 00106 _emit 0fh 00107 _emit 0aeh 00108 _emit 10h 00109 } 00110 }

__inline KIRQL Kix86StMXCsr PULONG  MXCsr  ) 
 

Definition at line 117 of file ke/i386/misc.c.

Referenced by KeSaveFloatingPointState().

00120 { 00121 _asm { 00122 mov eax, MXCsr 00123 ;STMXCSR [eax] 00124 _emit 0fh 00125 _emit 0aeh 00126 _emit 18h 00127 } 00128 }


Variable Documentation

BOOLEAN KeI386FxsrPresent
 

Definition at line 27 of file ke/i386/misc.c.

BOOLEAN KeI386XMMIPresent
 

Definition at line 28 of file ke/i386/misc.c.


Generated on Sat May 15 19:44:43 2004 for test by doxygen 1.3.7