mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-11 17:00:37 +00:00
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:39b3a79105
NONSTOP_TSC:40fb17152c
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.
This commit is contained in:
parent
1d96d5eea4
commit
8a01be4849
Notes:
sideshowbarker
2024-07-19 01:58:53 +09:00
Author: https://github.com/nico Commit: https://github.com/SerenityOS/serenity/commit/8a01be48491 Pull-request: https://github.com/SerenityOS/serenity/pull/3710
3 changed files with 41 additions and 12 deletions
|
@ -998,15 +998,31 @@ void Processor::cpu_detect()
|
|||
u32 family = (processor_info.eax() >> 8) & 0xf;
|
||||
if (!(family == 6 && model < 3 && stepping < 3))
|
||||
set_feature(CPUFeature::SEP);
|
||||
if ((family == 6 && model >= 3) || (family == 0xf && model >= 0xe))
|
||||
set_feature(CPUFeature::CONSTANT_TSC);
|
||||
}
|
||||
|
||||
u32 max_extended_leaf = CPUID(0x80000000).eax();
|
||||
|
||||
ASSERT(max_extended_leaf >= 0x80000001);
|
||||
CPUID extended_processor_info(0x80000001);
|
||||
if (extended_processor_info.edx() & (1 << 20))
|
||||
set_feature(CPUFeature::NX);
|
||||
if (extended_processor_info.edx() & (1 << 27))
|
||||
set_feature(CPUFeature::RDTSCP);
|
||||
if (extended_processor_info.edx() & (1 << 11)) {
|
||||
// Only available in 64 bit mode
|
||||
set_feature(CPUFeature::SYSCALL);
|
||||
}
|
||||
|
||||
if (max_extended_leaf >= 0x80000007) {
|
||||
CPUID cpuid(0x80000007);
|
||||
if (cpuid.edx() & (1 << 8)) {
|
||||
set_feature(CPUFeature::CONSTANT_TSC);
|
||||
set_feature(CPUFeature::NONSTOP_TSC);
|
||||
}
|
||||
}
|
||||
|
||||
CPUID extended_features(0x7);
|
||||
if (extended_features.ebx() & (1 << 20))
|
||||
set_feature(CPUFeature::SMAP);
|
||||
|
@ -1107,6 +1123,12 @@ String Processor::features_string() const
|
|||
return "sse";
|
||||
case CPUFeature::TSC:
|
||||
return "tsc";
|
||||
case CPUFeature::RDTSCP:
|
||||
return "rdtscp";
|
||||
case CPUFeature::CONSTANT_TSC:
|
||||
return "constant_tsc";
|
||||
case CPUFeature::NONSTOP_TSC:
|
||||
return "nonstop_tsc";
|
||||
case CPUFeature::UMIP:
|
||||
return "umip";
|
||||
case CPUFeature::SEP:
|
||||
|
|
|
@ -606,15 +606,18 @@ enum class CPUFeature : u32 {
|
|||
SMEP = (1 << 6),
|
||||
SSE = (1 << 7),
|
||||
TSC = (1 << 8),
|
||||
UMIP = (1 << 9),
|
||||
SEP = (1 << 10),
|
||||
SYSCALL = (1 << 11),
|
||||
MMX = (1 << 12),
|
||||
SSE2 = (1 << 13),
|
||||
SSE3 = (1 << 14),
|
||||
SSSE3 = (1 << 15),
|
||||
SSE4_1 = (1 << 16),
|
||||
SSE4_2 = (1 << 17)
|
||||
RDTSCP = (1 << 9),
|
||||
CONSTANT_TSC = (1 << 10),
|
||||
NONSTOP_TSC = (1 << 11),
|
||||
UMIP = (1 << 12),
|
||||
SEP = (1 << 13),
|
||||
SYSCALL = (1 << 14),
|
||||
MMX = (1 << 15),
|
||||
SSE2 = (1 << 16),
|
||||
SSE3 = (1 << 17),
|
||||
SSSE3 = (1 << 18),
|
||||
SSE4_1 = (1 << 19),
|
||||
SSE4_2 = (1 << 20),
|
||||
};
|
||||
|
||||
class Thread;
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue