|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen master] x86/cpuid: Recalculate a domains CPUID policy when appropriate
commit 736a48bf9339f672be9279180ceea7620241cdd7
Author: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
AuthorDate: Wed Jan 11 11:59:02 2017 +0000
Commit: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
CommitDate: Wed Jan 11 11:59:02 2017 +0000
x86/cpuid: Recalculate a domains CPUID policy when appropriate
Introduce recalculate_cpuid_policy() which clamps a CPUID policy based on
the
domains current restrictions.
Each adjustment introduced here mirrors what currently happens in
{pv,hvm}_cpuid(), although some logic is expressed differently.
* The clearing X86_FEATURE_LM for 32bit PV guests, sanitise_featureset()
takes out all 64bit-dependent features in one go.
* The toolstacks choice of X86_FEATURE_ITSC in (by default) clobbered in
domain_cpuid(), but {pv,hvm}_cpuid() needed to account for the host ITSC
value when masking the toolstack value.
This now requires that sanitise_featureset(), lookup_deep_deps() and
associated data needs to be available at runtime, so moves out of __init.
Recalculate the cpuid policy when:
* The domain is first created
* Switching a PV guest to being compat
* Setting disable_migrate or vTSC modes
* The toolstack sets new policy data
The disable_migrate code was previously common. To compensate, move the
code
to each archs arch_do_domctl(), as the implementations now differ.
From this point on, domains have full and correct feature-leaf information
in
their CPUID policies, allowing for substantial cleanup and improvements.
Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx>
Acked-by: Stefano Stabellini <sstabellini@xxxxxxxxxx>
---
xen/arch/arm/domctl.c | 5 +++
xen/arch/x86/cpuid.c | 70 ++++++++++++++++++++++++++++++++++++----
xen/arch/x86/domain.c | 1 +
xen/arch/x86/domctl.c | 29 +++++++++++++++++
xen/arch/x86/time.c | 2 ++
xen/common/domctl.c | 4 ---
xen/include/asm-x86/cpufeature.h | 1 +
xen/include/asm-x86/cpuid.h | 10 +++---
8 files changed, 105 insertions(+), 17 deletions(-)
diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c
index 09d9959..c5d1c33 100644
--- a/xen/arch/arm/domctl.c
+++ b/xen/arch/arm/domctl.c
@@ -115,6 +115,11 @@ long arch_do_domctl(struct xen_domctl *domctl, struct
domain *d,
return 0;
}
+
+ case XEN_DOMCTL_disable_migrate:
+ d->disable_migrate = domctl->u.disable_migrate.disable;
+ return 0;
+
default:
{
int rc;
diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c
index fcd9acc..fc3c90e 100644
--- a/xen/arch/x86/cpuid.c
+++ b/xen/arch/x86/cpuid.c
@@ -10,10 +10,10 @@
const uint32_t known_features[] = INIT_KNOWN_FEATURES;
const uint32_t special_features[] = INIT_SPECIAL_FEATURES;
-static const uint32_t __initconst pv_featuremask[] = INIT_PV_FEATURES;
-static const uint32_t __initconst hvm_shadow_featuremask[] =
INIT_HVM_SHADOW_FEATURES;
-static const uint32_t __initconst hvm_hap_featuremask[] =
INIT_HVM_HAP_FEATURES;
-static const uint32_t __initconst deep_features[] = INIT_DEEP_FEATURES;
+static const uint32_t pv_featuremask[] = INIT_PV_FEATURES;
+static const uint32_t hvm_shadow_featuremask[] = INIT_HVM_SHADOW_FEATURES;
+static const uint32_t hvm_hap_featuremask[] = INIT_HVM_HAP_FEATURES;
+static const uint32_t deep_features[] = INIT_DEEP_FEATURES;
#define EMPTY_LEAF ((struct cpuid_leaf){})
@@ -33,7 +33,7 @@ static void cpuid_count_leaf(uint32_t leaf, uint32_t subleaf,
cpuid_count(leaf, subleaf, &data->a, &data->b, &data->c, &data->d);
}
-static void __init sanitise_featureset(uint32_t *fs)
+static void sanitise_featureset(uint32_t *fs)
{
/* for_each_set_bit() uses unsigned longs. Extend with zeroes. */
uint32_t disabled_features[
@@ -232,12 +232,12 @@ void __init init_guest_cpuid(void)
calculate_hvm_max_policy();
}
-const uint32_t * __init lookup_deep_deps(uint32_t feature)
+const uint32_t *lookup_deep_deps(uint32_t feature)
{
static const struct {
uint32_t feature;
uint32_t fs[FSCAPINTS];
- } deep_deps[] __initconst = INIT_DEEP_DEPS;
+ } deep_deps[] = INIT_DEEP_DEPS;
unsigned int start = 0, end = ARRAY_SIZE(deep_deps);
BUILD_BUG_ON(ARRAY_SIZE(deep_deps) != NR_DEEP_DEPS);
@@ -262,6 +262,60 @@ const uint32_t * __init lookup_deep_deps(uint32_t feature)
return NULL;
}
+void recalculate_cpuid_policy(struct domain *d)
+{
+ struct cpuid_policy *p = d->arch.cpuid;
+ const struct cpuid_policy *max =
+ is_pv_domain(d) ? &pv_max_policy : &hvm_max_policy;
+ uint32_t fs[FSCAPINTS], max_fs[FSCAPINTS];
+ unsigned int i;
+
+ cpuid_policy_to_featureset(p, fs);
+ memcpy(max_fs, max->fs, sizeof(max_fs));
+
+ /*
+ * HVM domains using Shadow paging have further restrictions on their
+ * available paging features.
+ */
+ if ( is_hvm_domain(d) && !hap_enabled(d) )
+ {
+ for ( i = 0; i < ARRAY_SIZE(max_fs); i++ )
+ max_fs[i] &= hvm_shadow_featuremask[i];
+ }
+
+ /*
+ * 32bit PV domains can't use any Long Mode features, and cannot use
+ * SYSCALL on non-AMD hardware.
+ */
+ if ( is_pv_32bit_domain(d) )
+ {
+ __clear_bit(X86_FEATURE_LM, max_fs);
+ if ( boot_cpu_data.x86_vendor != X86_VENDOR_AMD )
+ __clear_bit(X86_FEATURE_SYSCALL, max_fs);
+ }
+
+ /*
+ * ITSC is masked by default (so domains are safe to migrate), but a
+ * toolstack which has configured disable_migrate or vTSC for a domain may
+ * safely select it, and needs a way of doing so.
+ */
+ if ( cpu_has_itsc && (d->disable_migrate || d->arch.vtsc) )
+ __set_bit(X86_FEATURE_ITSC, max_fs);
+
+ /* Clamp the toolstacks choices to reality. */
+ for ( i = 0; i < ARRAY_SIZE(fs); i++ )
+ fs[i] &= max_fs[i];
+
+ sanitise_featureset(fs);
+
+ /* Fold host's FDP_EXCP_ONLY and NO_FPU_SEL into guest's view. */
+ fs[FEATURESET_7b0] &= ~special_features[FEATURESET_7b0];
+ fs[FEATURESET_7b0] |= (host_featureset[FEATURESET_7b0] &
+ special_features[FEATURESET_7b0]);
+
+ cpuid_featureset_to_policy(fs, p);
+}
+
int init_domain_cpuid_policy(struct domain *d)
{
d->arch.cpuid = xmalloc(struct cpuid_policy);
@@ -271,6 +325,8 @@ int init_domain_cpuid_policy(struct domain *d)
*d->arch.cpuid = is_pv_domain(d) ? pv_max_policy : hvm_max_policy;
+ recalculate_cpuid_policy(d);
+
return 0;
}
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index c1f95cc..7d33c41 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -352,6 +352,7 @@ int switch_compat(struct domain *d)
}
domain_set_alloc_bitsize(d);
+ recalculate_cpuid_policy(d);
d->arch.x87_fip_width = 4;
diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
index ab141b1..a37a6a1 100644
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -51,6 +51,30 @@ static int gdbsx_guest_mem_io(domid_t domid, struct
xen_domctl_gdbsx_memio *iop)
static void update_domain_cpuid_info(struct domain *d,
const xen_domctl_cpuid_t *ctl)
{
+ struct cpuid_policy *p = d->arch.cpuid;
+ const struct cpuid_leaf leaf = { ctl->eax, ctl->ebx, ctl->ecx, ctl->edx };
+
+ /* Insert ctl data into cpuid_policy. */
+ if ( ctl->input[0] < ARRAY_SIZE(p->basic.raw) )
+ {
+ if ( ctl->input[0] == 7 )
+ {
+ if ( ctl->input[1] < ARRAY_SIZE(p->feat.raw) )
+ p->feat.raw[ctl->input[1]] = leaf;
+ }
+ else if ( ctl->input[0] == XSTATE_CPUID )
+ {
+ if ( ctl->input[1] < ARRAY_SIZE(p->xstate.raw) )
+ p->xstate.raw[ctl->input[1]] = leaf;
+ }
+ else
+ p->basic.raw[ctl->input[0]] = leaf;
+ }
+ else if ( (ctl->input[0] - 0x80000000) < ARRAY_SIZE(p->extd.raw) )
+ p->extd.raw[ctl->input[0] - 0x80000000] = leaf;
+
+ recalculate_cpuid_policy(d);
+
switch ( ctl->input[0] )
{
case 0: {
@@ -1409,6 +1433,11 @@ long arch_do_domctl(
}
break;
+ case XEN_DOMCTL_disable_migrate:
+ d->disable_migrate = domctl->u.disable_migrate.disable;
+ recalculate_cpuid_policy(d);
+ break;
+
default:
ret = iommu_do_domctl(domctl, d, u_domctl);
break;
diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c
index b89fa13..e17da1b 100644
--- a/xen/arch/x86/time.c
+++ b/xen/arch/x86/time.c
@@ -2106,6 +2106,8 @@ void tsc_set_info(struct domain *d,
d->arch.hvm_domain.sync_tsc);
}
}
+
+ recalculate_cpuid_policy(d);
}
/* vtsc may incur measurable performance degradation, diagnose with this */
diff --git a/xen/common/domctl.c b/xen/common/domctl.c
index b0ee961..12cf4a9 100644
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -1103,10 +1103,6 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t)
u_domctl)
copyback = 1;
break;
- case XEN_DOMCTL_disable_migrate:
- d->disable_migrate = op->u.disable_migrate.disable;
- break;
-
#ifdef CONFIG_HAS_MEM_ACCESS
case XEN_DOMCTL_set_access_required:
if ( unlikely(current->domain == d) ) /* no domain_pause() */
diff --git a/xen/include/asm-x86/cpufeature.h b/xen/include/asm-x86/cpufeature.h
index 9326616..f34d01c 100644
--- a/xen/include/asm-x86/cpufeature.h
+++ b/xen/include/asm-x86/cpufeature.h
@@ -71,6 +71,7 @@
#define cpu_has_eist boot_cpu_has(X86_FEATURE_EIST)
#define cpu_has_hypervisor boot_cpu_has(X86_FEATURE_HYPERVISOR)
#define cpu_has_cmp_legacy boot_cpu_has(X86_FEATURE_CMP_LEGACY)
+#define cpu_has_itsc boot_cpu_has(X86_FEATURE_ITSC)
enum _cache_type {
CACHE_TYPE_NULL = 0,
diff --git a/xen/include/asm-x86/cpuid.h b/xen/include/asm-x86/cpuid.h
index 77a467a..0592b38 100644
--- a/xen/include/asm-x86/cpuid.h
+++ b/xen/include/asm-x86/cpuid.h
@@ -86,13 +86,8 @@ struct cpuid_policy
*
* Per-domain objects:
*
- * - Host accurate:
- * - max_{,sub}leaf
- * - {xcr0,xss}_{high,low}
- * - All FEATURESET_* words
- *
* - Guest accurate:
- * - Nothing
+ * - All FEATURESET_* words
*
* Everything else should be considered inaccurate, and not necesserily 0.
*/
@@ -202,6 +197,9 @@ extern struct cpuid_policy raw_policy, host_policy,
pv_max_policy,
/* Allocate and initialise a CPUID policy suitable for the domain. */
int init_domain_cpuid_policy(struct domain *d);
+/* Clamp the CPUID policy to reality. */
+void recalculate_cpuid_policy(struct domain *d);
+
void guest_cpuid(const struct vcpu *v, uint32_t leaf,
uint32_t subleaf, struct cpuid_leaf *res);
--
generated by git-patchbot for /home/xen/git/xen.git#master
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
https://lists.xenproject.org/xen-changelog
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |