[Midnightbsd-cvs] src [6835] trunk/sys/amd64: update cpu feature detection logic
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Fri Oct 3 08:37:57 EDT 2014
Revision: 6835
http://svnweb.midnightbsd.org/src/?rev=6835
Author: laffer1
Date: 2014-10-03 08:37:57 -0400 (Fri, 03 Oct 2014)
Log Message:
-----------
update cpu feature detection logic
Modified Paths:
--------------
trunk/sys/amd64/amd64/identcpu.c
trunk/sys/amd64/amd64/initcpu.c
trunk/sys/amd64/include/md_var.h
Modified: trunk/sys/amd64/amd64/identcpu.c
===================================================================
--- trunk/sys/amd64/amd64/identcpu.c 2014-10-03 12:37:30 UTC (rev 6834)
+++ trunk/sys/amd64/amd64/identcpu.c 2014-10-03 12:37:57 UTC (rev 6835)
@@ -213,8 +213,8 @@
if (cpu_vendor_id == CPU_VENDOR_INTEL ||
cpu_vendor_id == CPU_VENDOR_AMD ||
cpu_vendor_id == CPU_VENDOR_CENTAUR) {
- printf(" Family = %x", CPUID_TO_FAMILY(cpu_id));
- printf(" Model = %x", CPUID_TO_MODEL(cpu_id));
+ printf(" Family = 0x%x", CPUID_TO_FAMILY(cpu_id));
+ printf(" Model = 0x%x", CPUID_TO_MODEL(cpu_id));
printf(" Stepping = %u", cpu_id & CPUID_STEPPING);
/*
@@ -384,6 +384,18 @@
);
}
+ if (cpu_stdext_feature != 0) {
+ printf("\n Standard Extended Features=0x%b",
+ cpu_stdext_feature,
+ "\020"
+ "\001GSFSBASE"
+ "\002TSCADJ"
+ "\010SMEP"
+ "\012ENHMOVSB"
+ "\013INVPCID"
+ );
+ }
+
if (via_feature_rng != 0 || via_feature_xcrypt != 0)
print_via_padlock_info();
@@ -469,7 +481,7 @@
void
identify_cpu(void)
{
- u_int regs[4];
+ u_int regs[4], cpu_stdext_disable;
do_cpuid(0, regs);
cpu_high = regs[0];
@@ -501,6 +513,25 @@
}
}
+ 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_HV) {
+ 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) {
Modified: trunk/sys/amd64/amd64/initcpu.c
===================================================================
--- trunk/sys/amd64/amd64/initcpu.c 2014-10-03 12:37:30 UTC (rev 6834)
+++ trunk/sys/amd64/amd64/initcpu.c 2014-10-03 12:37:57 UTC (rev 6835)
@@ -34,6 +34,7 @@
#include <sys/param.h>
#include <sys/kernel.h>
+#include <sys/pcpu.h>
#include <sys/systm.h>
#include <sys/sysctl.h>
@@ -72,6 +73,7 @@
u_int cpu_fxsr; /* SSE enabled */
u_int cpu_mxcsr_mask; /* Valid bits in mxcsr */
u_int cpu_clflush_line_size = 32;
+u_int cpu_stdext_feature;
u_int cpu_max_ext_state_size;
SYSCTL_UINT(_hw, OID_AUTO, via_feature_rng, CTLFLAG_RD,
@@ -91,11 +93,17 @@
*
* http://support.amd.com/us/Processor_TechDocs/41322_10h_Rev_Gd.pdf
* http://support.amd.com/us/Processor_TechDocs/44739_12h_Rev_Gd.pdf
+ *
+ * Hypervisors do not provide access to the errata MSR,
+ * causing #GP exception on attempt to apply the errata. The
+ * MSR write shall be done on host and persist globally
+ * anyway, so do not try to do it when under virtualization.
*/
switch (CPUID_TO_FAMILY(cpu_id)) {
case 0x10:
case 0x12:
- wrmsr(0xc0011029, rdmsr(0xc0011029) | 1);
+ if ((cpu_feature2 & CPUID2_HV) == 0)
+ wrmsr(0xc0011029, rdmsr(0xc0011029) | 1);
break;
}
}
@@ -146,11 +154,25 @@
initializecpu(void)
{
uint64_t msr;
+ uint32_t cr4;
+ cr4 = rcr4();
if ((cpu_feature & CPUID_XMM) && (cpu_feature & CPUID_FXSR)) {
- load_cr4(rcr4() | CR4_FXSR | CR4_XMM);
+ cr4 |= CR4_FXSR | CR4_XMM;
cpu_fxsr = hw_instruction_sse = 1;
}
+ if (cpu_stdext_feature & CPUID_STDEXT_FSGSBASE)
+ cr4 |= CR4_FSGSBASE;
+
+ /*
+ * Postpone enabling the SMEP on the boot CPU until the page
+ * tables are switched from the boot loader identity mapping
+ * to the kernel tables. The boot loader enables the U bit in
+ * its tables.
+ */
+ if (!IS_BSP() && (cpu_stdext_feature & CPUID_STDEXT_SMEP))
+ cr4 |= CR4_SMEP;
+ load_cr4(cr4);
if ((amd_feature & AMDID_NX) != 0) {
msr = rdmsr(MSR_EFER) | EFER_NXE;
wrmsr(MSR_EFER, msr);
Modified: trunk/sys/amd64/include/md_var.h
===================================================================
--- trunk/sys/amd64/include/md_var.h 2014-10-03 12:37:30 UTC (rev 6834)
+++ trunk/sys/amd64/include/md_var.h 2014-10-03 12:37:57 UTC (rev 6835)
@@ -48,6 +48,7 @@
extern u_int via_feature_rng;
extern u_int via_feature_xcrypt;
extern u_int cpu_clflush_line_size;
+extern u_int cpu_stdext_feature;
extern u_int cpu_fxsr;
extern u_int cpu_high;
extern u_int cpu_id;
@@ -57,6 +58,7 @@
extern u_int cpu_procinfo2;
extern char cpu_vendor[];
extern u_int cpu_vendor_id;
+extern char ctx_switch_xsave[];
extern char kstack[];
extern char sigcode[];
extern int szsigcode;
@@ -115,5 +117,6 @@
struct savefpu *get_pcb_user_save_td(struct thread *td);
struct savefpu *get_pcb_user_save_pcb(struct pcb *pcb);
struct pcb *get_pcb_td(struct thread *td);
+void amd64_db_resume_dbreg(void);
#endif /* !_MACHINE_MD_VAR_H_ */
More information about the Midnightbsd-cvs
mailing list