xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Andrew Cooper <andrew.cooper3@citrix.com>
To: Xen-devel <xen-devel@lists.xen.org>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>,
	Jan Beulich <JBeulich@suse.com>
Subject: [PATCH RFC 27/31] xen/x86: Rework Intel masking/faulting setup
Date: Wed, 16 Dec 2015 21:24:29 +0000	[thread overview]
Message-ID: <1450301073-28191-28-git-send-email-andrew.cooper3@citrix.com> (raw)
In-Reply-To: <1450301073-28191-1-git-send-email-andrew.cooper3@citrix.com>

This patch is best reviewed as its end result rather than as a diff, as it
rewrites almost all of the setup.

On the BSP, cpuid information is used to evaluate the potential available set
of masking MSRs, and they are unconditionally probed, filling in the
availability information and hardware defaults.  A side effect of this is that
probe_intel_cpuid_faulting() can move to being __init.

The command line parameters are then combined with the hardware defaults to
further restrict the Xen default masking level.  Each cpu is then context
switched into the default levelling state.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
---
 xen/arch/x86/cpu/intel.c | 219 ++++++++++++++++++++++++++++-------------------
 1 file changed, 132 insertions(+), 87 deletions(-)

diff --git a/xen/arch/x86/cpu/intel.c b/xen/arch/x86/cpu/intel.c
index d251b53..f1bb222 100644
--- a/xen/arch/x86/cpu/intel.c
+++ b/xen/arch/x86/cpu/intel.c
@@ -18,11 +18,18 @@
 
 #define select_idle_routine(x) ((void)0)
 
-static unsigned int probe_intel_cpuid_faulting(void)
+static bool_t __init probe_intel_cpuid_faulting(void)
 {
 	uint64_t x;
-	return !rdmsr_safe(MSR_INTEL_PLATFORM_INFO, x) &&
-		(x & MSR_PLATFORM_INFO_CPUID_FAULTING);
+
+	if ( rdmsr_safe(MSR_INTEL_PLATFORM_INFO, x) ||
+	     !(x & MSR_PLATFORM_INFO_CPUID_FAULTING) )
+		return 0;
+
+	expected_levelling_cap |= LCAP_faulting;
+	levelling_caps |=  LCAP_faulting;
+	__set_bit(X86_FEATURE_CPUID_FAULTING, boot_cpu_data.x86_capability);
+	return 1;
 }
 
 static DEFINE_PER_CPU(bool_t, cpuid_faulting_enabled);
@@ -44,41 +51,45 @@ void set_cpuid_faulting(bool_t enable)
 }
 
 /*
- * opt_cpuid_mask_ecx/edx: cpuid.1[ecx, edx] feature mask.
- * For example, E8400[Intel Core 2 Duo Processor series] ecx = 0x0008E3FD,
- * edx = 0xBFEBFBFF when executing CPUID.EAX = 1 normally. If you want to
- * 'rev down' to E8400, you can set these values in these Xen boot parameters.
+ * Set caps in expected_levelling_cap, probe a specific masking MSR, and set
+ * caps in levelling_caps if it is found, or clobber the MSR index if missing.
+ * If preset, reads the default value into msr_val.
  */
-static void __devinit set_cpuidmask(const struct cpuinfo_x86 *c)
+static void __init __probe_mask_msr(unsigned int *msr, uint64_t caps,
+				    uint64_t *msr_val)
 {
-	static unsigned int msr_basic, msr_ext, msr_xsave;
-	static enum { not_parsed, no_mask, set_mask } status;
-	u64 msr_val;
+	uint64_t val;
 
-	if (status == no_mask)
-		return;
+	expected_levelling_cap |= caps;
 
-	if (status == set_mask)
-		goto setmask;
+	if (rdmsr_safe(*msr, val) || wrmsr_safe(*msr, val))
+		*msr = 0;
+	else
+	{
+		levelling_caps |= caps;
+		*msr_val = val;
+	}
+}
 
-	ASSERT((status == not_parsed) && (c == &boot_cpu_data));
-	status = no_mask;
+static unsigned int __read_mostly msr_basic, msr_ext, msr_xsave;
 
