ReactOS 0.4.15-dev-8191-gbc6c731
common.c File Reference
#include <windef.h>
#include <debug.h>
#include <fast486.h>
#include "common.h"
Include dependency graph for common.c:

Go to the source code of this file.

Functions

BOOLEAN FASTCALL Fast486ReadMemory (PFAST486_STATE State, FAST486_SEG_REGS SegmentReg, ULONG Offset, BOOLEAN InstFetch, PVOID Buffer, ULONG Size)
 
BOOLEAN FASTCALL Fast486WriteMemory (PFAST486_STATE State, FAST486_SEG_REGS SegmentReg, ULONG Offset, PVOID Buffer, ULONG Size)
 
static BOOLEAN FASTCALL Fast486GetIntVector (PFAST486_STATE State, UCHAR Number, PFAST486_IDT_ENTRY IdtEntry)
 
static BOOLEAN FASTCALL Fast486InterruptInternal (PFAST486_STATE State, PFAST486_IDT_ENTRY IdtEntry, BOOLEAN PushErrorCode, ULONG ErrorCode)
 
BOOLEAN FASTCALL Fast486PerformInterrupt (PFAST486_STATE State, UCHAR Number)
 
VOID FASTCALL Fast486ExceptionWithErrorCode (PFAST486_STATE State, FAST486_EXCEPTIONS ExceptionCode, ULONG ErrorCode)
 
BOOLEAN FASTCALL Fast486TaskSwitch (PFAST486_STATE State, FAST486_TASK_SWITCH_TYPE Type, USHORT Selector)
 
BOOLEAN FASTCALL Fast486CallGate (PFAST486_STATE State, PFAST486_CALL_GATE Gate, BOOLEAN Call)
 

Function Documentation

◆ Fast486CallGate()

BOOLEAN FASTCALL Fast486CallGate ( PFAST486_STATE  State,
PFAST486_CALL_GATE  Gate,
BOOLEAN  Call 
)

Definition at line 1116 of file common.c.

1119{
1120 BOOLEAN Valid;
1121 FAST486_GDT_ENTRY NewCodeSegment;
1122 BOOLEAN GateSize = (Gate->Type == FAST486_CALL_GATE_SIGNATURE);
1123 FAST486_TSS Tss;
1124 PFAST486_LEGACY_TSS LegacyTss = (PFAST486_LEGACY_TSS)&Tss;
1125 USHORT OldCs = State->SegmentRegs[FAST486_REG_CS].Selector;
1126 ULONG OldEip = State->InstPtr.Long;
1127 USHORT OldCpl = State->Cpl;
1128 USHORT OldSs = State->SegmentRegs[FAST486_REG_SS].Selector;
1129 ULONG OldEsp = State->GeneralRegs[FAST486_REG_ESP].Long;
1130 ULONG ParamBuffer[32]; /* Maximum possible size - 32 DWORDs */
1131 PULONG LongParams = (PULONG)ParamBuffer;
1132 PUSHORT ShortParams = (PUSHORT)ParamBuffer;
1133
1134 if (!Gate->Selector)
1135 {
1136 /* The code segment is NULL */
1137 Fast486Exception(State, FAST486_EXCEPTION_GP);
1138 return FALSE;
1139 }
1140
1141 if (!Fast486ReadDescriptorEntry(State, Gate->Selector, &Valid, &NewCodeSegment))
1142 {
1143 /* Exception occurred */
1144 return FALSE;
1145 }
1146
1147 if (!Valid || (NewCodeSegment.Dpl > Fast486GetCurrentPrivLevel(State)))
1148 {
1149 /* Code segment invalid */
1150 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Gate->Selector);
1151 return FALSE;
1152 }
1153
1154 if (Call && Gate->ParamCount)
1155 {
1156 /* Read the parameters */
1158 FAST486_REG_SS,
1159 OldEsp,
1160 FALSE,
1161 ParamBuffer,
1162 Gate->ParamCount * (GateSize ? sizeof(ULONG) : sizeof(USHORT))))
1163 {
1164 /* Exception occurred */
1165 return FALSE;
1166 }
1167 }
1168
1169 /* Check if the new code segment is more privileged */
1170 if (NewCodeSegment.Dpl < OldCpl)
1171 {
1172 if (Call)
1173 {
1174 USHORT NewSs;
1175 ULONG NewEsp;
1176
1177 /* Read the TSS */
1178 if (!Fast486ReadLinearMemory(State,
1179 State->TaskReg.Base,
1180 &Tss,
1181 State->TaskReg.Modern
1182 ? sizeof(FAST486_TSS) : sizeof(FAST486_LEGACY_TSS),
1183 FALSE))
1184 {
1185 /* Exception occurred */
1186 return FALSE;
1187 }
1188
1189 /* Switch to the new privilege level */
1190 State->Cpl = NewCodeSegment.Dpl;
1191
1192 /* Check the new (higher) privilege level */
1193 switch (State->Cpl)
1194 {
1195 case 0:
1196 {
1197 if (State->TaskReg.Modern)
1198 {
1199 NewSs = Tss.Ss0;
1200 NewEsp = Tss.Esp0;
1201 }
1202 else
1203 {
1204 NewSs = LegacyTss->Ss0;
1205 NewEsp = LegacyTss->Sp0;
1206 }
1207
1208 break;
1209 }
1210
1211 case 1:
1212 {
1213 if (State->TaskReg.Modern)
1214 {
1215 NewSs = Tss.Ss1;
1216 NewEsp = Tss.Esp1;
1217 }
1218 else
1219 {
1220 NewSs = LegacyTss->Ss1;
1221 NewEsp = LegacyTss->Sp1;
1222 }
1223
1224 break;
1225 }
1226
1227 case 2:
1228 {
1229 if (State->TaskReg.Modern)
1230 {
1231 NewSs = Tss.Ss2;
1232 NewEsp = Tss.Esp2;
1233 }
1234 else
1235 {
1236 NewSs = LegacyTss->Ss2;
1237 NewEsp = LegacyTss->Sp2;
1238 }
1239
1240 break;
1241 }
1242
1243 default:
1244 {
1245 /* Should never reach here! */
1246 ASSERT(FALSE);
1247 }
1248 }
1249
1250 if (!Fast486LoadSegment(State, FAST486_REG_SS, NewSs))
1251 {
1252 /* Exception occurred */
1253 return FALSE;
1254 }
1255
1256 State->GeneralRegs[FAST486_REG_ESP].Long = NewEsp;
1257 }
1258 else if (!NewCodeSegment.DirConf)
1259 {
1260 /* This is not allowed for jumps */
1261 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Gate->Selector);
1262 return FALSE;
1263 }
1264 }
1265
1266 /* Load new CS */
1267 if (!Fast486LoadSegment(State, FAST486_REG_CS, Gate->Selector))
1268 {
1269 /* An exception occurred during the jump */
1270 return FALSE;
1271 }
1272
1273 /* Set the instruction pointer */
1274 if (GateSize) State->InstPtr.Long = MAKELONG(Gate->Offset, Gate->OffsetHigh);
1275 else State->InstPtr.Long = Gate->Offset;
1276
1277 if (Call)
1278 {
1279 INT i;
1280
1281 /* Check if the new code segment is more privileged (again) */
1282 if (NewCodeSegment.Dpl < OldCpl)
1283 {
1284 /* Push SS selector */
1285 if (!Fast486StackPushInternal(State, GateSize, OldSs)) return FALSE;
1286
1287 /* Push stack pointer */
1288 if (!Fast486StackPushInternal(State, GateSize, OldEsp)) return FALSE;
1289 }
1290
1291 /* Push the parameters in reverse order */
1292 for (i = Gate->ParamCount - 1; i >= 0; i--)
1293 {
1294 if (!Fast486StackPushInternal(State,
1295 GateSize,
1296 GateSize ? LongParams[i] : ShortParams[i]))
1297 {
1298 /* Exception occurred */
1299 return FALSE;
1300 }
1301 }
1302
1303 /* Push CS selector */
1304 if (!Fast486StackPushInternal(State, GateSize, OldCs)) return FALSE;
1305
1306 /* Push the instruction pointer */
1307 if (!Fast486StackPushInternal(State, GateSize, OldEip)) return FALSE;
1308 }
1309
1310 return TRUE;
1311}
unsigned char BOOLEAN
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define FAST486_CALL_GATE_SIGNATURE
Definition: fast486.h:94
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define ASSERT(a)
Definition: mode.c:44
unsigned short USHORT
Definition: pedump.c:61
VOID FASTCALL Fast486ExceptionWithErrorCode(PFAST486_STATE State, FAST486_EXCEPTIONS ExceptionCode, ULONG ErrorCode)
Definition: common.c:557
BOOLEAN FASTCALL Fast486ReadMemory(PFAST486_STATE State, FAST486_SEG_REGS SegmentReg, ULONG Offset, BOOLEAN InstFetch, PVOID Buffer, ULONG Size)
Definition: common.c:36
uint32_t * PULONG
Definition: typedefs.h:59
int32_t INT
Definition: typedefs.h:58
uint16_t * PUSHORT
Definition: typedefs.h:56
#define MAKELONG(a, b)
Definition: typedefs.h:249
uint32_t ULONG
Definition: typedefs.h:59

◆ Fast486ExceptionWithErrorCode()

VOID FASTCALL Fast486ExceptionWithErrorCode ( PFAST486_STATE  State,
FAST486_EXCEPTIONS  ExceptionCode,
ULONG  ErrorCode 
)

Definition at line 557 of file common.c.

560{
561 FAST486_IDT_ENTRY IdtEntry;
562
563 /* Increment the exception count */
564 State->ExceptionCount++;
565
566 /* Check if the exception occurred more than once */
567 if (State->ExceptionCount > 1)
568 {
569 /* Then this is a double fault */
570 ExceptionCode = FAST486_EXCEPTION_DF;
571 }
572
573 /* Check if this is a triple fault */
574 if (State->ExceptionCount == 3)
575 {
576 DPRINT("Fast486ExceptionWithErrorCode(%04X:%08X) -- Triple fault\n",
577 State->SegmentRegs[FAST486_REG_CS].Selector,
578 State->InstPtr.Long);
579
580 /* Reset the CPU */
582 return;
583 }
584
585 /* Clear the prefix flags */
586 State->PrefixFlags = 0;
587
588 /* Restore the IP to the saved IP */
589 State->InstPtr = State->SavedInstPtr;
590
591 /* Restore the SP to the saved SP */
592 State->GeneralRegs[FAST486_REG_ESP] = State->SavedStackPtr;
593
594 /* Get the interrupt vector */
595 if (!Fast486GetIntVector(State, ExceptionCode, &IdtEntry))
596 {
597 /*
598 * If this function failed, that means Fast486Exception
599 * was called again, so just return in this case.
600 */
601 return;
602 }
603
604 /* Perform the interrupt */
606 &IdtEntry,
608 && (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE),
609 ErrorCode))
610 {
611 /*
612 * If this function failed, that means Fast486Exception
613 * was called again, so just return in this case.
614 */
615 return;
616 }
617
618 /* Reset the exception count */
619 State->ExceptionCount = 0;
620}
_Inout_ PIRP _In_ NTSTATUS ExceptionCode
Definition: cdprocs.h:1774
VOID NTAPI Fast486Reset(PFAST486_STATE State)
Definition: fast486.c:131
#define FAST486_CR0_PE
Definition: fast486.h:46
_In_ NDIS_ERROR_CODE ErrorCode
Definition: ndis.h:4436
static BOOLEAN FASTCALL Fast486InterruptInternal(PFAST486_STATE State, PFAST486_IDT_ENTRY IdtEntry, BOOLEAN PushErrorCode, ULONG ErrorCode)
Definition: common.c:298
static BOOLEAN FASTCALL Fast486GetIntVector(PFAST486_STATE State, UCHAR Number, PFAST486_IDT_ENTRY IdtEntry)
Definition: common.c:251
#define EXCEPTION_HAS_ERROR_CODE(x)
Definition: common.h:41
#define DPRINT
Definition: sndvol32.h:73

Referenced by FAST486_OPCODE_HANDLER(), Fast486CallGate(), and Fast486TaskSwitch().

◆ Fast486GetIntVector()

static BOOLEAN FASTCALL Fast486GetIntVector ( PFAST486_STATE  State,
UCHAR  Number,
PFAST486_IDT_ENTRY  IdtEntry 
)
inlinestatic

Definition at line 251 of file common.c.

254{
255 /* Check for protected mode */
256 if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
257 {
258 /* Read from the IDT */
259 if (!Fast486ReadLinearMemory(State,
260 State->Idtr.Address
261 + Number * sizeof(*IdtEntry),
262 IdtEntry,
263 sizeof(*IdtEntry),
264 FALSE))
265 {
266 /* Exception occurred */
267 return FALSE;
268 }
269 }
270 else
271 {
272 /* Read from the real-mode IVT */
273 ULONG FarPointer;
274
275 /* Paging is always disabled in real mode */
276 State->MemReadCallback(State,
277 State->Idtr.Address
278 + Number * sizeof(FarPointer),
279 &FarPointer,
280 sizeof(FarPointer));
281
282 /* Fill a fake IDT entry */
283 IdtEntry->Offset = LOWORD(FarPointer);
284 IdtEntry->Selector = HIWORD(FarPointer);
285 IdtEntry->Zero = 0;
286 IdtEntry->Type = FAST486_IDT_INT_GATE;
287 IdtEntry->Storage = FALSE;
288 IdtEntry->Dpl = 0;
289 IdtEntry->Present = TRUE;
290 IdtEntry->OffsetHigh = 0;
291 }
292
293 return TRUE;
294}
#define FAST486_IDT_INT_GATE
Definition: fast486.h:90
_In_opt_ PENTER_STATE_SYSTEM_HANDLER _In_opt_ PVOID _In_ LONG _In_opt_ LONG volatile * Number
Definition: ntpoapi.h:207
#define LOWORD(l)
Definition: pedump.c:82
#define HIWORD(l)
Definition: typedefs.h:247

Referenced by Fast486ExceptionWithErrorCode(), and Fast486PerformInterrupt().

◆ Fast486InterruptInternal()

static BOOLEAN FASTCALL Fast486InterruptInternal ( PFAST486_STATE  State,
PFAST486_IDT_ENTRY  IdtEntry,
BOOLEAN  PushErrorCode,
ULONG  ErrorCode 
)
inlinestatic

Definition at line 298 of file common.c.

302{
303 BOOLEAN GateSize = (IdtEntry->Type == FAST486_IDT_INT_GATE_32) ||
304 (IdtEntry->Type == FAST486_IDT_TRAP_GATE_32);
305 USHORT OldCs = State->SegmentRegs[FAST486_REG_CS].Selector;
306 ULONG OldEip = State->InstPtr.Long;
307 ULONG OldFlags = State->Flags.Long;
308 UCHAR OldCpl = State->Cpl;
309
310 /* Check for protected mode */
311 if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
312 {
313 USHORT OldSs = State->SegmentRegs[FAST486_REG_SS].Selector;
314 ULONG OldEsp = State->GeneralRegs[FAST486_REG_ESP].Long;
315 BOOLEAN OldVm = State->Flags.Vm;
316
317 if (IdtEntry->Type == FAST486_TASK_GATE_SIGNATURE)
318 {
319 /* Task call */
320 if (!Fast486TaskSwitch(State, FAST486_TASK_CALL, IdtEntry->Selector))
321 {
322 /* Exception occurred */
323 return FALSE;
324 }
325
326 goto Finish;
327 }
328
329 /* Check if the interrupt handler is more privileged or if we're in V86 mode */
330 if ((OldCpl > GET_SEGMENT_RPL(IdtEntry->Selector)) || State->Flags.Vm)
331 {
332 FAST486_TSS Tss;
333 PFAST486_LEGACY_TSS LegacyTss = (PFAST486_LEGACY_TSS)&Tss;
334 USHORT NewSs;
335 ULONG NewEsp;
336
337 /* Read the TSS */
338 if (!Fast486ReadLinearMemory(State,
339 State->TaskReg.Base,
340 &Tss,
341 State->TaskReg.Modern
342 ? sizeof(FAST486_TSS) : sizeof(FAST486_LEGACY_TSS),
343 FALSE))
344 {
345 /* Exception occurred */
346 return FALSE;
347 }
348
349 /* Switch to the new privilege level */
350 State->Cpl = GET_SEGMENT_RPL(IdtEntry->Selector);
351
352 /* Clear the VM flag */
353 State->Flags.Vm = FALSE;
354
355 /* Check the new (higher) privilege level */
356 switch (State->Cpl)
357 {
358 case 0:
359 {
360 if (State->TaskReg.Modern)
361 {
362 NewSs = Tss.Ss0;
363 NewEsp = Tss.Esp0;
364 }
365 else
366 {
367 NewSs = LegacyTss->Ss0;
368 NewEsp = LegacyTss->Sp0;
369 }
370
371 break;
372 }
373
374 case 1:
375 {
376 if (State->TaskReg.Modern)
377 {
378 NewSs = Tss.Ss1;
379 NewEsp = Tss.Esp1;
380 }
381 else
382 {
383 NewSs = LegacyTss->Ss1;
384 NewEsp = LegacyTss->Sp1;
385 }
386
387 break;
388 }
389
390 case 2:
391 {
392 if (State->TaskReg.Modern)
393 {
394 NewSs = Tss.Ss2;
395 NewEsp = Tss.Esp2;
396 }
397 else
398 {
399 NewSs = LegacyTss->Ss2;
400 NewEsp = LegacyTss->Sp2;
401 }
402
403 break;
404 }
405
406 default:
407 {
408 /* Should never reach here! */
409 ASSERT(FALSE);
410 }
411 }
412
413 if (!Fast486LoadSegment(State, FAST486_REG_SS, NewSs))
414 {
415 /* Exception occurred */
416 return FALSE;
417 }
418
419 State->GeneralRegs[FAST486_REG_ESP].Long = NewEsp;
420 }
421
422 /* Load new CS */
423 if (!Fast486LoadSegment(State, FAST486_REG_CS, IdtEntry->Selector))
424 {
425 /* An exception occurred during the jump */
426 return FALSE;
427 }
428
429 if (GateSize)
430 {
431 /* 32-bit code segment, use EIP */
432 State->InstPtr.Long = MAKELONG(IdtEntry->Offset, IdtEntry->OffsetHigh);
433 }
434 else
435 {
436 /* 16-bit code segment, use IP */
437 State->InstPtr.LowWord = IdtEntry->Offset;
438 }
439
440 /* Clear NT */
441 State->Flags.Nt = FALSE;
442
443 if (OldVm)
444 {
445 /* Push GS, FS, DS and ES */
446 if (!Fast486StackPushInternal(State,
447 GateSize,
448 State->SegmentRegs[FAST486_REG_GS].Selector))
449 {
450 return FALSE;
451 }
452 if (!Fast486StackPushInternal(State,
453 GateSize,
454 State->SegmentRegs[FAST486_REG_FS].Selector))
455 {
456 return FALSE;
457 }
458 if (!Fast486StackPushInternal(State,
459 GateSize,
460 State->SegmentRegs[FAST486_REG_DS].Selector))
461 {
462 return FALSE;
463 }
464 if (!Fast486StackPushInternal(State,
465 GateSize,
466 State->SegmentRegs[FAST486_REG_ES].Selector))
467 {
468 return FALSE;
469 }
470
471 /* Now load them with NULL selectors, since they are useless in protected mode */
472 if (!Fast486LoadSegment(State, FAST486_REG_GS, 0)) return FALSE;
473 if (!Fast486LoadSegment(State, FAST486_REG_FS, 0)) return FALSE;
474 if (!Fast486LoadSegment(State, FAST486_REG_DS, 0)) return FALSE;
475 if (!Fast486LoadSegment(State, FAST486_REG_ES, 0)) return FALSE;
476 }
477
478 /* Check if the interrupt handler is more privileged or we're in VM86 mode (again) */
479 if ((OldCpl > GET_SEGMENT_RPL(IdtEntry->Selector)) || OldVm)
480 {
481 /* Push SS selector */
482 if (!Fast486StackPushInternal(State, GateSize, OldSs)) return FALSE;
483
484 /* Push the stack pointer */
485 if (!Fast486StackPushInternal(State, GateSize, OldEsp)) return FALSE;
486 }
487 }
488 else
489 {
490 /* Load new CS */
491 if (!Fast486LoadSegment(State, FAST486_REG_CS, IdtEntry->Selector))
492 {
493 /* An exception occurred during the jump */
494 return FALSE;
495 }
496
497 /* Set the new IP */
498 State->InstPtr.LowWord = IdtEntry->Offset;
499 }
500
501 /* Push EFLAGS */
502 if (!Fast486StackPushInternal(State, GateSize, OldFlags)) return FALSE;
503
504 /* Push CS selector */
505 if (!Fast486StackPushInternal(State, GateSize, OldCs)) return FALSE;
506
507 /* Push the instruction pointer */
508 if (!Fast486StackPushInternal(State, GateSize, OldEip)) return FALSE;
509
510Finish:
511
512 if (PushErrorCode)
513 {
514 /* Push the error code */
515 if (!Fast486StackPushInternal(State, GateSize, ErrorCode)) return FALSE;
516 }
517
518 if ((IdtEntry->Type == FAST486_IDT_INT_GATE)
519 || (IdtEntry->Type == FAST486_IDT_INT_GATE_32))
520 {
521 /* Disable interrupts after a jump to an interrupt gate handler */
522 State->Flags.If = FALSE;
523 }
524
525 /* Clear TF */
526 State->Flags.Tf = FALSE;
527
528 return TRUE;
529}
#define FAST486_TASK_GATE_SIGNATURE
Definition: fast486.h:89
#define FAST486_IDT_INT_GATE_32
Definition: fast486.h:95
#define FAST486_IDT_TRAP_GATE_32
Definition: fast486.h:96
SHORT OldFlags
Definition: fxioqueue.cpp:1325
BOOLEAN FASTCALL Fast486TaskSwitch(PFAST486_STATE State, FAST486_TASK_SWITCH_TYPE Type, USHORT Selector)
Definition: common.c:624
#define GET_SEGMENT_RPL(s)
Definition: common.h:38
@ FAST486_TASK_CALL
Definition: common.h:88
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by Fast486ExceptionWithErrorCode(), and Fast486PerformInterrupt().

