00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
#include "ki.h"
00030
#include "ia32def.h"
00031
#include "vdmntos.h"
00032
00033
#if DEVL
00034
ULONG ExVdmOpcodeDispatchCounts[MAX_VDM_INDEX];
00035 ULONG ExVdmSegmentNotPresent;
00036
#endif
00037
00038 extern ULONG
KeIA32EFlagsAndMaskV86;
00039 extern ULONG
KeIA32EFlagsOrMaskV86;
00040 extern BOOLEAN
KeIA32VdmIoplAllowed;
00041 extern ULONG
KeIA32VirtualIntExtensions;
00042
00043
#if defined(WX86) && defined(TRY_NTVDM)
00044
00045
00046
00047
00048 BOOLEAN
00049 KiIA32VdmDispatchIo(
00050 IN ULONG PortNumber,
00051 IN ULONG Size,
00052 IN BOOLEAN Read,
00053 IN UCHAR InstructionSize,
00054 IN PKIA32_FRAME TrapFrame
00055 );
00056
00057 BOOLEAN
00058 KiIA32VdmDispatchStringIo(
00059 IN ULONG PortNumber,
00060 IN ULONG Size,
00061 IN BOOLEAN Rep,
00062 IN BOOLEAN Read,
00063 IN ULONG Count,
00064 IN ULONG Address,
00065 IN UCHAR InstructionSize,
00066 IN PKIA32_FRAME TrapFrame
00067 );
00068
00069
00070
00071
00072
00073 BOOLEAN
00074 PushInt(
00075 IN ULONG InterruptNumber,
00076 IN OUT PREGINFO Regs
00077 );
00078
00079 BOOLEAN
00080 PushException(
00081 IN ULONG ExceptionNumber,
00082 IN OUT PREGINFO Regs
00083 );
00084
00085 BOOLEAN
00086 CsToLinear(
00087 IN OUT PREGINFO Regs,
00088 IN BOOLEAN IsV86
00089 );
00090
00091 BOOLEAN
00092 SsToLinear(
00093 IN OUT PREGINFO Regs,
00094 IN BOOLEAN IsV86
00095 );
00096
00097 BOOLEAN
00098 CheckEip(
00099 IN PREGINFO Regs
00100 );
00101
00102 BOOLEAN
00103 CheckEsp(
00104 IN PREGINFO Regs,
00105 IN ULONG StackNeeded
00106 );
00107
00108
VOID
00109 GetVirtualBits(
00110 IN OUT PULONG PFlags,
00111 IN PKIA32_FRAME Frame
00112 );
00113
00114
VOID
00115 SetVirtualBits(
00116 IN ULONG Flags,
00117 IN PREGINFO PRegs
00118 );
00119
00120
VOID
00121 VdmDispatchIntAck(
00122 IN PKIA32_FRAME Frame
00123 );
00124
00125
VOID
00126 CheckVdmFlags(
00127 IN OUT PREGINFO Regs
00128 );
00129
00130
VOID
00131 KeIA32AndOrVdmLock(
00132 IN ULONG AndMask,
00133 IN ULONG OrMask
00134 );
00135
00136 BOOLEAN
00137 KeIA32UnscrambleLdtEntry(
00138 IN ULONG Selector,
00139 OUT PKXDESCRIPTOR XDescriptor
00140 );
00141
00142 ULONGLONG
00143 KeIA32Unscramble(
00144 IN PLDT_ENTRY Descriptor
00145 );
00146
00147
NTSTATUS
00148
PspQueryDescriptorThread (
00149
PETHREAD Thread,
00150 PVOID ThreadInformation,
00151 ULONG ThreadInformationLength,
00152 PULONG ReturnLength
00153 );
00154
00155
00156
00157
00158 BOOLEAN
00159
KiIA32DispatchOpcode(
00160 IN PKIA32_FRAME Frame
00161 )
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 {
00183 REGINFO Regs;
00184 ULONG IOPort;
00185 ULONG IOCount;
00186 ULONG IOAddress;
00187 ULONG flags;
00188 KXDESCRIPTOR NewXDescriptor;
00189
00190
00191
00192
00193
00194 PULONG longPtr;
00195
PUSHORT shortPtr;
00196 PUCHAR charPtr;
00197
00198
00199
00200
00201 Regs.RiInstLength = 1;
00202 Regs.RiPrefixFlags = 0;
00203 Regs.RiTrapFrame = Frame;
00204 Regs.RiSegCs = Frame->SegCs;
00205 Regs.RiEip = Frame->Eip;
00206
00207
00208
00209
00210
if (! CsToLinear(&Regs, VM86USER(Frame))) {
00211
return FALSE;
00212 }
00213
00214
00215
00216
00217
00218
while (Regs.RiInstLength <=
MAX_INSTRUCTION_LENGTH) {
00219
00220
00221 Regs.RiOpcode = *Regs.RiLinearAddr;
00222
00223
switch(Regs.RiOpcode) {
00224
case 0x0f:
00225
00226
#if DEVL
00227
ExVdmOpcodeDispatchCounts[VDM_INDEX_0F]++;
00228
#endif
00229
#if VDMDBG
00230
DbgPrintf(
"Saw 0x0f opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00231
#endif
00232
return(VdmOpcode0F(&Regs));
00233
00234
case 0x26:
00235
#if DEVL
00236
ExVdmOpcodeDispatchCounts[VDM_INDEX_ESPrefix]++;
00237
#endif
00238
#if VDMDBG
00239
DbgPrintf(
"Saw ES Prefix opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00240
#endif
00241
Regs.RiPrefixFlags |= PREFIX_ES;
00242
break;
00243
00244
case 0x2e:
00245
#if DEVL
00246
ExVdmOpcodeDispatchCounts[VDM_INDEX_CSPrefix]++;
00247
#endif
00248
#if VDMDBG
00249
DbgPrintf(
"Saw CS Prefix opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00250
#endif
00251
Regs.RiPrefixFlags |= PREFIX_CS;
00252
break;
00253
00254
case 0x36:
00255
#if DEVL
00256
ExVdmOpcodeDispatchCounts[VDM_INDEX_SSPrefix]++;
00257
#endif
00258
#if VDMDBG
00259
DbgPrintf(
"Saw SS Prefix opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00260
#endif
00261
Regs.RiPrefixFlags |= PREFIX_SS;
00262
break;
00263
00264
case 0x3e:
00265
#if DEVL
00266
ExVdmOpcodeDispatchCounts[VDM_INDEX_DSPrefix]++;
00267
#endif
00268
#if VDMDBG
00269
DbgPrintf(
"Saw DS Prefix opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00270
#endif
00271
Regs.RiPrefixFlags |= PREFIX_DS;
00272
break;
00273
00274
case 0x64:
00275
#if DEVL
00276
ExVdmOpcodeDispatchCounts[VDM_INDEX_FSPrefix]++;
00277
#endif
00278
#if VDMDBG
00279
DbgPrintf(
"Saw FS Prefix opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00280
#endif
00281
Regs.RiPrefixFlags |= PREFIX_FS;
00282
break;
00283
00284
case 0x65:
00285
#if DEVL
00286
ExVdmOpcodeDispatchCounts[VDM_INDEX_GSPrefix]++;
00287
#endif
00288
#if VDMDBG
00289
DbgPrintf(
"Saw GS Prefix opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00290
#endif
00291
Regs.RiPrefixFlags |= PREFIX_GS;
00292
break;
00293
00294
case 0x66:
00295
#if DEVL
00296
ExVdmOpcodeDispatchCounts[VDM_INDEX_OPER32Prefix]++;
00297
#endif
00298
#if VDMDBG
00299
DbgPrintf(
"Saw Operand 32 Prefix opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00300
#endif
00301
Regs.RiPrefixFlags |= PREFIX_OPER32;
00302
break;
00303
00304
case 0x67:
00305
#if DEVL
00306
ExVdmOpcodeDispatchCounts[VDM_INDEX_ADDR32Prefix]++;
00307
#endif
00308
#if VDMDBG
00309
DbgPrintf(
"Saw Address 32 Prefix opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00310
#endif
00311
Regs.RiPrefixFlags |= PREFIX_ADDR32;
00312
break;
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
case 0x6c:
00323
00324
#if DEVL
00325
ExVdmOpcodeDispatchCounts[VDM_INDEX_INSB]++;
00326
#endif
00327
#if VDMDBG
00328
DbgPrintf(
"Saw INSB opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00329
#endif
00330
IOAddress = ( Frame->SegEs << 16 ) + Frame->Edi;
00331
00332
if (Regs.RiPrefixFlags & PREFIX_REP) {
00333 IOCount = Frame->Ecx;
00334 }
00335
else {
00336 IOCount = 1;
00337 }
00338 IOPort = Frame->Edx;
00339
00340
return(KiIA32VdmDispatchStringIo(IOPort, 1, Regs.RiPrefixFlags & PREFIX_REP, TRUE, IOCount, IOAddress, Regs.RiInstLength, Frame));
00341
00342
case 0x6d:
00343
00344
#if DEVL
00345
ExVdmOpcodeDispatchCounts[VDM_INDEX_INSW]++;
00346
#endif
00347
#if VDMDBG
00348
DbgPrintf(
"Saw INSW opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00349
#endif
00350
IOAddress = ( Frame->SegEs << 16 ) + Frame->Edi;
00351
00352
if (Regs.RiPrefixFlags & PREFIX_REP) {
00353 IOCount = Frame->Ecx;
00354 }
00355
else {
00356 IOCount = 1;
00357 }
00358 IOPort = Frame->Edx;
00359
00360
return(KiIA32VdmDispatchStringIo(IOPort, 2, Regs.RiPrefixFlags & PREFIX_REP, TRUE, IOCount, IOAddress, Regs.RiInstLength, Frame));
00361
00362
case 0x6e:
00363
00364
#if DEVL
00365
ExVdmOpcodeDispatchCounts[VDM_INDEX_OUTSB]++;
00366
#endif
00367
#if VDMDBG
00368
DbgPrintf(
"Saw OUTSB opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00369
#endif
00370
IOAddress = ( Frame->SegEs << 16 ) + Frame->Edi;
00371
00372
if (Regs.RiPrefixFlags & PREFIX_REP) {
00373 IOCount = Frame->Ecx;
00374 }
00375
else {
00376 IOCount = 1;
00377 }
00378 IOPort = Frame->Edx;
00379
00380
return(KiIA32VdmDispatchStringIo(IOPort, 1, Regs.RiPrefixFlags & PREFIX_REP, FALSE, IOCount, IOAddress, Regs.RiInstLength, Frame));
00381
00382
case 0x6f:
00383
00384
#if DEVL
00385
ExVdmOpcodeDispatchCounts[VDM_INDEX_OUTSW]++;
00386
#endif
00387
#if VDMDBG
00388
DbgPrintf(
"Saw OUTSW opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00389
#endif
00390
IOAddress = ( Frame->SegEs << 16 ) + Frame->Edi;
00391
00392
if (Regs.RiPrefixFlags & PREFIX_REP) {
00393 IOCount = Frame->Ecx;
00394 }
00395
else {
00396 IOCount = 1;
00397 }
00398 IOPort = Frame->Edx;
00399
00400
return(KiIA32VdmDispatchStringIo(IOPort, 2, Regs.RiPrefixFlags & PREFIX_REP, FALSE, IOCount, IOAddress, Regs.RiInstLength, Frame));
00401
00402
case 0x9b:
00403
case 0x0d8:
00404
case 0x0d9:
00405
case 0x0da:
00406
case 0x0db:
00407
case 0x0dc:
00408
case 0x0dd:
00409
case 0x0de:
00410
case 0x0df:
00411
#if DEVL
00412
ExVdmOpcodeDispatchCounts[VDM_INDEX_NPX]++;
00413
#endif
00414
#if VDMDBG
00415
DbgPrintf(
"Saw NPX opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00416
#endif
00417
break;
00418
00419
case 0x09c:
00420
#if DEVL
00421
ExVdmOpcodeDispatchCounts[VDM_INDEX_PUSHF]++;
00422
#endif
00423
#if VDMDBG
00424
DbgPrintf(
"Saw PUSHF opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00425
#endif
00426
00427
if (! VM86USER(Frame)) {
00428
return FALSE;
00429 }
00430
00431 flags = Frame->EFlags & (~EFLAGS_INTERRUPT_MASK);
00432 flags |= EFLAGS_IOPL_MASK;
00433 flags |= (*
VdmFixedStateLinear & (
VDM_VIRTUAL_INTERRUPTS | EFLAGS_ALIGN_CHECK | EFLAGS_NT_MASK));
00434
00435
if (Regs.RiPrefixFlags & PREFIX_OPER32) {
00436 Frame->HardwareEsp = (Frame->HardwareEsp - 4) & 0xffff;
00437 longPtr = (PULONG) (Frame->SegSs << 4) + Frame->HardwareEsp;
00438 *longPtr = flags;
00439 }
00440
else {
00441 Frame->HardwareEsp = (Frame->HardwareEsp - 2) & 0xffff;
00442 shortPtr = (
PUSHORT) (Frame->SegSs << 4) + Frame->HardwareEsp;
00443 *shortPtr = flags & 0xffff;
00444 }
00445
00446 Frame->Eip += Regs.RiInstLength;
00447
00448
return TRUE;
00449
00450
case 0x9d:
00451
#if DEVL
00452
ExVdmOpcodeDispatchCounts[VDM_INDEX_POPF]++;
00453
#endif
00454
#if VDMDBG
00455
DbgPrintf(
"Saw POPF opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00456
#endif
00457
00458
if (! VM86USER(Frame)) {
00459
return FALSE;
00460 }
00461
00462
if (Regs.RiPrefixFlags & PREFIX_OPER32) {
00463 longPtr = (PULONG) ((Frame->SegSs << 4) + Frame->HardwareEsp);
00464 flags = *longPtr;
00465 Frame->HardwareEsp = (Frame->HardwareEsp + 4) & 0xffff;
00466 }
00467
else {
00468 shortPtr = (
PUSHORT) ((Frame->SegSs << 4) + Frame->HardwareEsp);
00469 flags = *shortPtr;
00470 Frame->HardwareEsp = (Frame->HardwareEsp + 2) & 0xffff;
00471 }
00472
00473 flags &= ~EFLAGS_IOPL_MASK;
00474
00475 KeIA32AndOrVdmLock(~(EFLAGS_INTERRUPT_MASK | EFLAGS_ALIGN_CHECK | EFLAGS_NT_MASK), (flags & (EFLAGS_INTERRUPT_MASK | EFLAGS_ALIGN_CHECK | EFLAGS_NT_MASK)));
00476
00477 flags &= ~EFLAGS_NT_MASK;
00478
00479
00480
00481
00482
00483
if (
KeIA32VirtualIntExtensions & V86_VIRTUAL_INT_EXTENSIONS) {
00484 flags |= EFLAGS_VIF;
00485
if (! (flags & EFLAGS_INTERRUPT_MASK)) {
00486 flags &= ~EFLAGS_VIF;
00487 }
00488 }
00489 flags |= (EFLAGS_INTERRUPT_MASK | EFLAGS_V86_MASK);
00490 Frame->EFlags = flags;
00491
00492 Frame->Eip += Regs.RiInstLength;
00493
00494
return TRUE;
00495
00496
case 0x0cd:
00497
#if DEVL
00498
ExVdmOpcodeDispatchCounts[VDM_INDEX_INTnn]++;
00499
#endif
00500
#if VDMDBG
00501
DbgPrintf(
"Saw INTnn opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00502
#endif
00503
if (VM86USER(Frame)) {
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514 Frame->HardwareEsp = (Frame->HardwareEsp - 2) & 0xffff;
00515 shortPtr = (
PUSHORT) ((Frame->SegSs << 4) + Frame->HardwareEsp);
00516 flags = Frame->EFlags;
00517
00518
if (!
KeIA32VdmIoplAllowed) {
00519 flags = (flags & ~EFLAGS_INTERRUPT_MASK) | (*
VdmFixedStateLinear & (
VDM_INTERRUPT_PENDING | EFLAGS_ALIGN_CHECK));
00520 }
00521
00522 flags |= EFLAGS_IOPL_MASK;
00523 *shortPtr = flags;
00524
00525
00526
00527
00528 flags = Frame->EFlags;
00529
00530
if (
KeIA32VdmIoplAllowed) {
00531 flags &= ~EFLAGS_INTERRUPT_MASK;
00532 }
00533
else {
00534 KeIA32AndOrVdmLock(~VDM_VIRTUAL_INTERRUPTS, 0);
00535 flags |= EFLAGS_INTERRUPT_MASK;
00536 }
00537
00538 flags &= ~(EFLAGS_NT_MASK | EFLAGS_TF_MASK);
00539 Frame->EFlags = flags;
00540
00541
00542 Frame->HardwareEsp = (Frame->HardwareEsp - 2) & 0xffff;
00543 shortPtr = (
PUSHORT) ((Frame->SegSs << 4) + Frame->HardwareEsp);
00544 *shortPtr = Frame->SegCs;
00545
00546
00547 Frame->HardwareEsp = (Frame->HardwareEsp - 2) & 0xffff;
00548 shortPtr = (
PUSHORT) ((Frame->SegSs << 4) + Frame->HardwareEsp);
00549 *shortPtr = Frame->Eip;
00550
00551
00552
00553
00554
00555 Regs.RiLinearAddr++;
00556 longPtr = (PULONG) (*(Regs.RiLinearAddr) * 4);
00557
00558
00559
00560
00561
00562 Frame->Eip = *longPtr & 0xffff;
00563 Frame->SegCs = *longPtr >> 16;
00564 }
00565
else {
00566
00567
00568
00569
00570
00571
00572
00573 flags = Frame->EFlags;
00574 GetVirtualBits(&flags, Frame);
00575 Regs.RiEFlags = flags;
00576
00577
00578
00579
00580 Regs.RiSegSs = Frame->SegSs;
00581 Regs.RiEsp = Frame->HardwareEsp;
00582
if (! SsToLinear(&Regs, VM86USER(Frame))) {
00583
return FALSE;
00584 }
00585
00586
00587
00588
00589
00590 Regs.RiEip++;
00591 Regs.RiLinearAddr++;
00592
if (! CheckEip(&Regs)) {
00593
return FALSE;
00594 }
00595
00596
00597
00598
00599 Regs.RiEip++;
00600 Regs.RiLinearAddr++;
00601
00602
00603
00604
00605
00606
if (! PushInt(*(Regs.RiLinearAddr - 1), &Regs)) {
00607
return FALSE;
00608 }
00609
00610
00611
00612
00613
00614
if (! KeIA32UnscrambleLdtEntry(Regs.RiSegCs, &NewXDescriptor)) {
00615
return FALSE;
00616 }
00617
00618 Frame->HardwareEsp = Regs.RiEsp;
00619 Frame->EFlags = Regs.RiEFlags;
00620 Frame->SegCs = Regs.RiSegCs;
00621 Frame->Eip = Regs.RiEip;
00622 }
00623
00624
return TRUE;
00625
00626
case 0x0ce:
00627
#if DEVL
00628
ExVdmOpcodeDispatchCounts[VDM_INDEX_INTO]++;
00629
#endif
00630
#if VDMDBG
00631
DbgPrintf(
"Saw INTO opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00632
#endif
00633
00634
00635
00636
00637
00638
return FALSE;
00639
00640
break;
00641
00642
case 0x0cf:
00643
#if DEVL
00644
ExVdmOpcodeDispatchCounts[VDM_INDEX_IRET]++;
00645
#endif
00646
#if VDMDBG
00647
DbgPrintf(
"Saw IRET opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00648
#endif
00649
00650
00651
00652
00653
if (! VM86USER(Frame)) {
00654
return FALSE;
00655 }
00656
00657
00658
00659
00660
00661
00662
if (Regs.RiPrefixFlags & PREFIX_OPER32) {
00663 longPtr = (PULONG) ((Frame->SegSs << 4) + Frame->HardwareEsp);
00664
00665 Frame->Eip = *longPtr++;
00666 Frame->SegCs = *longPtr++;
00667 flags = *longPtr;
00668
00669 Frame->HardwareEsp = (Frame->HardwareEsp + 12) & 0xffff;
00670 }
00671
else {
00672 shortPtr = (
PUSHORT) ((Frame->SegSs << 4) + Frame->HardwareEsp);
00673
00674 Frame->Eip = *shortPtr++ & 0xffff;
00675 Frame->SegCs = *shortPtr++ & 0xffff;
00676 flags = *shortPtr & 0xffff;
00677
00678 Frame->HardwareEsp = (Frame->HardwareEsp + 6) & 0xffff;
00679 }
00680
00681 flags &= ~(EFLAGS_IOPL_MASK | EFLAGS_NT_MASK);
00682
00683 KeIA32AndOrVdmLock(~VDM_VIRTUAL_INTERRUPTS, flags & EFLAGS_INTERRUPT_MASK );
00684
00685
00686
00687
00688
00689
if (
KeIA32VirtualIntExtensions & V86_VIRTUAL_INT_EXTENSIONS) {
00690
if (flags & EFLAGS_INTERRUPT_MASK) {
00691 flags |= EFLAGS_VIF;
00692 }
00693
else {
00694 flags &= ~EFLAGS_VIF;
00695 }
00696 }
00697
00698 flags |= (EFLAGS_INTERRUPT_MASK | EFLAGS_V86_MASK);
00699 Frame->EFlags = flags;
00700
00701
00702 shortPtr = (Frame->SegCs << 4) + Frame->Eip;
00703
00704
if ((*shortPtr & 0xffff) == BOP_OPCODE) {
00705 VdmDispatchBop(Frame);
00706 }
00707
else if ((*
VdmFixedStateLinear &
VDM_INTERRUPT_PENDING) &&
00708 (*
VdmFixedStateLinear &
VDM_VIRTUAL_INTERRUPTS)) {
00709 VdmDispatchIntAck(Frame);
00710 }
00711
00712
return TRUE;
00713
00714
case 0x0e4:
00715
#if DEVL
00716
ExVdmOpcodeDispatchCounts[VDM_INDEX_INBimm]++;
00717
#endif
00718
#if VDMDBG
00719
DbgPrintf(
"Saw INB immediate opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00720
#endif
00721
00722 Regs.RiInstLength++;
00723
00724
00725 charPtr = Regs.RiLinearAddr + 1;
00726
if ((charPtr - Regs.RiCsBase) > Regs.RiCsLimit) {
00727
return FALSE;
00728 }
00729
00730 IOPort = *charPtr;
00731
00732
return(KiIA32VdmDispatchIo(IOPort, 1, TRUE, Regs.RiInstLength, Frame));
00733
00734
case 0x0e5:
00735
#if DEVL
00736
ExVdmOpcodeDispatchCounts[VDM_INDEX_INWimm]++;
00737
#endif
00738
#if VDMDBG
00739
DbgPrintf(
"Saw INW immediate opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00740
#endif
00741
00742 Regs.RiInstLength++;
00743
00744
00745 charPtr = Regs.RiLinearAddr + 1;
00746
if ((charPtr - Regs.RiCsBase) > Regs.RiCsLimit) {
00747
return FALSE;
00748 }
00749
00750 IOPort = *charPtr;
00751
00752
return(KiIA32VdmDispatchIo(IOPort, 2, TRUE, Regs.RiInstLength, Frame));
00753
case 0x0e6:
00754
#if DEVL
00755
ExVdmOpcodeDispatchCounts[VDM_INDEX_OUTBimm]++;
00756
#endif
00757
#if VDMDBG
00758
DbgPrintf(
"Saw OUTB immediate opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00759
#endif
00760
00761 Regs.RiInstLength++;
00762
00763
00764 charPtr = Regs.RiLinearAddr + 1;
00765
if ((charPtr - Regs.RiCsBase) > Regs.RiCsLimit) {
00766
return FALSE;
00767 }
00768
00769 IOPort = *charPtr;
00770
00771
return(KiIA32VdmDispatchIo(IOPort, 1, FALSE, Regs.RiInstLength, Frame));
00772
case 0x0e7:
00773
#if DEVL
00774
ExVdmOpcodeDispatchCounts[VDM_INDEX_OUTWimm]++;
00775
#endif
00776
#if VDMDBG
00777
DbgPrintf(
"Saw OUTW immediate opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00778
#endif
00779
00780 Regs.RiInstLength++;
00781
00782
00783 charPtr = Regs.RiLinearAddr + 1;
00784
if ((charPtr - Regs.RiCsBase) > Regs.RiCsLimit) {
00785
return FALSE;
00786 }
00787
00788 IOPort = *charPtr;
00789
00790
return(KiIA32VdmDispatchIo(IOPort, 2, FALSE, Regs.RiInstLength, Frame));
00791
00792
case 0x0ec:
00793
#if DEVL
00794
ExVdmOpcodeDispatchCounts[VDM_INDEX_INB]++;
00795
#endif
00796
#if VDMDBG
00797
DbgPrintf(
"Saw INB opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00798
#endif
00799
IOPort = Frame->Edx;
00800
00801
00802
00803
00804
#ifdef NON_PCAT
00805
if (VM86USER(Frame)) {
00806
if (KeIA32MachineType & MACHINE_TYPE_MASK) {
00807
return(KiIA32VdmDispatchIo(IOPort, 1, TRUE, Regs.RiInstLength, Frame));
00808 }
00809 }
00810
#endif
00811
00812
switch (IOPort) {
00813
case 0x03bd:
00814
case 0x0379:
00815
case 0x0279:
00816
if (
VdmPrinterStatus(IOPort, Regs.RiInstLength, Frame)) {
00817
return TRUE;
00818 }
00819
00820
default:
00821
return(KiIA32VdmDispatchIo(IOPort, 1, TRUE, Regs.RiInstLength, Frame));
00822 }
00823
00824
return FALSE;
00825
00826
case 0x0ed:
00827
#if DEVL
00828
ExVdmOpcodeDispatchCounts[VDM_INDEX_INW]++;
00829
#endif
00830
#if VDMDBG
00831
DbgPrintf(
"Saw INW opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00832
#endif
00833
IOPort = Frame->Edx;
00834
return(KiIA32VdmDispatchIo(IOPort, 2, TRUE, Regs.RiInstLength, Frame));
00835
00836
case 0x0ee:
00837
#if DEVL
00838
ExVdmOpcodeDispatchCounts[VDM_INDEX_OUTB]++;
00839
#endif
00840
#if VDMDBG
00841
DbgPrintf(
"Saw OUTB opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00842
#endif
00843
IOPort = Frame->Edx;
00844
00845
00846
switch (IOPort) {
00847
case 0x03bc:
00848
case 0x0378:
00849
case 0x0278:
00850
if (
VdmPrinterWriteData(IOPort, Regs.RiInstLength, Frame)) {
00851
return TRUE;
00852 }
00853
00854
00855
00856
default:
00857
return(KiIA32VdmDispatchIo(IOPort, 1, FALSE, Regs.RiInstLength, Frame));
00858 }
00859
00860
return FALSE;
00861
00862
case 0x0ef:
00863
#if DEVL
00864
ExVdmOpcodeDispatchCounts[VDM_INDEX_OUTW]++;
00865
#endif
00866
#if VDMDBG
00867
DbgPrintf(
"Saw OUTW opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00868
#endif
00869
IOPort = Frame->Edx;
00870
return(KiIA32VdmDispatchIo(IOPort, 2, FALSE, Regs.RiInstLength, Frame));
00871
00872
case 0x0f0:
00873
#if DEVL
00874
ExVdmOpcodeDispatchCounts[VDM_INDEX_LOCKPrefix]++;
00875
#endif
00876
#if VDMDBG
00877
DbgPrintf(
"Saw LOCK Prefix (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00878
#endif
00879
Regs.RiPrefixFlags |= PREFIX_LOCK;
00880
break;
00881
00882
case 0x0f2:
00883
#if DEVL
00884
ExVdmOpcodeDispatchCounts[VDM_INDEX_REPNEPrefix]++;
00885
#endif
00886
#if VDMDBG
00887
DbgPrintf(
"Saw REPNE Prefix (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00888
#endif
00889
Regs.RiPrefixFlags |= PREFIX_REPNE;
00890
break;
00891
00892
case 0x0f3:
00893
#if DEVL
00894
ExVdmOpcodeDispatchCounts[VDM_INDEX_REPPrefix]++;
00895
#endif
00896
#if VDMDBG
00897
DbgPrintf(
"Saw REP Prefix (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00898
#endif
00899
Regs.RiPrefixFlags |= PREFIX_REP;
00900
break;
00901
00902
case 0x0f4:
00903
#if DEVL
00904
ExVdmOpcodeDispatchCounts[VDM_INDEX_HLT]++;
00905
#endif
00906
#if VDMDBG
00907
DbgPrintf(
"Saw HLT opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00908
#endif
00909
00910
00911
if (! VM86USER(Frame)) {
00912
return FALSE;
00913 }
00914
00915
00916
00917
00918
00919
00920
00921 Frame->Eip = (Frame->Eip + Regs.RiInstLength) & 0xffff;
00922
00923
return TRUE;
00924
00925
break;
00926
00927
case 0x0fa:
00928
#if DEVL
00929
ExVdmOpcodeDispatchCounts[VDM_INDEX_CLI]++;
00930
#endif
00931
#if VDMDBG
00932
DbgPrintf(
"Saw CLI opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00933
#endif
00934
if (! VM86USER(Frame)) {
00935 flags = Frame->EFlags & ~EFLAGS_INTERRUPT_MASK;
00936 SetVirtualBits(flags, &Regs);
00937 }
00938
else {
00939 KeIA32AndOrVdmLock(~VDM_VIRTUAL_INTERRUPTS, 0);
00940 }
00941
00942
00943 Frame->Eip += Regs.RiInstLength;
00944
00945
return TRUE;
00946
00947
case 0x0fb:
00948
#if DEVL
00949
ExVdmOpcodeDispatchCounts[VDM_INDEX_STI]++;
00950
#endif
00951
#if VDMDBG
00952
DbgPrintf(
"Saw STI opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00953
#endif
00954
if (! VM86USER(Frame)) {
00955 flags = Frame->EFlags | EFLAGS_INTERRUPT_MASK;
00956 SetVirtualBits(flags, &Regs);
00957 }
00958
else {
00959
00960
00961
if (
KeIA32VirtualIntExtensions & V86_VIRTUAL_INT_EXTENSIONS) {
00962 Frame->EFlags |= EFLAGS_VIF;
00963 }
00964
00965 KeIA32AndOrVdmLock(0xffffffff, EFLAGS_INTERRUPT_MASK);
00966 }
00967
00968
00969 Frame->Eip += Regs.RiInstLength;
00970
00971
00972
00973
if (*
VdmFixedStateLinear &
VDM_INTERRUPT_PENDING) {
00974 VdmDispatchIntAck(Frame);
00975 }
00976
return TRUE;
00977
00978
default:
00979
00980
#if VDMDBG
00981
DbgPrintf(
"Saw unexpected opcode (0x%02x) at linear address 0x%08lx\n", (
int) Regs.RiOpcode, (
long) Regs.RiLinearAddr);
00982
#endif
00983
return FALSE;
00984
00985 }
00986
00987
00988
00989 Regs.RiLinearAddr++;
00990 Regs.RiInstLength++;
00991 }
00992
00993
00994
00995
return (
FALSE);
00996 }
00997
00998
00999
VOID
01000 VdmDispatchIntAck(
01001 IN PKIA32_FRAME Frame
01002 )
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022 {
01023
PVDM_TIB VdmTib;
01024
01025 VdmTib = (
PsGetCurrentThread()->Tcb.Teb)->Vdm;
01026
01027
if (*
VdmFixedStateLinear & VDM_INT_HARDWARE) {
01028
01029
01030
VdmDispatchInterrupts(Frame, VdmTib);
01031 }
01032
else {
01033
01034
01035 VdmTib->
EventInfo.
Event =
VdmIntAck;
01036 VdmTib->
EventInfo.
Size = 0;
01037 VdmTib->
EventInfo.IntAckInfo = 0;
01038
VdmEndExecution(Frame, VdmTib);
01039 }
01040 }
01041
01042
01043
01044
01045
#define _VDM_EXTOFF_FUNC(x) (x = (x & ~EFLAGS_INTERRUPT_MASK) | (*VdmFixedStateLinear & (VDM_VIRTUAL_INTERRUPTS | EFLAGS_ALIGN_CHECK)) | EFLAGS_IOPL_MASK)
01046
#define _VDM_EXTON_FUNC(x) (x = (x & ~EFLAGS_INTERRUPT_MASK) | (*VdmFixedStateLinear & (VDM_VIRTUAL_INTERRUPTS | EFLAGS_ALIGN_CHECK)) | EFLAGS_IOPL_MASK)
01047
#define _VDM_IOPL_FUNC(x) (x = (x & ~EFLAGS_ALIGN_CHECK) | (*VdmFixedStateLinear & EFLAGS_ALIGN_CHECK) | EFLAGS_IOPL_MASK)
01048
01049
01050
VOID
01051 GetVirtualBits(
01052 IN OUT PULONG PFlags,
01053 IN PKIA32_FRAME Frame
01054 )
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073 {
01074
01075
if (
KeIA32VdmIoplAllowed) {
01076
if (*PFlags & EFLAGS_V86_MASK) {
01077 _VDM_IOPL_FUNC(*PFlags);
01078 }
01079
else {
01080 _VDM_EXTOFF_FUNC(*PFlags);
01081 }
01082 }
01083
else {
01084
01085
01086
01087
01088
01089
01090
if (
KeIA32VirtualIntExtensions & (V86_VIRTUAL_INT_EXTENSIONS | PM_VIRTUAL_INT_EXTENSIONS)) {
01091
if (*PFlags & EFLAGS_V86_MASK) {
01092
if (
KeIA32VirtualIntExtensions & V86_VIRTUAL_INT_EXTENSIONS) {
01093 _VDM_EXTON_FUNC(*PFlags);
01094 }
01095
else {
01096 _VDM_EXTOFF_FUNC(*PFlags);
01097 }
01098 }
01099
else {
01100
if (
KeIA32VirtualIntExtensions & PM_VIRTUAL_INT_EXTENSIONS) {
01101 _VDM_EXTON_FUNC(*PFlags);
01102 }
01103
else {
01104 _VDM_EXTOFF_FUNC(*PFlags);
01105 }
01106 }
01107 }
01108
else {
01109 _VDM_EXTOFF_FUNC(*PFlags);
01110 }
01111 }
01112 }
01113
01114
VOID
01115 SetVirtualBits(
01116 IN ULONG Flags,
01117 IN PREGINFO PRegs
01118 )
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136 {
01137 KeIA32AndOrVdmLock(~VDM_VIRTUAL_INTERRUPTS, Flags & EFLAGS_INTERRUPT_MASK);
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
#if 0
01149
if (
KeIA32VirtualIntExtensions & (V86_VIRTUAL_INT_EXTENSIONS | PM_VIRTUAL_INT_EXTENSIONS)) {
01150
if (Flags & EFLAGS_V86_MASK) {
01151
if (
KeIA32VirtualIntExtensions & V86_VIRTUAL_INT_EXTENSIONS) {
01152 }
01153
else {
01154 }
01155 }
01156
else {
01157
if (
KeIA32VirtualIntExtensions & PM_VIRTUAL_INT_EXTENSIONS) {
01158 }
01159
else {
01160 }
01161 }
01162 }
01163
else {
01164 }
01165
#endif
01166
01167
if (PRegs->RiPrefixFlags & PREFIX_OPER32) {
01168 KeIA32AndOrVdmLock(~EFLAGS_ALIGN_CHECK, Flags & EFLAGS_ALIGN_CHECK);
01169 }
01170 }
01171
01172
01173 BOOLEAN
01174
KiIA32VdmReflectException(
01175 IN OUT PKIA32_FRAME Frame,
01176 IN ULONG Code
01177 )
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200 {
01201 REGINFO Regs;
01202 KXDESCRIPTOR NewXCsDescriptor, NewXSsDescriptor;
01203
01204
01205
01206
01207
if ((Code ==
EXCEPTION_GP_FAULT) && (*
VdmFixedStateLinear & VDM_BREAK_EXCEPTIONS)) {
01208 VdmDispatchException(Frame, STATUS_ACCESS_VIOLATION, Frame->Eip, 2, 0, -1, 0);
01209
return TRUE;
01210 }
01211
01212
01213
01214
01215
if (*
VdmFixedStateLinear & VDM_BREAK_DEBUGGER) {
01216
if (Code ==
EXCEPTION_DEBUG) {
01217
01218
01219
01220
01221 Frame->EFlags &= ~EFLAGS_TF_MASK;
01222 VdmDispatchException(Frame, STATUS_SINGLE_STEP, Frame->Eip, 0, 0, 0, 0);
01223
return TRUE;
01224 }
01225
if (Code ==
EXCEPTION_INT3) {
01226 VdmDispatchException(Frame, STATUS_BREAKPOINT, Frame->Eip - 1, 3, USER_BREAKPOINT, 0, 0);
01227
01228
return TRUE;
01229 }
01230 }
01231
01232
01233
01234
01235
if (FLATUSER(Frame)) {
01236
return TRUE;
01237 }
01238
01239
01240
#if DEVL
01241
if (Code ==
EXCEPTION_SEGMENT_NOT_PRESENT) {
01242 ExVdmSegmentNotPresent++;
01243 }
01244
#endif
01245
01246
01247
01248
01249
01250 Regs.RiTrapFrame = Frame;
01251 Regs.RiSegSs = Frame->SegSs;
01252 Regs.RiEsp = Frame->HardwareEsp;
01253 Regs.RiEFlags = Frame->EFlags;
01254 Regs.RiEip = Frame->Eip;
01255 Regs.RiSegCs = Frame->SegCs;
01256
01257
if (! CsToLinear(&Regs, VM86USER(Frame))) {
01258
return FALSE;
01259 }
01260
01261
if (! SsToLinear(&Regs, VM86USER(Frame))) {
01262
return FALSE;
01263 }
01264
01265
if (! PushException(Code, &Regs)) {
01266
return FALSE;
01267 }
01268
01269
01270
01271
01272
01273
01274
if (Regs.RiEFlags & EFLAGS_V86_MASK) {
01275
01276 NewXCsDescriptor.DescriptorWords = (ULONGLONG) (Regs.RiSegCs << 4);
01277 NewXSsDescriptor.DescriptorWords = (ULONGLONG) (Regs.RiSegSs << 4);
01278 }
01279
else {
01280
if (! KeIA32UnscrambleLdtEntry(Regs.RiSegCs, &NewXCsDescriptor)) {
01281
return FALSE;
01282 }
01283
01284
if (! KeIA32UnscrambleLdtEntry(Regs.RiSegSs, &NewXSsDescriptor)) {
01285
return FALSE;
01286 }
01287 }
01288
01289 Frame->HardwareEsp = Regs.RiEsp;
01290
01291
01292
01293
01294 Frame->SegSs = Regs.RiSegSs;
01295 Frame->EFlags = Regs.RiEFlags;
01296
01297
01298
01299
01300 Frame->SegCs = Regs.RiSegCs;
01301 Frame->Eip = Regs.RiEip;
01302
01303
if (Code ==
EXCEPTION_DEBUG) {
01304
01305
01306
01307
01308 Frame->EFlags &= ~EFLAGS_TF_MASK;
01309 }
01310
01311
return TRUE;
01312 }
01313
01314
01315 BOOLEAN
01316
KiIA32VdmSegmentNotPresent(
01317 IN OUT PKIA32_FRAME Frame
01318 )
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338 {
01339
PVDM_TIB VdmTib;
01340 PVDM_FAULTHANDLER NoSegFault;
01341 ULONG Flags;
01342 KXDESCRIPTOR NewXCsDescriptor;
01343 KXDESCRIPTOR NewXSsDescriptor;
01344 ULONG
Offset;
01345
01346
01347
01348
01349 VdmTib = (
PVDM_TIB) (
PsGetCurrentThread()->Tcb.Teb)->Vdm;
01350
01351
01352
01353
01354
if (VdmTib->PmStackInfo.LockCount != 0) {
01355
return(
KiIA32VdmReflectException(Frame, EXCEPTION_SEGMENT_NOT_PRESENT));
01356 }
01357
01358 NoSegFault = &(VdmTib->VdmFaultHandlers[
EXCEPTION_SEGMENT_NOT_PRESENT]);
01359
01360
#if DEVL
01361
ExVdmSegmentNotPresent++;
01362
#endif
01363
01364
01365
01366
01367 VdmTib->PmStackInfo.LockCount++;
01368 VdmTib->PmStackInfo.SaveEip = Frame->Eip;
01369 VdmTib->PmStackInfo.SaveEsp = Frame->HardwareEsp;
01370 VdmTib->PmStackInfo.SaveSsSelector = Frame->SegSs;
01371
01372
01373
01374
01375
01376
if (! KeIA32UnscrambleLdtEntry(NoSegFault->CsSelector, &NewXCsDescriptor)) {
01377
return FALSE;
01378 }
01379
01380
if (! KeIA32UnscrambleLdtEntry(VdmTib->PmStackInfo.SsSelector, &NewXSsDescriptor)) {
01381
return FALSE;
01382 }
01383
01384
01385
01386
01387 Flags = Frame->EFlags;
01388 GetVirtualBits(&Flags, Frame);
01389
01390
01391
01392
01393
if (VdmTib->PmStackInfo.
Flags & 1) {
01394 PULONG ExcptStack32;
01395
01396
01397
01398
01399 ExcptStack32 = (PULONG) (NewXSsDescriptor.Words.Bits.Base + DPMISTACK_OFFSET);
01400
01401
01402
01403
01404
01405 *--ExcptStack32 = Frame->SegSs;
01406 *--ExcptStack32 = Frame->HardwareEsp;
01407 *--ExcptStack32 = Flags;
01408
01409 *--ExcptStack32 = Frame->SegCs;
01410 *--ExcptStack32 = Frame->Eip;
01411 *--ExcptStack32 = Frame->ISRCode;
01412
01413
01414
01415
01416 *--ExcptStack32 = VdmTib->PmStackInfo.DosxFaultIretD >> 16;
01417 *--ExcptStack32 = VdmTib->PmStackInfo.DosxFaultIretD & 0x0ffff;
01418
01419
Offset = ((PUCHAR) ExcptStack32) - NewXSsDescriptor.Words.Bits.Base;
01420 }
01421
else {
01422
PUSHORT ExcptStack16;
01423
01424
01425
01426
01427 ExcptStack16 = NewXSsDescriptor.Words.Bits.Base + DPMISTACK_OFFSET;
01428
01429
01430
01431
01432 *--ExcptStack16 = Frame->SegSs;
01433 *--ExcptStack16 = Frame->HardwareEsp;
01434 *--ExcptStack16 = Flags;
01435
01436 *--ExcptStack16 = Frame->SegCs;
01437 *--ExcptStack16 = Frame->Eip;
01438 *--ExcptStack16 = Frame->ISRCode;
01439
01440
01441
01442
01443 *--ExcptStack16 = VdmTib->PmStackInfo.DosxFaultIretD >> 16;
01444 *--ExcptStack16 = VdmTib->PmStackInfo.DosxFaultIretD & 0x0ffff;
01445
Offset = ((PUCHAR) ExcptStack16) - NewXSsDescriptor.Words.Bits.Base;
01446 }
01447
01448
if (NoSegFault->Flags & VDM_INT_INT_GATE) {
01449 KeIA32AndOrVdmLock(~VDM_VIRTUAL_INTERRUPTS, 0);
01450 Frame->EFlags &= ~EFLAGS_VIF;
01451 }
01452
01453 Frame->SegCs = NoSegFault->CsSelector;
01454 Frame->Eip = NoSegFault->Eip;
01455 Frame->SegSs = VdmTib->PmStackInfo.SsSelector;
01456 Frame->HardwareEsp =
Offset;
01457
01458
return TRUE;
01459 }
01460
01461
01462
VOID
01463 VdmDispatchException(
01464 IN PKIA32_FRAME Frame,
01465 IN NTSTATUS ExcepCode,
01466 IN PVOID ExcepAddr,
01467 IN ULONG NumParms,
01468 IN ULONG Parm1,
01469 IN ULONG Parm2,
01470 IN ULONG Parm3
01471 )
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489 {
01490
01491
01492
01493
01494
KeLowerIrql(0);
01495
01496
01497
01498
01499
ASSERT(NumParms <= 3);
01500
01501
01502
01503
01504
01505 KiIA32ExceptionDispatch(Frame, ExcepCode, ExcepAddr, NumParms, Parm1, Parm2, Parm3);
01506
01507
01508
01509
01510 }
01511
01512
01513 BOOLEAN
01514 PushInt(IN ULONG InterruptNumber,
01515 IN OUT PREGINFO Regs
01516 )
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536 {
01537
PVDM_TIB VdmTib;
01538
PVDM_INTERRUPTHANDLER IntHandler;
01539 PULONG ExcptStack32;
01540
PUSHORT ExcptStack16;
01541 ULONG Flags;
01542
01543
ASSERT(InterruptNumber < 256);
01544
01545 VdmTib = (
PVDM_TIB) (
PsGetCurrentThread()->Tcb.Teb)->Vdm;
01546
01547 IntHandler = &(VdmTib->
VdmInterruptHandlers[InterruptNumber]);
01548
01549
01550
01551
01552
if (! Regs->RiSsDescriptor.Words.Bits.Default_Big) {
01553 Regs->RiEsp &= 0xffff;
01554 }
01555
01556
01557
01558
01559
if (IntHandler->Flags & VDM_INT_32) {
01560
if (Regs->RiEsp <= (3 *
sizeof(PVOID))) {
01561
return FALSE;
01562 }
01563
01564 Regs->RiEsp -= 3 *
sizeof(PVOID);
01565 }
01566
else {
01567
if (Regs->RiEsp <= (3 *
sizeof(
SHORT))) {
01568
return FALSE;
01569 }
01570
01571 Regs->RiEsp -= 3 *
sizeof(
SHORT);
01572 }
01573
01574
01575
01576
01577
if (Regs->RiSsDescriptor.Words.Bits.Type & DESCRIPTOR_EXPAND_DOWN) {
01578
if (Regs->RiEsp <= Regs->RiSsLimit) {
01579
return FALSE;
01580 }
01581 }
01582
else {
01583
if (Regs->RiEsp >= Regs->RiSsLimit) {
01584
return FALSE;
01585 }
01586 }
01587
01588
01589
01590
01591
01592
01593
01594
01595 Flags = Regs->RiEFlags;
01596 GetVirtualBits(&Flags, Regs->RiTrapFrame);
01597
01598
if (IntHandler->Flags & VDM_INT_32) {
01599 ExcptStack32 = Regs->RiSsBase + Regs->RiEsp;
01600
01601
01602
01603
01604 *ExcptStack32++ = Regs->RiEip;
01605 *ExcptStack32++ = Regs->RiSegCs;
01606 *ExcptStack32 = Flags;
01607 }
01608
else {
01609 ExcptStack16 = Regs->RiSsBase + Regs->RiEsp;
01610
01611
01612
01613
01614 *ExcptStack16++ = Regs->RiEip;
01615 *ExcptStack16++ = Regs->RiSegCs;
01616 *ExcptStack16 = Flags;
01617 }
01618
01619
01620
01621
01622 Regs.RiSegCs = IntHandler->
CsSelector;
01623 Regs.RiEip = IntHandler->
Eip;
01624
01625
if (CsToLinear(&Regs, ! (IntHandler->Flags & VDM_INT_32))) {
01626
if (! Regs->RiCsDescriptor.Words.Bits.Pres) {
01627
return FALSE;
01628 }
01629 }
01630
else {
01631
01632
01633
01634
01635
01636
01637
if (Regs.RiEip >= Regs.RiCsLimit) {
01638
return FALSE;
01639 }
01640 }
01641
01642 Regs.RiEFlags &= ~EFLAGS_TF_MASK;
01643
01644
if (IntHandler->Flags & VDM_INT_INT_GATE) {
01645
if (
KeIA32VirtualIntExtensions & PM_VIRTUAL_INT_EXTENSIONS) {
01646 Regs->RiEFlags &= ~EFLAGS_VIF;
01647 }
01648 KeIA32AndOrVdmLock(~EFLAGS_INTERRUPT_MASK, 0);
01649 }
01650
01651 Regs.RiEFlags &= ~(EFLAGS_IOPL_MASK | EFLAGS_NT_MASK | EFLAGS_V86_MASK);
01652 Regs.RiEFlags |= EFLAGS_INTERRUPT_MASK;
01653
01654
return TRUE;
01655 }
01656
01657
01658 BOOLEAN
01659 PushException(
01660 IN ULONG ExceptionNumber,
01661 IN OUT PREGINFO Regs
01662 )
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682 {
01683
PVDM_TIB VdmTib;
01684 PVDM_FAULTHANDLER ExceptHandler;
01685 ULONG Flags;
01686
01687
ASSERT(ExceptionNumber < 32);
01688
01689 VdmTib = (
PVDM_TIB) (
PsGetCurrentThread()->Tcb.Teb)->Vdm;
01690 ExceptHandler = &(VdmTib->VdmFaultHandlers[ExceptionNumber]);
01691
01692
if (Regs->RiEFlags & EFLAGS_V86_MASK) {
01693
PUSHORT ExcptStack16;
01694
01695
01696
01697
01698
01699
01700
01701
if (ExceptionNumber > 7) {
01702
return FALSE;
01703 }
01704
01705
01706
01707
01708
01709 Regs->RiEsp = ((Regs->RiEsp - 2) & 0xffff);
01710 ExcptStack16 = Regs->RiSsBase + Regs->RiEsp;
01711 Flags = Regs->RiEFlags;
01712 GetVirtualBits(&Flags, Regs->RiTrapFrame);
01713 *ExcptStack16 = Flags;
01714
01715 Regs->RiEsp = ((Regs->RiEsp - 2) & 0xffff);
01716 ExcptStack16 = Regs->RiSsBase + Regs->RiEsp;
01717 *ExcptStack16 = Regs->RiSegCs;
01718
01719 Regs->RiEsp = ((Regs->RiEsp - 2) & 0xffff);
01720 ExcptStack16 = Regs->RiSsBase + Regs->RiEsp;
01721 *ExcptStack16 = Regs->RiEip;
01722 }
01723
else {
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735
if (VdmTib->PmStackInfo.LockCount == 0) {
01736 VdmTib->PmStackInfo.SaveEip = Regs.RiEip;
01737 VdmTib->PmStackInfo.SaveEsp = Regs.RiEsp;
01738 VdmTib->PmStackInfo.SaveSsSelector = Regs.RiSegSs;
01739
01740 Regs->RiSegSs = VdmTib->PmStackInfo.SsSelector;
01741 Regs->RiEsp = DPMISTACK_EXCEPTION_OFFSET;
01742
01743
01744
01745
01746
if (! SsToLinear(Regs, FALSE)) {
01747
return FALSE;
01748 }
01749
01750 VdmTib->PmStackInfo.LockCount++;
01751 }
01752
01753
01754
01755
01756 Regs->RiEsp -= 0x20;
01757
01758
if (! Regs->RiSsDescriptor.Words.Bits.Default_Big) {
01759
01760
01761
01762 Regs->RiEsp &= 0xffff;
01763 }
01764
01765 Flags = Regs->RiEFlags;
01766 GetVirtualBits(&Flags, Regs->RiTrapFrame);
01767
01768
if (VdmTib->PmStackInfo.
Flags) {
01769 PULONG ExcptStack32;
01770
01771
01772
01773
01774
01775
if (! CheckEsp(Regs, 32)) {
01776
return FALSE;
01777 }
01778
01779 ExcptStack32 = Regs.RiSsBase + Regs.RiEsp;
01780 *--ExcptStack32 = VdmTib->PmStackInfo.SaveSsSelector;
01781 *--ExcptStack32 = VdmTib->PmStackInfo.SaveEsp;
01782 *--ExcptStack32 = Flags;
01783 *--ExcptStack32 = Regs->RiSegCs;
01784 *--ExcptStack32 = VdmTib->PmStackInfo.SaveEip;
01785 *--ExcptStack32 = Regs->RiTrapFrame->ISRCode;
01786
01787
01788
01789
01790 *--ExcptStack32 = VdmTib->PmStackInfo.DosxFaultIretD >> 16;
01791 *--ExcptStack32 = VdmTib->PmStackInfo.DosxFaultIretD & 0x0ffff;
01792
01793
01794 Regs.RiEsp = ExcptStack32 - Regs.RiSsBase;
01795
01796 }
01797
else {
01798
PUSHORT ExcptStack16;
01799
01800
01801
01802
01803
01804
if (! CheckEsp(Regs, 16)) {
01805
return FALSE;
01806 }
01807
01808 ExcptStack16 = Regs.RiSsBase + Regs.RiEsp;
01809 *--ExcptStack16 = VdmTib->PmStackInfo.SaveSsSelector;
01810 *--ExcptStack16 = VdmTib->PmStackInfo.SaveEsp;
01811 *--ExcptStack16 = Flags;
01812 *--ExcptStack16 = Regs->RiSegCs;
01813 *--ExcptStack16 = VdmTib->PmStackInfo.SaveEip;
01814 *--ExcptStack16 = Regs->RiTrapFrame->ISRCode;
01815
01816
01817
01818
01819 *--ExcptStack16 = VdmTib->PmStackInfo.DosxFaultIretD >> 16;
01820 *--ExcptStack16 = VdmTib->PmStackInfo.DosxFaultIretD & 0x0ffff;
01821
01822 Regs->RiEsp = ExcptStack16 - Regs.RiSsBase;
01823 }
01824 }
01825
01826
01827
01828
01829 Regs.RiSegCs = ExceptHandler->CsSelector;
01830 Regs.RiEip = ExceptHandler->Eip;
01831
01832
if (! CsToLinear(&Regs, Regs->RiEFlags & EFLAGS_V86_MASK)) {
01833
return FALSE;
01834 }
01835
01836
01837
01838
01839
01840
01841
01842
01843
if (ExceptHandler->Flags & VDM_INT_INT_GATE) {
01844 SetVirtualBits(Regs->RiEFlags & ~(EFLAGS_INTERRUPT_MASK | EFLAGS_TF_MASK), &Regs);
01845 }
01846
01847 CheckVdmFlags(&Regs);
01848
01849 Regs.RiEFlags &= ~EFLAGS_TF_MASK;
01850
01851
return TRUE;
01852 }
01853
01854
01855 BOOLEAN
01856 CsToLinear(
01857 IN OUT PREGINFO Regs,
01858 IN BOOLEAN IsV86
01859 )
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880 {
01881
if (IsV86) {
01882
01883
01884
01885 Regs->RiCsBase = Regs->RiSegCs << 4;
01886
01887 Regs->RiCsDescriptor.DescriptorWords = (ULONGLONG) Regs->RiCsBase;
01888 Regs->RiCsLimit = 0xffff;
01889 }
01890
else {
01891
01892
if (! KeIA32UnscrambleLdtEntry(Regs->RiSegCs, &Regs->RiCsDescriptor)) {
01893
return FALSE;
01894 }
01895
01896
01897
01898
01899
01900 Regs->RiCsBase = (ULONG) Regs->RiCsDescriptor.Words.Bits.Base;
01901 Regs->RiCsLimit = (ULONG) Regs->RiCsDescriptor.Words.Bits.Limit;
01902
01903
01904
01905
01906
if (Regs->RiCsDescriptor.Words.Bits.Granularity) {
01907 Regs->RiCsLimit <<= 12;
01908 Regs->RiCsLimit |= 0xfff;
01909 }
01910
01911
01912
01913
01914
01915
01916
01917
01918
if ((Regs->RiCsDescriptor.Words.Bits.Type & TYPE_CODE_USER ) !=
01919 TYPE_CODE_USER) {
01920
return FALSE;
01921 }
01922 }
01923
01924
01925
01926
01927
if (Regs->RiEip > Regs->RiCsLimit) {
01928
return FALSE;
01929 }
01930
01931
01932
01933
01934 Regs->RiLinearAddr = Regs->RiEip + Regs->RiCsBase;
01935
01936
return TRUE;
01937 }
01938
01939
01940 BOOLEAN
01941 CheckEip(
01942 IN PREGINFO Regs
01943 )
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962 {
01963
if (Regs->RiEFlags & EFLAGS_V86_MASK) {
01964 Regs->RiEip &= Regs->RiCsLimit;
01965 }
01966
else {
01967
if (Regs->RiEip > Regs->RiCsLimit) {
01968
return FALSE;
01969 }
01970 }
01971
01972
return TRUE;
01973 }
01974
01975
01976 BOOLEAN
01977 SsToLinear(
01978 IN OUT PREGINFO Regs,
01979 IN BOOLEAN IsV86
01980 )
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003 {
02004
if (IsV86) {
02005
02006
02007
02008 Regs->RiSsBase = Regs->RiSegSs << 4;
02009 Regs->RiSsDescriptor.DescriptorWords = (ULONGLONG) Regs->RiSsBase;
02010 Regs->RiSsLimit = 0xffff;
02011 }
02012
else {
02013
if (! KeIA32UnscrambleLdtEntry(Regs->RiSegSs, &Regs->RiSsDescriptor)) {
02014
return FALSE;
02015 }
02016
02017
02018
02019
02020
02021
if ((Regs->RiSsDescriptor.Words.Bits.Type & DESCRIPTOR_DATA_READWRITE) !=
02022 DESCRIPTOR_DATA_READWRITE ) {
02023
return FALSE;
02024 }
02025
02026
02027
02028
02029 Regs->RiSsBase = (ULONG) (Regs->RiSsDescriptor.Words.Bits.Base);
02030 Regs->RiSsLimit = (ULONG) (Regs->RiSsDescriptor.Words.Bits.Limit);
02031
02032
02033
02034
02035
if (Regs->RiSsDescriptor.Words.Bits.Default_Big) {
02036 Regs->RiSsLimit <<= 12;
02037 Regs->RiSsLimit |= 0xfff;
02038 }
02039 }
02040
02041
return TRUE;
02042 }
02043
02044
02045 BOOLEAN
02046 CheckEsp(
02047 IN PREGINFO Regs,
02048 IN ULONG StackNeeded
02049 )
02050
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070 {
02071
if (Regs->RiEFlags & EFLAGS_V86_MASK) {
02072 Regs->RiEsp &= Regs->RiSsLimit;
02073 }
02074
else {
02075
if (! Regs->RiSsDescriptor.Words.Bits.Default_Big) {
02076
02077
02078
02079 Regs->RiEsp &= 0xffff;
02080 }
02081
02082
02083
02084
02085
if (StackNeeded > Regs->RiEsp) {
02086
return FALSE;
02087 }
02088
02089
if ((Regs->RiSsDescriptor.Words.Bits.Type & DESCRIPTOR_EXPAND_DOWN) ==
02090 DESCRIPTOR_EXPAND_DOWN ) {
02091
if (Regs->RiEsp - StackNeeded - 1 < Regs->RiSsLimit) {
02092
return FALSE;
02093 }
02094 }
02095
else {
02096
if (Regs->RiEsp >= Regs->RiSsLimit) {
02097
return FALSE;
02098 }
02099 }
02100 }
02101
02102
return TRUE;
02103 }
02104
02105
02106 BOOLEAN
02107 KeIA32UnscrambleLdtEntry(
02108 IN ULONG Selector,
02109 OUT PKXDESCRIPTOR XDescriptor
02110 )
02111
02112
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130 {
02131
PETHREAD Thread;
02132 DESCRIPTOR_TABLE_ENTRY DescriptorEntry;
02133
NTSTATUS Status;
02134
02135
02136
02137
02138
if ((Selector & (SELECTOR_TABLE_INDEX | DPL_USER)) != (SELECTOR_TABLE_INDEX | DPL_USER)) {
02139
02140
return FALSE;
02141 }
02142
02143 Thread =
KeGetCurrentThread();
02144 DescriptorEntry.Selector = Selector;
02145
02146
Status =
PspQueryDescriptorThread(Thread, &DescriptorEntry,
sizeof(DescriptorEntry), NULL);
02147
if (!
NT_SUCCESS(Status)) {
02148
return FALSE;
02149 }
02150
02151 XDescriptor->Words.DescriptorWords = KeIA32Unscramble(&DescriptorEntry.Descriptor);
02152
02153
return TRUE;
02154 }
02155
02156
02157 ULONGLONG
02158 KeIA32Unscramble(
02159 IN PLDT_ENTRY Descriptor
02160 )
02161
02162
02163
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183 {
02184 KXDESCRIPTOR Result;
02185
02186
02187
02188
02189 Result.Words.Bits.Base = Descriptor->BaseLow | (Descriptor->HighWord.Bytes.BaseMid << 16) | (Descriptor->HighWord.Bytes.BaseHi << 24);
02190
02191
02192
02193
02194 Result.Words.Bits.Limit = (Descriptor->LimitLow | (Descriptor->HighWord.Bits.LimitHi << 16)) << UNSCRAM_LIMIT_OFFSET;
02195
02196
02197
02198
02199
02200
02201 Result.Words.Bits.Type = Descriptor->HighWord.Bits.Type;
02202 Result.Words.Bits.Dpl = Descriptor->HighWord.Bits.Dpl;
02203 Result.Words.Bits.Pres = Descriptor->HighWord.Bits.Pres;
02204 Result.Words.Bits.Sys = Descriptor->HighWord.Bits.Sys;
02205 Result.Words.Bits.Reserved_0 = Descriptor->HighWord.Bits.Reserved_0;
02206 Result.Words.Bits.Default_Big = Descriptor->HighWord.Bits.Default_Big;
02207 Result.Words.Bits.Granularity = Descriptor->HighWord.Bits.Granularity;
02208
02209
return Result.Words.DescriptorWords;
02210 }
02211
02212
02213
02214
02215
02216
#define _VDM_CHECK_OR_FUNC(x) ((x) |= EFLAGS_INTERRUPT_MASK)
02217
#define _VDM_CHECK_AND_FUNC(x) ((x) &= ~(EFLAGS_IOPL_MASK | EFLAGS_NT_MASK | EFLAGS_VIF | EFLAGS_VIP))
02218
02219
02220
VOID
02221 CheckVdmFlags(
02222 IN OUT PREGINFO Regs
02223 )
02224
02225
02226
02227
02228
02229
02230
02231
02232
02233
02234
02235
02236
02237
02238
02239
02240
02241 {
02242
if (
KeIA32VdmIoplAllowed) {
02243
if (! (Regs->RiEFlags & EFLAGS_V86_MASK)) {
02244 _VDM_CHECK_OR_FUNC(Regs->RiEFlags);
02245 }
02246 _VDM_CHECK_AND_FUNC(Regs->RiEFlags);
02247
return;
02248 }
02249
02250
02251
02252
02253
02254
02255
02256
02257
02258
02259
#if 0
02260
if (
KeIA32VirtualIntExtensions & (V86_VIRTUAL_INT_EXTENSIONS | PM_VIRTUAL_INT_EXTENSIONS)) {
02261
if (Regs->RiEflags & EFLAGS_V86_MASK) {
02262
if (
KeIA32VirtualIntExtensions & V86_VIRTUAL_INT_EXTENSIONS) {
02263 }
02264
else {
02265 }
02266 }
02267
else {
02268
if (
KeIA32VirtualIntExtensions & PM_VIRTUAL_INT_EXTENSIONS) {
02269 }
02270
else {
02271 }
02272 }
02273 }
02274
#endif
02275
02276 _VDM_CHECK_OR_FUNC(Regs->RiEFlags);
02277 _VDM_CHECK_AND_FUNC(Regs->RiEFlags);
02278 }
02279
02280
02281
VOID
02282 KeIA32AndOrVdmLock(
02283 IN ULONG AndMask,
02284 IN ULONG OrMask
02285 )
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300
02301
02302
02303
02304 {
02305
#ifdef NT_UP
02306
*
VdmFixedStateLinear = (*
VdmFixedStateLinear & AndMask) | OrMask;
02307
#else
02308
VdmGenericAndOrLock(VdmFixedStateLinear, AndMask, OrMask);
02309
#endif
02310
}
02311
02312
#else // defined(WX86) && defined(TRY_NTVDM)
02313
02314
02315 BOOLEAN
02316 KiIA32VdmReflectException(
02317 IN OUT PKIA32_FRAME Frame,
02318 IN ULONG Code
02319 )
02320
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332
02333
02334
02335
02336
02337
02338
02339
02340
02341
02342 {
02343
02344
02345
02346
return(
FALSE);
02347 }
02348
02349
02350 BOOLEAN
02351 KiIA32DispatchOpcode(
02352 IN PKIA32_FRAME Frame
02353 )
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374 {
02375
02376
02377
02378
02379
return(
FALSE);
02380 }
02381
02382
02383 BOOLEAN
02384 KiIA32VdmSegmentNotPresent(
02385 IN OUT PKIA32_FRAME Frame
02386 )
02387
02388
02389
02390
02391
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403
02404
02405
02406 {
02407
02408
02409
02410
02411
return(
FALSE);
02412 }
02413
02414
#endif // defined(WX86) && defined(TRY_NTVDM)