00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
#include "ki.h"
00023
00024
NTSTATUS
00025
Ki386CheckDivideByZeroTrap (
00026 IN PKTRAP_FRAME UserFrame
00027 );
00028
00029
00030
#ifdef ALLOC_PRAGMA
00031
#pragma alloc_text(PAGE, Ki386CheckDivideByZeroTrap)
00032
#endif
00033
00034
00035 #define REG(field) ((ULONG)(&((KTRAP_FRAME *)0)->field))
00036 #define GETREG(frame,reg) ((PULONG) (((ULONG) frame)+reg))[0]
00037
00038 typedef struct {
00039 UCHAR RmDisplaceOnly;
00040 UCHAR RmSib;
00041 UCHAR RmDisplace;
00042 UCHAR Disp;
00043 }
KMOD, *
PKMOD;
00044
00045 static UCHAR
RM32[] = {
00046
REG(Eax),
00047
REG(Ecx),
00048
REG(Edx),
00049
REG(Ebx),
00050
REG(HardwareEsp),
00051
REG(Ebp),
00052
REG(Esi),
00053
REG(Edi)
00054 };
00055
00056 static UCHAR
RM8[] = {
00057
REG(Eax),
00058
REG(Ecx),
00059
REG(Edx),
00060
REG(Ebx),
00061
REG(Eax) + 1,
00062
REG(Ecx) + 1,
00063
REG(Edx) + 1,
00064
REG(Ebx) + 1
00065 };
00066
00067 static KMOD MOD32[] = {
00068 5, 4, 0x20, 4,
00069 0xff, 4, 0xff, 1,
00070 0xff, 4, 0xff, 4,
00071 0xff, 0xff, 0x00, 0
00072 } ;
00073
00074
static struct {
00075 UCHAR
Opcode1,
Opcode2;
00076 UCHAR
ModRm,
type;
00077 }
NoWaitNpxInstructions[] = {
00078 0xDB, 0xE3, 0, 1,
00079 0xDB, 0xE2, 0, 1,
00080 0xD9, 0x06, 1, 1,
00081 0xDD, 0x06, 1, 1,
00082 0xD9, 0x07, 1, 2,
00083 0xDD, 0x07, 1, 3,
00084 0xDF, 0xE0, 0, 4,
00085 0x00, 0x00, 0, 1
00086 };
00087
00088
00089
NTSTATUS
00090 Ki386CheckDivideByZeroTrap (
00091 IN PKTRAP_FRAME UserFrame
00092 )
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 {
00113 ULONG operandsize, operandmask, i, accum;
00114 PUCHAR istream, pRM;
00115 UCHAR ibyte, rm;
00116
PKMOD Mod;
00117 BOOLEAN fPrefix;
00118
NTSTATUS status;
00119
00120 status = STATUS_INTEGER_DIVIDE_BY_ZERO;
00121
00122
if (UserFrame->SegCs == KGDT_R0_CODE) {
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
KeBugCheck (
UNEXPECTED_KERNEL_MODE_TRAP);
00134
00135 }
00136
00137
00138
try {
00139
00140
00141
00142
00143
00144 fPrefix =
TRUE;
00145 pRM =
RM32;
00146 operandsize = 4;
00147 operandmask = 0xffffffff;
00148 istream = (PUCHAR) UserFrame->Eip;
00149
while (fPrefix) {
00150 ibyte =
ProbeAndReadUchar(istream);
00151 istream++;
00152
switch (ibyte) {
00153
case 0x2e:
00154
case 0x36:
00155
case 0x3e:
00156
case 0x26:
00157
case 0x64:
00158
case 0x65:
00159
case 0xF3:
00160
case 0xF2:
00161
case 0xF0:
00162
break;
00163
00164
case 0x66:
00165
00166 operandsize = 2;
00167 operandmask = 0xffff;
00168
break;
00169
00170
case 0x67:
00171
00172
00173
goto try_exit;
00174
00175
default:
00176 fPrefix =
FALSE;
00177
break;
00178 }
00179 }
00180
00181
00182
00183
00184
00185
if (ibyte != 0xf7 && ibyte != 0xf6) {
00186
00187
goto try_exit;
00188 }
00189
00190
if (ibyte == 0xf6) {
00191
00192 operandsize = 1;
00193 operandmask = 0xff;
00194 }
00195
00196
00197
00198
00199
00200 ibyte =
ProbeAndReadUchar (istream);
00201 istream++;
00202 Mod =
MOD32 + (ibyte >> 6);
00203 rm = ibyte & 7;
00204
00205
00206
00207
00208
00209
if (operandsize == 1 && (ibyte & 0xc0) == 0xc0) {
00210 pRM =
RM8;
00211 }
00212
00213 accum = 0;
00214
if (rm != Mod->RmDisplaceOnly) {
00215
if (rm == Mod->RmSib) {
00216
00217 ibyte =
ProbeAndReadUchar(istream);
00218 istream++;
00219 i = (ibyte >> 3) & 7;
00220
if (i != 4) {
00221 accum =
GETREG(UserFrame,
RM32[i]);
00222 accum = accum << (ibyte >> 6);
00223 }
00224 i = ibyte & 7;
00225 accum = accum +
GETREG(UserFrame,
RM32[i]);
00226 }
else {
00227
00228 accum =
GETREG(UserFrame, pRM[rm]);
00229 }
00230 }
00231
00232
00233
00234
00235
00236
if (Mod->RmDisplace & (1 << rm)) {
00237
if (Mod->Disp == 4) {
00238 i =
ProbeAndReadUlong ((PULONG) istream);
00239 }
else {
00240 ibyte =
ProbeAndReadChar (istream);
00241 i = (
signed long) ((
signed char) ibyte);
00242 }
00243 accum += i;
00244 }
00245
00246
00247
00248
00249
00250
if (Mod->Disp) {
00251
switch (operandsize) {
00252
case 1: accum =
ProbeAndReadUchar((PUCHAR) accum);
break;
00253
case 2: accum =
ProbeAndReadUshort((
PUSHORT) accum);
break;
00254
case 4: accum =
ProbeAndReadUlong((PULONG) accum);
break;
00255 }
00256 }
00257
00258
00259
00260
00261
00262
00263
if (accum & operandmask) {
00264
00265 status = STATUS_INTEGER_OVERFLOW;
00266 }
00267
00268 try_exit: ;
00269 } except (
EXCEPTION_EXECUTE_HANDLER) {
00270
00271 }
00272
00273
return status;
00274 }
00275
00276 UCHAR
00277 KiNextIStreamByte (
00278 IN PKTRAP_FRAME UserFrame,
00279 IN PUCHAR *istream
00280 )
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 {
00293 UCHAR ibyte;
00294
00295
if (UserFrame->SegCs == KGDT_R0_CODE) {
00296 ibyte = **istream;
00297 }
else {
00298 ibyte =
ProbeAndReadUchar (*istream);
00299 }
00300
00301 *istream += 1;
00302
return ibyte;
00303 }
00304
00305
00306
00307
00308 BOOLEAN
00309 Ki386CheckDelayedNpxTrap (
00310 IN PKTRAP_FRAME UserFrame,
00311 IN PFX_SAVE_AREA NpxFrame
00312 )
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345 {
00346 EXCEPTION_RECORD ExceptionRecord;
00347 UCHAR ibyte1, ibyte2, inmodrm, status;
00348
USHORT StatusWord, ControlWord, UsersWord;
00349 PUCHAR istream;
00350 BOOLEAN fPrefix;
00351 UCHAR rm;
00352
PKMOD Mod;
00353 ULONG accum, i;
00354
00355 status = 0;
00356
try {
00357
00358
00359
00360
00361
00362 fPrefix =
TRUE;
00363 istream = (PUCHAR) UserFrame->Eip;
00364
while (fPrefix) {
00365 ibyte1 =
KiNextIStreamByte (UserFrame, &istream);
00366
switch (ibyte1) {
00367
case 0x2e:
00368
case 0x36:
00369
case 0x3e:
00370
case 0x26:
00371
case 0x64:
00372
case 0x65:
00373
break;
00374
00375
default:
00376 fPrefix =
FALSE;
00377
break;
00378 }
00379 }
00380
00381
00382
00383
00384
00385 ibyte2 =
KiNextIStreamByte (UserFrame, &istream);
00386 inmodrm = (ibyte2 >> 3) & 0x7;
00387
00388
for (i=0;
NoWaitNpxInstructions[i].Opcode1; i++) {
00389
if (
NoWaitNpxInstructions[i].Opcode1 == ibyte1) {
00390
00391
00392
00393
00394
00395
if (
NoWaitNpxInstructions[i].ModRm) {
00396
00397
00398
00399
00400
00401
if (((ibyte2 & 0xc0) != 0xc0) &&
00402 (
NoWaitNpxInstructions[i].Opcode2 == inmodrm)) {
00403
00404
00405
00406
00407
00408 status =
NoWaitNpxInstructions[i].type;
00409
break;
00410 }
00411
00412 }
else {
00413
if (
NoWaitNpxInstructions[i].Opcode2 == ibyte2) {
00414
00415
00416
00417
00418
00419 status =
NoWaitNpxInstructions[i].type;
00420
break;
00421 }
00422 }
00423 }
00424 }
00425
00426 } except (
EXCEPTION_EXECUTE_HANDLER) {
00427
00428 }
00429
00430
if (status == 0) {
00431
00432
00433
00434
00435
return FALSE;
00436 }
00437
00438
if (status == 1) {
00439
00440
00441
00442
00443
00444 _asm {
00445 mov eax, cr0
00446 and eax, NOT (CR0_MP+CR0_EM+CR0_TS)
00447 mov cr0, eax
00448 }
00449
00450 NpxFrame->Cr0NpxState &= ~CR0_TS;
00451
return TRUE;
00452 }
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465 _asm {
00466 mov eax, cr0
00467 mov ecx, eax
00468 and eax, NOT (CR0_MP+CR0_EM+CR0_TS)
00469 mov cr0, eax
00470
00471 fnstsw StatusWord
00472 fnstcw ControlWord
00473
00474 mov cr0, ecx
00475 sti
00476 }
00477
00478
if (status == 4) {
00479
00480
00481
00482
00483 UserFrame->Eip = (ULONG)istream;
00484 UserFrame->Eax = (UserFrame->Eax & 0xFFFF0000) | StatusWord;
00485
return TRUE;
00486 }
00487
00488
if (status == 2) {
00489 UsersWord = ControlWord;
00490 }
else {
00491 UsersWord = StatusWord;
00492 }
00493
00494
try {
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506 Mod =
MOD32 + (ibyte2 >> 6);
00507 rm = ibyte2 & 7;
00508
00509
00510
00511
00512
00513 accum = 0;
00514
if (rm != Mod->RmDisplaceOnly) {
00515
if (rm == Mod->RmSib) {
00516
00517 ibyte1 =
KiNextIStreamByte (UserFrame, &istream);
00518 i = (ibyte1 >> 3) & 7;
00519
if (i != 4) {
00520 accum =
GETREG(UserFrame,
RM32[i]);
00521 accum = accum << (ibyte1 >> 6);
00522 }
00523 i = ibyte1 & 7;
00524 accum = accum +
GETREG(UserFrame,
RM32[i]);
00525 }
else {
00526
00527 accum =
GETREG(UserFrame,
RM32[rm]);
00528 }
00529 }
00530
00531
00532
00533
00534
00535
if (Mod->RmDisplace & (1 << rm)) {
00536
if (Mod->Disp == 4) {
00537 i = (
KiNextIStreamByte (UserFrame, &istream) << 0) |
00538 (
KiNextIStreamByte (UserFrame, &istream) << 8) |
00539 (
KiNextIStreamByte (UserFrame, &istream) << 16) |
00540 (
KiNextIStreamByte (UserFrame, &istream) << 24);
00541 }
else {
00542 ibyte1 =
KiNextIStreamByte (UserFrame, &istream);
00543 i = (
signed long) ((
signed char) ibyte1);
00544 }
00545 accum += i;
00546 }
00547
00548
00549
00550
00551
00552
if (UserFrame->SegCs == KGDT_R0_CODE) {
00553 *((
PUSHORT) accum) = UsersWord;
00554 }
else {
00555
ProbeAndWriteUshort ((
PUSHORT) accum, UsersWord);
00556 }
00557 UserFrame->Eip = (ULONG)istream;
00558
00559 } except (
KiCopyInformation(&ExceptionRecord,
00560 (GetExceptionInformation())->ExceptionRecord)) {
00561
00562
00563
00564
00565
00566
00567 ExceptionRecord.ExceptionAddress = (PVOID)(UserFrame->Eip);
00568
KiDispatchException(
00569 &ExceptionRecord,
00570
NULL,
00571 UserFrame,
00572
UserMode,
00573
TRUE
00574 );
00575 }
00576
00577
return TRUE;
00578 }