Add memory manager probe functions
This commit is contained in:
@@ -60,6 +60,7 @@
|
||||
#define STATUS_TIMEOUT ((XTSTATUS) 0x00000102L)
|
||||
#define STATUS_PENDING ((XTSTATUS) 0x00000103L)
|
||||
#define STATUS_REPARSE ((XTSTATUS) 0x00000104L)
|
||||
#define STATUS_DATATYPE_MISALIGNMENT ((XTSTATUS) 0x80000002L)
|
||||
#define STATUS_WAKE_SYSTEM_DEBUGGER ((XTSTATUS) 0x80000007L)
|
||||
#define STATUS_END_OF_MEDIA ((XTSTATUS) 0x8000001EL)
|
||||
#define STATUS_RESOURCE_LOCKED ((XTSTATUS) 0xC0000000L)
|
||||
|
||||
@@ -85,6 +85,7 @@ list(APPEND XTOSKRNL_SOURCE
|
||||
${XTOSKRNL_SOURCE_DIR}/mm/paging.cc
|
||||
${XTOSKRNL_SOURCE_DIR}/mm/pfn.cc
|
||||
${XTOSKRNL_SOURCE_DIR}/mm/pool.cc
|
||||
${XTOSKRNL_SOURCE_DIR}/mm/probe.cc
|
||||
${XTOSKRNL_SOURCE_DIR}/mm/pte.cc
|
||||
${XTOSKRNL_SOURCE_DIR}/mm/quota.cc
|
||||
${XTOSKRNL_SOURCE_DIR}/po/idle.cc
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <mm/pfault.hh>
|
||||
#include <mm/pfn.hh>
|
||||
#include <mm/pool.hh>
|
||||
#include <mm/probe.hh>
|
||||
#include <mm/quota.hh>
|
||||
#include <mm/tags.hh>
|
||||
|
||||
|
||||
44
xtoskrnl/includes/mm/probe.hh
Normal file
44
xtoskrnl/includes/mm/probe.hh
Normal file
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtoskrnl/includes/mm/probe.hh
|
||||
* DESCRIPTION: Memory Manager read/write probe support
|
||||
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __XTOSKRNL_MM_PROBE_HH
|
||||
#define __XTOSKRNL_MM_PROBE_HH
|
||||
|
||||
#include <xtos.hh>
|
||||
|
||||
|
||||
/* Memory Manager */
|
||||
namespace MM
|
||||
{
|
||||
class Probe
|
||||
{
|
||||
public:
|
||||
STATIC XTAPI VOID ProbeForRead(IN CONST PVOID Address,
|
||||
IN SIZE_T Size,
|
||||
IN ULONG Alignment);
|
||||
STATIC XTAPI VOID ProbeForReadArray(IN CONST PVOID Array,
|
||||
IN ULONG ItemSize,
|
||||
IN ULONG ItemCount,
|
||||
IN ULONG Alignment);
|
||||
STATIC XTAPI VOID ProbeForReadStructure(IN CONST PVOID Address,
|
||||
IN SIZE_T Size,
|
||||
IN ULONG Alignment);
|
||||
STATIC XTAPI VOID ProbeForWrite(IN PVOID Address,
|
||||
IN SIZE_T Size,
|
||||
IN ULONG Alignment);
|
||||
STATIC XTAPI VOID ProbeForWriteArray(IN OUT PVOID Array,
|
||||
IN ULONG ItemSize,
|
||||
IN ULONG ItemCount,
|
||||
IN ULONG Alignment);
|
||||
STATIC XTAPI VOID ProbeForWriteStructure(IN PVOID Address,
|
||||
IN SIZE_T Size,
|
||||
IN ULONG Alignment);
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* __XTOSKRNL_MM_PROBE_HH */
|
||||
278
xtoskrnl/mm/probe.cc
Normal file
278
xtoskrnl/mm/probe.cc
Normal file
@@ -0,0 +1,278 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtoskrnl/mm/probe.cc
|
||||
* DESCRIPTION: Memory Manager read/write probe support
|
||||
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
|
||||
*/
|
||||
|
||||
#include <xtos.hh>
|
||||
|
||||
|
||||
/**
|
||||
* Probes a generic memory buffer for read accessibility.
|
||||
*
|
||||
* @param Address
|
||||
* Supplies the base address of the buffer to probe.
|
||||
*
|
||||
* @param Size
|
||||
* Supplies the size of the buffer in bytes.
|
||||
*
|
||||
* @param Alignment
|
||||
* Supplies the required data alignment (must be 1, 2, 4, 8, or 16).
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTAPI
|
||||
VOID
|
||||
MM::Probe::ProbeForRead(IN CONST PVOID Address,
|
||||
IN SIZE_T Size,
|
||||
IN ULONG Alignment)
|
||||
{
|
||||
/* Check if the buffer size is non-zero */
|
||||
if(Size)
|
||||
{
|
||||
/* Check if the base address violates the required alignment */
|
||||
if(((ULONG_PTR)Address & (Alignment - 1)) != 0)
|
||||
{
|
||||
/* Raise datatype misalignment exception */
|
||||
RTL::Exception::RaiseStatus(STATUS_DATATYPE_MISALIGNMENT);
|
||||
}
|
||||
|
||||
/* Verify that the end address do not overflow and remains within user space */
|
||||
if((((ULONG_PTR)Address + Size) < (ULONG_PTR)Address) ||
|
||||
(((ULONG_PTR)Address + Size) > MM::Paging::GetUserProbeAddress()))
|
||||
{
|
||||
/* Raise access violation exception */
|
||||
RTL::Exception::RaiseStatus(STATUS_ACCESS_VIOLATION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Probes an array of fixed-size items for read accessibility.
|
||||
*
|
||||
* @param Array
|
||||
* Supplies the base address of the array.
|
||||
*
|
||||
* @param ItemSize
|
||||
* Supplies the size of a single array element in bytes.
|
||||
*
|
||||
* @param ItemCount
|
||||
* Supplies the total number of elements in the array.
|
||||
*
|
||||
* @param Alignment
|
||||
* Supplies the required array alignment (must be 1, 2, 4, 8, or 16).
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTAPI
|
||||
VOID
|
||||
MM::Probe::ProbeForReadArray(IN CONST PVOID Array,
|
||||
IN ULONG ItemSize,
|
||||
IN ULONG ItemCount,
|
||||
IN ULONG Alignment)
|
||||
{
|
||||
ULONG ArraySize;
|
||||
|
||||
/* Calculate total array size */
|
||||
ArraySize = ItemSize * ItemCount;
|
||||
|
||||
/* Check for integer overflow */
|
||||
if((ItemSize != 0) && (ArraySize / ItemSize != ItemCount))
|
||||
{
|
||||
RTL::Exception::RaiseStatus(STATUS_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
/* Perform boundary and alignment verification */
|
||||
ProbeForRead(Array, ArraySize, Alignment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Probes a structure for read accessibility.
|
||||
*
|
||||
* @param Address
|
||||
* Supplies the base address of the structure to probe.
|
||||
*
|
||||
* @param Size
|
||||
* Supplies the total size of the structure in bytes.
|
||||
*
|
||||
* @param Alignment
|
||||
* Supplies the required structure alignment (must be 1, 2, 4, 8, or 16).
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTAPI
|
||||
VOID
|
||||
MM::Probe::ProbeForReadStructure(IN CONST PVOID Address,
|
||||
IN SIZE_T Size,
|
||||
IN ULONG Alignment)
|
||||
{
|
||||
/* Check if the buffer size is zero or greater than 64k */
|
||||
if((Size == 0) || (Size > 0x10000))
|
||||
{
|
||||
/* Perform boundary and alignment verification */
|
||||
ProbeForRead(Address, Size, Alignment);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check if the base address violates the required alignment */
|
||||
if(((ULONG_PTR)Address & (Alignment - 1)) != 0)
|
||||
{
|
||||
/* Raise datatype misalignment exception */
|
||||
RTL::Exception::RaiseStatus(STATUS_DATATYPE_MISALIGNMENT);
|
||||
}
|
||||
|
||||
/* Check address space boundary */
|
||||
if((ULONG_PTR)Address >= (ULONG_PTR)MM::Paging::GetUserProbeAddress())
|
||||
{
|
||||
/* Force access violation on the invalid probe boundary */
|
||||
*(VOLATILE PULONG CONST)MM::Paging::GetUserProbeAddress() = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Probes a generic memory buffer for write accessibility.
|
||||
*
|
||||
* @param Address
|
||||
* Supplies the base address of the buffer to probe.
|
||||
*
|
||||
* @param Size
|
||||
* Supplies the size of the buffer in bytes.
|
||||
*
|
||||
* @param Alignment
|
||||
* Supplies the required data alignment (must be 1, 2, 4, 8, or 16).
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTAPI
|
||||
VOID
|
||||
MM::Probe::ProbeForWrite(IN PVOID Address,
|
||||
IN SIZE_T Size,
|
||||
IN ULONG Alignment)
|
||||
{
|
||||
ULONG_PTR CurrentAddress, LastAddress;
|
||||
|
||||
/* Check if the buffer size is non-zero */
|
||||
if(Size)
|
||||
{
|
||||
/* Perform boundary and alignment verification */
|
||||
ProbeForRead(Address, Size, Alignment);
|
||||
|
||||
/* Store the current address */
|
||||
CurrentAddress = (ULONG_PTR)Address;
|
||||
|
||||
/* Calculate the end boundary of the requested buffer */
|
||||
LastAddress = CurrentAddress + Size - 1;
|
||||
LastAddress = (LastAddress & ~(MM_PAGE_SIZE - 1)) + MM_PAGE_SIZE;
|
||||
|
||||
/* Loop through each page in the range */
|
||||
while(CurrentAddress < LastAddress)
|
||||
{
|
||||
/* Touch the page with a read-write cycle */
|
||||
*(VOLATILE PCHAR)CurrentAddress = *(volatile CHAR*)CurrentAddress;
|
||||
|
||||
/* Advance to the next page */
|
||||
CurrentAddress = (CurrentAddress & ~(MM_PAGE_SIZE - 1)) + MM_PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Probes an array of fixed-size items for write accessibility.
|
||||
*
|
||||
* @param Array
|
||||
* Supplies the base address of the array.
|
||||
*
|
||||
* @param ItemSize
|
||||
* Supplies the size of a single array element in bytes.
|
||||
*
|
||||
* @param ItemCount
|
||||
* Supplies the total number of elements in the array.
|
||||
*
|
||||
* @param Alignment
|
||||
* Supplies the required data alignment (must be 1, 2, 4, 8, or 16).
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTAPI
|
||||
VOID
|
||||
MM::Probe::ProbeForWriteArray(IN OUT PVOID Array,
|
||||
IN ULONG ItemSize,
|
||||
IN ULONG ItemCount,
|
||||
IN ULONG Alignment)
|
||||
{
|
||||
ULONG ArraySize;
|
||||
|
||||
/* Calculate total array size */
|
||||
ArraySize = ItemSize * ItemCount;
|
||||
|
||||
/* Check for integer overflow */
|
||||
if((ItemSize != 0) && (ArraySize / ItemSize != ItemCount))
|
||||
{
|
||||
RTL::Exception::RaiseStatus(STATUS_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
/* Perform write accessibility verification */
|
||||
ProbeForWrite(Array, ArraySize, Alignment);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Probes a structure for write accessibility.
|
||||
*
|
||||
* @param Address
|
||||
* Supplies the base address of the structure to probe.
|
||||
*
|
||||
* @param Size
|
||||
* Supplies the total size of the structure in bytes.
|
||||
*
|
||||
* @param Alignment
|
||||
* Supplies the required structure alignment (must be 1, 2, 4, 8, or 16).
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTAPI
|
||||
VOID
|
||||
MM::Probe::ProbeForWriteStructure(IN PVOID Address,
|
||||
IN SIZE_T Size,
|
||||
IN ULONG Alignment)
|
||||
{
|
||||
/* Delegate fast-path boundary and alignment verification to the Read probe (DRY) */
|
||||
ProbeForReadStructure(Address, Size, Alignment);
|
||||
|
||||
/* Check if the buffer size is zero or exceeds the page size */
|
||||
if((Size == 0) || (Size >= MM_PAGE_SIZE))
|
||||
{
|
||||
/* Perform write accessibility verification */
|
||||
ProbeForWrite(Address, Size, Alignment);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Touch the first byte to verify write access */
|
||||
*(VOLATILE PUCHAR)Address = *(VOLATILE PUCHAR)Address;
|
||||
|
||||
/* Check if the buffer size exceeds the alignment */
|
||||
if(Size > Alignment)
|
||||
{
|
||||
/* Touch the last byte to ensure full structure spans valid memory */
|
||||
((VOLATILE PUCHAR)Address)[(Size - 1) & ~(SIZE_T)(Alignment - 1)] =
|
||||
((VOLATILE PUCHAR)Address)[(Size - 1) & ~(SIZE_T)(Alignment - 1)];
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user