Port components/Spinlock.c to Linux kernel module
Some checks are pending
vs2026-ci / win-amd64-build (debug, x64) (push) Waiting to run
vs2026-ci / win-amd64-build (release, x64) (push) Waiting to run
vs2026-ci / Deploy release (push) Blocked by required conditions

Route Spinlock.c's three MSVC intrinsics through the platform
intrinsics layer instead of the Windows builtins:
  _mm_pause                 -> CpuPause (already existed)
  _interlockedbittestandset -> CpuInterlockedBitTestAndSet (new)
  InterlockedCompareExchange-> CpuInterlockedCompareExchange (new, 32-bit)

Add the two new Cpu* wrappers to the kernel PlatformIntrinsics
{.h,.c} with win + linux arms (Linux uses __atomic_* builtins,
mirroring the existing 64-bit CAS), keeping the Cpu* wrappers the
single intrinsic boundary.
This commit is contained in:
Max Raulea 2026-08-14 11:35:21 +02:00
parent 368f0302f4
commit 4dc132937f
6 changed files with 77 additions and 11 deletions

View file

@ -86,12 +86,16 @@ HyperDbg-objs += include/platform/kernel/code/PlatformSpinlock.o
HyperDbg-objs += include/platform/kernel/code/PlatformTime.o
# --- components (shared, header-driven) ------------------------------------
# Self-contained (compile clean today):
HyperDbg-objs += include/components/spinlock/code/Spinlock.o
HyperDbg-objs += include/components/optimizations/code/AvlTree.o
HyperDbg-objs += include/components/optimizations/code/BinarySearch.o
HyperDbg-objs += include/components/optimizations/code/InsertionSort.o
HyperDbg-objs += include/components/optimizations/code/OptimizationsExamples.o
HyperDbg-objs += include/components/callback/code/HyperLogCallback.o
# hyperlog-gated — these pull in the logging layer (Log/LogInfo) and its globals
# (g_Callbacks), so they cannot compile until hyperlog/code/Logging.c is ported.
# Uncomment each alongside hyperlog.
# HyperDbg-objs += include/components/optimizations/code/BinarySearch.o
# HyperDbg-objs += include/components/optimizations/code/OptimizationsExamples.o
# HyperDbg-objs += include/components/callback/code/HyperLogCallback.o
# --- script-eval (script engine kernel eval) -------------------------------
# HyperDbg-objs += script-eval/code/Functions.o
@ -101,8 +105,8 @@ HyperDbg-objs += include/components/callback/code/HyperLogCallback.o
# HyperDbg-objs += script-eval/code/ScriptEngineEval.o
# --- hyperlog (message logging/tracing) ------------------------------------
# HyperDbg-objs += hyperlog/code/Logging.o
# HyperDbg-objs += hyperlog/code/UnloadDll.o
HyperDbg-objs += hyperlog/code/Logging.o
HyperDbg-objs += hyperlog/code/UnloadDll.o
# --- hyperhv (hypervisor: VMX/EPT) -----------------------------------------
# HyperDbg-objs += hyperhv/code/broadcast/Broadcast.o

View file

