Author: aandrejevic
Date: Sun Nov 10 22:27:24 2013
New Revision: 60923
URL:
http://svn.reactos.org/svn/reactos?rev=60923&view=rev
Log:
[FAST486]
Modularize linear memory access by adding two new functions:
Fast486ReadLinearMemory and Fast486WriteLinearMemory.
Implement Fast486GetPageTableEntry.
Modified:
branches/ntvdm/include/reactos/libs/fast486/fast486.h
branches/ntvdm/lib/fast486/common.c
branches/ntvdm/lib/fast486/common.h
branches/ntvdm/lib/fast486/common.inl
branches/ntvdm/lib/fast486/fast486.c
branches/ntvdm/subsystems/ntvdm/emulator.c
Modified: branches/ntvdm/include/reactos/libs/fast486/fast486.h
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/include/reactos/libs/fast…
==============================================================================
--- branches/ntvdm/include/reactos/libs/fast486/fast486.h [iso-8859-1] (original)
+++ branches/ntvdm/include/reactos/libs/fast486/fast486.h [iso-8859-1] Sun Nov 10 22:27:24
2013
@@ -401,6 +401,7 @@
FAST486_SEG_REGS SegmentOverride;
FAST486_INT_STATUS IntStatus;
UCHAR PendingIntNum;
+ PULONG Tlb;
};
/* FUNCTIONS ******************************************************************/
@@ -414,7 +415,8 @@
FAST486_IO_WRITE_PROC IoWriteCallback,
FAST486_IDLE_PROC IdleCallback,
FAST486_BOP_PROC BopCallback,
- FAST486_INT_ACK_PROC IntAckCallback);
+ FAST486_INT_ACK_PROC IntAckCallback,
+ PULONG Tlb);
VOID
NTAPI
Modified: branches/ntvdm/lib/fast486/common.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/lib/fast486/common.c?rev=…
==============================================================================
--- branches/ntvdm/lib/fast486/common.c [iso-8859-1] (original)
+++ branches/ntvdm/lib/fast486/common.c [iso-8859-1] Sun Nov 10 22:27:24 2013
@@ -29,19 +29,6 @@
#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
@@ -54,7 +41,6 @@
{
ULONG LinearAddress;
PFAST486_SEG_REG CachedDescriptor;
- INT Cpl = Fast486GetCurrentPrivLevel(State);
ASSERT(SegmentReg < FAST486_NUM_SEG_REGS);
@@ -108,58 +94,8 @@
/* 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);
- }
-
- /* Read the memory */
- State->MemReadCallback(State,
- (TableEntry.Address << 12) | PageOffset,
- Buffer,
- PageLength);
- }
- }
- else
- {
- /* Read the memory */
- State->MemReadCallback(State, LinearAddress, Buffer, Size);
- }
-
- return TRUE;
+ /* Read from the linear address */
+ return Fast486ReadLinearMemory(State, LinearAddress, Buffer, Size);
}
BOOLEAN
@@ -171,7 +107,6 @@
{
ULONG LinearAddress;
PFAST486_SEG_REG CachedDescriptor;
- INT Cpl = Fast486GetCurrentPrivLevel(State);
ASSERT(SegmentReg < FAST486_NUM_SEG_REGS);
@@ -220,60 +155,8 @@
/* 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);
- }
-
- /* Write the memory */
- State->MemWriteCallback(State,
- (TableEntry.Address << 12) | PageOffset,
- Buffer,
- PageLength);
- }
- }
- else
- {
- /* Write the memory */
- State->MemWriteCallback(State, LinearAddress, Buffer, Size);
- }
-
- return TRUE;
+ /* Write to the linear address */
+ return Fast486WriteLinearMemory(State, LinearAddress, Buffer, Size);
}
BOOLEAN
@@ -293,11 +176,14 @@
if (Fast486GetCurrentPrivLevel(State) > GET_SEGMENT_RPL(SegmentSelector))
{
/* Read the TSS */
- // FIXME: This code is only correct when paging is disabled!!!
- State->MemReadCallback(State,
- State->Tss.Address,
- &Tss,
- sizeof(Tss));
+ if (!Fast486ReadLinearMemory(State,
+ State->Tss.Address,
+ &Tss,
+ sizeof(Tss)))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
/* Check the new (higher) privilege level */
switch (GET_SEGMENT_RPL(SegmentSelector))
Modified: branches/ntvdm/lib/fast486/common.h
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/lib/fast486/common.h?rev=…
==============================================================================
--- branches/ntvdm/lib/fast486/common.h [iso-8859-1] (original)
+++ branches/ntvdm/lib/fast486/common.h [iso-8859-1] Sun Nov 10 22:27:24 2013
@@ -56,6 +56,9 @@
#define PAGE_ALIGN(x) ((x) & 0xFFFFF000)
#define PAGE_OFFSET(x) ((x) & 0x00000FFF)
+#define GET_ADDR_PDE(x) ((x) >> 22)
+#define GET_ADDR_PTE(x) (((x) >> 12) & 0x3FF)
+#define INVALID_TLB_FIELD 0xFFFFFFFF
#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
@@ -92,6 +95,8 @@
ULONG Value;
} FAST486_PAGE_DIR, *PFAST486_PAGE_DIR;
+C_ASSERT(sizeof(FAST486_PAGE_DIR) == sizeof(ULONG));
+
typedef union _FAST486_PAGE_TABLE
{
struct
@@ -110,6 +115,8 @@
};
ULONG Value;
} FAST486_PAGE_TABLE, *PFAST486_PAGE_TABLE;
+
+C_ASSERT(sizeof(FAST486_PAGE_DIR) == sizeof(ULONG));
#pragma pack(pop)
Modified: branches/ntvdm/lib/fast486/common.inl
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/lib/fast486/common.inl?re…
==============================================================================
--- branches/ntvdm/lib/fast486/common.inl [iso-8859-1] (original)
+++ branches/ntvdm/lib/fast486/common.inl [iso-8859-1] Sun Nov 10 22:27:24 2013
@@ -19,7 +19,221 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#include "common.h"
+
/* PUBLIC FUNCTIONS ***********************************************************/
+
+FORCEINLINE
+ULONG
+Fast486GetPageTableEntry(PFAST486_STATE State,
+ ULONG VirtualAddress,
+ BOOLEAN MarkAsDirty)
+{
+ ULONG PdeIndex = GET_ADDR_PDE(VirtualAddress);
+ ULONG PteIndex = GET_ADDR_PTE(VirtualAddress);
+ FAST486_PAGE_DIR DirectoryEntry;
+ FAST486_PAGE_TABLE TableEntry;
+ ULONG PageDirectory = State->ControlRegisters[FAST486_REG_CR3];
+
+ if ((State->Tlb != NULL)
+ && (State->Tlb[VirtualAddress >> 12] != INVALID_TLB_FIELD))
+ {
+ /* Return the cached entry */
+ return State->Tlb[VirtualAddress >> 12];
+ }
+
+ /* Read the directory entry */
+ State->MemReadCallback(State,
+ PageDirectory + PdeIndex * sizeof(ULONG),
+ &DirectoryEntry.Value,
+ sizeof(DirectoryEntry));
+
+ /* Make sure it is present */
+ if (!DirectoryEntry.Present) return 0;
+
+ /* Was the directory entry accessed before? */
+ if (!DirectoryEntry.Accessed)
+ {
+ /* Well, it is now */
+ DirectoryEntry.Accessed = TRUE;
+
+ /* Write back the directory entry */
+ State->MemWriteCallback(State,
+ PageDirectory + PdeIndex * sizeof(ULONG),
+ &DirectoryEntry.Value,
+ sizeof(DirectoryEntry));
+ }
+
+ /* Read the table entry */
+ State->MemReadCallback(State,
+ (DirectoryEntry.TableAddress << 12)
+ + PteIndex * sizeof(ULONG),
+ &TableEntry.Value,
+ sizeof(TableEntry));
+
+ /* Make sure it is present */
+ if (!TableEntry.Present) return 0;
+
+ if (MarkAsDirty) TableEntry.Dirty = TRUE;
+
+ /* Was the table entry accessed before? */
+ if (!TableEntry.Accessed)
+ {
+ /* Well, it is now */
+ TableEntry.Accessed = TRUE;
+
+ /* Write back the table entry */
+ State->MemWriteCallback(State,
+ (DirectoryEntry.TableAddress << 12)
+ + PteIndex * sizeof(ULONG),
+ &TableEntry.Value,
+ sizeof(TableEntry));
+ }
+
+ /*
+ * The resulting permissions depend on the permissions
+ * in the page directory table too
+ */
+ TableEntry.Writeable &= DirectoryEntry.Writeable;
+ TableEntry.Usermode &= DirectoryEntry.Usermode;
+
+ if (State->Tlb != NULL)
+ {
+ /* Set the TLB entry */
+ State->Tlb[VirtualAddress >> 12] = TableEntry.Value;
+ }
+
+ /* Return the table entry */
+ return TableEntry.Value;
+}
+
+FORCEINLINE
+BOOLEAN
+Fast486ReadLinearMemory(PFAST486_STATE State,
+ ULONG LinearAddress,
+ PVOID Buffer,
+ ULONG Size)
+{
+ INT Cpl = Fast486GetCurrentPrivLevel(State);
+
+ /* 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, FALSE);
+
+ 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);
+ }
+
+ /* Read the memory */
+ State->MemReadCallback(State,
+ (TableEntry.Address << 12) | PageOffset,
+ Buffer,
+ PageLength);
+ }
+ }
+ else
+ {
+ /* Read the memory */
+ State->MemReadCallback(State, LinearAddress, Buffer, Size);
+ }
+
+ return TRUE;
+}
+
+FORCEINLINE
+BOOLEAN
+Fast486WriteLinearMemory(PFAST486_STATE State,
+ ULONG LinearAddress,
+ PVOID Buffer,
+ ULONG Size)
+{
+ INT Cpl = Fast486GetCurrentPrivLevel(State);
+
+ /* 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, TRUE);
+
+ 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);
+ }
+
+ /* Write the memory */
+ State->MemWriteCallback(State,
+ (TableEntry.Address << 12) | PageOffset,
+ Buffer,
+ PageLength);
+ }
+ }
+ else
+ {
+ /* Write the memory */
+ State->MemWriteCallback(State, LinearAddress, Buffer, Size);
+ }
+
+ return TRUE;
+}
FORCEINLINE
VOID
@@ -185,12 +399,15 @@
}
/* Read the GDT */
- // FIXME: This code is only correct when paging is disabled!!!
- State->MemReadCallback(State,
- State->Gdtr.Address
- + GET_SEGMENT_INDEX(Selector),
- &GdtEntry,
- sizeof(GdtEntry));
+ if (!Fast486ReadLinearMemory(State,
+ State->Gdtr.Address
+ + GET_SEGMENT_INDEX(Selector),
+ &GdtEntry,
+ sizeof(GdtEntry)))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
if (Segment == FAST486_REG_SS)
{
@@ -388,12 +605,15 @@
if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
{
/* Read from the IDT */
- // FIXME: This code is only correct when paging is disabled!!!
- State->MemReadCallback(State,
- State->Idtr.Address
- + Number * sizeof(*IdtEntry),
- IdtEntry,
- sizeof(*IdtEntry));
+ if (!Fast486ReadLinearMemory(State,
+ State->Idtr.Address
+ + Number * sizeof(*IdtEntry),
+ IdtEntry,
+ sizeof(*IdtEntry)))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
}
else
{
@@ -417,10 +637,6 @@
IdtEntry->OffsetHigh = 0;
}
- /*
- * Once paging support is implemented this function
- * will not always return true
- */
return TRUE;
}
Modified: branches/ntvdm/lib/fast486/fast486.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/lib/fast486/fast486.c?rev…
==============================================================================
--- branches/ntvdm/lib/fast486/fast486.c [iso-8859-1] (original)
+++ branches/ntvdm/lib/fast486/fast486.c [iso-8859-1] Sun Nov 10 22:27:24 2013
@@ -203,7 +203,8 @@
FAST486_IO_WRITE_PROC IoWriteCallback,
FAST486_IDLE_PROC IdleCallback,
FAST486_BOP_PROC BopCallback,
- FAST486_INT_ACK_PROC IntAckCallback)
+ FAST486_INT_ACK_PROC IntAckCallback,
+ PULONG Tlb)
{
/* Set the callbacks (or use default ones if some are NULL) */
State->MemReadCallback = (MemReadCallback ? MemReadCallback :
Fast486MemReadCallback );
@@ -214,6 +215,9 @@
State->BopCallback = (BopCallback ? BopCallback :
Fast486BopCallback );
State->IntAckCallback = (IntAckCallback ? IntAckCallback :
Fast486IntAckCallback );
+ /* Set the TLB (if given) */
+ State->Tlb = Tlb;
+
/* Reset the CPU */
Fast486Reset(State);
}
@@ -231,6 +235,7 @@
FAST486_IDLE_PROC IdleCallback = State->IdleCallback;
FAST486_BOP_PROC BopCallback = State->BopCallback;
FAST486_INT_ACK_PROC IntAckCallback = State->IntAckCallback;
+ PULONG Tlb = State->Tlb;
/* Clear the entire structure */
RtlZeroMemory(State, sizeof(*State));
@@ -266,7 +271,7 @@
/* Initialize CR0 */
State->ControlRegisters[FAST486_REG_CR0] |= FAST486_CR0_ET;
- /* Restore the callbacks */
+ /* Restore the callbacks and TLB */
State->MemReadCallback = MemReadCallback;
State->MemWriteCallback = MemWriteCallback;
State->IoReadCallback = IoReadCallback;
@@ -274,6 +279,7 @@
State->IdleCallback = IdleCallback;
State->BopCallback = BopCallback;
State->IntAckCallback = IntAckCallback;
+ State->Tlb = Tlb;
}
VOID
Modified: branches/ntvdm/subsystems/ntvdm/emulator.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/emulator…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/emulator.c [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/emulator.c [iso-8859-1] Sun Nov 10 22:27:24 2013
@@ -296,7 +296,8 @@
EmulatorWriteIo,
NULL,
EmulatorBiosOperation,
- EmulatorIntAcknowledge);
+ EmulatorIntAcknowledge,
+ NULL /* TODO: Use a TLB */);
/* Enable interrupts */
EmulatorSetFlag(EMULATOR_FLAG_IF);