/* INCLUDES *******************************************************************/
-// #define WIN32_NO_STATUS
-// #define _INC_WINDOWS
#include <windef.h>
// #define NDEBUG
#include <fast486.h>
#include "common.h"
-/* PRIVATE FUNCTIONS **********************************************************/
-
-static inline
-ULONG
-Fast486GetPageTableEntry(PFAST486_STATE State,
- ULONG VirtualAddress)
-{
- // TODO: NOT IMPLEMENTED
- UNIMPLEMENTED;
-
- return 0;
-}
-
/* PUBLIC FUNCTIONS ***********************************************************/
BOOLEAN
{
ULONG LinearAddress;
PFAST486_SEG_REG CachedDescriptor;
- INT Cpl = Fast486GetCurrentPrivLevel(State);
ASSERT(SegmentReg < FAST486_NUM_SEG_REGS);
{
/* Read beyond limit */
Fast486Exception(State, FAST486_EXCEPTION_GP);
-
return FALSE;
}
return FALSE;
}
- if (GET_SEGMENT_RPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl)
+ if ((!InstFetch && (GET_SEGMENT_RPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl))
+ || (Fast486GetCurrentPrivLevel(State) > CachedDescriptor->Dpl))
{
Fast486Exception(State, FAST486_EXCEPTION_GP);
return FALSE;
if (!CachedDescriptor->Executable)
{
/* Data segment not executable */
-
Fast486Exception(State, FAST486_EXCEPTION_GP);
return FALSE;
}
if (CachedDescriptor->Executable && (!CachedDescriptor->ReadWrite))
{
/* Code segment not readable */
-
Fast486Exception(State, FAST486_EXCEPTION_GP);
return FALSE;
}
/* Find the linear address */
LinearAddress = CachedDescriptor->Base + Offset;
- /* Check if paging is enabled */
- if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PG)
- {
- ULONG Page;
- FAST486_PAGE_TABLE TableEntry;
-
- for (Page = PAGE_ALIGN(LinearAddress);
- Page <= PAGE_ALIGN(LinearAddress + Size - 1);
- Page += PAGE_SIZE)
- {
- ULONG PageOffset = 0, PageLength = PAGE_SIZE;
-
- /* Get the table entry */
- TableEntry.Value = Fast486GetPageTableEntry(State, Page);
-
- if (!TableEntry.Present || (!TableEntry.Usermode && (Cpl > 0)))
- {
- /* Exception */
- Fast486ExceptionWithErrorCode(State,
- FAST486_EXCEPTION_PF,
- TableEntry.Value & 0x07);
- return FALSE;
- }
-
- /* Check if this is the first page */
- if (Page == PAGE_ALIGN(LinearAddress))
- {
- /* Start copying from the offset from the beginning of the page */
- PageOffset = PAGE_OFFSET(LinearAddress);
- }
-
- /* Check if this is the last page */
- if (Page == PAGE_ALIGN(LinearAddress + Size - 1))
- {
- /* Copy only a part of the page */
- PageLength = PAGE_OFFSET(LinearAddress + Size);
- }
-
- /* Did the host provide a memory hook? */
- if (State->MemReadCallback)
- {
- /* Yes, call the host */
- State->MemReadCallback(State,
- (TableEntry.Address << 12) | PageOffset,
- Buffer,
- PageLength);
- }
- else
- {
- /* Read the memory directly */
- RtlMoveMemory(Buffer,
- (PVOID)((TableEntry.Address << 12) | PageOffset),
- PageLength);
- }
- }
- }
- else
- {
- /* Did the host provide a memory hook? */
- if (State->MemReadCallback)
- {
- /* Yes, call the host */
- State->MemReadCallback(State, LinearAddress, Buffer, Size);
- }
- else
- {
- /* Read the memory directly */
- RtlMoveMemory(Buffer, (PVOID)LinearAddress, Size);
- }
- }
-
- return TRUE;
+ /* Read from the linear address */
+ return Fast486ReadLinearMemory(State, LinearAddress, Buffer, Size);
}
BOOLEAN
{
ULONG LinearAddress;
PFAST486_SEG_REG CachedDescriptor;
- INT Cpl = Fast486GetCurrentPrivLevel(State);
ASSERT(SegmentReg < FAST486_NUM_SEG_REGS);
{
/* Write beyond limit */
Fast486Exception(State, FAST486_EXCEPTION_GP);
-
return FALSE;
}
return FALSE;
}
- if (GET_SEGMENT_RPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl)
+ if ((GET_SEGMENT_RPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl)
+ || (Fast486GetCurrentPrivLevel(State) > CachedDescriptor->Dpl))
{
Fast486Exception(State, FAST486_EXCEPTION_GP);
return FALSE;
if (CachedDescriptor->Executable)
{
/* Code segment not writable */
-
Fast486Exception(State, FAST486_EXCEPTION_GP);
return FALSE;
}
else if (!CachedDescriptor->ReadWrite)
{
/* Data segment not writeable */
-
Fast486Exception(State, FAST486_EXCEPTION_GP);
return FALSE;
}
/* Find the linear address */
LinearAddress = CachedDescriptor->Base + Offset;
- /* Check if paging is enabled */
- if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PG)
- {
- ULONG Page;
- FAST486_PAGE_TABLE TableEntry;
-
- for (Page = PAGE_ALIGN(LinearAddress);
- Page <= PAGE_ALIGN(LinearAddress + Size - 1);
- Page += PAGE_SIZE)
- {
- ULONG PageOffset = 0, PageLength = PAGE_SIZE;
-
- /* Get the table entry */
- TableEntry.Value = Fast486GetPageTableEntry(State, Page);
-
- if ((!TableEntry.Present || (!TableEntry.Usermode && (Cpl > 0)))
- || ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_WP)
- && !TableEntry.Writeable))
- {
- /* Exception */
- Fast486ExceptionWithErrorCode(State,
- FAST486_EXCEPTION_PF,
- TableEntry.Value & 0x07);
- return FALSE;
- }
-
- /* Check if this is the first page */
- if (Page == PAGE_ALIGN(LinearAddress))
- {
- /* Start copying from the offset from the beginning of the page */
- PageOffset = PAGE_OFFSET(LinearAddress);
- }
-
- /* Check if this is the last page */
- if (Page == PAGE_ALIGN(LinearAddress + Size - 1))
- {
- /* Copy only a part of the page */
- PageLength = PAGE_OFFSET(LinearAddress + Size);
- }
-
- /* Did the host provide a memory hook? */
- if (State->MemWriteCallback)
- {
- /* Yes, call the host */
- State->MemWriteCallback(State,
- (TableEntry.Address << 12) | PageOffset,
- Buffer,
- PageLength);
- }
- else
- {
- /* Read the memory directly */
- RtlMoveMemory((PVOID)((TableEntry.Address << 12) | PageOffset),
- Buffer,
- PageLength);
- }
- }
- }
- else
- {
- /* Did the host provide a memory hook? */
- if (State->MemWriteCallback)
- {
- /* Yes, call the host */
- State->MemWriteCallback(State, LinearAddress, Buffer, Size);
- }
- else
- {
- /* Write the memory directly */
- RtlMoveMemory((PVOID)LinearAddress, Buffer, Size);
- }
- }
-
- return TRUE;
+ /* Write to the linear address */
+ return Fast486WriteLinearMemory(State, LinearAddress, Buffer, Size);
}
BOOLEAN
if (Fast486GetCurrentPrivLevel(State) > GET_SEGMENT_RPL(SegmentSelector))
{
/* Read the TSS */
- // FIXME: This code is only correct when paging is disabled!!!
- if (State->MemReadCallback)
- {
- State->MemReadCallback(State,
- State->Tss.Address,
- &Tss,
- sizeof(Tss));
- }
- else
+ if (!Fast486ReadLinearMemory(State,
+ State->TaskReg.Base,
+ &Tss,
+ sizeof(Tss)))
{
- RtlMoveMemory(&Tss, (PVOID)State->Tss.Address, sizeof(Tss));
+ /* Exception occurred */
+ return FALSE;
}
/* Check the new (higher) privilege level */
if (!Fast486StackPush(State, OldEsp)) return FALSE;
}
}
+ else
+ {
+ if (State->SegmentRegs[FAST486_REG_CS].Size)
+ {
+ /* Set OPSIZE, because INT always pushes 16-bit values in real mode */
+ State->PrefixFlags |= FAST486_PREFIX_OPSIZE;
+ }
+ }
/* Push EFLAGS */
if (!Fast486StackPush(State, State->Flags.Long)) return FALSE;
&& (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE))
{
/* Push the error code */
- Fast486StackPush(State, ErrorCode);
+ if (!Fast486StackPush(State, ErrorCode))
+ {
+ /*
+ * If this function failed, that means Fast486Exception
+ * was called again, so just return in this case.
+ */
+ return;
+ }
}
+
+ /* Reset the exception count */
+ State->ExceptionCount = 0;
}
/* EOF */