◆ Fast486PerformInterrupt()

BOOLEAN FASTCALL Fast486PerformInterrupt ( PFAST486_STATE  State,
UCHAR  Number 
)

Definition at line 533 of file common.c.

535{
536 FAST486_IDT_ENTRY IdtEntry;
537
538 /* Get the interrupt vector */
539 if (!Fast486GetIntVector(State, Number, &IdtEntry))
540 {
541 /* Exception occurred */
542 return FALSE;
543 }
544
545 /* Perform the interrupt */
546 if (!Fast486InterruptInternal(State, &IdtEntry, FALSE, 0))
547 {
548 /* Exception occurred */
549 return FALSE;
550 }
551
552 return TRUE;
553}

Referenced by FAST486_OPCODE_HANDLER(), and Fast486ExecutionControl().

◆ Fast486ReadMemory()

BOOLEAN FASTCALL Fast486ReadMemory ( PFAST486_STATE  State,
FAST486_SEG_REGS  SegmentReg,
ULONG  Offset,
BOOLEAN  InstFetch,
PVOID  Buffer,
ULONG  Size 
)

Definition at line 36 of file common.c.

42{
43 ULONG LinearAddress;
44 PFAST486_SEG_REG CachedDescriptor;
45 FAST486_EXCEPTIONS Exception = SegmentReg != FAST486_REG_SS
46 ? FAST486_EXCEPTION_GP : FAST486_EXCEPTION_SS;
47
48 ASSERT(SegmentReg < FAST486_NUM_SEG_REGS);
49
50 /* Get the cached descriptor */
51 CachedDescriptor = &State->SegmentRegs[SegmentReg];
52
53 if (InstFetch || CachedDescriptor->Executable || !CachedDescriptor->DirConf)
54 {
55 if ((Offset + Size - 1) > CachedDescriptor->Limit)
56 {
57 /* Read beyond limit */
58 Fast486Exception(State, Exception);
59 return FALSE;
60 }
61 }
62 else
63 {
64 if (Offset < CachedDescriptor->Limit)
65 {
66 /* Read beyond limit */
67 Fast486Exception(State, Exception);
68 return FALSE;
69 }
70 }
71
72 /* Check for protected mode */
73 if ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) && !State->Flags.Vm)
74 {
75 /* Privilege checks */
76
77 if (!CachedDescriptor->Present)
78 {
79 Fast486Exception(State, Exception);
80 return FALSE;
81 }
82
83 if ((!InstFetch && (CachedDescriptor->Rpl > CachedDescriptor->Dpl))
84 || (Fast486GetCurrentPrivLevel(State) > CachedDescriptor->Dpl))
85 {
86 Fast486Exception(State, Exception);
87 return FALSE;
88 }
89
90 if (InstFetch)
91 {
92 if (!CachedDescriptor->Executable)
93 {
94 /* Data segment not executable */
95 Fast486Exception(State, Exception);
96 return FALSE;
97 }
98 }
99 else
100 {
101 if (CachedDescriptor->Executable && (!CachedDescriptor->ReadWrite))
102 {
103 /* Code segment not readable */
104 Fast486Exception(State, Exception);
105 return FALSE;
106 }
107 }
108 }
109
110 /* Find the linear address */
111 LinearAddress = CachedDescriptor->Base + Offset;
112
113#ifndef FAST486_NO_PREFETCH
114 if (InstFetch && ((Offset + FAST486_CACHE_SIZE - 1) <= CachedDescriptor->Limit))
115 {
116 State->PrefetchAddress = LinearAddress;
117
118 if ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PG)
119 && (PAGE_OFFSET(State->PrefetchAddress) > (FAST486_PAGE_SIZE - FAST486_CACHE_SIZE)))
120 {
121 /* We mustn't prefetch across a page boundary */
122 State->PrefetchAddress = PAGE_ALIGN(State->PrefetchAddress)
124
125 if ((LinearAddress - State->PrefetchAddress + Size) >= FAST486_CACHE_SIZE)
126 {
127 /* We can't prefetch without possibly violating page permissions */
128 State->PrefetchValid = FALSE;
129 return Fast486ReadLinearMemory(State, LinearAddress, Buffer, Size, TRUE);
130 }
131 }
132
133 /* Prefetch */
134 if (Fast486ReadLinearMemory(State,
135 State->PrefetchAddress,
136 State->PrefetchCache,
138 TRUE))
139 {
140 State->PrefetchValid = TRUE;
141
143 &State->PrefetchCache[LinearAddress - State->PrefetchAddress],
144 Size);
145 return TRUE;
146 }
147 else
148 {
149 State->PrefetchValid = FALSE;
150 return FALSE;
151 }
152 }
153 else
154#endif
155 {
156 /* Read from the linear address */
157 return Fast486ReadLinearMemory(State, LinearAddress, Buffer, Size, TRUE);
158 }
159}
Definition: bufpool.h:45
#define FAST486_CACHE_SIZE
Definition: fast486.h:108
#define FAST486_NUM_SEG_REGS
Definition: fast486.h:41
#define FAST486_PAGE_SIZE
Definition: fast486.h:107
#define FAST486_CR0_PG
Definition: fast486.h:56
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
#define PAGE_OFFSET(x)
Definition: common.h:68
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_In_ LONG _In_ LONG Limit
Definition: kefuncs.h:304
#define PAGE_ALIGN(Va)

