diff options
author | Nico Weber <thakis@chromium.org> | 2020-10-07 13:19:09 -0400 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-10-08 10:00:39 +0200 |
commit | 8a01be48491383d80213bdcb7c5b4e3d3c3ec624 (patch) | |
tree | 0fb1a61f87efcb237eaa1bf0f48a0f524b768fbd /Kernel/Arch/i386/ProcessorInfo.cpp | |
parent | 1d96d5eea44ea4813d947cca9bd84cf10733d927 (diff) | |
download | serenity-8a01be48491383d80213bdcb7c5b4e3d3c3ec624.zip |
Kernel: Add some CPU feature flags related to TSC
In case we want to rely more on TSC in time keeping in the future, idk
This adds:
- RDTSCP, for when the RDTSCP instruction is available
- CONSTANT_TSC, for when the TSC has a constant frequency, invariant
under things like the CPU boosting its frequency.
- NONSTOP_TSC, for when the TSC doesn't pause when the CPU enters
sleep states.
AMD cpus and newer intel cpus set the INVSTC bit (bit 8 in edx of
extended cpuid 0x8000000008), which implies both CONSTANT_TSC and
NONSTOP_TSC. Some older intel processors have CONSTANT_TSC but not
NONSTOP_TSC; this is set based on cpu model checks.
There isn't a ton of documentation on this, so this follows Linux
terminology and http://blog.tinola.com/?e=54
CONSTANT_TSC:
https://github.com/torvalds/linux/commit/39b3a7910556005a7a0d042ecb7ff98bfa84ea57
NONSTOP_TSC:
https://github.com/torvalds/linux/commit/40fb17152c50a69dc304dd632131c2f41281ce44
qemu disables invtsc (bit 8 in edx of extended cpuid 0x8000000008)
by default even if the host cpu supports it. It can be enabled by
running with `SERENITY_QEMU_CPU=host,migratable=off` set.
Diffstat (limited to 'Kernel/Arch/i386/ProcessorInfo.cpp')
-rw-r--r-- | Kernel/Arch/i386/ProcessorInfo.cpp | 10 |
1 files changed, 7 insertions, 3 deletions
diff --git a/Kernel/Arch/i386/ProcessorInfo.cpp b/Kernel/Arch/i386/ProcessorInfo.cpp index e570995472..273389424d 100644 --- a/Kernel/Arch/i386/ProcessorInfo.cpp +++ b/Kernel/Arch/i386/ProcessorInfo.cpp @@ -34,6 +34,7 @@ namespace Kernel { ProcessorInfo::ProcessorInfo(Processor& processor) : m_processor(processor) { + u32 max_leaf; { CPUID cpuid(0); StringBuilder builder; @@ -44,12 +45,14 @@ ProcessorInfo::ProcessorInfo(Processor& processor) (value >> 16) & 0xff, (value >> 24) & 0xff); }; + max_leaf = cpuid.eax(); emit_u32(cpuid.ebx()); emit_u32(cpuid.edx()); emit_u32(cpuid.ecx()); m_cpuid = builder.build(); } { + ASSERT(max_leaf >= 1); CPUID cpuid(1); m_stepping = cpuid.eax() & 0xf; u32 model = (cpuid.eax() >> 4) & 0xf; @@ -68,9 +71,10 @@ ProcessorInfo::ProcessorInfo(Processor& processor) m_display_model = model; } } - { - // FIXME: Check first that this is supported by calling CPUID with eax=0x80000000 - // and verifying that the returned eax>=0x80000004. + + u32 max_extended_leaf = CPUID(0x80000000).eax(); + + if (max_extended_leaf >= 0x80000004) { alignas(u32) char buffer[48]; u32* bufptr = reinterpret_cast<u32*>(buffer); auto copy_brand_string_part_to_buffer = [&](u32 i) { |