1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 14:17:36 +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:
Nico Weber 2020-10-07 13:19:09 -04:00 committed by Andreas Kling
parent 1d96d5eea4
commit 8a01be4849
3 changed files with 41 additions and 12 deletions

View file

@ -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: