├── .gitignore ├── Make.bat ├── README.md ├── build-exm.bat └── src ├── cpuid-32.cc ├── cpuid-64.cc ├── ntkrnlpa;x86.5.2.3790.3959.def ├── ntoskrnl;x64.5.2.3790.3959.def └── ntoskrnl;x86.5.2.3790.3959.def /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | /bin/* 3 | /exm/* 4 | -------------------------------------------------------------------------------- /Make.bat: -------------------------------------------------------------------------------- 1 | :: create directories 2 | mkdir bin 2>NUL 3 | mkdir exm 2>NUL 4 | mkdir dll 2>NUL 5 | 6 | :: build object files 7 | @call :gen_obj 32 8 | @endlocal 9 | @call :gen_obj 64 10 | 11 | :: build exm files 12 | @setlocal 13 | @call exmod.bat x64 14 | @call :gen_exm ntkrnlpa x86.5.2.3790.3959 cpuid-32.o 15 | @call :gen_exm ntoskrnl x86.5.2.3790.3959 cpuid-32.o 16 | @call :gen_exm ntoskrnl x64.5.2.3790.3959 cpuid-64.o 17 | build-exm.bat 18 | 19 | :gen_obj 20 | @setlocal 21 | @call exmod.bat x%1 22 | @gcc src\cpuid-%1.cc %CFLAGS2% -D__W32API_USE_DLLIMPORT__ -c -o cpuid-%1.o 23 | @exit /B 24 | 25 | :gen_exm 26 | exe_mod +exm\%1.exe;htfix.exm:%2 src\%1;%2.def %3 27 | @exit /B 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ntoskrnl_HT_FIX 2 | fixes hyperthreading for windows 2003 when running on newer cpus 3 | 4 | When windows 2003 is installed on newer multicore cpus such as the i7-4790 the kernel does not correctly detect the core topology. In the case of i7-4790 the cpu is detected as having a single core with 8 hyperthreads. Threads are not scheduled efficiently when the core topology is wrong. In the example case the kernel makes no effort to keep a thread on the same core, the thread jumps randomly between cores on every context switch, this murders the cache resulting in somewhat lower performance. 5 | 6 | The kernel detects the core topology by way of the instruction cpuid. On older cpus the number of logical cores per physical core is returned in Bits 23-16, of Ebx, when Eax=1. For some reason, intel, at some point changed the meaning of these bits, they no longer reflect the number of logical cores per pysical and instead return some value of unknown meaning which in my case the kernel interprets as as 16 logical cores per pysical cpu. 7 | 8 | This problem is corrected by patching the cpuid function in ntoskrnl.exe. The new function replaces Bits 23-16, of Ebx, when Eax=1, With the expected value for an older hyperthreaded cpu. With this patch threads are now scheduled correctly. 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /build-exm.bat: -------------------------------------------------------------------------------- 1 | @call exmod.bat 2 | exe_mod dll\@ bin\@ exm\*.exm 3 | -------------------------------------------------------------------------------- /src/cpuid-32.cc: -------------------------------------------------------------------------------- 1 | 2 | extern "C" 3 | void __stdcall CPUID(int a1, int* a2, int* a3, int* a4, int* a5) 4 | { 5 | int EAX, EBX, ECX, EDX; 6 | asm("cpuid" : "=a"(EAX), "=b"(EBX), 7 | "=c"(ECX), "=d"(EDX) : "a"(a1)); 8 | if(a1 == 1) { 9 | EBX = (EBX & 0xFF00FFFF) | 0x00020000; } 10 | *a2 = EAX; *a3 = EBX; 11 | *a4 = ECX; *a5 = EDX; 12 | } 13 | -------------------------------------------------------------------------------- /src/cpuid-64.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef struct _CPU_INFO { 4 | ULONG Eax; 5 | ULONG Ebx; 6 | ULONG Ecx; 7 | ULONG Edx; 8 | } CPU_INFO, *PCPU_INFO; 9 | 10 | extern "C" 11 | VOID KiCpuId (ULONG Function, 12 | ULONG Index, PCPU_INFO CpuInfo 13 | ) 14 | { 15 | int EAX, EBX, ECX, EDX; 16 | asm("cpuid" : "=a"(EAX), "=b"(EBX), "=c"(ECX), 17 | "=d"(EDX) : "a"(Function), "c"(Index)); 18 | if(Function == 1) { 19 | EBX = (EBX & 0xFF00FFFF) | 0x00020000; } 20 | CpuInfo->Eax = EAX; CpuInfo->Ebx = EBX; 21 | CpuInfo->Ecx = ECX; CpuInfo->Edx = EDX; 22 | } 23 | -------------------------------------------------------------------------------- /src/ntkrnlpa;x86.5.2.3790.3959.def: -------------------------------------------------------------------------------- 1 | MAKEJUMP(0x00610060, _CPUID@20) -------------------------------------------------------------------------------- /src/ntoskrnl;x64.5.2.3790.3959.def: -------------------------------------------------------------------------------- 1 | MAKEJUMP(0x4266D0, KiCpuId) -------------------------------------------------------------------------------- /src/ntoskrnl;x86.5.2.3790.3959.def: -------------------------------------------------------------------------------- 1 | MAKEJUMP(0x0062AF13, _CPUID@20) --------------------------------------------------------------------------------