Author: aandrejevic Date: Fri Mar 13 17:57:51 2015 New Revision: 66666
URL: http://svn.reactos.org/svn/reactos?rev=66666&view=rev Log: [NTVDM][FAST486] - Implement VDDInstallMemoryHook and VDDDeInstallMemoryHook using page guards. - Implement another API for memory hooks that should be faster than page guards (for NTVDM only). - Adjust the VGA and EMS memory handlers to use this method. - In Fast486, implement a method that will allow us to "rewind" the current instruction, in case it was interrupted by a memory hook page fault. - Use a memory hook to protect the BIOS ROM from being written to.
Added: trunk/reactos/subsystems/mvdm/ntvdm/memory.c (with props) trunk/reactos/subsystems/mvdm/ntvdm/memory.h (with props) Modified: trunk/reactos/include/reactos/libs/fast486/fast486.h trunk/reactos/lib/fast486/fast486.c trunk/reactos/subsystems/mvdm/ntvdm/CMakeLists.txt trunk/reactos/subsystems/mvdm/ntvdm/bios/bios.c trunk/reactos/subsystems/mvdm/ntvdm/cpu/cpu.c trunk/reactos/subsystems/mvdm/ntvdm/ems.c trunk/reactos/subsystems/mvdm/ntvdm/ems.h trunk/reactos/subsystems/mvdm/ntvdm/emulator.c trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/vga.c trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/vga.h
Modified: trunk/reactos/include/reactos/libs/fast486/fast486.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/libs/fast48... ============================================================================== --- trunk/reactos/include/reactos/libs/fast486/fast486.h [iso-8859-1] (original) +++ trunk/reactos/include/reactos/libs/fast486/fast486.h [iso-8859-1] Fri Mar 13 17:57:51 2015 @@ -576,6 +576,10 @@ USHORT Selector );
+VOID +NTAPI +Fast486Rewind(PFAST486_STATE State); + #endif // _FAST486_H_
/* EOF */
Modified: trunk/reactos/lib/fast486/fast486.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/fast486.c?rev=6... ============================================================================== --- trunk/reactos/lib/fast486/fast486.c [iso-8859-1] (original) +++ trunk/reactos/lib/fast486/fast486.c [iso-8859-1] Fri Mar 13 17:57:51 2015 @@ -333,4 +333,14 @@ Fast486LoadSegment(State, Segment, Selector); }
+VOID +NTAPI +Fast486Rewind(PFAST486_STATE State) +{ + /* This function is used when an instruction has been interrupted remotely */ + State->PrefixFlags = 0; + State->InstPtr.Long = State->SavedInstPtr.Long; + State->PrefetchValid = FALSE; +} + /* EOF */
Modified: trunk/reactos/subsystems/mvdm/ntvdm/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/CMake... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/CMakeLists.txt [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/CMakeLists.txt [iso-8859-1] Fri Mar 13 17:57:51 2015 @@ -37,6 +37,7 @@ emulator.c int32.c io.c + memory.c utils.c vddsup.c ntvdm.c @@ -45,6 +46,6 @@
add_executable(ntvdm ${SOURCE}) set_module_type(ntvdm win32cui UNICODE IMAGEBASE 0x0F000000) -target_link_libraries(ntvdm fast486) +target_link_libraries(ntvdm fast486 ${PSEH_LIB}) add_importlibs(ntvdm user32 gdi32 advapi32 msvcrt kernel32 ntdll) add_cd_file(TARGET ntvdm DESTINATION reactos/system32 FOR all)
Modified: trunk/reactos/subsystems/mvdm/ntvdm/bios/bios.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/bios/... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/bios/bios.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/bios/bios.c [iso-8859-1] Fri Mar 13 17:57:51 2015 @@ -11,6 +11,7 @@ #define NDEBUG
#include "emulator.h" +#include "memory.h" #include "cpu/callback.h" #include "cpu/bop.h"
@@ -39,6 +40,12 @@ PBIOS_CONFIG_TABLE Bct;
/* PRIVATE FUNCTIONS **********************************************************/ + +static BOOLEAN NTAPI BiosRomWrite(ULONG Address, PVOID Buffer, ULONG Size) +{ + /* Prevent writing to ROM */ + return FALSE; +}
/* PUBLIC FUNCTIONS ***********************************************************/
@@ -73,6 +80,11 @@ // /* Register the BIOS support BOPs */ // RegisterBop(BOP_EQUIPLIST , BiosEquipmentService); // RegisterBop(BOP_GETMEMSIZE, BiosGetMemorySize); + + MemInstallFastMemoryHook((PVOID)ROM_AREA_START, + ROM_AREA_END - ROM_AREA_START + 1, + NULL, + BiosRomWrite);
if (BiosFileName && BiosFileName[0] != '\0') {
Modified: trunk/reactos/subsystems/mvdm/ntvdm/cpu/cpu.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/cpu/c... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/cpu/cpu.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/cpu/cpu.c [iso-8859-1] Fri Mar 13 17:57:51 2015 @@ -13,9 +13,11 @@ #include "cpu.h"
#include "emulator.h" +#include "memory.h" #include "callback.h" #include "bop.h" #include <isvbop.h> +#include <pseh/pseh2.h>
#include "clock.h" #include "bios/rom.h" @@ -112,6 +114,8 @@
VOID CpuSimulate(VOID) { + EXCEPTION_RECORD LocalExceptionRecord; + if (CpuCallLevel > MaxCpuCallLevel) { DisplayMessage(L"Too many CPU levels of recursion (%d, expected maximum %d)", @@ -125,7 +129,29 @@ DPRINT("CpuSimulate --> Level %d\n", CpuCallLevel);
CpuRunning = TRUE; - while (VdmRunning && CpuRunning) ClockUpdate(); + while (VdmRunning && CpuRunning) + { + _SEH2_TRY + { + while (VdmRunning && CpuRunning) ClockUpdate(); + } + _SEH2_EXCEPT(LocalExceptionRecord = *_SEH2_GetExceptionInformation()->ExceptionRecord, + EXCEPTION_EXECUTE_HANDLER) + { + BOOLEAN Writing = (LocalExceptionRecord.ExceptionInformation[0] == 1); + DWORD FaultingAddress = (DWORD)LocalExceptionRecord.ExceptionInformation[1]; + + /* Make sure this was an access violation */ + ASSERT(LocalExceptionRecord.ExceptionCode == EXCEPTION_ACCESS_VIOLATION); + + /* Fix the CPU state */ + Fast486Rewind(&EmulatorContext); + + /* Call the handler */ + MemExceptionHandler(FaultingAddress, Writing); + } + _SEH2_END; + }
DPRINT("CpuSimulate <-- Level %d\n", CpuCallLevel); CpuCallLevel--;
Modified: trunk/reactos/subsystems/mvdm/ntvdm/ems.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/ems.c... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/ems.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/ems.c [iso-8859-1] Fri Mar 13 17:57:51 2015 @@ -15,6 +15,7 @@ #include <ndk/rtltypes.h> #include <ndk/rtlfuncs.h> #include "ems.h" +#include "memory.h"
/* PRIVATE VARIABLES **********************************************************/
@@ -294,23 +295,26 @@ } }
-/* PUBLIC FUNCTIONS ***********************************************************/ - -VOID EmsReadMemory(ULONG Address, PVOID Buffer, ULONG Size) +static VOID NTAPI EmsReadMemory(ULONG Address, PVOID Buffer, ULONG Size) { // TODO: NOT IMPLEMENTED UNIMPLEMENTED; }
-VOID EmsWriteMemory(ULONG Address, PVOID Buffer, ULONG Size) +static BOOLEAN NTAPI EmsWriteMemory(ULONG Address, PVOID Buffer, ULONG Size) { // TODO: NOT IMPLEMENTED UNIMPLEMENTED; -} + return TRUE; +} + +/* PUBLIC FUNCTIONS ***********************************************************/
VOID EmsInitialize(VOID) { ULONG i; + + RtlZeroMemory(BitmapBuffer, sizeof(BitmapBuffer)); RtlInitializeBitMap(&AllocBitmap, BitmapBuffer, EMS_TOTAL_PAGES);
for (i = 0; i < EMS_MAX_HANDLES; i++) @@ -320,5 +324,16 @@ InitializeListHead(&HandleTable[i].PageList); }
+ MemInstallFastMemoryHook(SEG_OFF_TO_PTR(EMS_SEGMENT, 0), + EMS_PHYSICAL_PAGES * EMS_PAGE_SIZE, + EmsReadMemory, + EmsWriteMemory); + RegisterBiosInt32(EMS_INTERRUPT_NUM, EmsIntHandler); } + +VOID EmsCleanup(VOID) +{ + MemRemoveFastMemoryHook(SEG_OFF_TO_PTR(EMS_SEGMENT, 0), + EMS_PHYSICAL_PAGES * EMS_PAGE_SIZE); +}
Modified: trunk/reactos/subsystems/mvdm/ntvdm/ems.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/ems.h... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/ems.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/ems.h [iso-8859-1] Fri Mar 13 17:57:51 2015 @@ -12,15 +12,13 @@ /* DEFINITIONS ****************************************************************/
#define EMS_INTERRUPT_NUM 0x67 -#define EMS_SEGMENT 0xE000 +#define EMS_SEGMENT 0xD000 #define EMS_MAX_HANDLES 16 #define EMS_TOTAL_PAGES 256 #define EMS_PAGE_BITS 14 #define EMS_PAGE_SIZE (1 << EMS_PAGE_BITS) #define EMS_ADDRESS 0xA00000 #define EMS_PHYSICAL_PAGES 4 -#define EMS_START_ADDRESS (EMS_SEGMENT << 4) -#define EMS_END_ADDRESS (EMS_START_ADDRESS + EMS_PHYSICAL_PAGES * EMS_PAGE_SIZE)
#define EMS_STATUS_OK 0x00 #define EMS_STATUS_INTERNAL_ERROR 0x80 @@ -66,9 +64,8 @@
/* FUNCTIONS ******************************************************************/
-VOID EmsReadMemory(ULONG Address, PVOID Buffer, ULONG Size); -VOID EmsWriteMemory(ULONG Address, PVOID Buffer, ULONG Size); VOID EmsInitialize(VOID); +VOID EmsCleanup(VOID);
#endif // _EMS_H_
Modified: trunk/reactos/subsystems/mvdm/ntvdm/emulator.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/emula... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/emulator.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/emulator.c [iso-8859-1] Fri Mar 13 17:57:51 2015 @@ -11,6 +11,7 @@ #define NDEBUG
#include "emulator.h" +#include "memory.h"
#include "cpu/callback.h" #include "cpu/cpu.h" @@ -66,143 +67,35 @@
/* PRIVATE FUNCTIONS **********************************************************/
-static inline VOID -EmulatorMoveMemory(OUT VOID UNALIGNED *Destination, - IN const VOID UNALIGNED *Source, - IN SIZE_T Length) -{ -#if 1 - /* - * We use a switch here to detect small moves of memory, as these - * constitute the bulk of our moves. - * Using RtlMoveMemory for all these small moves would be slow otherwise. - */ - switch (Length) - { - case 0: - return; - - case sizeof(UCHAR): - *(PUCHAR)Destination = *(PUCHAR)Source; - return; - - case sizeof(USHORT): - *(PUSHORT)Destination = *(PUSHORT)Source; - return; - - case sizeof(ULONG): - *(PULONG)Destination = *(PULONG)Source; - return; - - case sizeof(ULONGLONG): - *(PULONGLONG)Destination = *(PULONGLONG)Source; - return; - - default: -#if defined(__GNUC__) - __builtin_memmove(Destination, Source, Length); -#else - RtlMoveMemory(Destination, Source, Length); -#endif - } - -#else // defined(_MSC_VER) - - PUCHAR Dest = (PUCHAR)Destination; - PUCHAR Src = (PUCHAR)Source; - - SIZE_T Count, NewSize = Length; - - /* Move dword */ - Count = NewSize >> 2; // NewSize / sizeof(ULONG); - NewSize = NewSize & 3; // NewSize % sizeof(ULONG); - __movsd(Dest, Src, Count); - Dest += Count << 2; // Count * sizeof(ULONG); - Src += Count << 2; - - /* Move word */ - Count = NewSize >> 1; // NewSize / sizeof(USHORT); - NewSize = NewSize & 1; // NewSize % sizeof(USHORT); - __movsw(Dest, Src, Count); - Dest += Count << 1; // Count * sizeof(USHORT); - Src += Count << 1; - - /* Move byte */ - Count = NewSize; // NewSize / sizeof(UCHAR); - // NewSize = NewSize; // NewSize % sizeof(UCHAR); - __movsb(Dest, Src, Count); - -#endif -} - VOID WINAPI EmulatorReadMemory(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size) { UNREFERENCED_PARAMETER(State);
- // BIG HACK!!!! To make BIOS images working correctly, - // until Aleksander rewrites memory management!! + /* Mirror 0x000FFFF0 at 0xFFFFFFF0 */ if (Address >= 0xFFFFFFF0) Address -= 0xFFF00000;
/* If the A20 line is disabled, mask bit 20 */ - if (!A20Line) Address &= ~(1 << 20); - - /* Make sure the requested address is valid */ - if ((Address + Size) >= MAX_ADDRESS) return; - - /* - * Check if we are going to read the VGA memory and - * copy it into the virtual address space if needed. - */ - if (((Address + Size) >= VgaGetVideoBaseAddress()) - && (Address < VgaGetVideoLimitAddress())) - { - DWORD VgaAddress = max(Address, VgaGetVideoBaseAddress()); - DWORD ActualSize = min(Address + Size - 1, VgaGetVideoLimitAddress()) - - VgaAddress + 1; - LPBYTE DestBuffer = (LPBYTE)REAL_TO_PHYS(VgaAddress); - - /* Read from the VGA memory */ - VgaReadMemory(VgaAddress, DestBuffer, ActualSize); - } - - /* Read the data from the virtual address space and store it in the buffer */ - EmulatorMoveMemory(Buffer, REAL_TO_PHYS(Address), Size); + if (!A20Line) Address &= ~(1 << 20); + + if (Address >= MAX_ADDRESS) return; + Size = min(Size, MAX_ADDRESS - Address); + + /* Read while calling fast memory hooks */ + MemRead(Address, Buffer, Size); }
VOID WINAPI EmulatorWriteMemory(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size) { UNREFERENCED_PARAMETER(State);
- // BIG HACK!!!! To make BIOS images working correctly, - // until Aleksander rewrites memory management!! - if (Address >= 0xFFFFFFF0) Address -= 0xFFF00000; - /* If the A20 line is disabled, mask bit 20 */ - if (!A20Line) Address &= ~(1 << 20); - - /* Make sure the requested address is valid */ - if ((Address + Size) >= MAX_ADDRESS) return; - - /* Make sure we don't write to the ROM area */ - if ((Address + Size) >= ROM_AREA_START && (Address < ROM_AREA_END)) return; - - /* Read the data from the buffer and store it in the virtual address space */ - EmulatorMoveMemory(REAL_TO_PHYS(Address), Buffer, Size); - - /* - * Check if we modified the VGA memory. - */ - if (((Address + Size) >= VgaGetVideoBaseAddress()) - && (Address < VgaGetVideoLimitAddress())) - { - DWORD VgaAddress = max(Address, VgaGetVideoBaseAddress()); - DWORD ActualSize = min(Address + Size - 1, VgaGetVideoLimitAddress()) - - VgaAddress + 1; - LPBYTE SrcBuffer = (LPBYTE)REAL_TO_PHYS(VgaAddress); - - /* Write to the VGA memory */ - VgaWriteMemory(VgaAddress, SrcBuffer, ActualSize); - } + if (!A20Line) Address &= ~(1 << 20); + + if (Address >= MAX_ADDRESS) return; + Size = min(Size, MAX_ADDRESS - Address); + + /* Write while calling fast memory hooks */ + MemWrite(Address, Buffer, Size); }
UCHAR WINAPI EmulatorIntAcknowledge(PFAST486_STATE State) @@ -566,56 +459,12 @@
BOOLEAN EmulatorInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput) { -#ifdef STANDALONE - - /* Allocate 16 MB memory for the 16-bit address space */ - BaseAddress = HeapAlloc(GetProcessHeap(), /*HEAP_ZERO_MEMORY*/ 0, MAX_ADDRESS); - if (BaseAddress == NULL) - { - wprintf(L"FATAL: Failed to allocate VDM memory.\n"); + /* Initialize memory */ + if (!MemInitialize()) + { + wprintf(L"Memory initialization failed.\n"); return FALSE; } - -#else - - NTSTATUS Status; - SIZE_T MemorySize = MAX_ADDRESS; // See: kernel32/client/vdm.c!BaseGetVdmConfigInfo - - /* - * The reserved region starts from the very first page. - * We need to commit the reserved first 16 MB virtual address. - */ - BaseAddress = (PVOID)1; // NULL has another signification for NtAllocateVirtualMemory - - /* - * Since to get NULL, we allocated from 0x1, account for this. - * See also: kernel32/client/proc.c!CreateProcessInternalW - */ - MemorySize -= 1; - - /* Commit the reserved memory */ - Status = NtAllocateVirtualMemory(NtCurrentProcess(), - &BaseAddress, - 0, - &MemorySize, - MEM_COMMIT, - PAGE_EXECUTE_READWRITE); - if (!NT_SUCCESS(Status)) - { - wprintf(L"FATAL: Failed to commit VDM memory, Status 0x%08lx\n", Status); - return FALSE; - } - - ASSERT(BaseAddress == NULL); - -#endif - - /* - * For diagnostics purposes, we fill the memory with INT 0x03 codes - * so that if a program wants to execute random code in memory, we can - * retrieve the exact CS:IP where the problem happens. - */ - RtlFillMemory(BaseAddress, MAX_ADDRESS, 0xCC);
/* Initialize I/O ports */ /* Initialize RAM */ @@ -700,11 +549,6 @@
VOID EmulatorCleanup(VOID) { -#ifndef STANDALONE - NTSTATUS Status; - SIZE_T MemorySize = MAX_ADDRESS; -#endif - VgaCleanup();
/* Close the input thread handle */ @@ -713,6 +557,7 @@
PS2Cleanup();
+ EmsCleanup(); SpeakerCleanup(); CmosCleanup(); // PitCleanup(); @@ -721,29 +566,7 @@ // DmaCleanup();
CpuCleanup(); - -#ifdef STANDALONE - - /* Free the memory allocated for the 16-bit address space */ - if (BaseAddress != NULL) HeapFree(GetProcessHeap(), 0, BaseAddress); - -#else - - /* The reserved region starts from the very first page */ - // BaseAddress = (PVOID)1; - - /* Since to get NULL, we allocated from 0x1, account for this */ - MemorySize -= 1; - - Status = NtFreeVirtualMemory(NtCurrentProcess(), - &BaseAddress, - &MemorySize, - MEM_DECOMMIT); - if (!NT_SUCCESS(Status)) - { - DPRINT1("NTVDM: Failed to decommit VDM memory, Status 0x%08lx\n", Status); - } -#endif + MemCleanup(); }
Modified: trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/vga.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/hardw... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/vga.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/vga.c [iso-8859-1] Fri Mar 13 17:57:51 2015 @@ -14,6 +14,7 @@ #include "vga.h" #include <bios/vidbios.h>
+#include "memory.h" #include "io.h"
/* PRIVATE VARIABLES **********************************************************/ @@ -418,6 +419,16 @@ static inline DWORD VgaGetAddressSize(VOID); static VOID VgaUpdateTextCursor(VOID);
+static inline DWORD VgaGetVideoBaseAddress(VOID) +{ + return MemoryBase[(VgaGcRegisters[VGA_GC_MISC_REG] >> 2) & 0x03]; +} + +static inline DWORD VgaGetVideoLimitAddress(VOID) +{ + return MemoryLimit[(VgaGcRegisters[VGA_GC_MISC_REG] >> 2) & 0x03]; +} + static VOID VgaUpdateCursorPosition(VOID) { /* @@ -1745,16 +1756,6 @@
/* PUBLIC FUNCTIONS ***********************************************************/
-DWORD VgaGetVideoBaseAddress(VOID) -{ - return MemoryBase[(VgaGcRegisters[VGA_GC_MISC_REG] >> 2) & 0x03]; -} - -DWORD VgaGetVideoLimitAddress(VOID) -{ - return MemoryLimit[(VgaGcRegisters[VGA_GC_MISC_REG] >> 2) & 0x03]; -} - COORD VgaGetDisplayResolution(VOID) { COORD Resolution; @@ -1881,12 +1882,15 @@ InHorizontalRetrace = TRUE; }
-VOID VgaReadMemory(DWORD Address, LPBYTE Buffer, DWORD Size) +VOID NTAPI VgaReadMemory(ULONG Address, PVOID Buffer, ULONG Size) { DWORD i; DWORD VideoAddress; + PUCHAR BufPtr = (PUCHAR)Buffer;
DPRINT("VgaReadMemory: Address 0x%08X, Size %lu\n", Address, Size); + Address = max(min(Address, VgaGetVideoLimitAddress() - 1), VgaGetVideoBaseAddress()); + Size = min(Size, VgaGetVideoLimitAddress() - Address + 1);
/* Ignore if video RAM access is disabled */ if ((VgaMiscRegister & VGA_MISC_RAM_ENABLED) == 0) return; @@ -1897,7 +1901,7 @@ VideoAddress = VgaTranslateReadAddress(Address + i);
/* Copy the value to the buffer */ - Buffer[i] = VgaMemory[VideoAddress]; + BufPtr[i] = VgaMemory[VideoAddress]; }
/* Load the latch registers */ @@ -1907,18 +1911,21 @@ VgaLatchRegisters[3] = VgaMemory[(3 * VGA_BANK_SIZE) + LOWORD(VideoAddress)]; }
-VOID VgaWriteMemory(DWORD Address, LPBYTE Buffer, DWORD Size) +BOOLEAN NTAPI VgaWriteMemory(ULONG Address, PVOID Buffer, ULONG Size) { DWORD i, j; DWORD VideoAddress; + PUCHAR BufPtr = (PUCHAR)Buffer;
DPRINT("VgaWriteMemory: Address 0x%08X, Size %lu\n", Address, Size); + Address = max(min(Address, VgaGetVideoLimitAddress() - 1), VgaGetVideoBaseAddress()); + Size = min(Size, VgaGetVideoLimitAddress() - Address + 1);
/* Ignore if video RAM access is disabled */ - if ((VgaMiscRegister & VGA_MISC_RAM_ENABLED) == 0) return; + if ((VgaMiscRegister & VGA_MISC_RAM_ENABLED) == 0) return TRUE;
/* Also ignore if write access to all planes is disabled */ - if ((VgaSeqRegisters[VGA_SEQ_MASK_REG] & 0x0F) == 0x00) return; + if ((VgaSeqRegisters[VGA_SEQ_MASK_REG] & 0x0F) == 0x00) return TRUE;
/* Loop through each byte */ for (i = 0; i < Size; i++) @@ -1951,9 +1958,11 @@ }
/* Copy the value to the VGA memory */ - VgaMemory[VideoAddress + j * VGA_BANK_SIZE] = VgaTranslateByteForWriting(Buffer[i], j); - } - } + VgaMemory[VideoAddress + j * VGA_BANK_SIZE] = VgaTranslateByteForWriting(BufPtr[i], j); + } + } + + return TRUE; }
VOID VgaClearMemory(VOID) @@ -2074,6 +2083,9 @@
/* Clear the VGA memory */ VgaClearMemory(); + + /* Register the memory hook */ + MemInstallFastMemoryHook((PVOID)0xA0000, 0x20000, VgaReadMemory, VgaWriteMemory);
/* Register the I/O Ports */ RegisterIoPort(0x3CC, VgaReadPort, NULL); // VGA_MISC_READ @@ -2112,6 +2124,7 @@ }
VgaDetachFromConsole(FALSE); + MemRemoveFastMemoryHook((PVOID)0xA0000, 0x20000);
CloseHandle(AnotherEvent); CloseHandle(EndEvent);
Modified: trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/vga.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/hardw... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/vga.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/vga.h [iso-8859-1] Fri Mar 13 17:57:51 2015 @@ -258,14 +258,10 @@ BOOL VgaAttachToConsole(VOID); VOID VgaDetachFromConsole(BOOL ChangeMode);
-DWORD VgaGetVideoBaseAddress(VOID); -DWORD VgaGetVideoLimitAddress(VOID); COORD VgaGetDisplayResolution(VOID); VOID VgaRefreshDisplay(VOID); VOID VgaHorizontalRetrace(VOID); VOID VgaWriteFont(UINT FontNumber, CONST UCHAR *FontData, UINT Height); -VOID VgaReadMemory(DWORD Address, LPBYTE Buffer, DWORD Size); -VOID VgaWriteMemory(DWORD Address, LPBYTE Buffer, DWORD Size); VOID VgaClearMemory(VOID);
BOOLEAN VgaInitialize(HANDLE TextHandle);
Added: trunk/reactos/subsystems/mvdm/ntvdm/memory.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/memor... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/memory.c (added) +++ trunk/reactos/subsystems/mvdm/ntvdm/memory.c [iso-8859-1] Fri Mar 13 17:57:51 2015 @@ -0,0 +1,422 @@ +/* + * COPYRIGHT: GPLv2+ - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: memory.c + * PURPOSE: Expanded Memory Support + * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org> + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" +#include <ndk/mmfuncs.h> +#include <ndk/rtlfuncs.h> +#include "memory.h" + +/* PRIVATE VARIABLES **********************************************************/ + +static LIST_ENTRY HookList; +static PMEM_HOOK PageTable[TOTAL_PAGES]; + +/* PRIVATE FUNCTIONS **********************************************************/ + +static inline VOID +MemFastMoveMemory(OUT VOID UNALIGNED *Destination, + IN const VOID UNALIGNED *Source, + IN SIZE_T Length) +{ +#if 1 + /* + * We use a switch here to detect small moves of memory, as these + * constitute the bulk of our moves. + * Using RtlMoveMemory for all these small moves would be slow otherwise. + */ + switch (Length) + { + case 0: + return; + + case sizeof(UCHAR): + *(PUCHAR)Destination = *(PUCHAR)Source; + return; + + case sizeof(USHORT): + *(PUSHORT)Destination = *(PUSHORT)Source; + return; + + case sizeof(ULONG): + *(PULONG)Destination = *(PULONG)Source; + return; + + case sizeof(ULONGLONG): + *(PULONGLONG)Destination = *(PULONGLONG)Source; + return; + + default: +#if defined(__GNUC__) + __builtin_memmove(Destination, Source, Length); +#else + RtlMoveMemory(Destination, Source, Length); +#endif + } + +#else // defined(_MSC_VER) + + PUCHAR Dest = (PUCHAR)Destination; + PUCHAR Src = (PUCHAR)Source; + + SIZE_T Count, NewSize = Length; + + /* Move dword */ + Count = NewSize >> 2; // NewSize / sizeof(ULONG); + NewSize = NewSize & 3; // NewSize % sizeof(ULONG); + __movsd(Dest, Src, Count); + Dest += Count << 2; // Count * sizeof(ULONG); + Src += Count << 2; + + /* Move word */ + Count = NewSize >> 1; // NewSize / sizeof(USHORT); + NewSize = NewSize & 1; // NewSize % sizeof(USHORT); + __movsw(Dest, Src, Count); + Dest += Count << 1; // Count * sizeof(USHORT); + Src += Count << 1; + + /* Move byte */ + Count = NewSize; // NewSize / sizeof(UCHAR); + // NewSize = NewSize; // NewSize % sizeof(UCHAR); + __movsb(Dest, Src, Count); + +#endif +} + +static +inline +VOID +ReadPage(PMEM_HOOK Hook, ULONG Address, PVOID Buffer, ULONG Size) +{ + if (Hook && !Hook->hVdd && Hook->FastReadHandler) + { + Hook->FastReadHandler(Address, REAL_TO_PHYS(Address), Size); + } + + MemFastMoveMemory(Buffer, REAL_TO_PHYS(Address), Size); +} + +static +inline +VOID +WritePage(PMEM_HOOK Hook, ULONG Address, PVOID Buffer, ULONG Size) +{ + if (!Hook + || Hook->hVdd + || !Hook->FastWriteHandler + || Hook->FastWriteHandler(Address, Buffer, Size)) + { + MemFastMoveMemory(REAL_TO_PHYS(Address), Buffer, Size); + } +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +VOID +MemRead(ULONG Address, PVOID Buffer, ULONG Size) +{ + ULONG i, Offset, Length; + ULONG FirstPage = Address >> 12; + ULONG LastPage = (Address + Size - 1) >> 12; + + MemFastMoveMemory(Buffer, REAL_TO_PHYS(Address), Size); + + if (FirstPage == LastPage) + { + ReadPage(PageTable[FirstPage], Address, Buffer, Size); + } + else + { + for (i = FirstPage; i <= LastPage; i++) + { + Offset = (i == FirstPage) ? (Address & (PAGE_SIZE - 1)) : 0; + Length = ((i == LastPage) ? (Address + Size - (LastPage << 12)) : PAGE_SIZE) - Offset; + + ReadPage(PageTable[i], (i << 12) + Offset, Buffer, Length); + Buffer = (PVOID)((ULONG_PTR)Buffer + Length); + } + } +} + +VOID +MemWrite(ULONG Address, PVOID Buffer, ULONG Size) +{ + ULONG i, Offset, Length; + ULONG FirstPage = Address >> 12; + ULONG LastPage = (Address + Size - 1) >> 12; + + if (FirstPage == LastPage) + { + WritePage(PageTable[FirstPage], Address, Buffer, Size); + } + else + { + for (i = FirstPage; i <= LastPage; i++) + { + Offset = (i == FirstPage) ? (Address & (PAGE_SIZE - 1)) : 0; + Length = ((i == LastPage) ? (Address + Size - (LastPage << 12)) : PAGE_SIZE) - Offset; + + WritePage(PageTable[i], (i << 12) + Offset, Buffer, Length); + Buffer = (PVOID)((ULONG_PTR)Buffer + Length); + } + } +} + +VOID +MemExceptionHandler(DWORD Address, BOOLEAN Writing) +{ + PMEM_HOOK Hook = PageTable[Address >> 12]; + DPRINT("The memory at 0x%08X could not be %s.\n", Address, Writing ? "written" : "read"); + + /* Exceptions are only supposed to happen when using VDD-style memory hooks */ + ASSERT(Address < MAX_ADDRESS && Hook != NULL && Hook->hVdd != NULL); + + /* Call the VDD handler */ + Hook->VddHandler(Address, Writing); +} + +BOOL +MemInstallFastMemoryHook(PVOID Address, + ULONG Size, + PMEMORY_READ_HANDLER ReadHandler, + PMEMORY_WRITE_HANDLER WriteHandler) +{ + PMEM_HOOK Hook; + ULONG i; + ULONG FirstPage = (ULONG)Address >> 12; + ULONG LastPage = ((ULONG)Address + Size - 1) >> 12; + + /* Make sure none of these pages are already allocated */ + for (i = FirstPage; i <= LastPage; i++) + { + if (PageTable[i] != NULL) return FALSE; + } + + Hook = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(MEM_HOOK)); + if (Hook == NULL) return FALSE; + + Hook->hVdd = NULL; + Hook->Count = LastPage - FirstPage + 1; + Hook->FastReadHandler = ReadHandler; + Hook->FastWriteHandler = WriteHandler; + + for (i = FirstPage; i <= LastPage; i++) PageTable[i] = Hook; + + InsertTailList(&HookList, &Hook->Entry); + return TRUE; +} + +BOOL +MemRemoveFastMemoryHook(PVOID Address, ULONG Size) +{ + ULONG i; + ULONG FirstPage = (ULONG)Address >> 12; + ULONG LastPage = ((ULONG)Address + Size - 1) >> 12; + + if (Size == 0) return FALSE; + + for (i = FirstPage; i <= LastPage; i++) + { + PMEM_HOOK Hook = PageTable[i]; + if (Hook == NULL || Hook->hVdd != NULL) continue; + + if (--Hook->Count == 0) + { + /* This hook has no more pages */ + RemoveEntryList(&Hook->Entry); + RtlFreeHeap(RtlGetProcessHeap(), 0, Hook); + } + + PageTable[i] = NULL; + } + + return TRUE; +} + +BOOL +WINAPI +VDDInstallMemoryHook(HANDLE hVdd, + PVOID pStart, + DWORD dwCount, + PVDD_MEMORY_HANDLER pHandler) +{ + NTSTATUS Status; + PMEM_HOOK Hook; + ULONG i; + ULONG FirstPage = (ULONG)pStart >> 12; + ULONG LastPage = ((ULONG)pStart + dwCount - 1) >> 12; + PVOID Address = (PVOID)(FirstPage * PAGE_SIZE); + SIZE_T Size = (LastPage - FirstPage + 1) * PAGE_SIZE; + + /* Check validity of the VDD handle */ + if (hVdd == NULL || hVdd == INVALID_HANDLE_VALUE) return FALSE; + if (dwCount == 0) return FALSE; + + /* Make sure none of these pages are already allocated */ + for (i = FirstPage; i <= LastPage; i++) + { + if (PageTable[i] != NULL) return FALSE; + } + + Hook = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(MEM_HOOK)); + if (Hook == NULL) return FALSE; + + Hook->hVdd = hVdd; + Hook->Count = LastPage - FirstPage + 1; + Hook->VddHandler = pHandler; + + /* Decommit the pages */ + Status = NtFreeVirtualMemory(NtCurrentProcess(), &Address, &Size, MEM_DECOMMIT); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, Hook); + return FALSE; + } + + for (i = FirstPage; i <= LastPage; i++) PageTable[i] = Hook; + + InsertTailList(&HookList, &Hook->Entry); + return TRUE; +} + +BOOL +WINAPI +VDDDeInstallMemoryHook(HANDLE hVdd, + PVOID pStart, + DWORD dwCount) +{ + NTSTATUS Status; + ULONG i; + ULONG FirstPage = (ULONG)pStart >> 12; + ULONG LastPage = ((ULONG)pStart + dwCount - 1) >> 12; + PVOID Address = (PVOID)(FirstPage * PAGE_SIZE); + SIZE_T Size = (LastPage - FirstPage + 1) * PAGE_SIZE; + + if (dwCount == 0) return FALSE; + + /* Commit the pages */ + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &Address, + 0, + &Size, + MEM_COMMIT, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) return FALSE; + + for (i = FirstPage; i <= LastPage; i++) + { + PMEM_HOOK Hook = PageTable[i]; + if (Hook == NULL) continue; + + if (Hook->hVdd != hVdd) + { + DPRINT1("VDDDeInstallMemoryHook: Page %u owned by someone else.\n", i); + continue; + } + + if (--Hook->Count == 0) + { + /* This hook has no more pages */ + RemoveEntryList(&Hook->Entry); + RtlFreeHeap(RtlGetProcessHeap(), 0, Hook); + } + + PageTable[i] = NULL; + } + + return TRUE; +} + +BOOLEAN +MemInitialize(VOID) +{ + NTSTATUS Status; + SIZE_T MemorySize = MAX_ADDRESS; // See: kernel32/client/vdm.c!BaseGetVdmConfigInfo + +#ifndef STANDALONE + + /* + * The reserved region starts from the very first page. + * We need to commit the reserved first 16 MB virtual address. + */ + BaseAddress = (PVOID)1; + + /* + * Since to get NULL, we allocated from 0x1, account for this. + * See also: kernel32/client/proc.c!CreateProcessInternalW + */ + MemorySize -= 1; + +#else + + /* Allocate it anywhere */ + BaseAddress = NULL; + +#endif + + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &MemorySize, +#ifndef STANDALONE + MEM_COMMIT, +#else + MEM_RESERVE | MEM_COMMIT, +#endif + PAGE_EXECUTE_READWRITE); + if (!NT_SUCCESS(Status)) + { + wprintf(L"FATAL: Failed to commit VDM memory, Status 0x%08lx\n", Status); + return FALSE; + } + +#ifndef STANDALONE + ASSERT(BaseAddress == NULL); +#endif + + InitializeListHead(&HookList); + + /* + * For diagnostics purposes, we fill the memory with INT 0x03 codes + * so that if a program wants to execute random code in memory, we can + * retrieve the exact CS:IP where the problem happens. + */ + RtlFillMemory(BaseAddress, MAX_ADDRESS, 0xCC); + return TRUE; +} + +VOID +MemCleanup(VOID) +{ + NTSTATUS Status; + SIZE_T MemorySize = MAX_ADDRESS; + + while (HookList.Flink != &HookList) + { + PLIST_ENTRY Pointer = RemoveHeadList(&HookList); + RtlFreeHeap(RtlGetProcessHeap(), 0, CONTAINING_RECORD(Pointer, MEM_HOOK, Entry)); + } + + /* Decommit the VDM memory */ + Status = NtFreeVirtualMemory(NtCurrentProcess(), + &BaseAddress, + &MemorySize, +#ifndef STANDALONE + MEM_DECOMMIT +#else + MEM_RELEASE +#endif + ); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NTVDM: Failed to decommit VDM memory, Status 0x%08lx\n", Status); + } +}
Propchange: trunk/reactos/subsystems/mvdm/ntvdm/memory.c ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/reactos/subsystems/mvdm/ntvdm/memory.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/memor... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/memory.h (added) +++ trunk/reactos/subsystems/mvdm/ntvdm/memory.h [iso-8859-1] Fri Mar 13 17:57:51 2015 @@ -0,0 +1,116 @@ +/* + * COPYRIGHT: GPLv2+ - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: memory.h + * PURPOSE: Expanded Memory Support + * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org> + */ + +#ifndef _MEMORY_H_ +#define _MEMORY_H_ + +/* DEFINITIONS ****************************************************************/ + +#define TOTAL_PAGES (MAX_ADDRESS / PAGE_SIZE) + +typedef VOID +(WINAPI *PVDD_MEMORY_HANDLER) +( + DWORD FaultingAddress, + BOOLEAN Writing +); + +typedef VOID +(WINAPI *PMEMORY_READ_HANDLER) +( + ULONG Address, + PVOID Buffer, + ULONG Size +); + +typedef BOOLEAN +(WINAPI *PMEMORY_WRITE_HANDLER) +( + ULONG Address, + PVOID Buffer, + ULONG Size +); + +typedef struct _MEM_HOOK +{ + LIST_ENTRY Entry; + HANDLE hVdd; + ULONG Count; + + union + { + PVDD_MEMORY_HANDLER VddHandler; + + struct + { + PMEMORY_READ_HANDLER FastReadHandler; + PMEMORY_WRITE_HANDLER FastWriteHandler; + }; + }; +} MEM_HOOK, *PMEM_HOOK; + +/* FUNCTIONS ******************************************************************/ + +BOOLEAN MemInitialize(VOID); +VOID MemCleanup(VOID); +VOID MemExceptionHandler(DWORD Address, BOOLEAN Writing); + +VOID +MemRead +( + ULONG Address, + PVOID Buffer, + ULONG Size +); + +VOID +MemWrite +( + ULONG Address, + PVOID Buffer, + ULONG Size +); + +BOOL +MemInstallFastMemoryHook +( + PVOID Address, + ULONG Size, + PMEMORY_READ_HANDLER ReadHandler, + PMEMORY_WRITE_HANDLER WriteHandler +); + +BOOL +MemRemoveFastMemoryHook +( + PVOID Address, + ULONG Size +); + +BOOL +WINAPI +VDDInstallMemoryHook +( + HANDLE hVdd, + PVOID pStart, + DWORD dwCount, + PVDD_MEMORY_HANDLER pHandler +); + +BOOL +WINAPI +VDDDeInstallMemoryHook +( + HANDLE hVdd, + PVOID pStart, + DWORD dwCount +); + +#endif // _MEMORY_H_ + +/* EOF */
Propchange: trunk/reactos/subsystems/mvdm/ntvdm/memory.h ------------------------------------------------------------------------------ svn:eol-style = native