Author: aandrejevic
Date: Fri Sep 13 23:01:18 2013
New Revision: 60089
URL:
http://svn.reactos.org/svn/reactos?rev=60089&view=rev
Log:
[SOFT386]
Start implementing paging support.
Add support for exception error codes.
Modified:
branches/ntvdm/lib/soft386/common.c
branches/ntvdm/lib/soft386/common.h
Modified: branches/ntvdm/lib/soft386/common.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/lib/soft386/common.c?rev=…
==============================================================================
--- branches/ntvdm/lib/soft386/common.c [iso-8859-1] (original)
+++ branches/ntvdm/lib/soft386/common.c [iso-8859-1] Fri Sep 13 23:01:18 2013
@@ -28,6 +28,18 @@
return GET_SEGMENT_RPL(State->SegmentRegs[SOFT386_REG_CS].Selector);
}
+static
+inline
+ULONG
+Soft386GetPageTableEntry(PSOFT386_STATE State,
+ ULONG VirtualAddress)
+{
+ // TODO: NOT IMPLEMENTED
+ UNIMPLEMENTED;
+
+ return 0;
+}
+
/* PUBLIC FUNCTIONS ***********************************************************/
inline
@@ -41,6 +53,7 @@
{
ULONG LinearAddress;
PSOFT386_SEG_REG CachedDescriptor;
+ INT Cpl = Soft386GetCurrentPrivLevel(State);
ASSERT(SegmentReg < SOFT386_NUM_SEG_REGS);
@@ -97,18 +110,75 @@
/* Find the linear address */
LinearAddress = CachedDescriptor->Base + Offset;
- // TODO: Paging support!
-
- /* Did the host provide a memory hook? */
- if (State->MemReadCallback)
- {
- /* Yes, call the host */
- State->MemReadCallback(State, LinearAddress, Buffer, Size);
+ /* Check if paging is enabled */
+ if (State->ControlRegisters[SOFT386_REG_CR0] & SOFT386_CR0_PG)
+ {
+ ULONG Page;
+ SOFT386_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 = Soft386GetPageTableEntry(State, Page);
+
+ if (!TableEntry.Present || (!TableEntry.Usermode && (Cpl > 0)))
+ {
+ /* Exception */
+ Soft386ExceptionWithErrorCode(State,
+ SOFT386_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
{
- /* Read the memory directly */
- RtlMoveMemory(Buffer, (PVOID)LinearAddress, Size);
+ /* 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;
@@ -124,6 +194,7 @@
{
ULONG LinearAddress;
PSOFT386_SEG_REG CachedDescriptor;
+ INT Cpl = Soft386GetCurrentPrivLevel(State);
ASSERT(SegmentReg < SOFT386_NUM_SEG_REGS);
@@ -174,18 +245,77 @@
/* Find the linear address */
LinearAddress = CachedDescriptor->Base + Offset;
- // TODO: Paging support!
-
- /* Did the host provide a memory hook? */
- if (State->MemWriteCallback)
- {
- /* Yes, call the host */
- State->MemWriteCallback(State, LinearAddress, Buffer, Size);
+ /* Check if paging is enabled */
+ if (State->ControlRegisters[SOFT386_REG_CR0] & SOFT386_CR0_PG)
+ {
+ ULONG Page;
+ SOFT386_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 = Soft386GetPageTableEntry(State, Page);
+
+ if ((!TableEntry.Present || (!TableEntry.Usermode && (Cpl > 0)))
+ || ((State->ControlRegisters[SOFT386_REG_CR0] & SOFT386_CR0_WP)
+ && !TableEntry.Writeable))
+ {
+ /* Exception */
+ Soft386ExceptionWithErrorCode(State,
+ SOFT386_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
{
- /* Write the memory directly */
- RtlMoveMemory((PVOID)LinearAddress, Buffer, Size);
+ /* 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;
@@ -709,7 +839,7 @@
VOID
FASTCALL
-Soft386Exception(PSOFT386_STATE State, INT ExceptionCode)
+Soft386ExceptionWithErrorCode(PSOFT386_STATE State, INT ExceptionCode, ULONG ErrorCode)
{
SOFT386_IDT_ENTRY IdtEntry;
@@ -752,6 +882,20 @@
*/
return;
}
+
+ if (EXCEPTION_HAS_ERROR_CODE(ExceptionCode))
+ {
+ /* Push the error code */
+ Soft386StackPush(State, ErrorCode);
+ }
+}
+
+inline
+VOID
+Soft386Exception(PSOFT386_STATE State, INT ExceptionCode)
+{
+ /* Call the internal function */
+ Soft386ExceptionWithErrorCode(State, ExceptionCode, 0);
}
inline
Modified: branches/ntvdm/lib/soft386/common.h
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/lib/soft386/common.h?rev=…
==============================================================================
--- branches/ntvdm/lib/soft386/common.h [iso-8859-1] (original)
+++ branches/ntvdm/lib/soft386/common.h [iso-8859-1] Fri Sep 13 23:01:18 2013
@@ -20,6 +20,13 @@
#define SIGN_FLAG_LONG 0x80000000
#define GET_SEGMENT_RPL(s) ((s) & 3)
#define GET_SEGMENT_INDEX(s) ((s) & 0xFFF8)
+#define EXCEPTION_HAS_ERROR_CODE(x) (((x) == 8) || ((x) >= 10 && (x) <=
14))
+#define PAGE_ALIGN(x) ((x) & 0xFFFFF000)
+#define PAGE_OFFSET(x) ((x) & 0x00000FFF)
+
+#ifndef PAGE_SIZE
+#define PAGE_SIZE 4096
+#endif
typedef struct _SOFT386_MOD_REG_RM
{
@@ -32,6 +39,47 @@
};
} SOFT386_MOD_REG_RM, *PSOFT386_MOD_REG_RM;
+#pragma pack(push, 1)
+
+typedef struct _SOFT386_PAGE_DIR
+{
+ union
+ {
+ ULONG Present : 1;
+ ULONG Writeable : 1;
+ ULONG Usermode : 1;
+ ULONG WriteThrough : 1;
+ ULONG NoCache : 1;
+ ULONG Accessed : 1;
+ ULONG AlwaysZero : 1;
+ ULONG Size : 1;
+ ULONG Unused : 4;
+ ULONG TableAddress : 20;
+ };
+ ULONG Value;
+} SOFT386_PAGE_DIR, *PSOFT386_PAGE_DIR;
+
+typedef struct _SOFT386_PAGE_TABLE
+{
+ union
+ {
+ ULONG Present : 1;
+ ULONG Writeable : 1;
+ ULONG Usermode : 1;
+ ULONG WriteThrough : 1;
+ ULONG NoCache : 1;
+ ULONG Accessed : 1;
+ ULONG Dirty : 1;
+ ULONG AlwaysZero : 1;
+ ULONG Global : 1;
+ ULONG Unused : 3;
+ ULONG Address : 20;
+ };
+ ULONG Value;
+} SOFT386_PAGE_TABLE, *PSOFT386_PAGE_TABLE;
+
+#pragma pack(pop)
+
/* FUNCTIONS ******************************************************************/
inline
@@ -126,7 +174,16 @@
);
VOID
-__fastcall
+FASTCALL
+Soft386ExceptionWithErrorCode
+(
+ PSOFT386_STATE State,
+ INT ExceptionCode,
+ ULONG ErrorCode
+);
+
+inline
+VOID
Soft386Exception
(
PSOFT386_STATE State,