mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
x86: Merge a domain's {cpuid,msr} policy objects
Right now, they're the same underlying type, containing disjoint information.
Drop the d->arch.msr pointer, and union d->arch.cpuid to give it a second name
of cpu_policy in the interim.
Merge init_domain_{cpuid,msr}_policy() into a single init_domain_cpu_policy(),
moving the implementation into cpu-policy.c
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>
(cherry picked from commit bd13dae348)
This commit is contained in:
1 parent
83a720e912
commit
99d01e3729
9 files changed
+85
-102
No files matched your search
@@ -1,10 +1,13 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#include <xen/cache.h>
|
||||
#include <xen/kernel.h>
|
||||
#include <xen/sched.h>
|
||||
|
||||
#include <xen/lib/x86/cpu-policy.h>
|
||||
|
||||
#include <asm/cpu-policy.h>
|
||||
#include <asm/msr-index.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
struct cpu_policy __read_mostly raw_cpu_policy;
|
||||
struct cpu_policy __read_mostly host_cpu_policy;
|
||||
@@ -16,3 +19,49 @@ struct cpu_policy __read_mostly pv_def_cpu_policy;
|
||||
struct cpu_policy __read_mostly hvm_max_cpu_policy;
|
||||
struct cpu_policy __read_mostly hvm_def_cpu_policy;
|
||||
#endif
|
||||
|
||||
int init_domain_cpu_policy(struct domain *d)
|
||||
{
|
||||
struct cpu_policy *p = is_pv_domain(d)
|
||||
? (IS_ENABLED(CONFIG_PV) ? &pv_def_cpu_policy : NULL)
|
||||
: (IS_ENABLED(CONFIG_HVM) ? &hvm_def_cpu_policy : NULL);
|
||||
|
||||
if ( !p )
|
||||
{
|
||||
ASSERT_UNREACHABLE();
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
p = xmemdup(p);
|
||||
if ( !p )
|
||||
return -ENOMEM;
|
||||
|
||||
/* See comment in ctxt_switch_levelling() */
|
||||
if ( !opt_dom0_cpuid_faulting && is_control_domain(d) && is_pv_domain(d) )
|
||||
p->platform_info.cpuid_faulting = false;
|
||||
|
||||
/*
|
||||
* Expose the "hardware speculation behaviour" bits of ARCH_CAPS to dom0,
|
||||
* so dom0 can turn off workarounds as appropriate. Temporary, until the
|
||||
* domain policy logic gains a better understanding of MSRs.
|
||||
*/
|
||||
if ( is_hardware_domain(d) && cpu_has_arch_caps )
|
||||
{
|
||||
uint64_t val;
|
||||
|
||||
rdmsrl(MSR_ARCH_CAPABILITIES, val);
|
||||
|
||||
p->arch_caps.raw = val &
|
||||
(ARCH_CAPS_RDCL_NO | ARCH_CAPS_IBRS_ALL | ARCH_CAPS_RSBA |
|
||||
ARCH_CAPS_SSB_NO | ARCH_CAPS_MDS_NO | ARCH_CAPS_IF_PSCHANGE_MC_NO |
|
||||
ARCH_CAPS_TAA_NO | ARCH_CAPS_SBDR_SSDP_NO | ARCH_CAPS_FBSDP_NO |
|
||||
ARCH_CAPS_PSDP_NO | ARCH_CAPS_FB_CLEAR | ARCH_CAPS_RRSBA |
|
||||
ARCH_CAPS_BHI_NO | ARCH_CAPS_PBRSB_NO);
|
||||
}
|
||||
|
||||
d->arch.cpu_policy = p;
|
||||
|
||||
recalculate_cpuid_policy(d);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -755,29 +755,6 @@ void recalculate_cpuid_policy(struct domain *d)
|
||||
p->extd.raw[0x19] = EMPTY_LEAF;
|
||||
}
|
||||
|
||||
int init_domain_cpuid_policy(struct domain *d)
|
||||
{
|
||||
struct cpuid_policy *p = is_pv_domain(d)
|
||||
? (IS_ENABLED(CONFIG_PV) ? &pv_def_cpu_policy : NULL)
|
||||
: (IS_ENABLED(CONFIG_HVM) ? &hvm_def_cpu_policy : NULL);
|
||||
|
||||
if ( !p )
|
||||
{
|
||||
ASSERT_UNREACHABLE();
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
p = xmemdup(p);
|
||||
if ( !p )
|
||||
return -ENOMEM;
|
||||
|
||||
d->arch.cpuid = p;
|
||||
|
||||
recalculate_cpuid_policy(d);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __init init_dom0_cpuid_policy(struct domain *d)
|
||||
{
|
||||
struct cpuid_policy *p = d->arch.cpuid;
|
||||
|
||||
+5
-10
@@ -64,6 +64,7 @@
|
||||
#include <xen/numa.h>
|
||||
#include <xen/iommu.h>
|
||||
#include <compat/vcpu.h>
|
||||
#include <asm/cpu-policy.h>
|
||||
#include <asm/psr.h>
|
||||
#include <asm/pv/domain.h>
|
||||
#include <asm/pv/mm.h>
|
||||
@@ -534,8 +535,7 @@ int arch_domain_create(struct domain *d,
|
||||
|
||||
d->arch.ctxt_switch = &idle_csw;
|
||||
|
||||
d->arch.cpuid = ZERO_BLOCK_PTR; /* Catch stray misuses. */
|
||||
d->arch.msr = ZERO_BLOCK_PTR;
|
||||
d->arch.cpu_policy = ZERO_BLOCK_PTR; /* Catch stray misuses. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -588,10 +588,7 @@ int arch_domain_create(struct domain *d,
|
||||
goto fail;
|
||||
paging_initialised = true;
|
||||
|
||||
if ( (rc = init_domain_cpuid_policy(d)) )
|
||||
goto fail;
|
||||
|
||||
if ( (rc = init_domain_msr_policy(d)) )
|
||||
if ( (rc = init_domain_cpu_policy(d)) )
|
||||
goto fail;
|
||||
|
||||
d->arch.ioport_caps =
|
||||
@@ -660,8 +657,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.cpuid);
|
||||
xfree(d->arch.msr);
|
||||
XFREE(d->arch.cpu_policy);
|
||||
if ( paging_initialised )
|
||||
paging_final_teardown(d);
|
||||
free_perdomain_mappings(d);
|
||||
@@ -675,8 +671,7 @@ void arch_domain_destroy(struct domain *d)
|
||||
hvm_domain_destroy(d);
|
||||
|
||||
xfree(d->arch.e820);
|
||||
xfree(d->arch.cpuid);
|
||||
xfree(d->arch.msr);
|
||||
XFREE(d->arch.cpu_policy);
|
||||
|
||||
free_domain_pirqs(d);
|
||||
if ( !is_idle_domain(d) )
|
||||
|
||||
+17
-18
@@ -219,11 +219,11 @@ void domain_cpu_policy_changed(struct domain *d)
|
||||
static int update_domain_cpu_policy(struct domain *d,
|
||||
xen_domctl_cpu_policy_t *xdpc)
|
||||
{
|
||||
struct old_cpu_policy new = {};
|
||||
struct cpu_policy *new;
|
||||
struct cpu_policy *sys = is_pv_domain(d)
|
||||
? (IS_ENABLED(CONFIG_PV) ? &pv_max_cpu_policy : NULL)
|
||||
: (IS_ENABLED(CONFIG_HVM) ? &hvm_max_cpu_policy : NULL);
|
||||
struct old_cpu_policy old_sys = { sys, sys };
|
||||
struct old_cpu_policy old_sys = { sys, sys }, old_new;
|
||||
struct cpu_policy_errors err = INIT_CPU_POLICY_ERRORS;
|
||||
int ret = -ENOMEM;
|
||||
|
||||
@@ -233,33 +233,33 @@ static int update_domain_cpu_policy(struct domain *d,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* Start by copying the domain's existing policies. */
|
||||
if ( !(new.cpuid = xmemdup(d->arch.cpuid)) ||
|
||||
!(new.msr = xmemdup(d->arch.msr)) )
|
||||
/* Start by copying the domain's existing policy. */
|
||||
if ( !(new = xmemdup(d->arch.cpu_policy)) )
|
||||
goto out;
|
||||
|
||||
old_new = (struct old_cpu_policy){ new, new };
|
||||
|
||||
/* Merge the toolstack provided data. */
|
||||
if ( (ret = x86_cpuid_copy_from_buffer(
|
||||
new.cpuid, xdpc->leaves, xdpc->nr_leaves,
|
||||
new, xdpc->leaves, xdpc->nr_leaves,
|
||||
&err.leaf, &err.subleaf)) ||
|
||||
(ret = x86_msr_copy_from_buffer(
|
||||
new.msr, xdpc->msrs, xdpc->nr_msrs, &err.msr)) )
|
||||
new, xdpc->msrs, xdpc->nr_msrs, &err.msr)) )
|
||||
goto out;
|
||||
|
||||
/* Trim any newly-stale out-of-range leaves. */
|
||||
x86_cpuid_policy_clear_out_of_range_leaves(new.cpuid);
|
||||
x86_cpuid_policy_clear_out_of_range_leaves(new);
|
||||
|
||||
/* Audit the combined dataset. */
|
||||
ret = x86_cpu_policies_are_compatible(&old_sys, &new, &err);
|
||||
ret = x86_cpu_policies_are_compatible(&old_sys, &old_new, &err);
|
||||
if ( ret )
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Audit was successful. Replace existing policies, leaving the old
|
||||
* policies to be freed.
|
||||
* Audit was successful. Replace the existing policy, leaving the old one
|
||||
* to be freed.
|
||||
*/
|
||||
SWAP(new.cpuid, d->arch.cpuid);
|
||||
SWAP(new.msr, d->arch.msr);
|
||||
SWAP(new, d->arch.cpu_policy);
|
||||
|
||||
/* TODO: Drop when x86_cpu_policies_are_compatible() is completed. */
|
||||
recalculate_cpuid_policy(d);
|
||||
@@ -268,9 +268,8 @@ static int update_domain_cpu_policy(struct domain *d,
|
||||
domain_cpu_policy_changed(d);
|
||||
|
||||
out:
|
||||
/* Free whichever cpuid/msr structs are not installed in struct domain. */
|
||||
xfree(new.cpuid);
|
||||
xfree(new.msr);
|
||||
/* Free whichever struct is not installed in struct domain. */
|
||||
xfree(new);
|
||||
|
||||
if ( ret )
|
||||
{
|
||||
@@ -1461,7 +1460,7 @@ long arch_do_domctl(
|
||||
if ( guest_handle_is_null(domctl->u.cpu_policy.leaves) )
|
||||
domctl->u.cpu_policy.nr_leaves = CPUID_MAX_SERIALISED_LEAVES;
|
||||
else if ( (ret = x86_cpuid_copy_to_buffer(
|
||||
d->arch.cpuid,
|
||||
d->arch.cpu_policy,
|
||||
domctl->u.cpu_policy.leaves,
|
||||
&domctl->u.cpu_policy.nr_leaves)) )
|
||||
break;
|
||||
@@ -1470,7 +1469,7 @@ long arch_do_domctl(
|
||||
if ( guest_handle_is_null(domctl->u.cpu_policy.msrs) )
|
||||
domctl->u.cpu_policy.nr_msrs = MSR_MAX_SERIALISED_ENTRIES;
|
||||
else if ( (ret = x86_msr_copy_to_buffer(
|
||||
d->arch.msr,
|
||||
d->arch.cpu_policy,
|
||||
domctl->u.cpu_policy.msrs,
|
||||
&domctl->u.cpu_policy.nr_msrs)) )
|
||||
break;
|
||||
|
||||
@@ -119,50 +119,6 @@ void __init init_guest_msr_policy(void)
|
||||
}
|
||||
}
|
||||
|
||||
int init_domain_msr_policy(struct domain *d)
|
||||
{
|
||||
struct msr_policy *mp = is_pv_domain(d)
|
||||
? (IS_ENABLED(CONFIG_PV) ? &pv_def_cpu_policy : NULL)
|
||||
: (IS_ENABLED(CONFIG_HVM) ? &hvm_def_cpu_policy : NULL);
|
||||
|
||||
if ( !mp )
|
||||
{
|
||||
ASSERT_UNREACHABLE();
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
mp = xmemdup(mp);
|
||||
if ( !mp )
|
||||
return -ENOMEM;
|
||||
|
||||
/* See comment in ctxt_switch_levelling() */
|
||||
if ( !opt_dom0_cpuid_faulting && is_control_domain(d) && is_pv_domain(d) )
|
||||
mp->platform_info.cpuid_faulting = false;
|
||||
|
||||
/*
|
||||
* Expose the "hardware speculation behaviour" bits of ARCH_CAPS to dom0,
|
||||
* so dom0 can turn off workarounds as appropriate. Temporary, until the
|
||||
* domain policy logic gains a better understanding of MSRs.
|
||||
*/
|
||||
if ( is_hardware_domain(d) && cpu_has_arch_caps )
|
||||
{
|
||||
uint64_t val;
|
||||
|
||||
rdmsrl(MSR_ARCH_CAPABILITIES, val);
|
||||
|
||||
mp->arch_caps.raw = val &
|
||||
(ARCH_CAPS_RDCL_NO | ARCH_CAPS_IBRS_ALL | ARCH_CAPS_RSBA |
|
||||
ARCH_CAPS_SSB_NO | ARCH_CAPS_MDS_NO | ARCH_CAPS_IF_PSCHANGE_MC_NO |
|
||||
ARCH_CAPS_TAA_NO | ARCH_CAPS_SBDR_SSDP_NO | ARCH_CAPS_FBSDP_NO |
|
||||
ARCH_CAPS_PSDP_NO | ARCH_CAPS_FB_CLEAR | ARCH_CAPS_RRSBA |
|
||||
ARCH_CAPS_BHI_NO | ARCH_CAPS_PBRSB_NO);
|
||||
}
|
||||
|
||||
d->arch.msr = mp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int init_vcpu_msr_policy(struct vcpu *v)
|
||||
{
|
||||
struct vcpu_msrs *msrs = xzalloc(struct vcpu_msrs);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#define X86_CPU_POLICY_H
|
||||
|
||||
struct cpu_policy;
|
||||
struct domain;
|
||||
|
||||
extern struct cpu_policy raw_cpu_policy;
|
||||
extern struct cpu_policy host_cpu_policy;
|
||||
@@ -11,4 +12,7 @@ extern struct cpu_policy pv_def_cpu_policy;
|
||||
extern struct cpu_policy hvm_max_cpu_policy;
|
||||
extern struct cpu_policy hvm_def_cpu_policy;
|
||||
|
||||
/* Allocate and initialise a CPU policy suitable for the domain. */
|
||||
int init_domain_cpu_policy(struct domain *d);
|
||||
|
||||
#endif /* X86_CPU_POLICY_H */
|
||||
@@ -49,9 +49,6 @@ extern struct cpuidmasks cpuidmask_defaults;
|
||||
/* Check that all previously present features are still available. */
|
||||
bool recheck_cpu_features(unsigned int cpu);
|
||||
|
||||
/* Allocate and initialise a CPUID policy suitable for the domain. */
|
||||
int init_domain_cpuid_policy(struct domain *d);
|
||||
|
||||
/* Apply dom0-specific tweaks to the CPUID policy. */
|
||||
void init_dom0_cpuid_policy(struct domain *d);
|
||||
|
||||
|
||||
@@ -368,9 +368,16 @@ struct arch_domain
|
||||
*/
|
||||
uint8_t x87_fip_width;
|
||||
|
||||
/* CPUID and MSR policy objects. */
|
||||
struct cpuid_policy *cpuid;
|
||||
struct msr_policy *msr;
|
||||
/*
|
||||
* The domain's CPU Policy. "cpu_policy" is considered the canonical
|
||||
* pointer, but the "cpuid" and "msr" aliases exist so the most
|
||||
* appropriate one can be used for local code clarity.
|
||||
*/
|
||||
union {
|
||||
struct cpu_policy *cpu_policy;
|
||||
struct cpu_policy *cpuid;
|
||||
struct cpu_policy *msr;
|
||||
};
|
||||
|
||||
struct PITState vpit;
|
||||
|
||||
|
||||
@@ -334,7 +334,6 @@ struct vcpu_msrs
|
||||
};
|
||||
|
||||
void init_guest_msr_policy(void);
|
||||
int init_domain_msr_policy(struct domain *d);
|
||||
int init_vcpu_msr_policy(struct vcpu *v);
|
||||
|
||||
/*
|
||||
|
||||