-	if (!~(opt_cpuid_mask_ecx & opt_cpuid_mask_edx &
-	       opt_cpuid_mask_ext_ecx & opt_cpuid_mask_ext_edx &
-	       opt_cpuid_mask_xsave_eax))
-		return;
+/*
+ * Probe for the existance of the expected masking MSRs.  They might easily
+ * not be available if Xen is running virtualised.
+ */
+static void __init probe_masking_msrs(void)
+{
+	const struct cpuinfo_x86 *c = &boot_cpu_data;
+	unsigned int exp_msr_basic = 0, exp_msr_ext = 0, exp_msr_xsave = 0;
 
 	/* Only family 6 supports this feature. */
-	if (c->x86 != 6) {
-		printk("No CPUID feature masking support available\n");
+	if (c->x86 != 6)
 		return;
-	}
 
 	switch (c->x86_model) {
 	case 0x17: /* Yorkfield, Wolfdale, Penryn, Harpertown(DP) */
 	case 0x1d: /* Dunnington(MP) */
-		msr_basic = MSR_INTEL_MASK_V1_CPUID1;
+		exp_msr_basic = msr_basic = MSR_INTEL_MASK_V1_CPUID1;
 		break;
 
 	case 0x1a: /* Bloomfield, Nehalem-EP(Gainestown) */
@@ -88,72 +99,115 @@ static void __devinit set_cpuidmask(const struct cpuinfo_x86 *c)
 	case 0x2c: /* Gulftown, Westmere-EP */
 	case 0x2e: /* Nehalem-EX(Beckton) */
 	case 0x2f: /* Westmere-EX */
-		msr_basic = MSR_INTEL_MASK_V2_CPUID1;
-		msr_ext   = MSR_INTEL_MASK_V2_CPUID80000001;
+		exp_msr_basic = msr_basic = MSR_INTEL_MASK_V2_CPUID1;
+		exp_msr_ext   = msr_ext   = MSR_INTEL_MASK_V2_CPUID80000001;
 		break;
 
 	case 0x2a: /* SandyBridge */
 	case 0x2d: /* SandyBridge-E, SandyBridge-EN, SandyBridge-EP */
-		msr_basic = MSR_INTEL_MASK_V3_CPUID1;
-		msr_ext   = MSR_INTEL_MASK_V3_CPUID80000001;
-		msr_xsave = MSR_INTEL_MASK_V3_CPUIDD_01;
+		exp_msr_basic = msr_basic = MSR_INTEL_MASK_V3_CPUID1;
+		exp_msr_ext   = msr_ext   = MSR_INTEL_MASK_V3_CPUID80000001;
+		exp_msr_xsave = msr_xsave = MSR_INTEL_MASK_V3_CPUIDD_01;
 		break;
 	}
 
-	status = set_mask;
+	if (msr_basic)
+		__probe_mask_msr(&msr_basic, LCAP_1cd, &cpumask_defaults._1cd);
+
+	if (msr_ext)
+		__probe_mask_msr(&msr_ext, LCAP_e1cd, &cpumask_defaults.e1cd);
+
+	if (msr_xsave)
+		__probe_mask_msr(&msr_xsave, LCAP_Da1, &cpumask_defaults.Da1);
+
+	/*
+	 * Don't bother warning about a mismatch if virtualised.  These MSRs
+	 * are not architectural and almost never virtualised.
+	 */
+	if ((expected_levelling_cap == levelling_caps) ||
+	    cpu_has_hypervisor)
+		return;
+
+	printk(XENLOG_WARNING "Mismatch between expected (%#x"
+	       ") and real (%#x) levelling caps: missing %#x\n",
+	       expected_levelling_cap, levelling_caps,
+	       (expected_levelling_cap ^ levelling_caps) & levelling_caps);
+	printk(XENLOG_WARNING "Fam %#x, model %#x expected (%#x/%#x/%#x), "
+	       "got (%#x/%#x/%#x)\n", c->x86, c->x86_model,
+	       exp_msr_basic, exp_msr_ext, exp_msr_xsave,
+	       msr_basic, msr_ext, msr_xsave);
+	printk(XENLOG_WARNING
+	       "If not running virtualised, please report a bug\n");
+}
+
+void intel_ctxt_switch_levelling(const struct domain *nextd)
+{
+	struct cpumasks *these_masks = &this_cpu(cpumasks);
+	const struct cpumasks *masks = &cpumask_defaults;
+
+#define LAZY(msr, field)						\
+	({								\
+		if ( msr && (these_masks->field != masks->field) )	\
+		{							\
+			wrmsrl(msr, masks->field);			\
+			these_masks->field = masks->field;		\
+		}							\
+	})
+
+	LAZY(msr_basic, _1cd);
+	LAZY(msr_ext,   e1cd);
+	LAZY(msr_xsave, Da1);
+
+#undef LAZY
+}
 
-	if (~(opt_cpuid_mask_ecx & opt_cpuid_mask_edx)) {
-		if (msr_basic)
+/*
+ * opt_cpuid_mask_ecx/edx: cpuid.1[ecx, edx] feature mask.
+ * For example, E8400[Intel Core 2 Duo Processor series] ecx = 0x0008E3FD,
+ * edx = 0xBFEBFBFF when executing CPUID.EAX = 1 normally. If you want to
+ * 'rev down' to E8400, you can set these values in these Xen boot parameters.
+ */
+static void __init noinline intel_init_levelling(void)
+{
+	if ( !probe_intel_cpuid_faulting() )
+		probe_masking_msrs();
+
+	if ( msr_basic )
+	{
+		cpumask_defaults._1cd =
+			((u64)opt_cpuid_mask_edx << 32) | opt_cpuid_mask_ecx;
+
+		if ( !~(opt_cpuid_mask_ecx & opt_cpuid_mask_edx) )
 			printk("Writing CPUID feature mask ecx:edx -> %08x:%08x\n",
 			       opt_cpuid_mask_ecx, opt_cpuid_mask_edx);
-		else
-			printk("No CPUID feature mask available\n");
 	}
-	else
-		msr_basic = 0;
+	else if ( !~(opt_cpuid_mask_ecx & opt_cpuid_mask_edx) )
+		printk("No CPUID feature mask available\n");
+
+	if ( msr_ext )
+	{
+		cpumask_defaults.e1cd =
+			((u64)opt_cpuid_mask_ext_edx << 32) |
+			opt_cpuid_mask_ext_ecx;
 
-	if (~(opt_cpuid_mask_ext_ecx & opt_cpuid_mask_ext_edx)) {
-		if (msr_ext)
+		if ( !~(opt_cpuid_mask_ext_ecx & opt_cpuid_mask_ext_edx) )
 			printk("Writing CPUID extended feature mask ecx:edx -> %08x:%08x\n",
 			       opt_cpuid_mask_ext_ecx, opt_cpuid_mask_ext_edx);
-		else
-			printk("No CPUID extended feature mask available\n");
 	}
-	else
-		msr_ext = 0;
+	else if ( !~(opt_cpuid_mask_ext_ecx & opt_cpuid_mask_ext_edx) )
+		printk("No CPUID extended feature mask available\n");
+
+	if ( msr_xsave )
+	{
+		cpumask_defaults.Da1 &= (~0ULL << 32);
+		cpumask_defaults.Da1 |= opt_cpuid_mask_xsave_eax;
 
-	if (~opt_cpuid_mask_xsave_eax) {
-		if (msr_xsave)
+		if ( !~opt_cpuid_mask_xsave_eax )
 			printk("Writing CPUID xsave feature mask eax -> %08x\n",
 			       opt_cpuid_mask_xsave_eax);
-		else
-			printk("No CPUID xsave feature mask available\n");
-	}
-	else
-		msr_xsave = 0;
-
- setmask:
-	if (msr_basic &&
-	    wrmsr_safe(msr_basic,
-		       ((u64)opt_cpuid_mask_edx << 32) | opt_cpuid_mask_ecx)){
-		msr_basic = 0;
-		printk("Failed to set CPUID feature mask\n");
-	}
-
-	if (msr_ext &&
-	    wrmsr_safe(msr_ext,
-		       ((u64)opt_cpuid_mask_ext_edx << 32) | opt_cpuid_mask_ext_ecx)){
-		msr_ext = 0;
-		printk("Failed to set CPUID extended feature mask\n");
-	}
-
-	if (msr_xsave &&
-	    (rdmsr_safe(msr_xsave, msr_val) ||
-	     wrmsr_safe(msr_xsave,
-			(msr_val & (~0ULL << 32)) | opt_cpuid_mask_xsave_eax))){
-		msr_xsave = 0;
-		printk("Failed to set CPUID xsave feature mask\n");
 	}
+	else if ( !~opt_cpuid_mask_xsave_eax )
+		printk("No CPUID xsave feature mask available\n");
 }
 
 static void early_init_intel(struct cpuinfo_x86 *c)
@@ -183,22 +237,13 @@ static void early_init_intel(struct cpuinfo_x86 *c)
 	    (boot_cpu_data.x86_mask == 3 || boot_cpu_data.x86_mask == 4))
 		paddr_bits = 36;
 
-	if (c == &boot_cpu_data && c->x86 == 6) {
-		if (probe_intel_cpuid_faulting())
-			__set_bit(X86_FEATURE_CPUID_FAULTING,
-				  c->x86_capability);
-	} else if (boot_cpu_has(X86_FEATURE_CPUID_FAULTING)) {
-		BUG_ON(!probe_intel_cpuid_faulting());
-		__set_bit(X86_FEATURE_CPUID_FAULTING, c->x86_capability);
-	}
+	if (c == &boot_cpu_data)
+		intel_init_levelling();
+
+	if (test_bit(X86_FEATURE_CPUID_FAULTING, boot_cpu_data.x86_capability))
+            __set_bit(X86_FEATURE_CPUID_FAULTING, c->x86_capability);
 
-	if (!cpu_has_cpuid_faulting)
-		set_cpuidmask(c);
-	else if ((c == &boot_cpu_data) &&
-		 (~(opt_cpuid_mask_ecx & opt_cpuid_mask_edx &
-		    opt_cpuid_mask_ext_ecx & opt_cpuid_mask_ext_edx &
-		    opt_cpuid_mask_xsave_eax)))
-		printk("No CPUID feature masking support available\n");
+	intel_ctxt_switch_levelling(NULL);
 }
 
 /*
-- 
2.1.4

  parent reply	other threads:[~2015-12-16 21:24 UTC|newest]

Thread overview: 123+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-12-16 21:24 [PATCH RFC 00/31] x86: Improvements to cpuid handling for guests Andrew Cooper
2015-12-16 21:24 ` [PATCH RFC 01/31] xen/public: Export featureset information in the public API Andrew Cooper
2015-12-22 16:28   ` Jan Beulich
2015-12-22 16:42     ` Andrew Cooper
2015-12-22 16:59       ` Jan Beulich
2015-12-23 10:05         ` Andrew Cooper
2015-12-23 10:24           ` Jan Beulich
2015-12-23 11:26             ` Andrew Cooper
2016-01-06  7:43               ` Jan Beulich
2015-12-16 21:24 ` [PATCH RFC 02/31] tools/libxc: Use public/featureset.h for cpuid policy generation Andrew Cooper
2015-12-22 16:29   ` Jan Beulich
2016-01-05 14:13     ` Ian Campbell
2016-01-05 14:17       ` Andrew Cooper
2016-01-05 14:18         ` Ian Campbell
2016-01-05 14:23           ` Andrew Cooper
2016-01-05 15:02             ` Ian Campbell
2016-01-05 15:42               ` Andrew Cooper
2016-01-05 16:09                 ` Ian Campbell
2015-12-16 21:24 ` [PATCH RFC 03/31] xen/x86: Store antifeatures inverted in a featureset Andrew Cooper
2015-12-22 16:32   ` Jan Beulich
2015-12-22 17:03     ` Andrew Cooper
2016-01-05 14:19       ` Ian Campbell
2016-01-05 14:24         ` Andrew Cooper
2015-12-16 21:24 ` [PATCH RFC 04/31] xen/x86: Mask out unknown features from Xen's capabilities Andrew Cooper
2015-12-22 16:42   ` Jan Beulich
2015-12-22 17:01     ` Andrew Cooper
2015-12-16 21:24 ` [PATCH RFC 05/31] xen/x86: Collect more CPUID feature words Andrew Cooper
2015-12-22 16:46   ` Jan Beulich
2015-12-22 17:17     ` Andrew Cooper
2015-12-16 21:24 ` [PATCH RFC 06/31] xen/x86: Infrastructure to calculate guest featuresets Andrew Cooper
2015-12-22 16:50   ` Jan Beulich
2015-12-16 21:24 ` [PATCH RFC 07/31] xen/x86: Export host featureset via SYSCTL Andrew Cooper
2015-12-22 16:57   ` Jan Beulich
2015-12-16 21:24 ` [PATCH RFC 08/31] tools/stubs: Expose host featureset to userspace Andrew Cooper
2016-01-05 15:36   ` Ian Campbell
2016-01-05 15:59     ` Andrew Cooper
2016-01-05 16:09       ` Ian Campbell
2016-01-05 16:19         ` Andrew Cooper
2016-01-05 16:38           ` Ian Campbell
2015-12-16 21:24 ` [PATCH RFC 09/31] xen/x86: Calculate PV featureset Andrew Cooper
2015-12-22 17:07   ` Jan Beulich
2015-12-22 17:13     ` Andrew Cooper
2015-12-22 17:18       ` Jan Beulich
2015-12-16 21:24 ` [PATCH RFC 10/31] xen/x86: Calculate HVM featureset Andrew Cooper
2015-12-22 17:11   ` Jan Beulich
2015-12-22 17:21     ` Andrew Cooper
2015-12-16 21:24 ` [PATCH RFC 11/31] xen/x86: Calculate Raw featureset Andrew Cooper
2015-12-22 17:14   ` Jan Beulich
2015-12-22 17:27     ` Andrew Cooper
2015-12-16 21:24 ` [PATCH RFC 12/31] tools: Utility for dealing with featuresets Andrew Cooper
2016-01-05 15:17   ` Ian Campbell
2016-01-05 16:14     ` Andrew Cooper
2016-01-05 16:34       ` Ian Campbell
2016-01-05 17:13         ` Andrew Cooper
2016-01-05 17:37           ` Ian Campbell
2016-01-05 18:04             ` Andrew Cooper
2016-01-06 10:38               ` Ian Campbell
2016-01-06 10:40   ` Ian Campbell
2016-01-06 10:42     ` Ian Campbell
2015-12-16 21:24 ` [PATCH RFC 13/31] tools/libxc: Wire a featureset through to cpuid policy logic Andrew Cooper
2016-01-05 15:42   ` Ian Campbell
2016-01-05 16:20     ` Andrew Cooper
2015-12-16 21:24 ` [PATCH RFC 14/31] tools/libxc: Use featureset rather than guesswork Andrew Cooper
2016-01-05 15:54   ` Ian Campbell
2016-01-05 16:22     ` Andrew Cooper
2015-12-16 21:24 ` [PATCH RFC 15/31] x86: Generate deep dependencies of x86 features Andrew Cooper
2016-01-05 16:03   ` Ian Campbell
2016-01-05 16:42     ` Andrew Cooper
2016-01-05 16:54       ` Ian Campbell
2016-01-05 17:09         ` Andrew Cooper
2016-01-05 17:19           ` Ian Campbell
2015-12-16 21:24 ` [PATCH RFC 16/31] x86: Automatically generate known_features Andrew Cooper
2015-12-16 21:24 ` [PATCH RFC 17/31] xen/x86: Clear dependent features when clearing a cpu cap Andrew Cooper
2015-12-16 21:24 ` [PATCH RFC 18/31] xen/x86: Improve disabling of features which have dependencies Andrew Cooper
2016-01-21 16:48   ` Jan Beulich
2015-12-16 21:24 ` [PATCH RFC 19/31] tools/libxc: Sanitise guest featuresets Andrew Cooper
2016-01-05 16:05   ` Ian Campbell
2015-12-16 21:24 ` [PATCH RFC 20/31] x86: Improvements to in-hypervisor cpuid sanity checks Andrew Cooper
2016-01-21 17:02   ` Jan Beulich
2016-01-21 17:21     ` Andrew Cooper
2016-01-21 18:15       ` Andrew Cooper
2016-01-22  7:47         ` Jan Beulich
2016-01-22  7:45       ` Jan Beulich
2015-12-16 21:24 ` [PATCH RFC 21/31] x86/domctl: Break out logic to update domain state from cpuid information Andrew Cooper
2016-01-21 17:05   ` Jan Beulich
2016-01-21 17:08     ` Andrew Cooper
2015-12-16 21:24 ` [PATCH RFC 22/31] x86/cpu: Move set_cpumask() calls into c_early_init() Andrew Cooper
2016-01-21 17:08   ` Jan Beulich
2015-12-16 21:24 ` [PATCH RFC 23/31] xen/x86: Export cpuid levelling capabilities via SYSCTL Andrew Cooper
2016-01-21 17:23   ` Jan Beulich
2015-12-16 21:24 ` [PATCH RFC 24/31] tools/stubs: Expose host levelling capabilities to userspace Andrew Cooper
2015-12-16 21:24 ` [PATCH RFC 25/31] xen/x86: Common infrastructure for levelling context switching Andrew Cooper
2016-01-22  8:56   ` Jan Beulich
2016-01-22 10:05     ` Andrew Cooper
2015-12-16 21:24 ` [PATCH RFC 26/31] xen/x86: Rework AMD masking MSR setup Andrew Cooper
2016-01-22  9:27   ` Jan Beulich
2016-01-22 11:01     ` Andrew Cooper
2016-01-22 11:13       ` Jan Beulich
2016-01-22 13:59         ` Andrew Cooper
2016-01-22 14:12           ` Jan Beulich
2016-01-22 17:03             ` Andrew Cooper
2016-01-25 11:25               ` Jan Beulich
2015-12-16 21:24 ` Andrew Cooper [this message]
2016-01-22  9:40   ` [PATCH RFC 27/31] xen/x86: Rework Intel masking/faulting setup Jan Beulich
2016-01-22 14:09     ` Andrew Cooper
2016-01-22 14:29       ` Jan Beulich
2016-01-22 14:46         ` Andrew Cooper
2016-01-22 14:53           ` Jan Beulich
2015-12-16 21:24 ` [PATCH RFC 28/31] xen/x86: Context switch all levelling state in context_switch() Andrew Cooper
2016-01-22  9:52   ` Jan Beulich
2016-01-22 14:19     ` Andrew Cooper
2016-01-22 14:31       ` Jan Beulich
2016-01-22 14:39         ` Andrew Cooper
2015-12-16 21:24 ` [PATCH RFC 29/31] x86/pv: Provide custom cpumasks for PV domains Andrew Cooper
2016-01-22  9:56   ` Jan Beulich
2016-01-22 14:24     ` Andrew Cooper
2016-01-22 14:33       ` Jan Beulich
2016-01-22 14:42         ` Andrew Cooper
2016-01-22 14:48           ` Jan Beulich
2016-01-22 14:56             ` Andrew Cooper
2015-12-16 21:24 ` [PATCH RFC 30/31] x86/domctl: Update PV domain cpumasks when setting cpuid policy Andrew Cooper
2016-01-22 10:02   ` Jan Beulich
2015-12-16 21:24 ` [PATCH RFC 31/31] tools/libxc: Calculate xstate cpuid leaf from guest information Andrew Cooper

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1450301073-28191-28-git-send-email-andrew.cooper3@citrix.com \
    --to=andrew.cooper3@citrix.com \
    --cc=JBeulich@suse.com \
    --cc=xen-devel@lists.xen.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).