From 6bc33366795d14a21a3244d0f3b63f7dccea87ef Mon Sep 17 00:00:00 2001
From: Andrew Cooper <andrew.cooper3@citrix.com>
Date: Wed, 29 Mar 2023 07:39:44 +0100
Subject: x86: Merge the system {cpuid,msr} policy objects

Right now, they're the same underlying type, containing disjoint information.

Introduce a new cpu-policy.{h,c} to be the new location for all policy
handling logic.  Place the combined objects in __ro_after_init, which is new
since the original logic was written.

As we're trying to phase out the use of struct old_cpu_policy entirely, rework
update_domain_cpu_policy() to not pointer-chase through system_policies[].

This in turn allows system_policies[] in sysctl.c to become static and reduced
in scope to XEN_SYSCTL_get_cpu_policy.

No practical change.  This undoes the transient doubling of storage space from
earlier patches.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>

--- a/xen/arch/x86/Makefile
+++ b/xen/arch/x86/Makefile
@@ -15,6 +15,7 @@ obj-y += bitops.o
 obj-bin-y += bzimage.init.o
 obj-bin-y += clear_page.o
 obj-bin-y += copy_page.o
+obj-y += cpu-policy.o
 obj-y += cpuid.o
 obj-y += compat.o x86_64/compat.o
 obj-$(CONFIG_KEXEC) += crash.o
--- /dev/null
+++ b/xen/arch/x86/cpu-policy.c
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#include <xen/cache.h>
+#include <xen/kernel.h>
+
+#include <asm/cpu-policy.h>
+
+struct cpu_policy __read_mostly       raw_cpu_policy;
+struct cpu_policy __read_mostly      host_cpu_policy;
+struct cpu_policy __read_mostly    pv_max_cpu_policy;
+struct cpu_policy __read_mostly   hvm_max_cpu_policy;
--- a/xen/arch/x86/cpuid.c
+++ b/xen/arch/x86/cpuid.c
@@ -133,15 +133,6 @@ static void zero_leaves(struct cpuid_lea
     memset(&l[first], 0, sizeof(*l) * (last - first + 1));
 }
 
