From bf4233dae7478d1c1ccae1275fb4f5c2c2a73df1 Mon Sep 17 00:00:00 2001
From: Sascha Wildner <saw@online.de>
Date: Sat, 10 Aug 2013 14:43:49 +0200
Subject: [PATCH] kernel: Display Standard Extended Features during CPU
 initialization.

Taken-from: FreeBSD
---
 sys/cpu/x86_64/include/specialreg.h | 17 ++++++++++++
 sys/platform/pc64/include/md_var.h  |  2 +-
 sys/platform/pc64/x86_64/identcpu.c | 52 ++++++++++++++++++++++++++++++++++++-
 sys/platform/pc64/x86_64/initcpu.c  |  1 +
 4 files changed, 70 insertions(+), 2 deletions(-)

diff --git a/sys/cpu/x86_64/include/specialreg.h b/sys/cpu/x86_64/include/specialreg.h
index 62b85b0..887fdbf 100644
--- a/sys/cpu/x86_64/include/specialreg.h
+++ b/sys/cpu/x86_64/include/specialreg.h
@@ -226,6 +226,23 @@
 #define	FUNC_B_LEVEL_MAX_SIBLINGS(ebx)	((ebx) & 0xffff)
 
 /*
+ * Structured Extended Features
+ */
+#define	CPUID_STDEXT_FSGSBASE	0x00000001
+#define	CPUID_STDEXT_TSC_ADJUST	0x00000002
+#define	CPUID_STDEXT_BMI1	0x00000008
+#define	CPUID_STDEXT_HLE	0x00000010
+#define	CPUID_STDEXT_AVX2	0x00000020
+#define	CPUID_STDEXT_SMEP	0x00000080
+#define	CPUID_STDEXT_BMI2	0x00000100
+#define	CPUID_STDEXT_ENH_MOVSB	0x00000200
+#define	CPUID_STDEXT_RTM	0x00000800
+#define	CPUID_STDEXT_INVPCID	0x00000400
+#define	CPUID_STDEXT_RDSEED	0x00040000
+#define	CPUID_STDEXT_ADX	0x00080000
+#define	CPUID_STDEXT_SMAP	0x00100000
+
+/*
  * CPUID manufacturers identifiers
  */
 #define	AMD_VENDOR_ID		"AuthenticAMD"
diff --git a/sys/platform/pc64/include/md_var.h b/sys/platform/pc64/include/md_var.h
index 8a98f53..393b49a 100644
--- a/sys/platform/pc64/include/md_var.h
+++ b/sys/platform/pc64/include/md_var.h
@@ -28,7 +28,6 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/amd64/include/md_var.h,v 1.71 2004/01/29 00:05:03 peter Exp $
- * $DragonFly: src/sys/platform/pc64/include/md_var.h,v 1.5 2008/08/29 17:07:17 dillon Exp $
  */
 
 #ifndef _MACHINE_MD_VAR_H_
@@ -50,6 +49,7 @@ extern	u_int	via_feature_xcrypt;
 extern	u_int	amd_feature;
 extern	u_int	amd_feature2;
 extern	u_int	cpu_clflush_line_size;
+extern	u_int	cpu_stdext_feature;
 extern	u_int	cpu_fxsr;
 extern	u_int	cpu_xsave;
 extern	u_int	cpu_high;
diff --git a/sys/platform/pc64/x86_64/identcpu.c b/sys/platform/pc64/x86_64/identcpu.c
index 3b33146..968305c 100644
--- a/sys/platform/pc64/x86_64/identcpu.c
+++ b/sys/platform/pc64/x86_64/identcpu.c
@@ -358,6 +358,37 @@ printcpuinfo(void)
 				);
 			}
 
+			if (cpu_stdext_feature != 0) {
+				kprintf("\n  Standard Extended Features=0x%b",
+				    cpu_stdext_feature,
+				       "\020"
+				       /* RDFSBASE/RDGSBASE/WRFSBASE/WRGSBASE */
+				       "\001GSFSBASE"
+				       "\002TSCADJ"
+				       /* Bit Manipulation Instructions */
+				       "\004BMI1"
+				       /* Hardware Lock Elision */
+				       "\005HLE"
+				       /* Advanced Vector Instructions 2 */
+				       "\006AVX2"
+				       /* Supervisor Mode Execution Prot. */
+				       "\010SMEP"
+				       /* Bit Manipulation Instructions */
+				       "\011BMI2"
+				       "\012ENHMOVSB"
+				       /* Invalidate Processor Context ID */
+				       "\013INVPCID"
+				       /* Restricted Transactional Memory */
+				       "\014RTM"
+				       /* Enhanced NRBG */
+				       "\023RDSEED"
+				       /* ADCX + ADOX */
+				       "\024ADX"
+				       /* Supervisor Mode Access Prevention */
+				       "\025SMAP"
+				       );
+			}
+
 			if (cpu_vendor_id == CPU_VENDOR_CENTAUR)
 				print_via_padlock_info();
 			/*
@@ -466,7 +497,7 @@ EVENTHANDLER_DEFINE(cpufreq_post_change, tsc_freq_changed, NULL,
 void
 identify_cpu(void)
 {
-	u_int regs[4];
+	u_int regs[4], cpu_stdext_disable;
 
 	do_cpuid(0, regs);
 	cpu_high = regs[0];
@@ -482,6 +513,25 @@ identify_cpu(void)
 	cpu_feature = regs[3];
 	cpu_feature2 = regs[2];
 
+	if (cpu_high >= 7) {
+		cpuid_count(7, 0, regs);
+		cpu_stdext_feature = regs[1];
+
+		/*
+		 * Some hypervisors fail to filter out unsupported
+		 * extended features.  For now, disable the
+		 * extensions, activation of which requires setting a
+		 * bit in CR4, and which VM monitors do not support.
+		 */
+		if (cpu_feature2 & CPUID2_VMM) {
+			cpu_stdext_disable = CPUID_STDEXT_FSGSBASE |
+			    CPUID_STDEXT_SMEP;
+		} else
+			cpu_stdext_disable = 0;
+		TUNABLE_INT_FETCH("hw.cpu_stdext_disable", &cpu_stdext_disable);
+		cpu_stdext_feature &= ~cpu_stdext_disable;
+	}
+
 	if (cpu_vendor_id == CPU_VENDOR_INTEL ||
 	    cpu_vendor_id == CPU_VENDOR_AMD ||
 	    cpu_vendor_id == CPU_VENDOR_CENTAUR) {
diff --git a/sys/platform/pc64/x86_64/initcpu.c b/sys/platform/pc64/x86_64/initcpu.c
index bbb28f4..48ebd85 100644
--- a/sys/platform/pc64/x86_64/initcpu.c
+++ b/sys/platform/pc64/x86_64/initcpu.c
@@ -65,6 +65,7 @@ u_int	cpu_fxsr;		/* SSE enabled */
 u_int	cpu_xsave;		/* AVX enabled by OS*/
 u_int	cpu_mxcsr_mask;		/* Valid bits in mxcsr */
 u_int	cpu_clflush_line_size = 32;	/* Default CLFLUSH line size */
+u_int	cpu_stdext_feature;
 
 /*
  * -1: automatic (enable on h/w, disable on VMs)
-- 
1.8.2.2

