[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) {