[kernel][arch] Give 'fieldless' CPUID types an uber-field
In the case of a register type that has no subfield, cosmetically
define a field ranging over all bits with a contextually sensible name.
For example, we give the 'max leaf' types as single "leaf" field.
Bug: 61093
Change-Id: Ibb601074b2add529aeea6de5919f69db9816f812
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/464634
Commit-Queue: Joshua Seaton <joshuaseaton@google.com>
Reviewed-by: Roland McGrath <mcgrathr@google.com>
diff --git a/zircon/kernel/arch/x86/mp.cc b/zircon/kernel/arch/x86/mp.cc
index c61ad08..a2c831a 100644
--- a/zircon/kernel/arch/x86/mp.cc
+++ b/zircon/kernel/arch/x86/mp.cc
@@ -113,10 +113,10 @@
}
memset(ap_percpus, 0, len);
- use_monitor = arch::BootCpuid<arch::CpuidFeatureFlagsC>().monitor() &&
- (arch::BootCpuid<arch::CpuidMaximumLeaf>().reg_value() >=
- arch::CpuidMonitorMwaitB::kLeaf) &&
- !x86_get_microarch_config()->idle_prefer_hlt;
+ use_monitor =
+ arch::BootCpuid<arch::CpuidFeatureFlagsC>().monitor() &&
+ (arch::BootCpuid<arch::CpuidMaximumLeaf>().leaf() >= arch::CpuidMonitorMwaitB::kLeaf) &&
+ !x86_get_microarch_config()->idle_prefer_hlt;
if (use_monitor) {
uint16_t monitor_size =
arch::BootCpuid<arch::CpuidMonitorMwaitB>().largest_monitor_line_size();
diff --git a/zircon/kernel/arch/x86/perf_mon.cc b/zircon/kernel/arch/x86/perf_mon.cc
index 9c0c3ef..70993e3 100644
--- a/zircon/kernel/arch/x86/perf_mon.cc
+++ b/zircon/kernel/arch/x86/perf_mon.cc
@@ -420,8 +420,7 @@
}
static void x86_perfmon_init_once(uint level) {
- if (arch::BootCpuid<arch::CpuidMaximumLeaf>().reg_value() <
- arch::CpuidPerformanceMonitoringA::kLeaf) {
+ if (arch::BootCpuid<arch::CpuidMaximumLeaf>().leaf() < arch::CpuidPerformanceMonitoringA::kLeaf) {
return;
}
diff --git a/zircon/kernel/arch/x86/proc_trace.cc b/zircon/kernel/arch/x86/proc_trace.cc
index b382847..dd691c5 100644
--- a/zircon/kernel/arch/x86/proc_trace.cc
+++ b/zircon/kernel/arch/x86/proc_trace.cc
@@ -111,7 +111,8 @@
static uint32_t ipt_num_traces TA_GUARDED(IptLock::Get());
void x86_processor_trace_init(void) {
- if (!arch::BootCpuid<arch::CpuidExtendedFeatureFlagsB>().intel_pt()) {
+ if ((arch::BootCpuid<arch::CpuidMaximumLeaf>().leaf() < arch::CpuidProcessorTraceMainB::kLeaf) ||
+ !arch::BootCpuid<arch::CpuidExtendedFeatureFlagsB>().intel_pt()) {
return;
}
diff --git a/zircon/kernel/lib/arch/include/lib/arch/x86/cpuid.h b/zircon/kernel/lib/arch/include/lib/arch/x86/cpuid.h
index 10c90b7..31979b0 100644
--- a/zircon/kernel/lib/arch/include/lib/arch/x86/cpuid.h
+++ b/zircon/kernel/lib/arch/include/lib/arch/x86/cpuid.h
@@ -122,21 +122,29 @@
//---------------------------------------------------------------------------//
// [amd/vol3]: E.3.1, CPUID Fn0000_0000_EAX Largest Standard Function Number.
-struct CpuidMaximumLeaf : public CpuidValueBase<CpuidMaximumLeaf, 0x0, 0x0, CpuidIo::kEax> {};
+struct CpuidMaximumLeaf : public CpuidValueBase<CpuidMaximumLeaf, 0x0, 0x0, CpuidIo::kEax> {
+ DEF_FIELD(31, 0, leaf);
+};
// [amd/vol3]: E.3.1, CPUID Fn0000_0000_E[D,C,B]X Processor Vendor.
-struct CpuidVendorB : public CpuidValueBase<CpuidVendorB, 0x0, 0x0, CpuidIo::kEbx> {};
-struct CpuidVendorC : public CpuidValueBase<CpuidVendorC, 0x0, 0x0, CpuidIo::kEcx> {};
-struct CpuidVendorD : public CpuidValueBase<CpuidVendorD, 0x0, 0x0, CpuidIo::kEdx> {};
+struct CpuidVendorB : public CpuidValueBase<CpuidVendorB, 0x0, 0x0, CpuidIo::kEbx> {
+ DEF_FIELD(31, 0, value);
+};
+struct CpuidVendorC : public CpuidValueBase<CpuidVendorC, 0x0, 0x0, CpuidIo::kEcx> {
+ DEF_FIELD(31, 0, value);
+};
+struct CpuidVendorD : public CpuidValueBase<CpuidVendorD, 0x0, 0x0, CpuidIo::kEdx> {
+ DEF_FIELD(31, 0, value);
+};
template <typename CpuidIoProvider>
Vendor GetVendor(CpuidIoProvider&& io) {
using namespace std::string_view_literals;
const uint32_t ids[] = {
- io.template Read<CpuidVendorB>().reg_value(),
- io.template Read<CpuidVendorD>().reg_value(),
- io.template Read<CpuidVendorC>().reg_value(),
+ io.template Read<CpuidVendorB>().value(),
+ io.template Read<CpuidVendorD>().value(),
+ io.template Read<CpuidVendorC>().value(),
};
std::string_view name{reinterpret_cast<const char*>(ids), sizeof(ids)};
if (name == "GenuineIntel"sv) {
@@ -419,14 +427,22 @@
//---------------------------------------------------------------------------//
struct CpuidMaximumHypervisorLeaf
- : public CpuidValueBase<CpuidMaximumHypervisorLeaf, 0x4000'0000, 0x0, CpuidIo::kEax> {};
+ : public CpuidValueBase<CpuidMaximumHypervisorLeaf, 0x4000'0000, 0x0, CpuidIo::kEax> {
+ DEF_FIELD(31, 0, leaf);
+};
struct CpuidHypervisorNameB
- : public CpuidValueBase<CpuidHypervisorNameB, 0x4000'0000, 0x0, CpuidIo::kEbx> {};
+ : public CpuidValueBase<CpuidHypervisorNameB, 0x4000'0000, 0x0, CpuidIo::kEbx> {
+ DEF_FIELD(31, 0, value);
+};
struct CpuidHypervisorNameC
- : public CpuidValueBase<CpuidHypervisorNameC, 0x4000'0000, 0x0, CpuidIo::kEcx> {};
+ : public CpuidValueBase<CpuidHypervisorNameC, 0x4000'0000, 0x0, CpuidIo::kEcx> {
+ DEF_FIELD(31, 0, value);
+};
struct CpuidHypervisorNameD
- : public CpuidValueBase<CpuidHypervisorNameD, 0x4000'0000, 0x0, CpuidIo::kEdx> {};
+ : public CpuidValueBase<CpuidHypervisorNameD, 0x4000'0000, 0x0, CpuidIo::kEdx> {
+ DEF_FIELD(31, 0, value);
+};
// HypervisorName is a simple class that serves to hold the content of a
// hypervisor's name (or "vendor string").
@@ -437,9 +453,9 @@
// Check if we are actually within a hypervisor.
if (io.template Read<CpuidFeatureFlagsC>().hypervisor()) {
const uint32_t values[] = {
- io.template Read<CpuidHypervisorNameB>().reg_value(),
- io.template Read<CpuidHypervisorNameC>().reg_value(),
- io.template Read<CpuidHypervisorNameD>().reg_value(),
+ io.template Read<CpuidHypervisorNameB>().value(),
+ io.template Read<CpuidHypervisorNameC>().value(),
+ io.template Read<CpuidHypervisorNameD>().value(),
};
static_assert(kSize == sizeof(values));
memcpy(str_.data(), values, kSize);
@@ -469,7 +485,9 @@
// [amd/vol3]: CPUID Fn8000_0000_EAX Largest Extended Function Number
struct CpuidMaximumExtendedLeaf
- : public CpuidValueBase<CpuidMaximumExtendedLeaf, 0x8000'0000, 0x0, CpuidIo::kEax> {};
+ : public CpuidValueBase<CpuidMaximumExtendedLeaf, 0x8000'0000, 0x0, CpuidIo::kEax> {
+ DEF_FIELD(31, 0, leaf);
+};
//---------------------------------------------------------------------------//
// Leaves/Functions 0x8000'0002 - 0x8000'0004
@@ -482,31 +500,55 @@
// express (zero-based) index into how the combine to form the processor name
// string.
struct CpuidProcessorName2A
- : public CpuidValueBase<CpuidProcessorName2A, 0x8000'0002, 0x0, CpuidIo::kEax> {};
+ : public CpuidValueBase<CpuidProcessorName2A, 0x8000'0002, 0x0, CpuidIo::kEax> {
+ DEF_FIELD(31, 0, value);
+};
struct CpuidProcessorName2B
- : public CpuidValueBase<CpuidProcessorName2B, 0x8000'0002, 0x0, CpuidIo::kEbx> {};
+ : public CpuidValueBase<CpuidProcessorName2B, 0x8000'0002, 0x0, CpuidIo::kEbx> {
+ DEF_FIELD(31, 0, value);
+};
struct CpuidProcessorName2C
- : public CpuidValueBase<CpuidProcessorName2C, 0x8000'0002, 0x0, CpuidIo::kEcx> {};
+ : public CpuidValueBase<CpuidProcessorName2C, 0x8000'0002, 0x0, CpuidIo::kEcx> {
+ DEF_FIELD(31, 0, value);
+};
struct CpuidProcessorName2D
- : public CpuidValueBase<CpuidProcessorName2D, 0x8000'0002, 0x0, CpuidIo::kEdx> {};
+ : public CpuidValueBase<CpuidProcessorName2D, 0x8000'0002, 0x0, CpuidIo::kEdx> {
+ DEF_FIELD(31, 0, value);
+};
struct CpuidProcessorName3A
- : public CpuidValueBase<CpuidProcessorName3A, 0x8000'0003, 0x0, CpuidIo::kEax> {};
+ : public CpuidValueBase<CpuidProcessorName3A, 0x8000'0003, 0x0, CpuidIo::kEax> {
+ DEF_FIELD(31, 0, value);
+};
struct CpuidProcessorName3B
- : public CpuidValueBase<CpuidProcessorName3B, 0x8000'0003, 0x0, CpuidIo::kEbx> {};
+ : public CpuidValueBase<CpuidProcessorName3B, 0x8000'0003, 0x0, CpuidIo::kEbx> {
+ DEF_FIELD(31, 0, value);
+};
struct CpuidProcessorName3C
- : public CpuidValueBase<CpuidProcessorName3C, 0x8000'0003, 0x0, CpuidIo::kEcx> {};
+ : public CpuidValueBase<CpuidProcessorName3C, 0x8000'0003, 0x0, CpuidIo::kEcx> {
+ DEF_FIELD(31, 0, value);
+};
struct CpuidProcessorName3D
- : public CpuidValueBase<CpuidProcessorName3D, 0x8000'0003, 0x0, CpuidIo::kEdx> {};
+ : public CpuidValueBase<CpuidProcessorName3D, 0x8000'0003, 0x0, CpuidIo::kEdx> {
+ DEF_FIELD(31, 0, value);
+};
struct CpuidProcessorName4A
- : public CpuidValueBase<CpuidProcessorName4A, 0x8000'0004, 0x0, CpuidIo::kEax> {};
+ : public CpuidValueBase<CpuidProcessorName4A, 0x8000'0004, 0x0, CpuidIo::kEax> {
+ DEF_FIELD(31, 0, value);
+};
struct CpuidProcessorName4B
- : public CpuidValueBase<CpuidProcessorName4B, 0x8000'0004, 0x0, CpuidIo::kEbx> {};
+ : public CpuidValueBase<CpuidProcessorName4B, 0x8000'0004, 0x0, CpuidIo::kEbx> {
+ DEF_FIELD(31, 0, value);
+};
struct CpuidProcessorName4C
- : public CpuidValueBase<CpuidProcessorName4C, 0x8000'0004, 0x0, CpuidIo::kEcx> {};
+ : public CpuidValueBase<CpuidProcessorName4C, 0x8000'0004, 0x0, CpuidIo::kEcx> {
+ DEF_FIELD(31, 0, value);
+};
struct CpuidProcessorName4D
- : public CpuidValueBase<CpuidProcessorName4D, 0x8000'0004, 0x0, CpuidIo::kEdx> {};
+ : public CpuidValueBase<CpuidProcessorName4D, 0x8000'0004, 0x0, CpuidIo::kEdx> {
+ DEF_FIELD(31, 0, value);
+};
// ProcessorName is a simple class that serves to hold the content of a
// processor name (or "brand string" in Intel-speak), a general identifier.
@@ -515,20 +557,20 @@
template <typename CpuidIoProvider>
explicit ProcessorName(CpuidIoProvider&& io) {
// The name string needs leaves 0x8000'0002-0x8000'0004.
- if (io.template Read<CpuidMaximumExtendedLeaf>().reg_value() >= CpuidProcessorName4D::kLeaf) {
+ if (io.template Read<CpuidMaximumExtendedLeaf>().leaf() >= CpuidProcessorName4D::kLeaf) {
const uint32_t values[] = {
- io.template Read<CpuidProcessorName2A>().reg_value(),
- io.template Read<CpuidProcessorName2B>().reg_value(),
- io.template Read<CpuidProcessorName2C>().reg_value(),
- io.template Read<CpuidProcessorName2D>().reg_value(),
- io.template Read<CpuidProcessorName3A>().reg_value(),
- io.template Read<CpuidProcessorName3B>().reg_value(),
- io.template Read<CpuidProcessorName3C>().reg_value(),
- io.template Read<CpuidProcessorName3D>().reg_value(),
- io.template Read<CpuidProcessorName4A>().reg_value(),
- io.template Read<CpuidProcessorName4B>().reg_value(),
- io.template Read<CpuidProcessorName4C>().reg_value(),
- io.template Read<CpuidProcessorName4D>().reg_value(),
+ io.template Read<CpuidProcessorName2A>().value(),
+ io.template Read<CpuidProcessorName2B>().value(),
+ io.template Read<CpuidProcessorName2C>().value(),
+ io.template Read<CpuidProcessorName2D>().value(),
+ io.template Read<CpuidProcessorName3A>().value(),
+ io.template Read<CpuidProcessorName3B>().value(),
+ io.template Read<CpuidProcessorName3C>().value(),
+ io.template Read<CpuidProcessorName3D>().value(),
+ io.template Read<CpuidProcessorName4A>().value(),
+ io.template Read<CpuidProcessorName4B>().value(),
+ io.template Read<CpuidProcessorName4C>().value(),
+ io.template Read<CpuidProcessorName4D>().value(),
};
static_assert(kSize == sizeof(values));
memcpy(str_.data(), values, kSize);
diff --git a/zircon/kernel/lib/arch/test/cpuid-corpus-tests.cc b/zircon/kernel/lib/arch/test/cpuid-corpus-tests.cc
index 10ee96f..6f4d90b 100644
--- a/zircon/kernel/lib/arch/test/cpuid-corpus-tests.cc
+++ b/zircon/kernel/lib/arch/test/cpuid-corpus-tests.cc
@@ -546,7 +546,7 @@
auto hypervisor = arch::HypervisorName(cpuid);
EXPECT_TRUE(hypervisor.name() == "VBoxVBoxVBox"sv);
- EXPECT_EQ(0x4000'0006, cpuid.Read<arch::CpuidMaximumHypervisorLeaf>().reg_value());
+ EXPECT_EQ(0x4000'0006, cpuid.Read<arch::CpuidMaximumHypervisorLeaf>().leaf());
{
auto features = cpuid.Read<arch::CpuidFeatureFlagsC>();
@@ -596,7 +596,7 @@
auto hypervisor = arch::HypervisorName(cpuid);
EXPECT_TRUE(hypervisor.name() == "KVMKVMKVM"sv);
- EXPECT_EQ(0x4000'0001, cpuid.Read<arch::CpuidMaximumHypervisorLeaf>().reg_value());
+ EXPECT_EQ(0x4000'0001, cpuid.Read<arch::CpuidMaximumHypervisorLeaf>().leaf());
{
auto features = cpuid.Read<arch::CpuidFeatureFlagsC>();
@@ -646,7 +646,7 @@
auto hypervisor = arch::HypervisorName(cpuid);
EXPECT_TRUE(hypervisor.name() == "VMwareVMware"sv);
- EXPECT_EQ(0x4000'0010, cpuid.Read<arch::CpuidMaximumHypervisorLeaf>().reg_value());
+ EXPECT_EQ(0x4000'0010, cpuid.Read<arch::CpuidMaximumHypervisorLeaf>().leaf());
{
auto features = cpuid.Read<arch::CpuidFeatureFlagsC>();
@@ -694,7 +694,7 @@
auto hypervisor = arch::HypervisorName(cpuid);
EXPECT_TRUE(hypervisor.name() == "Microsoft Hv"sv);
- EXPECT_EQ(0x4000'000b, cpuid.Read<arch::CpuidMaximumHypervisorLeaf>().reg_value());
+ EXPECT_EQ(0x4000'000b, cpuid.Read<arch::CpuidMaximumHypervisorLeaf>().leaf());
{
auto features = cpuid.Read<arch::CpuidFeatureFlagsC>();
diff --git a/zircon/kernel/lib/arch/test/fake-cpuid-tests.cc b/zircon/kernel/lib/arch/test/fake-cpuid-tests.cc
index 946489b..e848a7b 100644
--- a/zircon/kernel/lib/arch/test/fake-cpuid-tests.cc
+++ b/zircon/kernel/lib/arch/test/fake-cpuid-tests.cc
@@ -59,7 +59,7 @@
// Read should be a shortcut to reading our the value type.
EXPECT_EQ(0x0000'0014, io->values_[arch::CpuidIo::kEax]);
- EXPECT_EQ(0x0000'0014, cpuid.Read<arch::CpuidMaximumLeaf>().reg_value());
+ EXPECT_EQ(0x0000'0014, cpuid.Read<arch::CpuidMaximumLeaf>().leaf());
}
TEST(FakeCpuidIoTests, PopulateOverwrites) {