# Commit e32605b07ef2e01c9d05da9b2d5d7b8f9a5c7c1b
# Date 2020-08-27 12:48:46 +0100
# Author Andrew Cooper <andrew.cooper3@citrix.com>
# Committer Jan Beulich <jbeulich@suse.com>
x86: Begin to introduce support for MSR_ARCH_CAPS

... including serialisation/deserialisation logic and unit tests.

There is no current way to configure this MSR correctly for guests.
The toolstack side this logic needs building, which is far easier to
do with it in place.

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
@@ -6,6 +6,7 @@
 #include <asm/hvm/nestedhvm.h>
 #include <asm/hvm/svm/svm.h>
 #include <asm/hvm/vmx/vmcs.h>
+#include <asm/msr.h>
 #include <asm/paging.h>
 #include <asm/processor.h>
 #include <asm/xstate.h>
@@ -702,8 +703,9 @@ void recalculate_cpuid_policy(struct dom
 int init_domain_cpuid_policy(struct domain *d)
 {
     d->arch.cpuid = xmalloc(struct cpuid_policy);
+    d->arch.msr = xzalloc(struct msr_policy);
 
-    if ( !d->arch.cpuid )
+    if ( !d->arch.cpuid || !d->arch.msr )
         return -ENOMEM;
 
     *d->arch.cpuid = is_pv_domain(d) ? pv_max_policy : hvm_max_policy;
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -675,6 +675,7 @@ int arch_domain_create(struct domain *d,
     {
         d->arch.emulation_flags = 0;
         d->arch.cpuid = ZERO_BLOCK_PTR; /* Catch stray misuses. */
+        d->arch.msr = ZERO_BLOCK_PTR;
     }
     else
     {
@@ -855,6 +856,7 @@ int arch_domain_create(struct domain *d,
     iommu_domain_destroy(d);
     cleanup_domain_irq_mapping(d);
     free_xenheap_page(d->shared_info);
+    xfree(d->arch.msr);
     xfree(d->arch.cpuid);
     if ( paging_initialised )
         paging_final_teardown(d);
@@ -876,6 +878,7 @@ void arch_domain_destroy(struct domain *
 
     xfree(d->arch.e820);
     xfree(d->arch.cpuid);
+    xfree(d->arch.msr);
 
     free_domain_pirqs(d);
     if ( !is_idle_domain(d) )
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -3459,8 +3459,10 @@ int hvm_msr_read_intercept(unsigned int
         break;
 
     case MSR_ARCH_CAPABILITIES:
-        /* Not implemented yet. */
-        goto gp_fault;
+        if ( !d->arch.cpuid->feat.arch_caps )
+            goto gp_fault;
+        *msr_content = d->arch.msr->arch_caps.raw;
+        break;
 
     case MSR_K8_ENABLE_C1E:
     case MSR_AMD64_NB_CFG:
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -2685,8 +2685,10 @@ static int priv_op_read_msr(unsigned int
         return X86EMUL_OKAY;
 
     case MSR_ARCH_CAPABILITIES:
-        /* Not implemented yet. */
-        break;
+        if ( !currd->arch.cpuid->feat.arch_caps )
+            break;
+        *val = currd->arch.msr->arch_caps.raw;
+        return X86EMUL_OKAY;
 
     case MSR_INTEL_MISC_FEATURES_ENABLES:
         if ( !boot_cpu_has(X86_FEATURE_MSR_MISC_FEATURES) )
--- a/xen/include/asm-x86/domain.h
+++ b/xen/include/asm-x86/domain.h
@@ -401,6 +401,7 @@ struct arch_domain
 
     /* CPUID Policy. */
     struct cpuid_policy *cpuid;
+    struct msr_policy *msr;
 
     struct PITState vpit;
 
--- a/xen/include/asm-x86/msr.h
+++ b/xen/include/asm-x86/msr.h
@@ -222,6 +222,31 @@ static inline void wrmsr_tsc_aux(uint32_
     }
 }
 
+/* MSR policy object for shared per-domain MSRs */
+struct msr_policy {
+    /*
+     * 0x0000010a - MSR_ARCH_CAPABILITIES
+     *
+     * This is an Intel-only MSR, which provides miscellaneous enumeration,
+     * including those which indicate that microarchitectrual sidechannels are
+     * fixed in hardware.
+     */
+    union {
+        uint32_t raw;
+        struct {
+            bool rdcl_no:1;
+            bool ibrs_all:1;
+            bool rsba:1;
+            bool skip_l1dfl:1;
+            bool ssb_no:1;
+            bool mds_no:1;
+            bool if_pschange_mc_no:1;
+            bool tsx_ctrl:1;
+            bool taa_no:1;
+        };
+    } arch_caps;
+};
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __ASM_MSR_H */
--- a/xen/include/public/arch-x86/cpufeatureset.h
+++ b/xen/include/public/arch-x86/cpufeatureset.h
@@ -259,7 +259,7 @@ XEN_CPUFEATURE(TSX_FORCE_ABORT, 9*32+13)
 XEN_CPUFEATURE(IBRSB,         9*32+26) /*A  IBRS and IBPB support (used by Intel) */
 XEN_CPUFEATURE(STIBP,         9*32+27) /*A  STIBP */
 XEN_CPUFEATURE(L1D_FLUSH,     9*32+28) /*S  MSR_FLUSH_CMD and L1D flush. */
-XEN_CPUFEATURE(ARCH_CAPS,     9*32+29) /*   IA32_ARCH_CAPABILITIES MSR */
+XEN_CPUFEATURE(ARCH_CAPS,     9*32+29) /*!  IA32_ARCH_CAPABILITIES MSR */
 XEN_CPUFEATURE(SSBD,          9*32+31) /*A  MSR_SPEC_CTRL.SSBD available */
 
 #endif /* XEN_CPUFEATURE */
