From b672695e748869b2e2e2cb03f671f12003d2b079 Mon Sep 17 00:00:00 2001
From: Andrew Cooper <andrew.cooper3@citrix.com>
Date: Fri, 11 Jun 2021 11:37:53 +0100
Subject: x86/msr: Expose MSR_ARCH_CAPS in the raw and host policies

MSR_ARCH_CAPS is still not supported for guests yet (other than the hardware
domain), until the toolstack learns how to construct an MSR policy.

However, we want access to the host ARCH_CAPS_TSX_CTRL value in particular for
testing purposes.

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

--- a/xen/arch/x86/cpuid.c
+++ b/xen/arch/x86/cpuid.c
@@ -101,6 +101,10 @@ struct cpuid_policy __read_mostly raw_po
     __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 cpuid_leaf(uint32_t leaf, struct cpuid_leaf *data)
 {
@@ -310,6 +314,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;
     unsigned int i;
 
     cpuid_leaf(0, &p->basic.raw[0]);
@@ -385,11 +390,15 @@ static void __init calculate_raw_policy(
         cpuid_leaf(0x80000000 + i, &p->extd.raw[i]);
 
     p->x86_vendor = boot_cpu_data.x86_vendor;
+
+    if ( cpu_has_arch_caps )
+        rdmsrl(MSR_ARCH_CAPABILITIES, mp->arch_caps.raw);
 }
 
 static void __init calculate_host_policy(void)
 {
     struct cpuid_policy *p = &host_policy;
+    struct msr_policy *mp = &host_msr_policy;
     unsigned int max_extd_leaf;
 
     *p = raw_policy;
@@ -429,6 +438,14 @@ static void __init calculate_host_policy
         p->extd.raw[0xa].d |= ((1u << SVM_FEATURE_VMCBCLEAN) |
                                (1u << SVM_FEATURE_TSCRATEMSR));
     }
+
+    *mp = raw_msr_policy;
+
+    /* Temporary, until we have known_features[] for feature bits in MSRs. */
+    mp->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);
 }
 
 static void __init guest_common_feature_adjustments(uint32_t *fs)
@@ -456,6 +473,7 @@ 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;
     uint32_t pv_featureset[FSCAPINTS];
     unsigned int i;
 
@@ -479,11 +497,16 @@ static void __init calculate_pv_max_poli
     recalculate_xstate(p);
 
     p->extd.raw[0xa] = EMPTY_LEAF; /* No SVM for PV guests. */
+
+    *mp = host_msr_policy;
+
+    mp->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;
     uint32_t hvm_featureset[FSCAPINTS];
     unsigned int i;
     const uint32_t *hvm_featuremask;
@@ -539,6 +562,10 @@ static void __init calculate_hvm_max_pol
     sanitise_featureset(hvm_featureset);
     cpuid_featureset_to_policy(hvm_featureset, p);
     recalculate_xstate(p);
+
+    *mp = host_msr_policy;
+
+    mp->arch_caps.raw = 0; /* Not supported yet. */
 }
 
 void __init init_guest_cpuid(void)
--- a/xen/include/asm-x86/cpufeature.h
+++ b/xen/include/asm-x86/cpufeature.h
@@ -107,6 +107,7 @@
 
 /* CPUID level 0x00000007:0.edx */
 #define cpu_has_tsx_force_abort boot_cpu_has(X86_FEATURE_TSX_FORCE_ABORT)
+#define cpu_has_arch_caps       boot_cpu_has(X86_FEATURE_ARCH_CAPS)
 
 /* Synthesized. */
 #define cpu_has_arch_perfmon    boot_cpu_has(X86_FEATURE_ARCH_PERFMON)
