Add memory manager probe functions
All checks were successful
Builds / ExectOS (i686, release) (push) Successful in 34s
Builds / ExectOS (i686, debug) (push) Successful in 41s
Builds / ExectOS (amd64, release) (push) Successful in 36s
Builds / ExectOS (amd64, debug) (push) Successful in 43s

This commit is contained in:
2026-06-30 22:27:01 +02:00
parent ef4f9ba74d
commit d8f4f6bfd0
5 changed files with 325 additions and 0 deletions

View File

@@ -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)

View File

@@ -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

View File

@@ -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>

View 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
View 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)];
}
}
}