Referenced by FAST486_OPCODE_HANDLER(), Fast486CallGate(), and Fast486FpuLoadEnvironment().

◆ Fast486TaskSwitch()

BOOLEAN FASTCALL Fast486TaskSwitch ( PFAST486_STATE  State,
FAST486_TASK_SWITCH_TYPE  Type,
USHORT  Selector 
)

Definition at line 624 of file common.c.

625{
626 ULONG NewTssAddress;
627 ULONG NewTssLimit;
628 FAST486_SYSTEM_DESCRIPTOR NewTssDescriptor;
629 FAST486_TSS OldTss;
630 PFAST486_LEGACY_TSS OldLegacyTss = (PFAST486_LEGACY_TSS)&OldTss;
631 FAST486_TSS NewTss;
632 PFAST486_LEGACY_TSS NewLegacyTss = (PFAST486_LEGACY_TSS)&NewTss;
633 USHORT NewLdtr, NewEs, NewCs, NewSs, NewDs;
634
635 if ((State->TaskReg.Modern && State->TaskReg.Limit < (sizeof(FAST486_TSS) - 1))
636 || (!State->TaskReg.Modern && State->TaskReg.Limit < (sizeof(FAST486_LEGACY_TSS) - 1)))
637 {
638 /* Invalid task register limit */
639 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_TS, State->TaskReg.Selector);
640 return FALSE;
641 }
642
643 /* Read the old TSS */
644 if (!Fast486ReadLinearMemory(State,
645 State->TaskReg.Base,
646 &OldTss,
647 State->TaskReg.Modern
648 ? sizeof(FAST486_TSS) : sizeof(FAST486_LEGACY_TSS),
649 FALSE))
650 {
651 /* Exception occurred */
652 return FALSE;
653 }
654
655
656 /* If this is a task return, use the linked previous selector */
658 {
659 if (State->TaskReg.Modern) Selector = LOWORD(OldTss.Link);
660 else Selector = OldLegacyTss->Link;
661 }
662
663 /* Make sure the entry exists in the GDT (not LDT!) */
664 if ((GET_SEGMENT_INDEX(Selector) == 0)
665 || (Selector & SEGMENT_TABLE_INDICATOR)
666 || GET_SEGMENT_INDEX(Selector) >= (State->Gdtr.Size + 1u))
667 {
668 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_TS, Selector);
669 return FALSE;
670 }
671
672 /* Get the TSS descriptor from the GDT */
673 if (!Fast486ReadLinearMemory(State,
674 State->Gdtr.Address + GET_SEGMENT_INDEX(Selector),
675 &NewTssDescriptor,
676 sizeof(NewTssDescriptor),
677 FALSE))
678 {
679 /* Exception occurred */
680 return FALSE;
681 }
682
683 if (!NewTssDescriptor.Present)
684 {
685 /* Incoming task TSS not present */
686 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_NP, Selector);
687 return FALSE;
688 }
689
690 /* Calculate the linear address of the new TSS */
691 NewTssAddress = NewTssDescriptor.Base;
692 NewTssAddress |= NewTssDescriptor.BaseMid << 16;
693 NewTssAddress |= NewTssDescriptor.BaseHigh << 24;
694
695 /* Calculate the limit of the new TSS */
696 NewTssLimit = NewTssDescriptor.Limit | (NewTssDescriptor.LimitHigh << 16);
697
698 if (NewTssDescriptor.Granularity)
699 {
700 NewTssLimit <<= 12;
701 NewTssLimit |= 0x00000FFF;
702 }
703
704 if (NewTssLimit < (sizeof(FAST486_TSS) - 1)
705 && NewTssLimit != (sizeof(FAST486_LEGACY_TSS) - 1))
706 {
707 /* TSS limit invalid */
708 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_TS, Selector);
709 return FALSE;
710 }
711
712 /*
713 * The incoming task shouldn't be busy if we're executing it as a
714 * new task, and it should be busy if we're returning to it.
715 */
716 if ((((NewTssDescriptor.Signature != FAST486_TSS_SIGNATURE)
717 && (NewTssDescriptor.Signature != FAST486_TSS_16_SIGNATURE))
719 && (((NewTssDescriptor.Signature != FAST486_BUSY_TSS_SIGNATURE)
720 && (NewTssDescriptor.Signature != FAST486_BUSY_TSS_16_SIGNATURE))
721 || (Type != FAST486_TASK_RETURN)))
722 {
723 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
724 return FALSE;
725 }
726
727 /* Read the new TSS */
728 if (!Fast486ReadLinearMemory(State,
729 NewTssAddress,
730 &NewTss,
731 (NewTssDescriptor.Signature == FAST486_TSS_SIGNATURE)
732 || (NewTssDescriptor.Signature == FAST486_BUSY_TSS_SIGNATURE)
733 ? sizeof(FAST486_TSS) : sizeof(FAST486_LEGACY_TSS),
734 FALSE))
735 {
736 /* Exception occurred */
737 return FALSE;
738 }
739
740 if (Type != FAST486_TASK_CALL)
741 {
742 /* Clear the busy bit of the outgoing task */
743 FAST486_SYSTEM_DESCRIPTOR OldTssDescriptor;
744
745 if (!Fast486ReadLinearMemory(State,
746 State->Gdtr.Address
747 + GET_SEGMENT_INDEX(State->TaskReg.Selector),
748 &OldTssDescriptor,
749 sizeof(OldTssDescriptor),
750 FALSE))
751 {
752 /* Exception occurred */
753 return FALSE;
754 }
755
756 OldTssDescriptor.Signature = FAST486_TSS_SIGNATURE;
757
758 if (!Fast486WriteLinearMemory(State,
759 State->Gdtr.Address
760 + GET_SEGMENT_INDEX(State->TaskReg.Selector),
761 &OldTssDescriptor,
762 sizeof(OldTssDescriptor),
763 FALSE))
764 {
765 /* Exception occurred */
766 return FALSE;
767 }
768 }
769 else
770 {
771 /* Store the link */
772 if ((NewTssDescriptor.Signature == FAST486_TSS_SIGNATURE)
773 || (NewTssDescriptor.Signature == FAST486_BUSY_TSS_SIGNATURE))
774 {
775 NewTss.Link = State->TaskReg.Selector;
776
777 /* Write back the new TSS link */
778 if (!Fast486WriteLinearMemory(State,
779 NewTssAddress,
780 &NewTss.Link,
781 sizeof(NewTss.Link),
782 FALSE))
783 {
784 /* Exception occurred */
785 return FALSE;
786 }
787 }
788 else
789 {
790 NewLegacyTss->Link = State->TaskReg.Selector;
791
792 /* Write back the new legacy TSS link */
793 if (!Fast486WriteLinearMemory(State,
794 NewTssAddress,
795 &NewLegacyTss->Link,
796 sizeof(NewLegacyTss->Link),
797 FALSE))
798 {
799 /* Exception occurred */
800 return FALSE;
801 }
802 }
803 }
804
805 /* Save the current task into the TSS */
806 if (State->TaskReg.Modern)
807 {
808 OldTss.Cr3 = State->ControlRegisters[FAST486_REG_CR3];
809 OldTss.Eip = State->InstPtr.Long;
810 OldTss.Eflags = State->Flags.Long;
811 OldTss.Eax = State->GeneralRegs[FAST486_REG_EAX].Long;
812 OldTss.Ecx = State->GeneralRegs[FAST486_REG_ECX].Long;
813 OldTss.Edx = State->GeneralRegs[FAST486_REG_EDX].Long;
814 OldTss.Ebx = State->GeneralRegs[FAST486_REG_EBX].Long;
815 OldTss.Esp = State->GeneralRegs[FAST486_REG_ESP].Long;
816 OldTss.Ebp = State->GeneralRegs[FAST486_REG_EBP].Long;
817 OldTss.Esi = State->GeneralRegs[FAST486_REG_ESI].Long;
818 OldTss.Edi = State->GeneralRegs[FAST486_REG_EDI].Long;
819 OldTss.Es = State->SegmentRegs[FAST486_REG_ES].Selector;
820 OldTss.Cs = State->SegmentRegs[FAST486_REG_CS].Selector;
821 OldTss.Ss = State->SegmentRegs[FAST486_REG_SS].Selector;
822 OldTss.Ds = State->SegmentRegs[FAST486_REG_DS].Selector;
823 OldTss.Fs = State->SegmentRegs[FAST486_REG_FS].Selector;
824 OldTss.Gs = State->SegmentRegs[FAST486_REG_GS].Selector;
825 OldTss.Ldtr = State->Ldtr.Selector;
826 }
827 else
828 {
829 OldLegacyTss->Ip = State->InstPtr.LowWord;
830 OldLegacyTss->Flags = State->Flags.LowWord;
831 OldLegacyTss->Ax = State->GeneralRegs[FAST486_REG_EAX].LowWord;
832 OldLegacyTss->Cx = State->GeneralRegs[FAST486_REG_ECX].LowWord;
833 OldLegacyTss->Dx = State->GeneralRegs[FAST486_REG_EDX].LowWord;
834 OldLegacyTss->Bx = State->GeneralRegs[FAST486_REG_EBX].LowWord;
835 OldLegacyTss->Sp = State->GeneralRegs[FAST486_REG_ESP].LowWord;
836 OldLegacyTss->Bp = State->GeneralRegs[FAST486_REG_EBP].LowWord;
837 OldLegacyTss->Si = State->GeneralRegs[FAST486_REG_ESI].LowWord;
838 OldLegacyTss->Di = State->GeneralRegs[FAST486_REG_EDI].LowWord;
839 OldLegacyTss->Es = State->SegmentRegs[FAST486_REG_ES].Selector;
840 OldLegacyTss->Cs = State->SegmentRegs[FAST486_REG_CS].Selector;
841 OldLegacyTss->Ss = State->SegmentRegs[FAST486_REG_SS].Selector;
842 OldLegacyTss->Ds = State->SegmentRegs[FAST486_REG_DS].Selector;
843 OldLegacyTss->Ldtr = State->Ldtr.Selector;
844 }
845
846 /* Write back the old TSS */
847 if (!Fast486WriteLinearMemory(State,
848 State->TaskReg.Base,
849 &OldTss,
850 State->TaskReg.Modern
851 ? sizeof(FAST486_TSS) : sizeof(FAST486_LEGACY_TSS),
852 FALSE))
853 {
854 /* Exception occurred */
855 return FALSE;
856 }
857
858 /* Mark the new task as busy */
859 if (NewTssDescriptor.Signature == FAST486_TSS_SIGNATURE
860 || NewTssDescriptor.Signature == FAST486_BUSY_TSS_SIGNATURE)
861 {
862 /* 32-bit TSS */
863 NewTssDescriptor.Signature = FAST486_BUSY_TSS_SIGNATURE;
864 }
865 else
866 {
867 /* 16-bit TSS */
868 NewTssDescriptor.Signature = FAST486_BUSY_TSS_16_SIGNATURE;
869 }
870
871 /* Write back the new TSS descriptor */
872 if (!Fast486WriteLinearMemory(State,
873 State->Gdtr.Address + GET_SEGMENT_INDEX(Selector),
874 &NewTssDescriptor,
875 sizeof(NewTssDescriptor),
876 FALSE))
877 {
878 /* Exception occurred */
879 return FALSE;
880 }
881
882 /* Set the task switch bit */
883 State->ControlRegisters[FAST486_REG_CR0] |= FAST486_CR0_TS;
884
885 /* Load the task register with the new values */
886 State->TaskReg.Selector = Selector;
887 State->TaskReg.Base = NewTssAddress;
888 State->TaskReg.Limit = NewTssLimit;
889 State->TaskReg.Modern = (NewTssDescriptor.Signature == FAST486_BUSY_TSS_SIGNATURE);
890
891 if (NewTssDescriptor.Signature == FAST486_BUSY_TSS_SIGNATURE)
892 {
893 /* Change the page directory */
894 State->ControlRegisters[FAST486_REG_CR3] = NewTss.Cr3;
895 }
896
897 /* Flush the TLB */
898 Fast486FlushTlb(State);
899
900 /* Update the CPL */
901 if (NewTssDescriptor.Signature == FAST486_BUSY_TSS_SIGNATURE)
902 {
903 State->Cpl = GET_SEGMENT_RPL(NewTss.Cs);
904 }
905 else
906 {
907 State->Cpl = GET_SEGMENT_RPL(NewLegacyTss->Cs);
908 }
909
910#ifndef FAST486_NO_PREFETCH
911 /* Context switching invalidates the prefetch */
912 State->PrefetchValid = FALSE;
913#endif
914
915 /* Load the registers */
916 if (NewTssDescriptor.Signature == FAST486_BUSY_TSS_SIGNATURE)
917 {
918 State->InstPtr.Long = State->SavedInstPtr.Long = NewTss.Eip;
919 State->Flags.Long = NewTss.Eflags;
920 State->GeneralRegs[FAST486_REG_EAX].Long = NewTss.Eax;
921 State->GeneralRegs[FAST486_REG_ECX].Long = NewTss.Ecx;
922 State->GeneralRegs[FAST486_REG_EDX].Long = NewTss.Edx;
923 State->GeneralRegs[FAST486_REG_EBX].Long = NewTss.Ebx;
924 State->GeneralRegs[FAST486_REG_EBP].Long = NewTss.Ebp;
925 State->GeneralRegs[FAST486_REG_ESI].Long = NewTss.Esi;
926 State->GeneralRegs[FAST486_REG_EDI].Long = NewTss.Edi;
927 NewEs = NewTss.Es;
928 NewCs = NewTss.Cs;
929 NewDs = NewTss.Ds;
930 NewLdtr = NewTss.Ldtr;
931
932 if (Type == FAST486_TASK_CALL && State->Cpl < 3)
933 {
934 switch (State->Cpl)
935 {
936 case 0:
937 {
938 State->GeneralRegs[FAST486_REG_ESP].Long = NewTss.Esp0;
939 NewSs = NewTss.Ss0;
940 break;
941 }
942
943 case 1:
944 {
945 State->GeneralRegs[FAST486_REG_ESP].Long = NewTss.Esp1;
946 NewSs = NewTss.Ss1;
947 break;
948 }
949
950 case 2:
951 {
952 State->GeneralRegs[FAST486_REG_ESP].Long = NewTss.Esp2;
953 NewSs = NewTss.Ss2;
954 break;
955 }
956 }
957 }
958 else
959 {
960 State->GeneralRegs[FAST486_REG_ESP].Long = NewTss.Esp;
961 NewSs = NewTss.Ss;
962 }
963 }
964 else
965 {
966 State->InstPtr.LowWord = State->SavedInstPtr.LowWord = NewLegacyTss->Ip;
967 State->Flags.LowWord = NewLegacyTss->Flags;
968 State->GeneralRegs[FAST486_REG_EAX].LowWord = NewLegacyTss->Ax;
969 State->GeneralRegs[FAST486_REG_ECX].LowWord = NewLegacyTss->Cx;
970 State->GeneralRegs[FAST486_REG_EDX].LowWord = NewLegacyTss->Dx;
971 State->GeneralRegs[FAST486_REG_EBX].LowWord = NewLegacyTss->Bx;
972 State->GeneralRegs[FAST486_REG_EBP].LowWord = NewLegacyTss->Bp;
973 State->GeneralRegs[FAST486_REG_ESI].LowWord = NewLegacyTss->Si;
974 State->GeneralRegs[FAST486_REG_EDI].LowWord = NewLegacyTss->Di;
975 NewEs = NewLegacyTss->Es;
976 NewCs = NewLegacyTss->Cs;
977 NewDs = NewLegacyTss->Ds;
978 NewLdtr = NewLegacyTss->Ldtr;
979
980 if (Type == FAST486_TASK_CALL && State->Cpl < 3)
981 {
982 switch (State->Cpl)
983 {
984 case 0:
985 {
986 State->GeneralRegs[FAST486_REG_ESP].Long = NewLegacyTss->Sp0;
987 NewSs = NewLegacyTss->Ss0;
988 break;
989 }
990
991 case 1:
992 {
993 State->GeneralRegs[FAST486_REG_ESP].Long = NewLegacyTss->Sp1;
994 NewSs = NewLegacyTss->Ss1;
995 break;
996 }
997
998 case 2:
999 {
1000 State->GeneralRegs[FAST486_REG_ESP].Long = NewLegacyTss->Sp2;
1001 NewSs = NewLegacyTss->Ss2;
1002 break;
1003 }
1004 }
1005 }
1006 else
1007 {
1008 State->GeneralRegs[FAST486_REG_ESP].Long = NewLegacyTss->Sp;
1009 NewSs = NewLegacyTss->Ss;
1010 }
1011 }
1012
1013 /* Set the NT flag if nesting */
1014 if (Type == FAST486_TASK_CALL) State->Flags.Nt = TRUE;
1015
1016 if (GET_SEGMENT_INDEX(NewLdtr) != 0)
1017 {
1018 BOOLEAN Valid;
1019 FAST486_SYSTEM_DESCRIPTOR GdtEntry;
1020
1021 if (NewLdtr & SEGMENT_TABLE_INDICATOR)
1022 {
1023 /* This selector doesn't point to the GDT */
1024 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_TS, NewLdtr);
1025 return FALSE;
1026 }
1027
1028 if (!Fast486ReadDescriptorEntry(State, NewLdtr, &Valid, (PFAST486_GDT_ENTRY)&GdtEntry))
1029 {
1030 /* Exception occurred */
1031 return FALSE;
1032 }
1033
1034 if (!Valid)
1035 {
1036 /* Invalid selector */
1037 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_TS, NewLdtr);
1038 return FALSE;
1039 }
1040
1041 if (GdtEntry.Signature != FAST486_LDT_SIGNATURE)
1042 {
1043 /* This is not an LDT descriptor */
1044 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_TS, NewLdtr);
1045 return FALSE;
1046 }
1047
1048 if (!GdtEntry.Present)
1049 {
1050 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_TS, NewLdtr);
1051 return FALSE;
1052 }
1053
1054 /* Update the LDTR */
1055 State->Ldtr.Selector = NewLdtr;
1056 State->Ldtr.Base = GdtEntry.Base | (GdtEntry.BaseMid << 16) | (GdtEntry.BaseHigh << 24);
1057 State->Ldtr.Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16);
1058
1059 if (GdtEntry.Granularity)
1060 {
1061 State->Ldtr.Limit <<= 12;
1062 State->Ldtr.Limit |= 0x00000FFF;
1063 }
1064 }
1065 else
1066 {
1067 /* The LDT of this task is empty */
1068 RtlZeroMemory(&State->Ldtr, sizeof(State->Ldtr));
1069 }
1070
1071 /* Load the new segments */
1072 if (!Fast486LoadSegmentInternal(State, FAST486_REG_CS, NewCs, FAST486_EXCEPTION_TS))
1073 {
1074 return FALSE;
1075 }
1076
1077 if (!Fast486LoadSegmentInternal(State, FAST486_REG_SS, NewSs, FAST486_EXCEPTION_TS))
1078 {
1079 return FALSE;
1080 }
1081
1082 if (!Fast486LoadSegmentInternal(State, FAST486_REG_ES, NewEs, FAST486_EXCEPTION_TS))
1083 {
1084 return FALSE;
1085 }
1086
1087 if (!Fast486LoadSegmentInternal(State, FAST486_REG_DS, NewDs, FAST486_EXCEPTION_TS))
1088 {
1089 return FALSE;
1090 }
1091
1092 if (NewTssDescriptor.Signature == FAST486_BUSY_TSS_SIGNATURE)
1093 {
1094 if (!Fast486LoadSegmentInternal(State,
1095 FAST486_REG_FS,
1096 NewTss.Fs,
1097 FAST486_EXCEPTION_TS))
1098 {
1099 return FALSE;
1100 }
1101
1102 if (!Fast486LoadSegmentInternal(State,
1103 FAST486_REG_GS,
1104 NewTss.Gs,
1105 FAST486_EXCEPTION_TS))
1106 {
1107 return FALSE;
1108 }
1109 }
1110
1111 return TRUE;
1112}
Type
Definition: Type.h:7
#define FAST486_BUSY_TSS_16_SIGNATURE
Definition: fast486.h:87
#define FAST486_TSS_SIGNATURE
Definition: fast486.h:92
#define FAST486_TSS_16_SIGNATURE
Definition: fast486.h:85
#define FAST486_LDT_SIGNATURE
Definition: fast486.h:86
#define FAST486_BUSY_TSS_SIGNATURE
Definition: fast486.h:93
#define FAST486_CR0_TS
Definition: fast486.h:49
#define GET_SEGMENT_INDEX(s)
Definition: common.h:39
@ FAST486_TASK_RETURN
Definition: common.h:89
#define SEGMENT_TABLE_INDICATOR
Definition: common.h:40
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262

