Kernel/LibC: support RDTSCP based clock_gettime

RDTSCP seems to be faster than LSL and it removes the need for getting
the current cpu twice to make sure TSC is read on the correct CPU
This commit is contained in:
2026-07-03 05:27:54 +03:00
parent 917321eb5f
commit 63b2284324
5 changed files with 86 additions and 46 deletions

View File

@@ -1,3 +1,4 @@
#include <kernel/CPUID.h>
#include <kernel/InterruptController.h>
#include <kernel/Memory/Heap.h>
#include <kernel/Memory/kmalloc.h>
@@ -20,6 +21,8 @@ namespace Kernel
static constexpr uint32_t MSR_IA32_FMASK = 0xC0000084;
#endif
static constexpr uint32_t MSR_IA32_TSC_AUX = 0xC0000103;
ProcessorID Processor::s_bsp_id { PROCESSOR_NONE };
BAN::Atomic<uint8_t> Processor::s_processor_count { 0 };
BAN::Atomic<bool> Processor::s_is_smp_enabled { false };
@@ -219,6 +222,9 @@ namespace Kernel
shared_page.gdt_cpu_offset = GDT::cpu_index_offset();
shared_page.features = 0;
if (CPUID::has_rdtscp())
shared_page.features |= API::SPF_RDTSCP;
ASSERT(Processor::count() + sizeof(Kernel::API::SharedPage) <= PAGE_SIZE);
}
@@ -321,7 +327,10 @@ namespace Kernel
void Processor::update_tsc()
{
auto& lgettime = shared_page().cpus[current_index()].gettime_local;
lgettime.seq = lgettime.seq + 1;
const auto seq = BAN::atomic_load(lgettime.seq, BAN::memory_order_relaxed);
BAN::atomic_store(lgettime.seq, seq + 1, BAN::memory_order_release);
if (lgettime.seq == 1)
{
@@ -330,6 +339,9 @@ namespace Kernel
lgettime.mult = tsc_info.mult;
lgettime.last_ns = SystemTimer::get().ns_since_boot_no_tsc();
lgettime.last_tsc = __builtin_ia32_rdtsc();
if (CPUID::has_rdtscp())
asm volatile("wrmsr" :: "d"(0x00000000), "a"(current_index()), "c"(MSR_IA32_TSC_AUX));
}
else
{
@@ -353,7 +365,7 @@ namespace Kernel
lgettime.mult += correction_delta;
}
lgettime.seq = lgettime.seq + 1;
BAN::atomic_store(lgettime.seq, seq + 2, BAN::memory_order_release);
}
uint64_t Processor::ns_since_boot_tsc()