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

alignem.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1991 Microsoft Corporation 00004 Copyright (c) 1992 Digital Equipment Corporation 00005 00006 Module Name: 00007 00008 alignem.c 00009 00010 Abstract: 00011 00012 This module implements the code necessary to emulate unaligned data 00013 references. 00014 00015 Author: 00016 00017 David N. Cutler (davec) 17-Jun-1991 00018 Joe Notarangelo 14-May-1992 00019 00020 Environment: 00021 00022 Kernel mode only. 00023 00024 Revision History: 00025 00026 --*/ 00027 00028 #include "ki.h" 00029 00030 // 00031 // Function prototypes for emulation routines 00032 // 00033 ULONGLONG 00034 KiEmulateLoadLong( 00035 IN PULONG UnalignedAddress 00036 ); 00037 00038 ULONGLONG 00039 KiEmulateLoadQuad( 00040 IN PUQUAD UnalignedAddress 00041 ); 00042 00043 ULONGLONG 00044 KiEmulateLoadFloatIEEESingle( 00045 IN PULONG UnalignedAddress 00046 ); 00047 00048 ULONGLONG 00049 KiEmulateLoadFloatIEEEDouble( 00050 IN PUQUAD UnalignedAddress 00051 ); 00052 00053 VOID 00054 KiEmulateStoreLong( 00055 IN PULONG UnalignedAddress, 00056 IN ULONGLONG Data 00057 ); 00058 00059 VOID 00060 KiEmulateStoreQuad( 00061 IN PUQUAD UnalignedAddress, 00062 IN ULONGLONG Data 00063 ); 00064 00065 VOID 00066 KiEmulateStoreFloatIEEESingle( 00067 IN PULONG UnalignedAddress, 00068 IN ULONGLONG Data 00069 ); 00070 00071 VOID 00072 KiEmulateStoreFloatIEEEDouble( 00073 IN PUQUAD UnalignedAddress, 00074 IN ULONGLONG Data 00075 ); 00076 00077 VOID 00078 KiEnablePALAlignmentFixups( 00079 VOID 00080 ); 00081 00082 VOID 00083 KiDisablePALAlignmentFixups( 00084 VOID 00085 ); 00086 00087 VOID 00088 KiProfileInterrupt( 00089 IN KPROFILE_SOURCE ProfileSource, 00090 IN PKTRAP_FRAME TrapFrame 00091 ); 00092 00093 00094 VOID 00095 KiEnableAlignmentExceptions( 00096 VOID 00097 ) 00098 /*++ 00099 00100 Routine Description: 00101 00102 Enables alignment exceptions on the current processor by 00103 disabling automatic PAL code alignment fixups. PAL is 00104 called to turn off automatic fixups only if CPU is 00105 21164 or greater. 00106 00107 Arguments: 00108 00109 None 00110 00111 Return Value: 00112 00113 None 00114 00115 --*/ 00116 00117 { 00118 if (KeProcessorLevel >= PROCESSOR_ALPHA_21164) { 00119 KiDisablePALAlignmentFixups(); 00120 } 00121 } 00122 00123 00124 VOID 00125 KiDisableAlignmentExceptions( 00126 VOID 00127 ) 00128 /*++ 00129 00130 Routine Description: 00131 00132 Disables alignment exceptions on the current processor by 00133 enabling automatic PAL code alignment fixups. PAL is 00134 called to turn on automatic fixups only if CPU is 00135 21164 or greater and KiEnableAlignmentFaultExceptions==0 00136 00137 If KiEnableAlignmentFaultExceptions is either 1 or 2, then 00138 the kernel always needs to see alignment faults, so PAL 00139 automatic alignment fixups should not be enabled 00140 00141 Arguments: 00142 00143 None 00144 00145 Return Value: 00146 00147 None 00148 00149 --*/ 00150 00151 { 00152 if ((KeProcessorLevel >= PROCESSOR_ALPHA_21164) && 00153 (KiEnableAlignmentFaultExceptions == 0)) { 00154 KiEnablePALAlignmentFixups(); 00155 } 00156 } 00157 00158 00159 BOOLEAN 00160 KiEmulateReference ( 00161 IN OUT PEXCEPTION_RECORD ExceptionRecord, 00162 IN OUT PKEXCEPTION_FRAME ExceptionFrame, 00163 IN OUT PKTRAP_FRAME TrapFrame, 00164 IN BOOLEAN QuadwordOnly 00165 ) 00166 00167 /*++ 00168 00169 Routine Description: 00170 00171 Routine emulates an unaligned data reference from user part 00172 of the address space. 00173 00174 Arguments: 00175 00176 ExceptionRecord - Supplies a pointer to the exception record. 00177 00178 ExceptionFrame - Supplies a pointer to an exception frame. 00179 00180 TrapFrame - Supplies a pointer to a trap frame 00181 00182 QuadwordOnly - Supplies a boolean which controls whether both longword 00183 and quadword references are to be emulated or quadword references 00184 only. 00185 00186 Return Value: 00187 00188 True is returned if reference is successfully emulated, 00189 otherwise False is returned. 00190 00191 --*/ 00192 00193 { 00194 00195 ULONGLONG Data; 00196 PVOID EffectiveAddress; 00197 PVOID ExceptionAddress; 00198 ULONG Fa; 00199 ULONG Opcode; 00200 KPROCESSOR_MODE PreviousMode; 00201 ULONG Ra; 00202 KIRQL OldIrql; 00203 00204 // 00205 // Call out to profile interrupt if alignment profiling is active 00206 // 00207 if (KiProfileAlignmentFixup) { 00208 00209 if (++KiProfileAlignmentFixupCount >= KiProfileAlignmentFixupInterval) { 00210 00211 KeRaiseIrql(PROFILE_LEVEL, &OldIrql); 00212 KiProfileAlignmentFixupCount = 0; 00213 KiProfileInterrupt(ProfileAlignmentFixup, TrapFrame); 00214 KeLowerIrql(OldIrql); 00215 00216 } 00217 } 00218 00219 // 00220 // Save original exception address in case another exception occurs 00221 // 00222 00223 ExceptionAddress = ExceptionRecord->ExceptionAddress; 00224 00225 // 00226 // The ExceptionInformation in the ExceptionRecord has already 00227 // recorded information we need to emulate the access. 00228 // 00229 // ExceptionInformation: 00230 // [0] = opcode 00231 // [1] = destination register 00232 // [2] = effective address of access 00233 00234 Opcode = (ULONG)ExceptionRecord->ExceptionInformation[0]; 00235 Ra = (ULONG)ExceptionRecord->ExceptionInformation[1]; 00236 Fa = Ra + 32; // convert to floating register name for floating opcodes 00237 EffectiveAddress = (PVOID)ExceptionRecord->ExceptionInformation[2]; 00238 00239 // 00240 // Capture previous mode from trap frame not current thread. 00241 // 00242 00243 PreviousMode = (KPROCESSOR_MODE)(((PSR *)(&TrapFrame->Psr))->MODE); 00244 00245 // 00246 // Any exception that occurs during the attempted emulation will cause 00247 // the emulation to be aborted. The new exception code and information 00248 // will be copied to the original exception record and FALSE will be 00249 // returned. If the unaligned access was not from kernel mode then 00250 // probe the effective address before performing the emulation. 00251 // 00252 00253 try { 00254 00255 switch (Opcode) { 00256 00257 // 00258 // load longword 00259 // 00260 00261 case LDL_OP: 00262 if (QuadwordOnly != FALSE) { 00263 return FALSE; 00264 } 00265 if( PreviousMode != KernelMode ){ 00266 ProbeForRead( EffectiveAddress, 00267 sizeof(LONG), 00268 sizeof(UCHAR) ); 00269 } 00270 Data = KiEmulateLoadLong( EffectiveAddress ); 00271 KiSetRegisterValue( Ra, 00272 Data, 00273 ExceptionFrame, 00274 TrapFrame ); 00275 00276 break; 00277 00278 // 00279 // load quadword 00280 // 00281 00282 case LDQ_OP: 00283 if( PreviousMode != KernelMode ){ 00284 ProbeForRead( EffectiveAddress, 00285 sizeof(LONGLONG), 00286 sizeof(UCHAR) ); 00287 } 00288 Data = KiEmulateLoadQuad( EffectiveAddress ); 00289 KiSetRegisterValue( Ra, 00290 Data, 00291 ExceptionFrame, 00292 TrapFrame ); 00293 00294 break; 00295 00296 // 00297 // load IEEE single float 00298 // 00299 00300 case LDS_OP: 00301 if (QuadwordOnly != FALSE) { 00302 return FALSE; 00303 } 00304 if( PreviousMode != KernelMode ){ 00305 ProbeForRead( EffectiveAddress, 00306 sizeof(float), 00307 sizeof(UCHAR) ); 00308 } 00309 Data = KiEmulateLoadFloatIEEESingle( EffectiveAddress ); 00310 KiSetRegisterValue( Fa, 00311 Data, 00312 ExceptionFrame, 00313 TrapFrame ); 00314 00315 break; 00316 00317 // 00318 // load IEEE double float 00319 // 00320 00321 case LDT_OP: 00322 if( PreviousMode != KernelMode ){ 00323 ProbeForRead( EffectiveAddress, 00324 sizeof(DOUBLE), 00325 sizeof(UCHAR) ); 00326 } 00327 Data = KiEmulateLoadFloatIEEEDouble( EffectiveAddress ); 00328 KiSetRegisterValue( Fa, 00329 Data, 00330 ExceptionFrame, 00331 TrapFrame ); 00332 00333 break; 00334 00335 // 00336 // Load word unsigned. 00337 // 00338 00339 case LDWU_OP : 00340 if (QuadwordOnly != FALSE) { 00341 return FALSE; 00342 } 00343 if (PreviousMode != KernelMode) { 00344 ProbeForRead(EffectiveAddress, 00345 sizeof(SHORT), 00346 sizeof(UCHAR)); 00347 } 00348 Data = (ULONGLONG)*(UNALIGNED USHORT *)EffectiveAddress; 00349 KiSetRegisterValue(Ra, 00350 Data, 00351 ExceptionFrame, 00352 TrapFrame); 00353 00354 break; 00355 00356 // 00357 // store longword 00358 // 00359 00360 case STL_OP: 00361 if (QuadwordOnly != FALSE) { 00362 return FALSE; 00363 } 00364 if( PreviousMode != KernelMode ){ 00365 ProbeForWrite( EffectiveAddress, 00366 sizeof(LONG), 00367 sizeof(UCHAR) ); 00368 } 00369 Data = KiGetRegisterValue( Ra, 00370 ExceptionFrame, 00371 TrapFrame ); 00372 KiEmulateStoreLong( EffectiveAddress, (ULONG)Data ); 00373 00374 break; 00375 00376 // 00377 // store quadword 00378 // 00379 00380 case STQ_OP: 00381 if( PreviousMode != KernelMode ){ 00382 ProbeForWrite( EffectiveAddress, 00383 sizeof(LONGLONG), 00384 sizeof(UCHAR) ); 00385 } 00386 Data = KiGetRegisterValue( Ra, 00387 ExceptionFrame, 00388 TrapFrame ); 00389 KiEmulateStoreQuad( EffectiveAddress, Data ); 00390 00391 break; 00392 00393 // 00394 // store IEEE float single 00395 // 00396 00397 case STS_OP: 00398 if (QuadwordOnly != FALSE) { 00399 return FALSE; 00400 } 00401 if( PreviousMode != KernelMode ){ 00402 ProbeForWrite( EffectiveAddress, 00403 sizeof(float), 00404 sizeof(UCHAR) ); 00405 } 00406 Data = KiGetRegisterValue( Fa, 00407 ExceptionFrame, 00408 TrapFrame ); 00409 KiEmulateStoreFloatIEEESingle( EffectiveAddress, Data ); 00410 00411 break; 00412 00413 // 00414 // store IEEE float double 00415 // 00416 00417 case STT_OP: 00418 if( PreviousMode != KernelMode ){ 00419 ProbeForWrite( EffectiveAddress, 00420 sizeof(DOUBLE), 00421 sizeof(UCHAR) ); 00422 } 00423 Data = KiGetRegisterValue( Fa, 00424 ExceptionFrame, 00425 TrapFrame ); 00426 KiEmulateStoreFloatIEEEDouble( EffectiveAddress, Data ); 00427 00428 break; 00429 00430 // 00431 // Store word. 00432 // 00433 00434 case STW_OP : 00435 if (QuadwordOnly != FALSE) { 00436 return FALSE; 00437 } 00438 if (PreviousMode != KernelMode) { 00439 ProbeForWrite(EffectiveAddress, 00440 sizeof(SHORT), 00441 sizeof(UCHAR)); 00442 } 00443 Data = KiGetRegisterValue(Ra, 00444 ExceptionFrame, 00445 TrapFrame); 00446 *(UNALIGNED USHORT *)EffectiveAddress = (USHORT)Data; 00447 00448 break; 00449 00450 // 00451 // all other instructions are not emulated 00452 // 00453 00454 default: 00455 return FALSE; 00456 } 00457 00458 TrapFrame->Fir += 4; 00459 return TRUE; 00460 00461 } except (KiCopyInformation(ExceptionRecord, 00462 (GetExceptionInformation())->ExceptionRecord)) { 00463 00464 // 00465 // Preserve the original exception address 00466 // 00467 00468 ExceptionRecord->ExceptionAddress = ExceptionAddress; 00469 00470 return FALSE; 00471 } 00472 } 00473 

Generated on Sat May 15 19:39:13 2004 for test by doxygen 1.3.7