mirror of
https://github.com/reactos/reactos.git
synced 2025-08-01 19:22:58 +00:00
[KMTESTS:HAL] Add a test for string I/O intrinsic functions
CORE-20078
This commit is contained in:
parent
4a3a446ba7
commit
7c3a119d6d
3 changed files with 153 additions and 1 deletions
|
@ -124,7 +124,8 @@ if(ARCH STREQUAL "i386" OR ARCH STREQUAL "amd64")
|
|||
add_asm_files(KMTEST_DRV_ASM
|
||||
kmtest_drv/vm_detect.S)
|
||||
list(APPEND KMTEST_DRV_SOURCE
|
||||
${KMTEST_DRV_ASM})
|
||||
${KMTEST_DRV_ASM}
|
||||
hal/HalPortIo.c)
|
||||
endif()
|
||||
|
||||
add_library(kmtest_drv MODULE ${KMTEST_DRV_SOURCE})
|
||||
|
|
145
modules/rostests/kmtests/hal/HalPortIo.c
Normal file
145
modules/rostests/kmtests/hal/HalPortIo.c
Normal file
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Kernel-Mode Tests
|
||||
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
|
||||
* PURPOSE: Tests for string I/O intrinsic functions
|
||||
* COPYRIGHT: Copyright 2025 Dmitry Borisov <di.sean@protonmail.com>
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include <kmt_test.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
/* Compile with the highest optimization level to trigger a bug (See CORE-20078) */
|
||||
#ifdef _MSC_VER
|
||||
#pragma optimize("gst", on)
|
||||
#pragma auto_inline(on)
|
||||
#else
|
||||
#pragma GCC optimize("O3")
|
||||
#endif
|
||||
|
||||
/* Used to isolate the effects of intrinsics from each other */
|
||||
typedef struct _TEST_CONTEXT
|
||||
{
|
||||
PVOID OldBuffer;
|
||||
UCHAR Pad[78];
|
||||
USHORT Port;
|
||||
ULONG Size;
|
||||
PVOID Buffer;
|
||||
} TEST_CONTEXT, *PTEST_CONTEXT;
|
||||
|
||||
/* TEST FUNCTIONS *************************************************************/
|
||||
|
||||
static
|
||||
/*
|
||||
* Isolate the effects of intrinsics from each other
|
||||
* and hide the TEST_CONTEXT initialization from the optimizer.
|
||||
*/
|
||||
DECLSPEC_NOINLINE
|
||||
VOID
|
||||
TestWriteStringUshort(
|
||||
_In_ PTEST_CONTEXT Context)
|
||||
{
|
||||
__outwordstring(Context->Port, Context->Buffer, Context->Size / sizeof(USHORT));
|
||||
|
||||
/*
|
||||
* The 'rep outsw' instruction increments or decrements the address in ESI by Size * 2.
|
||||
* Test for CORE-20078: the ESI value should be preserved across calls.
|
||||
*/
|
||||
ok_eq_pointer(Context->Buffer, Context->OldBuffer);
|
||||
}
|
||||
|
||||
static
|
||||
DECLSPEC_NOINLINE
|
||||
VOID
|
||||
TestWriteStringUlong(
|
||||
_In_ PTEST_CONTEXT Context)
|
||||
{
|
||||
__outdwordstring(Context->Port, Context->Buffer, Context->Size / sizeof(ULONG));
|
||||
|
||||
ok_eq_pointer(Context->Buffer, Context->OldBuffer);
|
||||
}
|
||||
|
||||
static
|
||||
DECLSPEC_NOINLINE
|
||||
VOID
|
||||
TestWriteStringUchar(
|
||||
_In_ PTEST_CONTEXT Context)
|
||||
{
|
||||
__inbytestring(Context->Port, Context->Buffer, Context->Size);
|
||||
|
||||
ok_eq_pointer(Context->Buffer, Context->OldBuffer);
|
||||
}
|
||||
|
||||
static
|
||||
DECLSPEC_NOINLINE
|
||||
VOID
|
||||
TestReadStringUshort(
|
||||
_In_ PTEST_CONTEXT Context)
|
||||
{
|
||||
__inwordstring(Context->Port, Context->Buffer, Context->Size / sizeof(USHORT));
|
||||
|
||||
ok_eq_pointer(Context->Buffer, Context->OldBuffer);
|
||||
}
|
||||
|
||||
static
|
||||
DECLSPEC_NOINLINE
|
||||
VOID
|
||||
TestReadStringUlong(
|
||||
_In_ PTEST_CONTEXT Context)
|
||||
{
|
||||
__outdwordstring(Context->Port, Context->Buffer, Context->Size / sizeof(ULONG));
|
||||
|
||||
ok_eq_pointer(Context->Buffer, Context->OldBuffer);
|
||||
}
|
||||
|
||||
static
|
||||
DECLSPEC_NOINLINE
|
||||
VOID
|
||||
TestReadStringUchar(
|
||||
_In_ PTEST_CONTEXT Context)
|
||||
{
|
||||
__inbytestring(Context->Port, Context->Buffer, Context->Size);
|
||||
|
||||
ok_eq_pointer(Context->Buffer, Context->OldBuffer);
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
TestStringIo(VOID)
|
||||
{
|
||||
TEST_CONTEXT Context;
|
||||
UCHAR Buffer[20];
|
||||
|
||||
/* End of the x86 I/O range */
|
||||
Context.Port = 0xFFFF - sizeof(ULONG);
|
||||
|
||||
Context.Buffer = Buffer;
|
||||
Context.OldBuffer = Buffer;
|
||||
Context.Size = sizeof(Buffer);
|
||||
|
||||
TestReadStringUchar(&Context);
|
||||
TestReadStringUshort(&Context);
|
||||
TestReadStringUlong(&Context);
|
||||
|
||||
/*
|
||||
* Check whether the driver is running inside a virtual machine
|
||||
* as it's not safe to write to I/O ports
|
||||
* without having the port resources assigned.
|
||||
*/
|
||||
if (!skip(KmtIsVirtualMachine, "Please run those tests in a supported virtual machine\n"))
|
||||
{
|
||||
TestWriteStringUchar(&Context);
|
||||
TestWriteStringUshort(&Context);
|
||||
TestWriteStringUlong(&Context);
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(HalPortIo)
|
||||
{
|
||||
TestStringIo();
|
||||
}
|
|
@ -26,6 +26,9 @@ KMT_TESTFUNC Test_FsRtlLegal;
|
|||
KMT_TESTFUNC Test_FsRtlMcb;
|
||||
KMT_TESTFUNC Test_FsRtlRemoveDotsFromPath;
|
||||
KMT_TESTFUNC Test_FsRtlTunnel;
|
||||
#if defined(_M_IX86) || defined(_M_AMD64)
|
||||
KMT_TESTFUNC Test_HalPortIo;
|
||||
#endif
|
||||
KMT_TESTFUNC Test_HalSystemInfo;
|
||||
KMT_TESTFUNC Test_IoCreateFile;
|
||||
KMT_TESTFUNC Test_IoDeviceInterface;
|
||||
|
@ -110,6 +113,9 @@ const KMT_TEST TestList[] =
|
|||
{ "FsRtlMcb", Test_FsRtlMcb },
|
||||
{ "FsRtlRemoveDotsFromPath", Test_FsRtlRemoveDotsFromPath },
|
||||
{ "FsRtlTunnel", Test_FsRtlTunnel },
|
||||
#if defined(_M_IX86) || defined(_M_AMD64)
|
||||
{ "HalPortIo", Test_HalPortIo },
|
||||
#endif
|
||||
{ "HalSystemInfo", Test_HalSystemInfo },
|
||||
{ "IoCreateFile", Test_IoCreateFile },
|
||||
{ "IoDeviceInterface", Test_IoDeviceInterface },
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue