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;