mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
[UMKM_APITEST] Add a test for syscall handling
This is intentionally not part of ntdll_apitest, because that links to advapi32, which links to rpcrt4, which (wrongly!) links to ws2_32, which (wrongly!) links to user32, which breaks the test.
This commit is contained in:
parent
a771729e69
commit
ea28951607
8 changed files with 628 additions and 0 deletions
|
@ -49,6 +49,7 @@ add_subdirectory(shell32)
|
|||
add_subdirectory(shlwapi)
|
||||
add_subdirectory(spoolss)
|
||||
add_subdirectory(psapi)
|
||||
add_subdirectory(umkm)
|
||||
add_subdirectory(user32)
|
||||
add_subdirectory(user32_dynamic)
|
||||
add_subdirectory(userenv)
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#define ok_hr_(file, line, status, expected) ok_hex_(file, line, status, expected)
|
||||
|
||||
#define ok_eq_print(value, expected, spec) ok((value) == (expected), #value " = " spec ", expected " spec "\n", value, expected)
|
||||
#define ok_eq_print_(file, line, value, expected, spec) ok_(file,line)((value) == (expected), #value " = " spec ", expected " spec "\n", value, expected)
|
||||
#define ok_eq_pointer(value, expected) ok_eq_print(value, expected, "%p")
|
||||
#define ok_eq_int(value, expected) ok_eq_print(value, expected, "%d")
|
||||
#define ok_eq_uint(value, expected) ok_eq_print(value, expected, "%u")
|
||||
|
@ -83,6 +84,8 @@
|
|||
#define ok_eq_wstr(value, expected) ok(!wcscmp(value, expected), #value " = \"%ls\", expected \"%ls\"\n", value, expected)
|
||||
#define ok_eq_tag(value, expected) ok_eq_print(value, expected, "0x%08lx")
|
||||
|
||||
#define ok_eq_hex_(file, line, value, expected) ok_eq_print_(file, line, value, expected, "0x%08lx")
|
||||
#define ok_eq_hex64_(file, line, value, expected) ok_eq_print_(file, line, value, expected, "%I64x")
|
||||
#define ok_eq_hex64(value, expected) ok_eq_print(value, expected, "%I64x")
|
||||
#define ok_eq_xmm(value, expected) ok((value).Low == (expected).Low, #value " = %I64x'%08I64x, expected %I64x'%08I64x\n", (value).Low, (value).High, (expected).Low, (expected).High)
|
||||
|
||||
|
|
33
modules/rostests/apitests/umkm/CMakeLists.txt
Normal file
33
modules/rostests/apitests/umkm/CMakeLists.txt
Normal file
|
@ -0,0 +1,33 @@
|
|||
|
||||
include_directories(${REACTOS_SOURCE_DIR}/ntoskrnl/include)
|
||||
|
||||
list(APPEND SOURCE
|
||||
SystemCall.c
|
||||
precomp.h)
|
||||
|
||||
if(ARCH STREQUAL "i386")
|
||||
add_asm_files(umkm_apitest_asm
|
||||
i386/SystemCall_asm.s
|
||||
)
|
||||
elseif(ARCH STREQUAL "amd64")
|
||||
add_asm_files(umkm_apitest_asm
|
||||
amd64/SystemCall_asm.s
|
||||
)
|
||||
endif()
|
||||
|
||||
list(APPEND PCH_SKIP_SOURCE
|
||||
testlist.c)
|
||||
|
||||
add_executable(umkm_apitest
|
||||
${SOURCE}
|
||||
${umkm_apitest_asm}
|
||||
${PCH_SKIP_SOURCE})
|
||||
|
||||
target_link_libraries(umkm_apitest wine uuid ${PSEH_LIB})
|
||||
set_module_type(umkm_apitest win32cui)
|
||||
add_importlibs(umkm_apitest msvcrt kernel32 ntdll)
|
||||
add_pch(umkm_apitest precomp.h "${PCH_SKIP_SOURCE}")
|
||||
add_dependencies(umkm_apitest load_notifications)
|
||||
|
||||
add_rostests_file(TARGET umkm_apitest)
|
||||
|
314
modules/rostests/apitests/umkm/SystemCall.c
Normal file
314
modules/rostests/apitests/umkm/SystemCall.c
Normal file
|
@ -0,0 +1,314 @@
|
|||
/*
|
||||
* PROJECT: ReactOS API Tests
|
||||
* LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
|
||||
* PURPOSE: Tests for system calls
|
||||
* COPYRIGHT: Copyright 2024 Timo Kreuzer <timo.kreuzer@reactos.org>
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
#define EFLAGS_TF 0x100L
|
||||
#define EFLAGS_INTERRUPT_MASK 0x200L
|
||||
|
||||
ULONG g_NoopSyscallNumber = 0;
|
||||
ULONG g_HandlerCalled = 0;
|
||||
ULONG g_RandomSeed = 0x63c28b49;
|
||||
|
||||
VOID
|
||||
DoSyscallAndCaptureContext(
|
||||
_In_ ULONG SyscallNumber,
|
||||
_Out_ PCONTEXT PreContext,
|
||||
_Out_ PCONTEXT PostContext);
|
||||
|
||||
extern const UCHAR SyscallReturn;
|
||||
|
||||
ULONG_PTR
|
||||
DoSyscallWithUnalignedStack(
|
||||
_In_ ULONG64 SyscallNumber);
|
||||
|
||||
#ifdef _M_IX86
|
||||
__declspec(dllimport)
|
||||
VOID
|
||||
NTAPI
|
||||
KiFastSystemCallRet(VOID);
|
||||
#endif
|
||||
|
||||
static
|
||||
BOOLEAN
|
||||
InitSysCalls()
|
||||
{
|
||||
/* Scan instructions in NtFlushWriteBuffer to find the syscall number
|
||||
for NtFlushWriteBuffer, which is a noop syscall on x86/x64 */
|
||||
PUCHAR Instructions = (PUCHAR)NtFlushWriteBuffer;
|
||||
for (ULONG i = 0; i < 32; i++)
|
||||
{
|
||||
if (Instructions[i] == 0xB8)
|
||||
{
|
||||
g_NoopSyscallNumber = *(PULONG)&Instructions[i + 1];
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
LoadUser32()
|
||||
{
|
||||
HMODULE hUser32 = LoadLibraryW(L"user32.dll");
|
||||
ok(hUser32 != NULL, "Failed to load user32.dll\n");
|
||||
}
|
||||
|
||||
static
|
||||
LONG
|
||||
WINAPI
|
||||
VectoredExceptionHandlerForUserModeCallback(
|
||||
struct _EXCEPTION_POINTERS *ExceptionInfo)
|
||||
{
|
||||
g_HandlerCalled++;
|
||||
|
||||
/* Return from the callback */
|
||||
NtCallbackReturn(NULL, 0, 0xdeadbeef);
|
||||
|
||||
/* If that failed, we were not in a callback, keep searching */
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
VOID
|
||||
ValidateSyscall_(
|
||||
_In_ PCCH File,
|
||||
_In_ ULONG Line,
|
||||
_In_ ULONG_PTR SyscallId,
|
||||
_In_ ULONG_PTR Result)
|
||||
{
|
||||
CONTEXT PreContext, PostContext;
|
||||
|
||||
#ifdef _M_IX86
|
||||
DoSyscallAndCaptureContext(SyscallId, &PreContext, &PostContext);
|
||||
|
||||
/* Non-volatile registers and rsp are unchanged */
|
||||
ok_eq_hex_(File, Line, PostContext.Esp, PreContext.Esp);
|
||||
ok_eq_hex_(File, Line, PostContext.Ebx, PreContext.Ebx);
|
||||
ok_eq_hex_(File, Line, PostContext.Esi, PreContext.Esi);
|
||||
ok_eq_hex_(File, Line, PostContext.Edi, PreContext.Edi);
|
||||
ok_eq_hex_(File, Line, PostContext.Ebp, PreContext.Ebp);
|
||||
|
||||
/* Special cases */
|
||||
ok_eq_hex_(File, Line, PostContext.Ecx, PreContext.Esp - 0x4C);
|
||||
ok_eq_hex_(File, Line, PostContext.Edx, (ULONG)KiFastSystemCallRet);
|
||||
ok_eq_hex_(File, Line, PostContext.Eax, Result);
|
||||
|
||||
#elif defined(_M_AMD64)
|
||||
/* Initiaize the pre-contex with random numbers */
|
||||
PULONG64 IntegerRegs = &PreContext.Rax;
|
||||
PM128A XmmRegs = &PreContext.Xmm0;
|
||||
for (ULONG Index = 0; Index < 16; Index++)
|
||||
{
|
||||
IntegerRegs[Index] = (ULONG64)RtlRandom(&g_RandomSeed) << 32 | RtlRandom(&g_RandomSeed);
|
||||
XmmRegs[Index].Low = (ULONG64)RtlRandom(&g_RandomSeed) << 32 | RtlRandom(&g_RandomSeed);
|
||||
XmmRegs[Index].High = (ULONG64)RtlRandom(&g_RandomSeed) << 32 | RtlRandom(&g_RandomSeed);
|
||||
}
|
||||
PreContext.EFlags = RtlRandom(&g_RandomSeed);
|
||||
PreContext.EFlags &= ~(EFLAGS_TF | 0x20 | 0x40000);
|
||||
PreContext.EFlags |= EFLAGS_INTERRUPT_MASK;
|
||||
|
||||
PreContext.SegDs = 0; //0x0028;
|
||||
PreContext.SegEs = 0; //0x002B;
|
||||
PreContext.SegFs = 0; //0x0053;
|
||||
PreContext.SegGs = 0; //0x002B;
|
||||
PreContext.SegSs = 0; // 0x002B;
|
||||
|
||||
DoSyscallAndCaptureContext(SyscallId, &PreContext, &PostContext);
|
||||
|
||||
/* Non-volatile registers and rsp are unchanged */
|
||||
ok_eq_hex64_(File, Line, PostContext.Rsp, PreContext.Rsp);
|
||||
ok_eq_hex64_(File, Line, PostContext.Rbx, PreContext.Rbx);
|
||||
ok_eq_hex64_(File, Line, PostContext.Rsi, PreContext.Rsi);
|
||||
ok_eq_hex64_(File, Line, PostContext.Rdi, PreContext.Rdi);
|
||||
ok_eq_hex64_(File, Line, PostContext.Rbp, PreContext.Rbp);
|
||||
ok_eq_hex64_(File, Line, PostContext.R12, PreContext.R12);
|
||||
ok_eq_hex64_(File, Line, PostContext.R13, PreContext.R13);
|
||||
ok_eq_hex64_(File, Line, PostContext.R14, PreContext.R14);
|
||||
ok_eq_hex64_(File, Line, PostContext.R15, PreContext.R15);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm6.Low, PreContext.Xmm6.Low);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm6.High, PreContext.Xmm6.High);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm7.Low, PreContext.Xmm7.Low);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm7.High, PreContext.Xmm7.High);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm8.Low, PreContext.Xmm8.Low);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm8.High, PreContext.Xmm8.High);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm9.Low, PreContext.Xmm9.Low);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm9.High, PreContext.Xmm9.High);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm10.Low, PreContext.Xmm10.Low);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm10.High, PreContext.Xmm10.High);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm11.Low, PreContext.Xmm11.Low);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm11.High, PreContext.Xmm11.High);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm12.Low, PreContext.Xmm12.Low);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm12.High, PreContext.Xmm12.High);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm13.Low, PreContext.Xmm13.Low);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm13.High, PreContext.Xmm13.High);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm14.Low, PreContext.Xmm14.Low);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm14.High, PreContext.Xmm14.High);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm15.Low, PreContext.Xmm15.Low);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm15.High, PreContext.Xmm15.High);
|
||||
|
||||
/* Parity flag is flaky */
|
||||
ok_eq_hex64_(File, Line, PostContext.EFlags & ~0x4, PreContext.EFlags & ~0x9F5);
|
||||
|
||||
ok_eq_hex64_(File, Line, PostContext.SegCs, 0x0033);
|
||||
ok_eq_hex64_(File, Line, PostContext.SegSs, 0x002B);
|
||||
ok_(File, Line)(PostContext.SegDs == PreContext.SegDs || PostContext.SegDs == 0x002B,
|
||||
"Expected 0x002B, got 0x%04X\n", PostContext.SegDs);
|
||||
ok_(File, Line)(PostContext.SegEs == PreContext.SegEs || PostContext.SegEs == 0x002B,
|
||||
"Expected 0x002B, got 0x%04X\n", PostContext.SegEs);
|
||||
ok_(File, Line)(PostContext.SegFs == PreContext.SegFs || PostContext.SegFs == 0x0053,
|
||||
"Expected 0x002B, got 0x%04X\n", PostContext.SegFs);
|
||||
ok_(File, Line)(PostContext.SegGs == PreContext.SegGs || PostContext.SegGs == 0x002B,
|
||||
"Expected 0x002B, got 0x%04X\n", PostContext.SegGs);
|
||||
ok_eq_hex64_(File, Line, PostContext.SegSs, 0x002B);
|
||||
|
||||
/* These volatile registers are zeroed */
|
||||
ok_eq_hex64_(File, Line, PostContext.Rdx, 0);
|
||||
ok_eq_hex64_(File, Line, PostContext.R10, 0);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm0.Low, 0);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm0.High, 0);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm1.Low, 0);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm1.High, 0);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm2.Low, 0);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm2.High, 0);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm3.Low, 0);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm3.High, 0);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm4.Low, 0);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm4.High, 0);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm5.Low, 0);
|
||||
ok_eq_hex64_(File, Line, PostContext.Xmm5.High, 0);
|
||||
|
||||
/* Special cases */
|
||||
ok_eq_hex64_(File, Line, PostContext.Rax, Result);
|
||||
ok_eq_hex64_(File, Line, PostContext.Rcx, (ULONG64)&SyscallReturn);
|
||||
ok_eq_hex64_(File, Line, PostContext.R8, PreContext.Rsp);
|
||||
ok_eq_hex64_(File, Line, PostContext.R9, PreContext.Rbp);
|
||||
ok_eq_hex64_(File, Line, PostContext.R11, PostContext.EFlags);
|
||||
|
||||
// TODO:Debug regs, mxcsr, floating point, etc.
|
||||
#else
|
||||
#error Unsupported architecture
|
||||
#endif
|
||||
}
|
||||
|
||||
#define ValidateSyscall(SyscallId, Result) ValidateSyscall_(__FILE__, __LINE__, SyscallId, Result)
|
||||
|
||||
static
|
||||
VOID
|
||||
Test_SyscallNumbers()
|
||||
{
|
||||
BOOL Wow64Process;
|
||||
|
||||
if (IsWow64Process(NtCurrentProcess(), &Wow64Process) && Wow64Process)
|
||||
{
|
||||
skip("Skipping syscall tests on WOW64\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Test valid syscall number */
|
||||
ValidateSyscall(g_NoopSyscallNumber, STATUS_SUCCESS);
|
||||
|
||||
/* Test invalid syscall number */
|
||||
ValidateSyscall(0x0FFF, (ULONG)STATUS_INVALID_SYSTEM_SERVICE);
|
||||
|
||||
/* Add a vectored exception handler to catch the exception we will get
|
||||
when KiUserCallbackDispatcher is called and user32.dll is not loaded
|
||||
We cannot use SEH here, because the exception is outside of the try block */
|
||||
PVOID hHandler = AddVectoredExceptionHandler(TRUE, VectoredExceptionHandlerForUserModeCallback);
|
||||
ok(hHandler != NULL, "Failed to add vectored exception handler\n");
|
||||
|
||||
/* Test win32k syscall number without user32.dll loaded */
|
||||
#ifdef _M_AMD64
|
||||
ValidateSyscall(0x1000, STATUS_SUCCESS);
|
||||
#else
|
||||
ValidateSyscall(0x1000, (ULONG)STATUS_INVALID_SYSTEM_SERVICE);
|
||||
#endif
|
||||
ok_eq_ulong(g_HandlerCalled, 1UL);
|
||||
|
||||
/* Test invalid win32k syscall number without user32.dll loaded */
|
||||
#ifdef _M_IX86
|
||||
ValidateSyscall(0x1FFF, 0xffffffbf);
|
||||
#else
|
||||
ValidateSyscall(0x1FFF, (ULONG)STATUS_INVALID_SYSTEM_SERVICE);
|
||||
#endif
|
||||
|
||||
ok_eq_ulong(g_HandlerCalled, 2UL);
|
||||
|
||||
RemoveVectoredExceptionHandler(hHandler);
|
||||
|
||||
LoadUser32();
|
||||
|
||||
/* Test invalid win32k syscall number */
|
||||
#ifdef _M_IX86
|
||||
ValidateSyscall(0x1FFF, 0xffffffbf);
|
||||
#else
|
||||
ValidateSyscall(0x1FFF, (ULONG)STATUS_INVALID_SYSTEM_SERVICE);
|
||||
#endif
|
||||
|
||||
/* Test invalid syscall table number */
|
||||
ValidateSyscall(0x2000 + g_NoopSyscallNumber, STATUS_SUCCESS);
|
||||
ValidateSyscall(0x3000 + g_NoopSyscallNumber, STATUS_SUCCESS);
|
||||
|
||||
#if 0 // This only happens, when running the test from VS, but not from the command line
|
||||
/* For some unknown reason the result gets sign extended in this case */
|
||||
ULONG64 Result = DoSyscallWithUnalignedStack(0x2000);
|
||||
ok_eq_hex64(Result, (LONG)STATUS_ACCESS_VIOLATION);
|
||||
#endif
|
||||
|
||||
/* Test invalid upper bits in syscall number */
|
||||
ValidateSyscall(0xFFFFFFFFFFF70000ULL + g_NoopSyscallNumber, STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
Test_SyscallPerformance()
|
||||
{
|
||||
ULONG64 Start, End, Cycles;
|
||||
ULONG64 TotalCycles = 0, Min = -1, Max = 0;
|
||||
ULONG64 Count = 100000;
|
||||
ULONG Outliers = 0;
|
||||
ULONG_PTR OldAffinityMask;
|
||||
double AvgCycles;
|
||||
|
||||
OldAffinityMask = SetThreadAffinityMask(GetCurrentThread(), 1);
|
||||
|
||||
for (ULONG64 i = 0; i < Count; i++)
|
||||
{
|
||||
Start = __rdtsc();
|
||||
NtFlushWriteBuffer();
|
||||
End = __rdtsc();
|
||||
Cycles = End - Start;
|
||||
if (Cycles > 2000)
|
||||
{
|
||||
Outliers++;
|
||||
continue;
|
||||
}
|
||||
TotalCycles += Cycles;
|
||||
Min = min(Min, Cycles);
|
||||
Max = max(Max, Cycles);
|
||||
}
|
||||
|
||||
AvgCycles = (double)TotalCycles / (Count - Outliers);
|
||||
|
||||
trace("NtFlushWriteBuffer: avg %.2f cycles, min %I64u, max %I64u, Outliers %lu\n",
|
||||
AvgCycles, Min, Max, Outliers);
|
||||
|
||||
SetThreadAffinityMask(GetCurrentThread(), OldAffinityMask);
|
||||
}
|
||||
|
||||
START_TEST(SystemCall)
|
||||
{
|
||||
if (!InitSysCalls())
|
||||
{
|
||||
skip("Failed to initialize.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
Test_SyscallNumbers();
|
||||
Test_SyscallPerformance();
|
||||
}
|
167
modules/rostests/apitests/umkm/amd64/SystemCall_asm.s
Normal file
167
modules/rostests/apitests/umkm/amd64/SystemCall_asm.s
Normal file
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* PROJECT: ReactOS API Tests
|
||||
* LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
|
||||
* PURPOSE: x64 ASM helper functions for syscall tests
|
||||
* COPYRIGHT: Copyright 2024 Timo Kreuzer <timo.kreuzer@reactos.org>
|
||||
*/
|
||||
|
||||
#include <asm.inc>
|
||||
#include <ksamd64.inc>
|
||||
|
||||
.data
|
||||
g_Rcx:
|
||||
.quad 0
|
||||
g_SegSs:
|
||||
.short 0
|
||||
|
||||
.code64
|
||||
|
||||
EXTERN RtlCaptureContext:PROC
|
||||
EXTERN g_NoopSyscallNumber:DWORD
|
||||
|
||||
#define STACK_ARGUMENT_SPACE 16*8
|
||||
|
||||
LoadContext:
|
||||
push qword ptr [rcx + CxEFlags]
|
||||
popfq
|
||||
movdqu xmm0, [rcx + CxXmm0]
|
||||
movdqu xmm1, [rcx + CxXmm1]
|
||||
movdqu xmm2, [rcx + CxXmm2]
|
||||
movdqu xmm3, [rcx + CxXmm3]
|
||||
movdqu xmm4, [rcx + CxXmm4]
|
||||
movdqu xmm5, [rcx + CxXmm5]
|
||||
movdqu xmm6, [rcx + CxXmm6]
|
||||
movdqu xmm7, [rcx + CxXmm7]
|
||||
movdqu xmm8, [rcx + CxXmm8]
|
||||
movdqu xmm9, [rcx + CxXmm9]
|
||||
movdqu xmm10, [rcx + CxXmm10]
|
||||
movdqu xmm11, [rcx + CxXmm11]
|
||||
movdqu xmm12, [rcx + CxXmm12]
|
||||
movdqu xmm13, [rcx + CxXmm13]
|
||||
movdqu xmm14, [rcx + CxXmm14]
|
||||
movdqu xmm15, [rcx + CxXmm15]
|
||||
mov rax, [rcx + CxRax]
|
||||
mov rbx, [rcx + CxRbx]
|
||||
mov rdx, [rcx + CxRdx]
|
||||
mov rsi, [rcx + CxRsi]
|
||||
mov rdi, [rcx + CxRdi]
|
||||
mov rbp, [rcx + CxRbp]
|
||||
mov r8, [rcx + CxR8]
|
||||
mov r9, [rcx + CxR9]
|
||||
mov r10, [rcx + CxR10]
|
||||
mov r11, [rcx + CxR11]
|
||||
mov r12, [rcx + CxR12]
|
||||
mov r13, [rcx + CxR13]
|
||||
mov r14, [rcx + CxR14]
|
||||
mov r15, [rcx + CxR15]
|
||||
//mov rcx, [rcx + CxRcx]
|
||||
|
||||
mov ax, [rcx + CxSegDs]
|
||||
mov ds, ax
|
||||
mov ax, [rcx + CxSegEs]
|
||||
mov es, ax
|
||||
mov ax, [rcx + CxSegFs]
|
||||
mov fs, ax
|
||||
mov ax, [rcx + CxSegGs]
|
||||
//mov gs, ax // FIXME: ReactOS does not like this
|
||||
|
||||
ret
|
||||
|
||||
PUBLIC SyscallReturn
|
||||
|
||||
.PROC DoSyscallAndCaptureContext2
|
||||
/* Allocate enough space for the system call handler */
|
||||
sub rsp, STACK_ARGUMENT_SPACE + 5*8
|
||||
.ALLOCSTACK STACK_ARGUMENT_SPACE + 5*8
|
||||
.ENDPROLOG
|
||||
|
||||
/* Save rcx and r8 in the home space */
|
||||
mov [rsp + STACK_ARGUMENT_SPACE + 6*8], rcx
|
||||
mov [rsp + STACK_ARGUMENT_SPACE + 8*8], r8
|
||||
|
||||
/* Load the pre-context */
|
||||
mov rcx, rdx
|
||||
call LoadContext
|
||||
call RtlCaptureContext
|
||||
|
||||
mov ax, word ptr [rcx + CxSegSs]
|
||||
mov ss, ax
|
||||
|
||||
/* Do the syscall */
|
||||
mov rax, [rsp + STACK_ARGUMENT_SPACE + 6*8]
|
||||
syscall
|
||||
|
||||
GLOBAL_LABEL SyscallReturn
|
||||
|
||||
/* Save returned ss */
|
||||
mov qword ptr g_Rcx[rip], rcx
|
||||
mov cx, ss
|
||||
mov word ptr g_SegSs[rip], cx
|
||||
|
||||
mov cx, HEX(2B)
|
||||
mov ss, cx
|
||||
|
||||
/* Save the post-context */
|
||||
mov rcx, [rsp + STACK_ARGUMENT_SPACE + 8*8]
|
||||
call RtlCaptureContext
|
||||
|
||||
mov rcx, qword ptr g_Rcx[rip]
|
||||
mov rax, [rsp + STACK_ARGUMENT_SPACE + 8*8]
|
||||
mov [rax + CxRcx], rcx
|
||||
|
||||
mov ax, HEX(2B)
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
//mov gs, ax // FIXME: ReactOS does not like this
|
||||
mov ss, ax
|
||||
mov ax, HEX(53)
|
||||
mov fs, ax
|
||||
|
||||
cld
|
||||
|
||||
mov rcx, [rsp + STACK_ARGUMENT_SPACE + 8*8]
|
||||
mov ax, word ptr g_SegSs[rip]
|
||||
mov [rcx + CxSegSs], ax
|
||||
|
||||
add rsp, STACK_ARGUMENT_SPACE + 5*8
|
||||
ret
|
||||
.ENDP
|
||||
|
||||
/*
|
||||
* VOID
|
||||
* DoSyscallAndCaptureContext(
|
||||
* _In_ ULONG64 SyscallNumber,
|
||||
* _Out_ PCONTEXT PreContext,
|
||||
* _Out_ PCONTEXT PostContext);
|
||||
*/
|
||||
PUBLIC DoSyscallAndCaptureContext
|
||||
.PROC DoSyscallAndCaptureContext
|
||||
GENERATE_EXCEPTION_FRAME
|
||||
|
||||
call DoSyscallAndCaptureContext2
|
||||
|
||||
RESTORE_EXCEPTION_STATE
|
||||
ret
|
||||
|
||||
.ENDP
|
||||
|
||||
/*
|
||||
* ULONG64
|
||||
* DoSyscallWithUnalignedStack(
|
||||
* _In_ ULONG64 SyscallNumber);
|
||||
*/
|
||||
PUBLIC DoSyscallWithUnalignedStack
|
||||
.PROC DoSyscallWithUnalignedStack
|
||||
/* Allocate enough space for the system call handler */
|
||||
sub rsp, STACK_ARGUMENT_SPACE + 6*8
|
||||
.ALLOCSTACK STACK_ARGUMENT_SPACE + 6*8
|
||||
.ENDPROLOG
|
||||
|
||||
mov rax, rcx
|
||||
syscall
|
||||
|
||||
add rsp, STACK_ARGUMENT_SPACE + 6*8
|
||||
ret
|
||||
.ENDP
|
||||
|
||||
END
|
84
modules/rostests/apitests/umkm/i386/SystemCall_asm.s
Normal file
84
modules/rostests/apitests/umkm/i386/SystemCall_asm.s
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* PROJECT: ReactOS API Tests
|
||||
* LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
|
||||
* PURPOSE: x86 ASM helper functions for syscall tests
|
||||
* COPYRIGHT: Copyright 2024 Timo Kreuzer <timo.kreuzer@reactos.org>
|
||||
*/
|
||||
|
||||
#include <asm.inc>
|
||||
#include <ks386.inc>
|
||||
|
||||
.code
|
||||
|
||||
#define STACK_ARGUMENT_SPACE 16*4
|
||||
|
||||
EXTERN _RtlCaptureContext@4:PROC
|
||||
|
||||
DoSyscall:
|
||||
mov edx, esp
|
||||
sysenter
|
||||
ret
|
||||
|
||||
/*
|
||||
* VOID
|
||||
* DoSyscallAndCaptureContext(
|
||||
* _In_ ULONG64 SyscallNumber,
|
||||
* _Out_ PCONTEXT PreContext,
|
||||
* _Out_ PCONTEXT PostContext);
|
||||
*/
|
||||
PUBLIC _DoSyscallAndCaptureContext
|
||||
.PROC _DoSyscallAndCaptureContext
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
|
||||
/* Allocate enough space for the system call handler */
|
||||
sub esp, STACK_ARGUMENT_SPACE
|
||||
|
||||
/* Save the pre-context */
|
||||
push [ebp + 12]
|
||||
call _RtlCaptureContext@4
|
||||
|
||||
/* Do the system call */
|
||||
mov eax, [ebp + 8]
|
||||
Call DoSyscall
|
||||
|
||||
/* Save eax */
|
||||
push eax
|
||||
|
||||
/* Save the post-context */
|
||||
push dword ptr [ebp + 16]
|
||||
call _RtlCaptureContext@4
|
||||
|
||||
/* Restore eax and save it in the context */
|
||||
pop eax
|
||||
mov ecx, [ebp + 16]
|
||||
mov [ecx + CsEax], eax
|
||||
|
||||
mov esp, ebp
|
||||
pop ebp
|
||||
ret
|
||||
.ENDP
|
||||
|
||||
/*
|
||||
* ULONG64
|
||||
* DoSyscallWithUnalignedStack(
|
||||
* _In_ ULONG64 SyscallNumber);
|
||||
*/
|
||||
PUBLIC _DoSyscallWithUnalignedStack
|
||||
.PROC _DoSyscallWithUnalignedStack
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
|
||||
/* Allocate enough space for the system call handler */
|
||||
sub esp, STACK_ARGUMENT_SPACE
|
||||
|
||||
/* Do the sysenter */
|
||||
mov eax, [ebp + 8]
|
||||
sysenter
|
||||
|
||||
mov esp, ebp
|
||||
pop ebp
|
||||
ret
|
||||
.ENDP
|
||||
|
||||
END
|
13
modules/rostests/apitests/umkm/precomp.h
Normal file
13
modules/rostests/apitests/umkm/precomp.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define WIN32_NO_STATUS
|
||||
#define _INC_WINDOWS
|
||||
#define COM_NO_WINDOWS_H
|
||||
|
||||
#include <apitest.h>
|
||||
#include <apitest_guard.h>
|
||||
#include <ndk/ntndk.h>
|
||||
#include <strsafe.h>
|
||||
#include <pseh/pseh2.h>
|
13
modules/rostests/apitests/umkm/testlist.c
Normal file
13
modules/rostests/apitests/umkm/testlist.c
Normal file
|
@ -0,0 +1,13 @@
|
|||
#define __ROS_LONG64__
|
||||
|
||||
#define STANDALONE
|
||||
#include <apitest.h>
|
||||
|
||||
extern void func_SystemCall(void);
|
||||
|
||||
const struct test winetest_testlist[] =
|
||||
{
|
||||
{ "SystemCall", func_SystemCall },
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
Loading…
Reference in a new issue