From 9497adf974946fef48a5072dbce604fb7001014b Mon Sep 17 00:00:00 2001 From: Jun Kuriyama Date: Sun, 22 Nov 2009 14:32:32 +0000 Subject: [PATCH] - MFC r199067,199215,199253 - Add hw.clflush_disable loader tunable to avoid panic (trap 9) at map_invalidate_cache_range() even if CPU is not Intel. - This tunable can be set to -1 (default), 0 and 1. -1 is same as current behavior, which automatically disable CLFLUSH on Intel CPUs without CPUID_SS (should be occured on Xen only). You can specify 1 when this panic happened on non-Intel CPUs (such as AMD's). Because disabling CLFLUSH may reduce performance, you can try with setting 0 on Intel CPUs without SS to use CLFLUSH feature. - Amd64 init_secondary() calls initializecpu() while curthread is still not properly set up. r199067 added the call to TUNABLE_INT_FETCH() to initializecpu() that results in hang because AP are started when kernel environment is already dynamic and thus needs to acquire mutex, that is too early in AP start sequence to work. Extract the code that should be executed only once, because it sets up global variables, from initializecpu() to initializecpucache(), and call the later only from hammer_time() executed on BSP. Now, TUNABLE_INT_FETCH() is done only once at BSP at the early boot stage. --- sys/amd64/amd64/initcpu.c | 22 +++++++++++++++++++++- sys/amd64/amd64/machdep.c | 1 + sys/amd64/include/md_var.h | 1 + sys/i386/i386/initcpu.c | 17 ++++++++++++++++- 4 files changed, 39 insertions(+), 2 deletions(-) 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)