kernel/x86: Use rdtsc in the fallback arch_debug_snooze case.

This allows us to avoid extra calculations and read barriers
in spin() from system_time(), and it should be easier to detect
as an "idle loop" if emulators want to do that.
This commit is contained in:
Augustin Cavalier
2025-08-30 11:28:19 -04:00
parent b0c4061d51
commit 13e97a61cc
+20 -25
View File
@@ -1358,17 +1358,13 @@ arch_debug_gdb_get_registers(char* buffer, size_t bufferSize)
} }
static void (*sDebugSnooze)(bigtime_t) = NULL; static void (*sDebugSnooze)(uint32) = NULL;
static uint64 sDebugSnoozeConversionFactor = 0; static uint64 sDebugSnoozeConversionFactor = 0;
static void static void
debug_snooze_mwaitx(bigtime_t duration) debug_snooze_mwaitx(uint32 delay)
{ {
uint32 delay = (duration * sDebugSnoozeConversionFactor) / 1000;
if (delay == 0)
delay = 1;
// monitorx (r/eax = pointer, ecx = extensions, edx = hints) // monitorx (r/eax = pointer, ecx = extensions, edx = hints)
asm volatile(".byte 0x0f, 0x01, 0xfa;" asm volatile(".byte 0x0f, 0x01, 0xfa;"
:: "a" (sDebugSnooze), "c" (0), "d" (0)); :: "a" (sDebugSnooze), "c" (0), "d" (0));
@@ -1380,12 +1376,8 @@ debug_snooze_mwaitx(bigtime_t duration)
static void static void
debug_snooze_tpause(bigtime_t duration) debug_snooze_tpause(uint32 delay)
{ {
uint32 delay = (duration * sDebugSnoozeConversionFactor) / 1000;
if (delay == 0)
delay = 1;
memory_read_barrier(); memory_read_barrier();
uint64 target = __rdtsc() + delay; uint64 target = __rdtsc() + delay;
@@ -1399,30 +1391,33 @@ debug_snooze_tpause(bigtime_t duration)
void void
arch_debug_snooze(bigtime_t duration) arch_debug_snooze(bigtime_t duration)
{ {
uint32 delay = (duration * sDebugSnoozeConversionFactor) / 1000;
if (delay == 0)
delay = 1;
if (sDebugSnooze != NULL) { if (sDebugSnooze != NULL) {
sDebugSnooze(duration); sDebugSnooze(delay);
return; return;
} }
spin(duration); memory_read_barrier();
uint64 target = __rdtsc() + delay;
while (__rdtsc() < target)
arch_cpu_pause();
} }
status_t status_t
arch_debug_init(kernel_args* args) arch_debug_init(kernel_args* args)
{ {
bool haveMWAITX = x86_check_feature(IA32_FEATURE_AMD_EXT_MWAITX, FEATURE_EXT_AMD_ECX), // Store the TSC frequency in kHz.
haveTPAUSE = x86_check_feature(IA32_FEATURE_WAITPKG, FEATURE_7_ECX); sDebugSnoozeConversionFactor =
if (haveMWAITX || haveTPAUSE) { (uint64(1000) << 32) / args->arch_args.system_time_cv_factor;
// Store the TSC frequency in kHz. if (x86_check_feature(IA32_FEATURE_AMD_EXT_MWAITX, FEATURE_EXT_AMD_ECX))
sDebugSnoozeConversionFactor = sDebugSnooze = debug_snooze_mwaitx;
(uint64(1000) << 32) / args->arch_args.system_time_cv_factor; if (x86_check_feature(IA32_FEATURE_WAITPKG, FEATURE_7_ECX))
sDebugSnooze = debug_snooze_tpause;
if (haveMWAITX)
sDebugSnooze = debug_snooze_mwaitx;
else if (haveTPAUSE)
sDebugSnooze = debug_snooze_tpause;
}
add_debugger_command("where", &stack_trace, "Same as \"sc\""); add_debugger_command("where", &stack_trace, "Same as \"sc\"");
add_debugger_command("bt", &stack_trace, "Same as \"sc\" (as in gdb)"); add_debugger_command("bt", &stack_trace, "Same as \"sc\" (as in gdb)");