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/fast4... ============================================================================== --- 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=6... ============================================================================== --- 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=6... ============================================================================== --- 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?rev... ============================================================================== --- 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);