File xsa435-0-50.patch of Package xen.31135

# Commit 44fde35fdd5abb99a9d7de79ffe95176260b50fe
# Date 2023-08-03 19:14:19 +0100
# Author Roger Pau Monne <roger.pau@citrix.com>
# Committer Andrew Cooper <andrew.cooper3@citrix.com>
libs/guest: introduce support for setting guest MSRs

Like it's done with CPUID, introduce support for passing MSR values to
xc_cpuid_apply_policy().  The chosen format for expressing MSR policy
data matches the current one used for CPUID.  Note that existing
callers of xc_cpuid_apply_policy() can pass NULL as the value for the
newly introduced 'msr' parameter in order to preserve the same
functionality, and in fact that's done in libxl on this patch.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Acked-by: Anthony PERARD <anthony.perard@citrix.com>
(cherry picked from commit ed742cf1b65c822759833027ca5cbb087c506a41)

--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -1793,6 +1793,7 @@ int xc_domain_debug_control(xc_interface
                             uint32_t vcpu);
 
 #if defined(__i386__) || defined(__x86_64__)
+#define XC_X86_MSR_LEAF 0x006e6558 /* 'Xen\0' */
 int xc_cpuid_set(xc_interface *xch,
                  uint32_t domid,
                  const unsigned int *input,
--- a/tools/libxc/xc_cpuid_x86.c
+++ b/tools/libxc/xc_cpuid_x86.c
@@ -304,7 +304,8 @@ int xc_cpuid_set(
     unsigned int i, j, regs[4] = {}, polregs[4] = {};
     xc_dominfo_t di;
     xen_cpuid_leaf_t *leaves = NULL;
-    unsigned int nr_leaves, policy_leaves, nr_msrs;
+    xen_msr_entry_t *msrs = NULL;
+    unsigned int nr_leaves, policy_leaves, nr_msrs, policy_msrs;
     uint32_t err_leaf = -1, err_subleaf = -1, err_msr = -1;
 
     for ( i = 0; i < 4; ++i )
@@ -327,25 +328,39 @@ int xc_cpuid_set(
     }
 
     rc = -ENOMEM;
-    if ( (leaves = calloc(nr_leaves, sizeof(*leaves))) == NULL )
+    if ( (leaves = calloc(nr_leaves, sizeof(*leaves))) == NULL ||
+         (msrs = calloc(nr_msrs, sizeof(*msrs))) == NULL )
     {
         ERROR("Unable to allocate memory for %u CPUID leaves", nr_leaves);
         goto fail;
     }
 
     /* Get the domain's max policy. */
-    nr_msrs = 0;
+    policy_msrs = nr_msrs;
     policy_leaves = nr_leaves;
     rc = xc_get_system_cpu_policy(xch, di.hvm ? XEN_SYSCTL_cpu_policy_hvm_max
                                               : XEN_SYSCTL_cpu_policy_pv_max,
-                                  &policy_leaves, leaves, &nr_msrs, NULL);
+                                  &policy_leaves, leaves, &policy_msrs, msrs);
     if ( rc )
     {
         PERROR("Failed to obtain %s max policy", di.hvm ? "hvm" : "pv");
         rc = -errno;
         goto fail;
     }
-    for ( i = 0; i < policy_leaves; ++i )
+
+    i = 0;
+    if ( input[0] == XC_X86_MSR_LEAF )
+    {
+        for ( ; i < policy_msrs; ++i )
+            if ( msrs[i].idx == input[1] )
+            {
+                polregs[0] = (uint32_t)msrs[i].val;
+                polregs[3] = msrs[i].val >> 32;
+                break;
+            }
+        i = policy_leaves;
+    }
+    for ( ; i < policy_leaves; ++i )
         if ( leaves[i].leaf == input[0] && leaves[i].subleaf == input[1] )
         {
             polregs[0] = leaves[i].a;
@@ -356,17 +371,30 @@ int xc_cpuid_set(
         }
 
     /* Get the host policy. */
-    nr_msrs = 0;
+    policy_msrs = nr_msrs;
     policy_leaves = nr_leaves;
     rc = xc_get_system_cpu_policy(xch, XEN_SYSCTL_cpu_policy_host,
-                                  &policy_leaves, leaves, &nr_msrs, NULL);
+                                  &policy_leaves, leaves, &policy_msrs, msrs);
     if ( rc )
     {
         PERROR("Failed to obtain host policy");
         rc = -errno;
         goto fail;
     }
-    for ( i = 0; i < policy_leaves; ++i )
+
+    i = 0;
+    if ( input[0] == XC_X86_MSR_LEAF )
+    {
+        for ( ; i < policy_msrs; ++i )
+            if ( msrs[i].idx == input[1] )
+            {
+                regs[0] = (uint32_t)msrs[i].val;
+                regs[3] = msrs[i].val >> 32;
+                break;
+            }
+        i = policy_leaves;
+    }
+    for ( ; i < policy_leaves; ++i )
         if ( leaves[i].leaf == input[0] && leaves[i].subleaf == input[1] )
         {
             regs[0] = leaves[i].a;
@@ -426,10 +454,20 @@ int xc_cpuid_set(
     }
 
     /* Feed the transformed leaf back up to Xen. */
-    leaves[0] = (xen_cpuid_leaf_t){ input[0], input[1],
-                                    regs[0], regs[1], regs[2], regs[3] };
-    rc = xc_set_domain_cpu_policy(xch, domid, 1, leaves, 0, NULL,
-                                  &err_leaf, &err_subleaf, &err_msr);
+    if ( input[0] != XC_X86_MSR_LEAF )
+    {
+        leaves[0] = (xen_cpuid_leaf_t){ input[0], input[1],
+                                        regs[0], regs[1], regs[2], regs[3] };
+        rc = xc_set_domain_cpu_policy(xch, domid, 1, leaves, 0, NULL,
+                                      &err_leaf, &err_subleaf, &err_msr);
+    }
+    else
+    {
+        msrs[0] = (xen_msr_entry_t) { input[1], 0,
+                                      regs[0] | ((uint64_t)regs[3] << 32) };
+        rc = xc_set_domain_cpu_policy(xch, domid, 0, NULL, 1, msrs,
+                                      &err_leaf, &err_subleaf, &err_msr);
+    }
     if ( rc )
     {
         PERROR("Failed to set d%d's policy (err leaf %#x, subleaf %#x, msr %#x)",
@@ -449,6 +487,7 @@ int xc_cpuid_set(
     }
 
  out:
+    free(msrs);
     free(leaves);
 
     return rc;
@@ -461,6 +500,7 @@ int xc_cpuid_apply_policy(xc_interface *
     xc_dominfo_t di;
     unsigned int i, nr_leaves, nr_msrs;
     xen_cpuid_leaf_t *leaves = NULL;
+    xen_msr_entry_t *msrs = NULL;
     struct cpu_policy *p = NULL;
     uint32_t err_leaf = -1, err_subleaf = -1, err_msr = -1;
 
@@ -482,14 +522,14 @@ int xc_cpuid_apply_policy(xc_interface *
 
     rc = -ENOMEM;
     if ( (leaves = calloc(nr_leaves, sizeof(*leaves))) == NULL ||
+         (msrs = calloc(nr_msrs, sizeof(*msrs))) == NULL ||
          (p = calloc(1, sizeof(*p))) == NULL )
         goto out;
 
     /* Get the domain's default policy. */
-    nr_msrs = 0;
     rc = xc_get_system_cpu_policy(xch, di.hvm ? XEN_SYSCTL_cpu_policy_hvm_default
                                               : XEN_SYSCTL_cpu_policy_pv_default,
-                                  &nr_leaves, leaves, &nr_msrs, NULL);
+                                  &nr_leaves, leaves, &nr_msrs, msrs);
     if ( rc )
     {
         PERROR("Failed to obtain %s default policy", di.hvm ? "hvm" : "pv");
@@ -506,6 +546,14 @@ int xc_cpuid_apply_policy(xc_interface *
         goto out;
     }
 
+    rc = x86_msr_copy_from_buffer(p, msrs, nr_msrs, &err_msr);
+    if ( rc )
+    {
+        ERROR("Failed to deserialise MSRs (err msr %#x) (%d = %s)",
+              err_msr, -rc, strerror(-rc));
+        goto out;
+    }
+
     if ( featureset )
     {
         uint32_t disabled_features[FEATURESET_NR_ENTRIES],
@@ -662,7 +710,14 @@ int xc_cpuid_apply_policy(xc_interface *
         goto out;
     }
 
-    rc = xc_set_domain_cpu_policy(xch, domid, nr_leaves, leaves, 0, NULL,
+    rc = x86_msr_copy_to_buffer(p, msrs, &nr_msrs);
+    if ( rc )
+    {
+        ERROR("Failed to serialise MSRs (%d = %s)", -rc, strerror(-rc));
+        goto out;
+    }
+
+    rc = xc_set_domain_cpu_policy(xch, domid, nr_leaves, leaves, nr_msrs, msrs,
                                   &err_leaf, &err_subleaf, &err_msr);
     if ( rc )
     {
@@ -676,6 +731,7 @@ int xc_cpuid_apply_policy(xc_interface *
 
 out:
     free(p);
+    free(msrs);
     free(leaves);
 
     return rc;
openSUSE Build Service is sponsored by