diff --git a/Base/usr/share/man/man1/crash.md b/Base/usr/share/man/man1/crash.md index 94de627518f..f0d8b451ea4 100644 --- a/Base/usr/share/man/man1/crash.md +++ b/Base/usr/share/man/man1/crash.md @@ -34,6 +34,7 @@ kinds of crashes. * `-X`: Attempt to execute non-executable memory. (Not mapped with PROT\_EXEC.) * `-U`: Attempt to trigger an x86 User Mode Instruction Prevention fault. * `-I`: Use an x86 I/O instruction in userspace. +* `-c`: Read the x86 TSC (Time Stamp Counter) directly. ## Examples diff --git a/Kernel/Arch/i386/CPU.cpp b/Kernel/Arch/i386/CPU.cpp index cabb15d40fe..acb08e19ede 100644 --- a/Kernel/Arch/i386/CPU.cpp +++ b/Kernel/Arch/i386/CPU.cpp @@ -526,6 +526,7 @@ bool g_cpu_supports_pae; bool g_cpu_supports_pge; bool g_cpu_supports_smep; bool g_cpu_supports_sse; +bool g_cpu_supports_tsc; bool g_cpu_supports_umip; void detect_cpu_features() @@ -534,6 +535,7 @@ void detect_cpu_features() g_cpu_supports_pae = (processor_info.edx() & (1 << 6)); g_cpu_supports_pge = (processor_info.edx() & (1 << 13)); g_cpu_supports_sse = (processor_info.edx() & (1 << 25)); + g_cpu_supports_tsc = (processor_info.edx() & (1 << 4)); CPUID extended_processor_info(0x80000001); g_cpu_supports_nx = (extended_processor_info.edx() & (1 << 20)); diff --git a/Kernel/Arch/i386/CPU.h b/Kernel/Arch/i386/CPU.h index 2fa2136a1fb..c1980f0da41 100644 --- a/Kernel/Arch/i386/CPU.h +++ b/Kernel/Arch/i386/CPU.h @@ -513,4 +513,5 @@ extern bool g_cpu_supports_pae; extern bool g_cpu_supports_pge; extern bool g_cpu_supports_smep; extern bool g_cpu_supports_sse; +extern bool g_cpu_supports_tsc; extern bool g_cpu_supports_umip; diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 0dd13da90c1..7c5a834fc93 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -2452,6 +2452,8 @@ int Process::sys$read_tsc(u32* lsw, u32* msw) if (!validate_write_typed(msw)) return -EFAULT; read_tsc(*lsw, *msw); + if (!is_superuser()) + *lsw &= ~0xfff; return 0; } diff --git a/Kernel/init.cpp b/Kernel/init.cpp index 6cb9dbe598f..01ce09a943b 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -266,6 +266,14 @@ extern "C" [[noreturn]] void init(u32 physical_address_for_kernel_page_tables) kprintf("x86: UMIP support enabled\n"); } + if (g_cpu_supports_tsc) { + asm volatile( + "mov %cr4, %eax\n" + "orl $0x4, %eax\n" + "mov %eax, %cr4\n"); + kprintf("x86: RDTSC support restricted\n"); + } + RTC::initialize(); PIC::initialize(); gdt_init(); diff --git a/Userland/crash.cpp b/Userland/crash.cpp index 431d691ef39..933cd8faac4 100644 --- a/Userland/crash.cpp +++ b/Userland/crash.cpp @@ -11,7 +11,7 @@ static void print_usage_and_exit() { - printf("usage: crash -[AsdiamfMFTtSxyXUI]\n"); + printf("usage: crash -[AsdiamfMFTtSxyXUIc]\n"); exit(0); } @@ -101,6 +101,7 @@ int main(int argc, char** argv) ExecuteNonExecutableMemory, TriggerUserModeInstructionPrevention, UseIOInstruction, + ReadTimestampCounter, }; Mode mode = SegmentationViolation; @@ -143,6 +144,8 @@ int main(int argc, char** argv) mode = TriggerUserModeInstructionPrevention; else if (String(argv[1]) == "-I") mode = UseIOInstruction; + else if (String(argv[1]) == "-c") + mode = ReadTimestampCounter; else print_usage_and_exit(); @@ -342,5 +345,12 @@ int main(int argc, char** argv) }).run(run_type); } + if (mode == ReadTimestampCounter || mode == TestAllCrashTypes) { + Crash("Read the CPU timestamp counter", [] { + asm volatile("rdtsc"); + return Crash::Failure::DidNotCrash; + }).run(run_type); + } + return 0; }