-struct cpuid_policy __read_mostly raw_policy,
-    __read_mostly host_policy,
-    __read_mostly pv_max_policy,
-    __read_mostly hvm_max_policy;
-static struct msr_policy __read_mostly raw_msr_policy,
-    __read_mostly host_msr_policy,
-    __read_mostly pv_max_msr_policy,
-    __read_mostly hvm_max_msr_policy;
-
 static void sanitise_featureset(uint32_t *fs)
 {
     /* for_each_set_bit() uses unsigned longs.  Extend with zeroes. */
@@ -338,8 +329,7 @@ static void recalculate_misc(struct cpui
 
 static void __init calculate_raw_policy(void)
 {
-    struct cpuid_policy *p = &raw_policy;
-    struct msr_policy *mp = &raw_msr_policy;
+    struct cpuid_policy *p = &raw_cpu_policy;
     unsigned int i;
 
     cpuid_leaf(0, &p->basic.raw[0]);
@@ -417,16 +407,15 @@ static void __init calculate_raw_policy(
     p->x86_vendor = boot_cpu_data.x86_vendor;
 
     if ( cpu_has_arch_caps )
-        rdmsrl(MSR_ARCH_CAPABILITIES, mp->arch_caps.raw);
+        rdmsrl(MSR_ARCH_CAPABILITIES, p->arch_caps.raw);
 }
 
 static void __init calculate_host_policy(void)
 {
-    struct cpuid_policy *p = &host_policy;
-    struct msr_policy *mp = &host_msr_policy;
+    struct cpuid_policy *p = &host_cpu_policy;
     unsigned int max_extd_leaf;
 
-    *p = raw_policy;
+    *p = raw_cpu_policy;
 
     p->basic.max_leaf =
         min_t(uint32_t, p->basic.max_leaf,   ARRAY_SIZE(p->basic.raw) - 1);
@@ -464,10 +453,8 @@ static void __init calculate_host_policy
                                (1u << SVM_FEATURE_TSCRATEMSR));
     }
 
-    *mp = raw_msr_policy;
-
     /* Temporary, until we have known_features[] for feature bits in MSRs. */
-    mp->arch_caps.raw &=
+    p->arch_caps.raw &=
         (ARCH_CAPABILITIES_RDCL_NO | ARCH_CAPABILITIES_IBRS_ALL | ARCH_CAPS_RSBA |
          ARCH_CAPS_SKIP_L1DFL | ARCH_CAPS_SSB_NO | ARCH_CAPS_MDS_NO |
          ARCH_CAPS_IF_PSCHANGE_MC_NO | ARCH_CAPS_TSX_CTRL | ARCH_CAPS_TAA_NO |
@@ -500,12 +487,11 @@ static void __init guest_common_feature_
 
 static void __init calculate_pv_max_policy(void)
 {
-    struct cpuid_policy *p = &pv_max_policy;
-    struct msr_policy *mp = &pv_max_msr_policy;
+    struct cpuid_policy *p = &pv_max_cpu_policy;
     uint32_t pv_featureset[FSCAPINTS];
     unsigned int i;
 
-    *p = host_policy;
+    *p = host_cpu_policy;
     cpuid_policy_to_featureset(p, pv_featureset);
 
     for ( i = 0; i < ARRAY_SIZE(pv_featureset); ++i )
@@ -526,15 +512,12 @@ static void __init calculate_pv_max_poli
 
     p->extd.raw[0xa] = EMPTY_LEAF; /* No SVM for PV guests. */
 
-    *mp = host_msr_policy;
-
-    mp->arch_caps.raw = 0; /* Not supported yet. */
+    p->arch_caps.raw = 0; /* Not supported yet. */
 }
 
 static void __init calculate_hvm_max_policy(void)
 {
-    struct cpuid_policy *p = &hvm_max_policy;
-    struct msr_policy *mp = &hvm_max_msr_policy;
+    struct cpuid_policy *p = &hvm_max_cpu_policy;
     uint32_t hvm_featureset[FSCAPINTS];
     unsigned int i;
     const uint32_t *hvm_featuremask;
@@ -542,7 +525,7 @@ static void __init calculate_hvm_max_pol
     if ( !hvm_enabled )
         return;
 
-    *p = host_policy;
+    *p = host_cpu_policy;
     cpuid_policy_to_featureset(p, hvm_featureset);
 
     hvm_featuremask = hvm_funcs.hap_supported ?
@@ -562,7 +545,8 @@ static void __init calculate_hvm_max_pol
      * long mode (and init_amd() has cleared it out of host capabilities), but
      * HVM guests are able if running in protected mode.
      */
-    if ( (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && raw_policy.basic.sep )
+    if ( (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) &&
+         raw_cpu_policy.basic.sep )
         __set_bit(X86_FEATURE_SEP, hvm_featureset);
 
     /*
@@ -591,9 +575,7 @@ static void __init calculate_hvm_max_pol
     cpuid_featureset_to_policy(hvm_featureset, p);
     recalculate_xstate(p);
 
-    *mp = host_msr_policy;
-
-    mp->arch_caps.raw = 0; /* Not supported yet. */
+    p->arch_caps.raw = 0; /* Not supported yet. */
 }
 
 void __init init_guest_cpuid(void)
@@ -658,7 +640,7 @@ void recalculate_cpuid_policy(struct dom
 {
     struct cpuid_policy *p = d->arch.cpuid;
     const struct cpuid_policy *max =
-        is_pv_domain(d) ? &pv_max_policy : &hvm_max_policy;
+        is_pv_domain(d) ? &pv_max_cpu_policy : &hvm_max_cpu_policy;
     uint32_t fs[FSCAPINTS], max_fs[FSCAPINTS];
     unsigned int i;
 
@@ -748,7 +730,7 @@ void recalculate_cpuid_policy(struct dom
     /* Fold host's FDP_EXCP_ONLY and NO_FPU_SEL into guest's view. */
     fs[FEATURESET_7b0] &= ~(cpufeat_mask(X86_FEATURE_FDP_EXCP_ONLY) |
                             cpufeat_mask(X86_FEATURE_NO_FPU_SEL));
-    fs[FEATURESET_7b0] |= (host_policy.feat._7b0 &
+    fs[FEATURESET_7b0] |= (host_cpu_policy.feat._7b0 &
                            (cpufeat_mask(X86_FEATURE_FDP_EXCP_ONLY) |
                             cpufeat_mask(X86_FEATURE_NO_FPU_SEL)));
 
@@ -805,7 +787,8 @@ int init_domain_cpuid_policy(struct doma
     if ( !d->arch.cpuid || !d->arch.msr )
         return -ENOMEM;
 
-    *d->arch.cpuid = is_pv_domain(d) ? pv_max_policy : hvm_max_policy;
+    *d->arch.cpuid = is_pv_domain(d)
+        ? pv_max_cpu_policy : hvm_max_cpu_policy;
 
     recalculate_cpuid_policy(d);
 
@@ -1101,7 +1084,7 @@ void guest_cpuid(const struct vcpu *v, u
         if ( is_pv_domain(d) && is_hardware_domain(d) &&
              guest_kernel_mode(v, regs) && cpu_has_monitor &&
              regs->entry_vector == TRAP_gp_fault )
-            *res = raw_policy.basic.raw[leaf];
+            *res = raw_cpu_policy.basic.raw[5];
         break;
 
     case 0x7:
@@ -1239,14 +1222,14 @@ static void __init __maybe_unused build_
     /* Find some more clever allocation scheme if this trips. */
     BUILD_BUG_ON(sizeof(struct cpuid_policy) > PAGE_SIZE);
 
-    BUILD_BUG_ON(sizeof(raw_policy.basic) !=
-                 sizeof(raw_policy.basic.raw));
-    BUILD_BUG_ON(sizeof(raw_policy.feat) !=
-                 sizeof(raw_policy.feat.raw));
-    BUILD_BUG_ON(sizeof(raw_policy.xstate) !=
-                 sizeof(raw_policy.xstate.raw));
-    BUILD_BUG_ON(sizeof(raw_policy.extd) !=
-                 sizeof(raw_policy.extd.raw));
+    BUILD_BUG_ON(sizeof(raw_cpu_policy.basic) !=
+                 sizeof(raw_cpu_policy.basic.raw));
+    BUILD_BUG_ON(sizeof(raw_cpu_policy.feat) !=
+                 sizeof(raw_cpu_policy.feat.raw));
+    BUILD_BUG_ON(sizeof(raw_cpu_policy.xstate) !=
+                 sizeof(raw_cpu_policy.xstate.raw));
+    BUILD_BUG_ON(sizeof(raw_cpu_policy.extd) !=
+                 sizeof(raw_cpu_policy.extd.raw));
 }
 
 /*
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -35,7 +35,7 @@
 #include <asm/xstate.h>
 #include <asm/debugger.h>
 #include <asm/psr.h>
-#include <asm/cpuid.h>
+#include <asm/cpu-policy.h>
 
 static int gdbsx_guest_mem_io(domid_t domid, struct xen_domctl_gdbsx_memio *iop)
 {
--- a/xen/arch/x86/sysctl.c
+++ b/xen/arch/x86/sysctl.c
@@ -30,7 +30,7 @@
 #include <xen/cpu.h>
 #include <xsm/xsm.h>
 #include <asm/psr.h>
-#include <asm/cpuid.h>
+#include <asm/cpu-policy.h>
 
 struct l3_cache_info {
     int ret;
@@ -212,15 +212,15 @@ long arch_do_sysctl(
 
     case XEN_SYSCTL_get_cpu_featureset:
     {
-        static const struct cpuid_policy *const policy_table[] = {
-            [XEN_SYSCTL_cpu_featureset_raw]  = &raw_policy,
-            [XEN_SYSCTL_cpu_featureset_host] = &host_policy,
-            [XEN_SYSCTL_cpu_featureset_pv]   = &pv_max_policy,
-            [XEN_SYSCTL_cpu_featureset_hvm]  = &hvm_max_policy,
-            [XEN_SYSCTL_cpu_featureset_pv_max]  = &pv_max_policy,
-            [XEN_SYSCTL_cpu_featureset_hvm_max] = &hvm_max_policy,
+        static const struct cpu_policy *const policy_table[6] = {
+            [XEN_SYSCTL_cpu_featureset_raw]     = &raw_cpu_policy,
+            [XEN_SYSCTL_cpu_featureset_host]    = &host_cpu_policy,
+            [XEN_SYSCTL_cpu_featureset_pv]      = &pv_max_cpu_policy,
+            [XEN_SYSCTL_cpu_featureset_pv_max]  = &pv_max_cpu_policy,
+            [XEN_SYSCTL_cpu_featureset_hvm]     = &hvm_max_cpu_policy,
+            [XEN_SYSCTL_cpu_featureset_hvm_max] = &hvm_max_cpu_policy,
         };
-        const struct cpuid_policy *p = NULL;
+        const struct cpu_policy *p = NULL;
         uint32_t featureset[FSCAPINTS];
         unsigned int nr;
 
--- a/xen/include/asm-x86/cpu-policy.h
+++ b/xen/include/asm-x86/cpu-policy.h
@@ -309,6 +309,11 @@ struct cpu_policy
     uint8_t x86_vendor;
 };
 
+extern struct cpu_policy     raw_cpu_policy;
+extern struct cpu_policy    host_cpu_policy;
+extern struct cpu_policy  pv_max_cpu_policy;
+extern struct cpu_policy hvm_max_cpu_policy;
+
 /* Temporary */
 #define cpuid_policy cpu_policy
 #define msr_policy cpu_policy
--- a/xen/include/asm-x86/cpuid.h
+++ b/xen/include/asm-x86/cpuid.h
@@ -48,9 +48,6 @@ extern struct cpuidmasks cpuidmask_defau
 /* Whether or not cpuid faulting is available for the current domain. */
 DECLARE_PER_CPU(bool, cpuid_faulting_enabled);
 
-extern struct cpuid_policy raw_policy, host_policy, pv_max_policy,
-    hvm_max_policy;
-
 /* Allocate and initialise a CPUID policy suitable for the domain. */
 int init_domain_cpuid_policy(struct domain *d);
 
