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/fast4…
==============================================================================
--- 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=…
==============================================================================
--- 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/CMak…
==============================================================================
--- 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/…
==============================================================================
--- 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.…
==============================================================================
--- 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.…
==============================================================================
--- 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/emul…
==============================================================================
--- 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/hard…
==============================================================================
--- 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/hard…
==============================================================================
--- 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/memo…
==============================================================================
--- 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/memo…
==============================================================================
--- 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