@ -40,7 +40,7 @@ static UINT32 g_MaxWait = 65536;
BOOLEAN
SpinlockTryLock(volatile LONG * Lock)
{
return (!(*Lock) && !_interlockedbittestandset(Lock, 0));
return (!(*Lock) && !CpuInterlockedBitTestAndSet(Lock, 0));
}
/**
@ -58,7 +58,7 @@ SpinlockLock(volatile LONG * Lock)
{
for (UINT32 i = 0; i < Wait; ++i)
{
_mm_pause();
CpuPause();
}
//
@ -94,11 +94,11 @@ SpinlockInterlockedCompareExchange(
{
UINT32 Wait = 1;
while (InterlockedCompareExchange(Destination, Exchange, Comperand) != Comperand)
while (CpuInterlockedCompareExchange(Destination, Exchange, Comperand) != Comperand)
{
for (UINT32 i = 0; i < Wait; ++i)
{
_mm_pause();
CpuPause();
}
//
@ -133,7 +133,7 @@ SpinlockLockWithCustomWait(volatile LONG * Lock, UINT32 MaximumWait)
{
for (UINT32 i = 0; i < Wait; ++i)
{
_mm_pause();
CpuPause();
}
//

View file

@ -406,6 +406,40 @@ CpuInterlockedCompareExchange64(INT64 volatile * Destination, INT64 ExChange, IN
#endif
}
/**
* @brief Atomic 32-bit compare-exchange
*/
inline LONG
CpuInterlockedCompareExchange(LONG volatile * Destination, LONG ExChange, LONG Comparand)
{
#if defined(_WIN32) || defined(_WIN64)
return InterlockedCompareExchange(Destination, ExChange, Comparand);
#elif defined(__linux__)
LONG Expected = Comparand;
__atomic_compare_exchange_n(Destination, &Expected, ExChange, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
return Expected;
#else
# error "Unsupported platform"
#endif
}
/**
* @brief Atomically set a bit, returning its previous value
*/
inline UCHAR
CpuInterlockedBitTestAndSet(volatile LONG * Base, LONG Bit)
{
#if defined(_WIN32) || defined(_WIN64)
return _interlockedbittestandset(Base, Bit);
#elif defined(__linux__)
LONG Mask = (1L << Bit);
LONG Old = __atomic_fetch_or(Base, Mask, __ATOMIC_SEQ_CST);
return (UCHAR)((Old >> Bit) & 1);
#else
# error "Unsupported platform"
#endif
}
//////////////////////////////////////////////////
// Descriptor Table Instructions //
//////////////////////////////////////////////////

View file

@ -226,6 +226,12 @@ CpuInterlockedDecrement64(INT64 volatile * Addend);
extern inline INT64
CpuInterlockedCompareExchange64(INT64 volatile * Destination, INT64 ExChange, INT64 Comparand);
extern inline LONG
CpuInterlockedCompareExchange(LONG volatile * Destination, LONG ExChange, LONG Comparand);
extern inline UCHAR
CpuInterlockedBitTestAndSet(volatile LONG * Base, LONG Bit);
//////////////////////////////////////////////////
// Descriptor Table Instructions //
//////////////////////////////////////////////////

View file

@ -1050,6 +1050,28 @@ them). All three kernel symbols are module-exported (verified). Guard removed.
Note: upstream `Logging.c` currently has the timestamp *formatting* commented out
(`RtlStringCchPrintfA` not IRQL-safe), so the value is computed but not yet printed.
### `components/` layer — PARTIAL (2026-08-14)
Whole `components/` block had been uncommented in `Kbuild` optimistically, but only
three of six TUs are self-contained. Active now (compile clean, in `HyperDbg.ko`):
`spinlock/Spinlock.o`, `optimizations/AvlTree.o`, `optimizations/InsertionSort.o`.
Re-commented (hyperlog-gated — need `Log`/`LogInfo` + the `g_Callbacks` global):
`optimizations/BinarySearch.o`, `optimizations/OptimizationsExamples.o`,
`callback/HyperLogCallback.o`. Uncomment those alongside `hyperlog/Logging.c`.
**`Spinlock.c`** — three MSVC intrinsics routed through the platform-intrinsics
layer (chosen over file-local shims: keeps the `Cpu*` wrappers the single intrinsic
boundary). Two new kernel wrappers added to `PlatformIntrinsics.{h,c}` (both with
win + linux arms, mirroring the existing 64-bit CAS):
| Spinlock.c call | new wrapper | Linux impl |
|-----------------|-------------|-----------|
| `_mm_pause()` | `CpuPause()` (already existed) | `__asm__("pause")` |
| `_interlockedbittestandset(l,0)` | `CpuInterlockedBitTestAndSet` | `__atomic_fetch_or` → old bit |
| `InterlockedCompareExchange` | `CpuInterlockedCompareExchange` (32-bit) | `__atomic_compare_exchange_n` |
`HyperDbg.ko` links clean with these three components active.
---
## Building

@ -1 +1 @@
Subproject commit db026cdab3b9d00d2b02691243f215b237792a5b
Subproject commit 3fbd59540fd90cda22ad1d00c18129539202070b