diff --git a/sys/amd64/amd64/initcpu.c b/sys/amd64/amd64/initcpu.c index 7aaff821463..c97ad3dbbb1 100644 --- a/sys/amd64/amd64/initcpu.c +++ b/sys/amd64/amd64/initcpu.c @@ -47,6 +47,12 @@ __FBSDID("$FreeBSD$"); static int hw_instruction_sse; SYSCTL_INT(_hw, OID_AUTO, instruction_sse, CTLFLAG_RD, &hw_instruction_sse, 0, "SIMD/MMX2 instructions available in CPU"); +/* + * -1: automatic (default) + * 0: keep enable CLFLUSH + * 1: force disable CLFLUSH + */ +static int hw_clflush_disable = -1; int cpu; /* Are we 386, 386sx, 486, etc? */ u_int cpu_feature; /* Feature flags */ @@ -157,6 +163,11 @@ initializecpu(void) CPUID_TO_FAMILY(cpu_id) == 0x6 && CPUID_TO_MODEL(cpu_id) >= 0xf) init_via(); +} + +void +initializecpucache() +{ /* * CPUID with %eax = 1, %ebx returns @@ -169,6 +180,15 @@ initializecpu(void) * XXXKIB: (temporary) hack to work around traps generated when * CLFLUSHing APIC registers window. */ - if (cpu_vendor_id == CPU_VENDOR_INTEL && !(cpu_feature & CPUID_SS)) + TUNABLE_INT_FETCH("hw.clflush_disable", &hw_clflush_disable); + if (cpu_vendor_id == CPU_VENDOR_INTEL && !(cpu_feature & CPUID_SS) && + hw_clflush_disable == -1) + cpu_feature &= ~CPUID_CLFSH; + /* + * Allow to disable CLFLUSH feature manually by + * hw.clflush_disable tunable. This may help Xen guest on some AMD + * CPUs. + */ + if (hw_clflush_disable == 1) cpu_feature &= ~CPUID_CLFSH; } diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index 95db5d2d605..e4c51a3bb82 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -1667,6 +1667,7 @@ hammer_time(u_int64_t modulep, u_int64_t physfree) identify_cpu(); /* Final stage of CPU initialization */ initializecpu(); /* Initialize CPU registers */ + initializecpucache(); /* make an initial tss so cpu can get interrupt stack on syscall! */ common_tss[0].tss_rsp0 = thread0.td_kstack + \ diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h index c66fc9fdb36..15df851ee31 100644 --- a/sys/amd64/include/md_var.h +++ b/sys/amd64/include/md_var.h @@ -89,6 +89,7 @@ void gs_load_fault(void) __asm(__STRING(gs_load_fault)); void dump_add_page(vm_paddr_t); void dump_drop_page(vm_paddr_t); void initializecpu(void); +void initializecpucache(void); void fillw(int /*u_short*/ pat, void *base, size_t cnt); void fpstate_drop(struct thread *td); int is_physical_memory(vm_paddr_t addr); diff --git a/sys/i386/i386/initcpu.c b/sys/i386/i386/initcpu.c index dc8da0b0f2a..dad79197ec0 100644 --- a/sys/i386/i386/initcpu.c +++ b/sys/i386/i386/initcpu.c @@ -75,6 +75,12 @@ static void init_mendocino(void); static int hw_instruction_sse; SYSCTL_INT(_hw, OID_AUTO, instruction_sse, CTLFLAG_RD, &hw_instruction_sse, 0, "SIMD/MMX2 instructions available in CPU"); +/* + * -1: automatic (default) + * 0: keep enable CLFLUSH + * 1: force disable CLFLUSH + */ +static int hw_clflush_disable = -1; /* Must *NOT* be BSS or locore will bzero these after setting them */ int cpu = 0; /* Are we 386, 386sx, 486, etc? */ @@ -721,7 +727,16 @@ initializecpu(void) * XXXKIB: (temporary) hack to work around traps generated when * CLFLUSHing APIC registers window. */ - if (cpu_vendor_id == CPU_VENDOR_INTEL && !(cpu_feature & CPUID_SS)) + TUNABLE_INT_FETCH("hw.clflush_disable", &hw_clflush_disable); + if (cpu_vendor_id == CPU_VENDOR_INTEL && !(cpu_feature & CPUID_SS) && + hw_clflush_disable == -1) + cpu_feature &= ~CPUID_CLFSH; + /* + * Allow to disable CLFLUSH feature manually by + * hw.clflush_disable tunable. This may help Xen guest on some AMD + * CPUs. + */ + if (hw_clflush_disable == 1) cpu_feature &= ~CPUID_CLFSH; #if defined(PC98) && !defined(CPU_UPGRADE_HW_CACHE)