Referenced by FAST486_OPCODE_HANDLER(), and Fast486InterruptInternal().

◆ Fast486WriteMemory()

BOOLEAN FASTCALL Fast486WriteMemory ( PFAST486_STATE  State,
FAST486_SEG_REGS  SegmentReg,
ULONG  Offset,
PVOID  Buffer,
ULONG  Size 
)

Definition at line 163 of file common.c.

168{
169 ULONG LinearAddress;
170 PFAST486_SEG_REG CachedDescriptor;
171 FAST486_EXCEPTIONS Exception = SegmentReg != FAST486_REG_SS
172 ? FAST486_EXCEPTION_GP : FAST486_EXCEPTION_SS;
173
174 ASSERT(SegmentReg < FAST486_NUM_SEG_REGS);
175
176 /* Get the cached descriptor */
177 CachedDescriptor = &State->SegmentRegs[SegmentReg];
178
179 if (CachedDescriptor->Executable || !CachedDescriptor->DirConf)
180 {
181 if ((Offset + Size - 1) > CachedDescriptor->Limit)
182 {
183 /* Write beyond limit */
184 Fast486Exception(State, Exception);
185 return FALSE;
186 }
187 }
188 else
189 {
190 if (Offset < CachedDescriptor->Limit)
191 {
192 /* Write beyond limit */
193 Fast486Exception(State, Exception);
194 return FALSE;
195 }
196 }
197
198 /* Check for protected mode */
199 if ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) && !State->Flags.Vm)
200 {
201 /* Privilege checks */
202
203 if (!CachedDescriptor->Present)
204 {
205 Fast486Exception(State, Exception);
206 return FALSE;
207 }
208
209 if ((CachedDescriptor->Rpl > CachedDescriptor->Dpl)
210 || (Fast486GetCurrentPrivLevel(State) > CachedDescriptor->Dpl))
211 {
212 Fast486Exception(State, Exception);
213 return FALSE;
214 }
215
216 if (CachedDescriptor->Executable)
217 {
218 /* Code segment not writable */
219 Fast486Exception(State, Exception);
220 return FALSE;
221 }
222 else if (!CachedDescriptor->ReadWrite)
223 {
224 /* Data segment not writeable */
225 Fast486Exception(State, Exception);
226 return FALSE;
227 }
228 }
229
230 /* Find the linear address */
231 LinearAddress = CachedDescriptor->Base + Offset;
232
233#ifndef FAST486_NO_PREFETCH
234 if (State->PrefetchValid
235 && (LinearAddress >= State->PrefetchAddress)
236 && ((LinearAddress + Size) <= (State->PrefetchAddress + FAST486_CACHE_SIZE)))
237 {
238 /* Update the prefetch */
239 RtlMoveMemory(&State->PrefetchCache[LinearAddress - State->PrefetchAddress],
240 Buffer,
241 min(Size, FAST486_CACHE_SIZE + State->PrefetchAddress - LinearAddress));
242 }
243#endif
244
245 /* Write to the linear address */
246 return Fast486WriteLinearMemory(State, LinearAddress, Buffer, Size, TRUE);
247}
#define min(a, b)
Definition: monoChain.cc:55

Referenced by FAST486_OPCODE_HANDLER(), and Fast486FpuSaveEnvironment().