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) 1993 IBM Corporation and Microsoft Corporation 00004 00005 Module Name: 00006 00007 alignem.c 00008 00009 Abstract: 00010 00011 This module implements the code necessary to emulate unaligned data 00012 references. 00013 00014 Author: 00015 00016 Rick Simpson 4-Aug-1993 00017 00018 Based on MIPS version by David N. Cutler (davec) 17-Jun-1991 00019 00020 Environment: 00021 00022 Kernel mode only. 00023 00024 Revision History: 00025 00026 --*/ 00027 00028 #include "ki.h" 00029 00030 VOID 00031 KiSetFloatRegisterValue ( 00032 IN ULONG, 00033 IN DOUBLE, 00034 OUT PKEXCEPTION_FRAME, 00035 OUT PKTRAP_FRAME 00036 ); 00037 00038 DOUBLE 00039 KiGetFloatRegisterValue ( 00040 IN ULONG, 00041 IN PKEXCEPTION_FRAME, 00042 IN PKTRAP_FRAME 00043 ); 00044 00045 /*++ 00046 When PowerPC takes an Alignment Interrupt, the hardware loads the following: 00047 SRR 0 <- Address of instruction causing the interrupt 00048 SRR 1 <- MSR 00049 DAR <- Effective address of the misaligned reference as computed 00050 by the instruction that caused the interrupt 00051 DSISR <- Several fields relevant to the failing instruction: 00052 Bits 12..13 <- Extended op-code (XO) if instr is DS-form 00053 Bits 15..21 <- Index into the table below, identifying 00054 (for the most part) the failing instr 00055 Bits 22..26 <- RT/RS/FRT/FRS field (reg no.) of instr 00056 Bits 27..31 <- RA (reg no.) field for update-form instrs 00057 00058 For the most part, it is not necessary to retrieve the actual instruction 00059 in order to emulate the effects of an unaligned load or store. Enough 00060 information is in the DSISR to distinguish most cases. Special processing 00061 is required for certain instructions -- the DSISR does not have enough 00062 information for them. 00063 00064 It is unnecessary to compute the failing effective address by emulating 00065 the instruction's addressing arithmetic, because the value required is 00066 contained in the DAR. 00067 00068 The table here is indexed by bits 15..21 of the DSISR. 00069 00070 The "escape" flag indicates that some sort of special handling is needed, 00071 for one of the following reasons: 00072 1) More than one instruction maps to the same DSISR value 00073 (ld/ldu/lwa, std/stdu) 00074 2) The instruction is load-and-reserve or store-conditional, 00075 and misalignment should not be "fixed up" 00076 3) The instruction is a byte-reversed load or store 00077 4) The instruction is "ecowx" or "eciwx" 00078 5) The instruction is "dcbz" 00079 6) The instruction is "stfiwx" 00080 00081 NOTE: Even though lwz and lwarx share the same DSISR value (0), the 00082 table entry for position 0 is used only for lwz. This is so that the 00083 most likely case (load word from unaligned address) can take the 00084 mainline path. The less likely case (load word and reserve from 00085 unaligned address) is ignored and treated as if it were simply load 00086 word. Unaligned addresses are not supported for lwarx/stwcx. in the 00087 PowerPC architecture. The implementation here (allowing lwarx to 00088 proceed as if it were lwx, without establishing a reservation) is 00089 allowable according to the architecture; a matching store conditional 00090 (stwcx.) to the same unaligned address will fail (return FALSE from 00091 this routine), so the incorrect reservation address will be caught 00092 then. 00093 --*/ 00094 00095 typedef struct _ALFAULT { 00096 ULONG Valid : 1; // Valid DSISR value (1) vs. Should not occur (0) 00097 ULONG Load : 1; // Load (1) vs. Store (0) 00098 ULONG Length : 2; // Length: 2 bytes (1), 4 bytes (2), 8 bytes (3) 00099 ULONG Signed : 1; // Sign-extended (1) vs. Zero-extended (0) 00100 ULONG Fixed : 1; // Fixed point (1) vs. Floating point (0) 00101 ULONG Update : 1; // Update-form (1) vs. Non-Update-form (0) 00102 ULONG Escape : 1; // Needs special processing (1) vs. Regular (0) 00103 } ALFAULT, *PALFAULT; 00104 00105 // Table indices for instructions needing special handling 00106 00107 #define LDARX_INDEX_VALUE 1 00108 #define LD_INDEX_VALUE 13 00109 #define STD_INDEX_VALUE 15 00110 #define STWCX_INDEX_VALUE 66 00111 #define STDCX_INDEX_VALUE 67 00112 #define LWBRX_INDEX_VALUE 72 00113 #define STWBRX_INDEX_VALUE 74 00114 #define LHBRX_INDEX_VALUE 76 00115 #define STHBRX_INDEX_VALUE 78 00116 #define ECIWX_INDEX_VALUE 84 00117 #define ECOWX_INDEX_VALUE 86 00118 #define DCBZ_INDEX_VALUE 95 00119 #define STFIWX_INDEX_VALUE 111 00120 00121 static ALFAULT AlFault[128] = { 00122 00123 // Valid Load Length Signed Fixed Update Escape 00124 { 1, 1, 2, 0, 1, 0, 0 }, // 0 lwz, lwarx 00125 { 1, 1, 3, 0, 1, 0, 1 }, // 1 ldarx 00126 { 1, 0, 2, 0, 1, 0, 0 }, // 2 stw 00127 { 0, 0, 0, 0, 0, 0, 0 }, // 3 00128 { 1, 1, 1, 0, 1, 0, 0 }, // 4 lhz 00129 { 1, 1, 1, 1, 1, 0, 0 }, // 5 lha 00130 { 1, 0, 1, 0, 1, 0, 0 }, // 6 sth 00131 { 0, 0, 0, 0, 0, 0, 0 }, // 7 00132 { 1, 1, 2, 0, 0, 0, 0 }, // 8 lfs 00133 { 1, 1, 3, 0, 0, 0, 0 }, // 9 lfd 00134 { 1, 0, 2, 0, 0, 0, 0 }, // 10 stfs 00135 { 1, 0, 3, 0, 0, 0, 0 }, // 11 stfd 00136 { 0, 0, 0, 0, 0, 0, 0 }, // 12 00137 { 1, 1, 0, 0, 0, 0, 1 }, // 13 ld, ldu, lwa 00138 { 0, 0, 0, 0, 0, 0, 0 }, // 14 00139 { 1, 0, 0, 0, 0, 0, 1 }, // 15 std, stdu 00140 { 1, 1, 2, 0, 1, 1, 0 }, // 16 lwzu 00141 { 0, 0, 0, 0, 0, 0, 0 }, // 17 00142 { 1, 0, 2, 0, 1, 1, 0 }, // 18 stwu 00143 { 0, 0, 0, 0, 0, 0, 0 }, // 19 00144 { 1, 1, 1, 0, 1, 1, 0 }, // 20 lhzu 00145 { 1, 1, 1, 1, 1, 1, 0 }, // 21 lhau 00146 { 1, 0, 1, 0, 1, 1, 0 }, // 22 sthu 00147 { 0, 0, 0, 0, 0, 0, 0 }, // 23 00148 { 1, 1, 2, 0, 0, 1, 0 }, // 24 lfsu 00149 { 1, 1, 3, 0, 0, 1, 0 }, // 25 lfdu 00150 { 1, 0, 2, 0, 0, 1, 0 }, // 26 stfsu 00151 { 1, 0, 3, 0, 0, 1, 0 }, // 27 stfdu 00152 { 0, 0, 0, 0, 0, 0, 0 }, // 28 00153 { 0, 0, 0, 0, 0, 0, 0 }, // 29 00154 { 0, 0, 0, 0, 0, 0, 0 }, // 30 00155 { 0, 0, 0, 0, 0, 0, 0 }, // 31 00156 { 1, 1, 3, 0, 1, 0, 0 }, // 32 ldx 00157 { 0, 0, 0, 0, 0, 0, 0 }, // 33 00158 { 1, 0, 3, 0, 1, 0, 0 }, // 34 stdx 00159 { 0, 0, 0, 0, 0, 0, 0 }, // 35 00160 { 0, 0, 0, 0, 0, 0, 0 }, // 36 00161 { 1, 1, 2, 1, 1, 0, 0 }, // 37 lwax 00162 { 0, 0, 0, 0, 0, 0, 0 }, // 38 00163 { 0, 0, 0, 0, 0, 0, 0 }, // 39 00164 { 0, 0, 0, 0, 0, 0, 0 }, // 40 00165 { 0, 0, 0, 0, 0, 0, 0 }, // 41 00166 { 0, 0, 0, 0, 0, 0, 0 }, // 42 00167 { 0, 0, 0, 0, 0, 0, 0 }, // 43 00168 { 0, 0, 0, 0, 0, 0, 0 }, // 44 00169 { 0, 0, 0, 0, 0, 0, 0 }, // 45 00170 { 0, 0, 0, 0, 0, 0, 0 }, // 46 00171 { 0, 0, 0, 0, 0, 0, 0 }, // 47 00172 { 1, 1, 3, 0, 1, 1, 0 }, // 48 ldux 00173 { 0, 0, 0, 0, 0, 0, 0 }, // 49 00174 { 1, 0, 3, 0, 1, 1, 0 }, // 50 stdux 00175 { 0, 0, 0, 0, 0, 0, 0 }, // 51 00176 { 0, 0, 0, 0, 0, 0, 0 }, // 52 00177 { 1, 1, 2, 1, 1, 1, 0 }, // 53 lwaux 00178 { 0, 0, 0, 0, 0, 0, 0 }, // 54 00179 { 0, 0, 0, 0, 0, 0, 0 }, // 55 00180 { 0, 0, 0, 0, 0, 0, 0 }, // 56 00181 { 0, 0, 0, 0, 0, 0, 0 }, // 57 00182 { 0, 0, 0, 0, 0, 0, 0 }, // 58 00183 { 0, 0, 0, 0, 0, 0, 0 }, // 59 00184 { 0, 0, 0, 0, 0, 0, 0 }, // 60 00185 { 0, 0, 0, 0, 0, 0, 0 }, // 61 00186 { 0, 0, 0, 0, 0, 0, 0 }, // 62 00187 { 0, 0, 0, 0, 0, 0, 0 }, // 63 00188 { 0, 0, 0, 0, 0, 0, 0 }, // 64 00189 { 0, 0, 0, 0, 0, 0, 0 }, // 65 00190 { 1, 0, 2, 0, 1, 0, 1 }, // 66 stwcx. 00191 { 1, 0, 3, 0, 1, 0, 1 }, // 67 stdcx. 00192 { 0, 0, 0, 0, 0, 0, 0 }, // 68 00193 { 0, 0, 0, 0, 0, 0, 0 }, // 69 00194 { 0, 0, 0, 0, 0, 0, 0 }, // 70 00195 { 0, 0, 0, 0, 0, 0, 0 }, // 71 00196 { 1, 1, 2, 0, 1, 0, 1 }, // 72 lwbrx 00197 { 0, 0, 0, 0, 0, 0, 0 }, // 73 00198 { 1, 0, 2, 0, 1, 0, 1 }, // 74 stwbrx 00199 { 0, 0, 0, 0, 0, 0, 0 }, // 75 00200 { 1, 1, 1, 0, 1, 0, 1 }, // 76 lhbrx 00201 { 0, 0, 0, 0, 0, 0, 0 }, // 77 00202 { 1, 0, 1, 0, 1, 0, 1 }, // 78 sthbrx 00203 { 0, 0, 0, 0, 0, 0, 0 }, // 79 00204 { 0, 0, 0, 0, 0, 0, 0 }, // 80 00205 { 0, 0, 0, 0, 0, 0, 0 }, // 81 00206 { 0, 0, 0, 0, 0, 0, 0 }, // 82 00207 { 0, 0, 0, 0, 0, 0, 0 }, // 83 00208 { 1, 1, 2, 0, 1, 0, 1 }, // 84 eciwx 00209 { 0, 0, 0, 0, 0, 0, 0 }, // 85 00210 { 1, 0, 2, 0, 1, 0, 1 }, // 86 ecowx 00211 { 0, 0, 0, 0, 0, 0, 0 }, // 87 00212 { 0, 0, 0, 0, 0, 0, 0 }, // 88 00213 { 0, 0, 0, 0, 0, 0, 0 }, // 89 00214 { 0, 0, 0, 0, 0, 0, 0 }, // 90 00215 { 0, 0, 0, 0, 0, 0, 0 }, // 91 00216 { 0, 0, 0, 0, 0, 0, 0 }, // 92 00217 { 0, 0, 0, 0, 0, 0, 0 }, // 93 00218 { 0, 0, 0, 0, 0, 0, 0 }, // 94 00219 { 1, 0, 0, 0, 0, 0, 1 }, // 95 dcbz 00220 { 1, 1, 2, 0, 1, 0, 0 }, // 96 lwzx 00221 { 0, 0, 0, 0, 0, 0, 0 }, // 97 00222 { 1, 0, 2, 0, 1, 0, 0 }, // 98 stwzx 00223 { 0, 0, 0, 0, 0, 0, 0 }, // 99 00224 { 1, 1, 1, 0, 1, 0, 0 }, // 100 lhzx 00225 { 1, 1, 1, 1, 1, 0, 0 }, // 101 lhax 00226 { 1, 0, 1, 0, 1, 0, 0 }, // 102 sthx 00227 { 0, 0, 0, 0, 0, 0, 0 }, // 103 00228 { 1, 1, 2, 0, 0, 0, 0 }, // 104 lfsx 00229 { 1, 1, 3, 0, 0, 0, 0 }, // 105 lfdx 00230 { 1, 0, 2, 0, 0, 0, 0 }, // 106 stfsx 00231 { 1, 0, 3, 0, 0, 0, 0 }, // 107 stfdx 00232 { 0, 0, 0, 0, 0, 0, 0 }, // 108 00233 { 0, 0, 0, 0, 0, 0, 0 }, // 109 00234 { 0, 0, 0, 0, 0, 0, 0 }, // 110 00235 { 1, 0, 2, 0, 1, 0, 1 }, // 111 stfiwx 00236 { 1, 1, 2, 0, 1, 1, 0 }, // 112 lwzux 00237 { 0, 0, 0, 0, 0, 0, 0 }, // 113 00238 { 1, 0, 2, 0, 1, 1, 0 }, // 114 stwux 00239 { 0, 0, 0, 0, 0, 0, 0 }, // 115 00240 { 1, 1, 1, 0, 1, 1, 0 }, // 116 lhzux 00241 { 1, 1, 1, 1, 1, 1, 0 }, // 117 lhaux 00242 { 1, 0, 1, 0, 1, 1, 0 }, // 118 sthux 00243 { 0, 0, 0, 0, 0, 0, 0 }, // 119 00244 { 1, 1, 2, 0, 0, 1, 0 }, // 120 lfsux 00245 { 1, 1, 3, 0, 0, 1, 0 }, // 121 lfdux 00246 { 1, 0, 2, 0, 0, 1, 0 }, // 122 stfsux 00247 { 1, 0, 3, 0, 0, 1, 0 }, // 123 stfdux 00248 { 0, 0, 0, 0, 0, 0, 0 }, // 124 00249 { 0, 0, 0, 0, 0, 0, 0 }, // 125 00250 { 0, 0, 0, 0, 0, 0, 0 }, // 126 00251 { 0, 0, 0, 0, 0, 0, 0 } // 127 00252 }; 00253 00254 BOOLEAN 00255 KiEmulateReference ( 00256 IN OUT PEXCEPTION_RECORD ExceptionRecord, 00257 IN OUT PKEXCEPTION_FRAME ExceptionFrame, 00258 IN OUT PKTRAP_FRAME TrapFrame 00259 ) 00260 00261 /*++ 00262 00263 Routine Description: 00264 00265 This function is called to emulate an unaligned data reference to an 00266 address in the user part of the address space. 00267 00268 Arguments: 00269 00270 ExceptionRecord - Supplies a pointer to an exception record. 00271 00272 ExceptionFrame - Supplies a pointer to an exception frame. 00273 00274 TrapFrame - Supplies a pointer to a trap frame. 00275 00276 Return Value: 00277 00278 A value of TRUE is returned if the data reference is successfully 00279 emulated. Otherwise, a value of FALSE is returned. 00280 00281 --*/ 00282 00283 { 00284 00285 ULONG BranchAddress; 00286 PUCHAR DataAddress; 00287 00288 union { 00289 DOUBLE Double; 00290 float Float; 00291 ULONG Long; 00292 SHORT Short; 00293 } DataReference; 00294 PUCHAR DataValue = (PUCHAR) &DataReference; 00295 00296 PVOID ExceptionAddress; 00297 DSISR DsisrValue; 00298 ULONG TableIndex; 00299 ULONG DataRegNum; 00300 ALFAULT Info; 00301 KIRQL OldIrql; 00302 00303 // 00304 // Call out to profile interrupt if alignment profiling is active 00305 // 00306 if (KiProfileAlignmentFixup) { 00307 00308 if (++KiProfileAlignmentFixupCount >= KiProfileAlignmentFixupInterval) { 00309 00310 KeRaiseIrql(PROFILE_LEVEL, &OldIrql); 00311 KiProfileAlignmentFixupCount = 0; 00312 KeProfileInterruptWithSource(TrapFrame, ProfileAlignmentFixup); 00313 KeLowerIrql(OldIrql); 00314 00315 } 00316 } 00317 00318 // 00319 // Save the original exception address in case another exception 00320 // occurs. 00321 // 00322 00323 ExceptionAddress = ExceptionRecord->ExceptionAddress; 00324 00325 // 00326 // Any exception that occurs during the attempted emulation of the 00327 // unaligned reference causes the emulation to be aborted. The new 00328 // exception code and information is copied to the original exception 00329 // record and a value of FALSE is returned. 00330 // 00331 00332 try { 00333 00334 // 00335 // PowerPC has no branch-delay-slot complexities like MIPS 00336 // 00337 00338 BranchAddress = TrapFrame->Iar + 4; 00339 00340 // 00341 // The effective address of the reference from the DAR was saved 00342 // in the exception record. Check to make sure it is within the 00343 // user part of the address space. Alignment exceptions take 00344 // precedence over memory management exceptions (this is true 00345 // for PowerPC as well as MIPS) and the address could be a 00346 // system address. 00347 // 00348 00349 DataAddress = (PUCHAR) (ExceptionRecord->ExceptionInformation[1]); 00350 00351 if ((ULONG)DataAddress < MM_USER_PROBE_ADDRESS) { 00352 00353 // 00354 // Get information about the failing instruction from saved DSISR. 00355 // 00356 00357 DsisrValue = *(DSISR*) &(ExceptionRecord->ExceptionInformation[2]); 00358 TableIndex = DsisrValue.Index; 00359 DataRegNum = DsisrValue.DataReg; 00360 Info = AlFault[TableIndex]; 00361 00362 // 00363 // If table entry is marked invalid, we have some sort of logic error. 00364 // 00365 00366 if (!Info.Valid) 00367 return FALSE; 00368 00369 // 00370 // If table entry does not indicate special processing needed, 00371 // emulate the execution of the instruction 00372 // 00373 00374 if (!Info.Escape) { 00375 00376 // 00377 // Integer or float load or store 00378 // 00379 00380 if (Info.Fixed) { 00381 00382 // 00383 // Integer register 00384 // 00385 00386 if (Info.Load) { 00387 00388 // 00389 // Integer load 00390 // 00391 00392 switch (Info.Length) { 00393 00394 // 00395 // Halfword integer load 00396 // 00397 00398 case 1: 00399 DataValue[0] = DataAddress[0]; 00400 DataValue[1] = DataAddress[1]; 00401 KiSetRegisterValue 00402 (DataRegNum, 00403 Info.Signed ? // sign extension ... 00404 (ULONG) ((LONG) DataReference.Short) : 00405 (ULONG) ((USHORT) DataReference.Short), 00406 ExceptionFrame, 00407 TrapFrame); 00408 break; 00409 00410 // 00411 // Fullword integer load 00412 // 00413 00414 case 2: 00415 DataValue[0] = DataAddress[0]; 00416 DataValue[1] = DataAddress[1]; 00417 DataValue[2] = DataAddress[2]; 00418 DataValue[3] = DataAddress[3]; 00419 KiSetRegisterValue 00420 (DataRegNum, 00421 DataReference.Long, 00422 ExceptionFrame, 00423 TrapFrame); 00424 break; 00425 00426 // 00427 // Doubleword integer load 00428 // 00429 00430 case 3: 00431 return FALSE; // Have no 8-byte integer regs yet 00432 00433 } 00434 } else { 00435 00436 // 00437 // Integer store 00438 // 00439 00440 switch (Info.Length) { 00441 00442 // 00443 // Halfword integer store 00444 // 00445 00446 case 1: 00447 DataReference.Short = (SHORT) 00448 KiGetRegisterValue 00449 (DataRegNum, 00450 ExceptionFrame, 00451 TrapFrame); 00452 DataAddress[0] = DataValue[0]; 00453 DataAddress[1] = DataValue[1]; 00454 break; 00455 00456 // 00457 // Fullword integer store 00458 // 00459 00460 case 2: // Word 00461 DataReference.Long = 00462 KiGetRegisterValue 00463 (DataRegNum, 00464 ExceptionFrame, 00465 TrapFrame); 00466 DataAddress[0] = DataValue[0]; 00467 DataAddress[1] = DataValue[1]; 00468 DataAddress[2] = DataValue[2]; 00469 DataAddress[3] = DataValue[3]; 00470 break; 00471 00472 // 00473 // Doubleword integer store 00474 // 00475 00476 case 3: 00477 00478 return FALSE; // Have no 8-byte integer regs yet 00479 } 00480 } 00481 } else { // Floating point 00482 00483 // 00484 // Floating-point register 00485 // 00486 00487 if (Info.Load) { // Floating point load 00488 00489 // 00490 // Floating-point load 00491 // 00492 00493 if (Info.Length == 2) { 00494 00495 // 00496 // Floating-point single precision load 00497 // 00498 DataValue[0] = DataAddress[0]; 00499 DataValue[1] = DataAddress[1]; 00500 DataValue[2] = DataAddress[2]; 00501 DataValue[3] = DataAddress[3]; 00502 KiSetFloatRegisterValue 00503 (DataRegNum, 00504 (DOUBLE) DataReference.Float, 00505 ExceptionFrame, 00506 TrapFrame); 00507 00508 } else { 00509 00510 // 00511 // Floating-point double precision load 00512 // 00513 DataValue[0] = DataAddress[0]; 00514 DataValue[1] = DataAddress[1]; 00515 DataValue[2] = DataAddress[2]; 00516 DataValue[3] = DataAddress[3]; 00517 DataValue[4] = DataAddress[4]; 00518 DataValue[5] = DataAddress[5]; 00519 DataValue[6] = DataAddress[6]; 00520 DataValue[7] = DataAddress[7]; 00521 KiSetFloatRegisterValue 00522 (DataRegNum, 00523 DataReference.Double, 00524 ExceptionFrame, 00525 TrapFrame); 00526 } 00527 } else { 00528 00529 // 00530 // Floating-point store 00531 // 00532 00533 if (Info.Length == 2) { 00534 00535 // 00536 // Floating-point single precision store 00537 // 00538 00539 DataReference.Float = (float) 00540 KiGetFloatRegisterValue 00541 (DataRegNum, 00542 ExceptionFrame, 00543 TrapFrame); 00544 DataAddress[0] = DataValue[0]; 00545 DataAddress[1] = DataValue[1]; 00546 DataAddress[2] = DataValue[2]; 00547 DataAddress[3] = DataValue[3]; 00548 00549 } else { 00550 00551 // 00552 // Floating-point double precision store 00553 // 00554 DataReference.Double = 00555 KiGetFloatRegisterValue 00556 (DataRegNum, 00557 ExceptionFrame, 00558 TrapFrame); 00559 DataAddress[0] = DataValue[0]; 00560 DataAddress[1] = DataValue[1]; 00561 DataAddress[2] = DataValue[2]; 00562 DataAddress[3] = DataValue[3]; 00563 DataAddress[4] = DataValue[4]; 00564 DataAddress[5] = DataValue[5]; 00565 DataAddress[6] = DataValue[6]; 00566 DataAddress[7] = DataValue[7]; 00567 } 00568 } 00569 } 00570 00571 // 00572 // See if "update" (post-increment) form of addressing 00573 // 00574 00575 if (Info.Update) 00576 KiSetRegisterValue // Store effective addr back into base reg 00577 (DsisrValue.UpdateReg, 00578 (ULONG) DataAddress, 00579 ExceptionFrame, 00580 TrapFrame); 00581 00582 } 00583 00584 // 00585 // Table indicates that special processing is needed, either because 00586 // the DSISR does not contain enough information to disambiguate the 00587 // failing instruction, or the instruction is not a load or store, 00588 // or the instruction has some other unusual requirement. 00589 // 00590 00591 else { // Info.Escape == 1 00592 switch (TableIndex) { 00593 00594 // 00595 // Doubleword integers not yet supported 00596 // 00597 00598 case LD_INDEX_VALUE: 00599 case STD_INDEX_VALUE: 00600 return FALSE; 00601 00602 // 00603 // Load-and-reserve, store-conditional not supported 00604 // for misaligned addresses 00605 // 00606 00607 case LDARX_INDEX_VALUE: 00608 case STWCX_INDEX_VALUE: 00609 case STDCX_INDEX_VALUE: 00610 return FALSE; 00611 00612 // 00613 // Integer byte-reversed fullword load 00614 // 00615 00616 case LWBRX_INDEX_VALUE: 00617 DataValue[0] = DataAddress[3]; 00618 DataValue[1] = DataAddress[2]; 00619 DataValue[2] = DataAddress[1]; 00620 DataValue[3] = DataAddress[0]; 00621 KiSetRegisterValue 00622 (DataRegNum, 00623 DataReference.Long, 00624 ExceptionFrame, 00625 TrapFrame); 00626 break; 00627 00628 // 00629 // Integer byte-reversed fullword store 00630 // 00631 00632 case STWBRX_INDEX_VALUE: 00633 DataReference.Long = 00634 KiGetRegisterValue 00635 (DataRegNum, 00636 ExceptionFrame, 00637 TrapFrame); 00638 DataAddress[0] = DataValue[3]; 00639 DataAddress[1] = DataValue[2]; 00640 DataAddress[2] = DataValue[1]; 00641 DataAddress[3] = DataValue[0]; 00642 break; 00643 00644 // 00645 // Integer byte-reversed halfword load 00646 // 00647 00648 case LHBRX_INDEX_VALUE: 00649 DataValue[0] = DataAddress[1]; 00650 DataValue[1] = DataAddress[0]; 00651 KiSetRegisterValue 00652 (DataRegNum, 00653 Info.Signed ? // sign extension ... 00654 (ULONG) ((LONG) DataReference.Short) : 00655 (ULONG) ((USHORT) DataReference.Short), 00656 ExceptionFrame, 00657 TrapFrame); 00658 break; 00659 00660 // 00661 // Integer byte-reversed halfword store 00662 // 00663 00664 case STHBRX_INDEX_VALUE: 00665 DataReference.Short = (SHORT) 00666 KiGetRegisterValue 00667 (DataRegNum, 00668 ExceptionFrame, 00669 TrapFrame); 00670 DataAddress[0] = DataValue[1]; 00671 DataAddress[1] = DataValue[0]; 00672 break; 00673 00674 // 00675 // Special I/O instructions not supported yet 00676 // 00677 00678 case ECIWX_INDEX_VALUE: 00679 case ECOWX_INDEX_VALUE: 00680 return FALSE; 00681 00682 // 00683 // Data Cache Block Zero 00684 // 00685 // dcbz causes an alignment fault if cache is disabled 00686 // for the address range covered by the block. 00687 // 00688 // A data cache block is 32 bytes long, we emulate this 00689 // instruction by storing 8 zero integers a the address 00690 // specified. 00691 // 00692 // Note, dcbz zeros the block "containing" the address 00693 // so we round down first. 00694 // 00695 00696 case DCBZ_INDEX_VALUE: { 00697 PULONG DcbAddress = (PULONG)((ULONG)DataAddress & ~0x1f); 00698 00699 *DcbAddress++ = 0; 00700 *DcbAddress++ = 0; 00701 *DcbAddress++ = 0; 00702 *DcbAddress++ = 0; 00703 *DcbAddress++ = 0; 00704 *DcbAddress++ = 0; 00705 *DcbAddress++ = 0; 00706 *DcbAddress++ = 0; 00707 break; 00708 } 00709 00710 // 00711 // Store Floating as Integer 00712 // 00713 00714 case STFIWX_INDEX_VALUE: 00715 DataReference.Double = 00716 KiGetFloatRegisterValue 00717 (DataRegNum, 00718 ExceptionFrame, 00719 TrapFrame); 00720 DataAddress[0] = DataValue[0]; 00721 DataAddress[1] = DataValue[1]; 00722 DataAddress[2] = DataValue[2]; 00723 DataAddress[3] = DataValue[3]; 00724 } 00725 } 00726 00727 TrapFrame->Iar = BranchAddress; 00728 return TRUE; 00729 } 00730 00731 // 00732 // If an exception occurs, then copy the new exception information to the 00733 // original exception record and handle the exception. 00734 // 00735 00736 } except (KiCopyInformation(ExceptionRecord, 00737 (GetExceptionInformation())->ExceptionRecord)) { 00738 00739 // 00740 // Preserve the original exception address. 00741 // 00742 00743 ExceptionRecord->ExceptionAddress = ExceptionAddress; 00744 } 00745 00746 // 00747 // Return a value of FALSE. 00748 // 00749 00750 return FALSE; 00751 } 00752 00753 BOOLEAN 00754 KiEmulateDcbz ( 00755 IN OUT PEXCEPTION_RECORD ExceptionRecord, 00756 IN OUT PKEXCEPTION_FRAME ExceptionFrame, 00757 IN OUT PKTRAP_FRAME TrapFrame 00758 ) 00759 00760 /*++ 00761 00762 Routine Description: 00763 00764 This function is called to emulate a Data Cache Block Zero instruction. 00765 The PowerPC hardware will raise an alignment exception if a DCBZ is 00766 attempted on non-cached memory. We need to emulate this even in kernel 00767 mode so we can debug h/w problems by disabling the data cache. 00768 00769 Arguments: 00770 00771 ExceptionRecord - Supplies a pointer to an exception record. 00772 00773 ExceptionFrame - Supplies a pointer to an exception frame. 00774 00775 TrapFrame - Supplies a pointer to a trap frame. 00776 00777 Return Value: 00778 00779 A value of TRUE is returned if the data reference is successfully 00780 emulated. Otherwise, a value of FALSE is returned. 00781 00782 --*/ 00783 00784 { 00785 00786 PUCHAR DataAddress; 00787 PVOID ExceptionAddress; 00788 DSISR DsisrValue; 00789 ULONG TableIndex; 00790 ULONG DataRegNum; 00791 ALFAULT Info; 00792 00793 // 00794 // Save the original exception address in case another exception 00795 // occurs. 00796 // 00797 00798 ExceptionAddress = ExceptionRecord->ExceptionAddress; 00799 00800 // 00801 // Any exception that occurs during the attempted emulation of the 00802 // unaligned reference causes the emulation to be aborted. The new 00803 // exception code and information is copied to the original exception 00804 // record and a value of FALSE is returned. 00805 // 00806 00807 try { 00808 00809 // 00810 // The effective address of the reference from the DAR was saved 00811 // in the exception record. Check to make sure it is within the 00812 // user part of the address space. Alignment exceptions take 00813 // precedence over memory management exceptions (this is true 00814 // for PowerPC as well as MIPS) and the address could be a 00815 // system address. 00816 // 00817 00818 DataAddress = (PUCHAR) (ExceptionRecord->ExceptionInformation[1]); 00819 00820 // 00821 // Get information about the failing instruction from saved DSISR. 00822 // 00823 00824 DsisrValue = *(DSISR*) &(ExceptionRecord->ExceptionInformation[2]); 00825 TableIndex = DsisrValue.Index; 00826 DataRegNum = DsisrValue.DataReg; 00827 Info = AlFault[TableIndex]; 00828 00829 // 00830 // If table entry is valid and does not indicate special processing 00831 // needed, and is a DCBZ instruction, emulate the execution of the 00832 // instruction 00833 // 00834 00835 if (Info.Valid && Info.Escape && (TableIndex == DCBZ_INDEX_VALUE)) { 00836 00837 // 00838 // Data Cache Block Zero 00839 // 00840 // A data cache block is 32 bytes long, we emulate this 00841 // instruction by storing 8 zero integers a the address 00842 // specified. 00843 // 00844 // Note, dcbz zeros the block "containing" the address 00845 // so we round down first. 00846 // 00847 00848 PULONG DcbAddress = (PULONG)((ULONG)DataAddress & ~0x1f); 00849 00850 *DcbAddress++ = 0; 00851 *DcbAddress++ = 0; 00852 *DcbAddress++ = 0; 00853 *DcbAddress++ = 0; 00854 *DcbAddress++ = 0; 00855 *DcbAddress++ = 0; 00856 *DcbAddress++ = 0; 00857 *DcbAddress++ = 0; 00858 00859 // 00860 // Bump instruction address to next instruction. 00861 // 00862 00863 TrapFrame->Iar += 4; 00864 00865 return TRUE; 00866 } 00867 00868 // 00869 // If an exception occurs, then copy the new exception information to the 00870 // original exception record and handle the exception. 00871 // 00872 00873 } except (KiCopyInformation(ExceptionRecord, 00874 (GetExceptionInformation())->ExceptionRecord)) { 00875 00876 // 00877 // Preserve the original exception address. 00878 // 00879 00880 ExceptionRecord->ExceptionAddress = ExceptionAddress; 00881 } 00882 00883 // 00884 // Return a value of FALSE. 00885 // 00886 00887 return FALSE; 00888 }

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