[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 3/3] x86: correct fencing around CLFLUSH
As noted in the context of 3330013e6739 ("VT-d / x86: re-arrange cache syncing"): While cache_writeback() has the SFENCE on the correct side of CLFLUSHOPT, flush_area_local() doesn't. While I can't prove it due to lacking a copy of the old SDM version, I can only assume this placement was a result of what had been described there originally. In any event recent versions of the SDM hve been telling us otherwise. For AMD (and Hygon, albeit there it's benign, since all their CPUs are expected to support CLFLUSHOPT) the situation is more complex: MFENCE is needed ahead and/or after CLFLUSH when the CPU doesn't also support CLFLUSHOPT. (It's "and" in our case, as we cannot know what the caller's needs are.) Fixes: 623c720fc8da3 ("x86: use CLFLUSHOPT when available") Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> --- a/xen/arch/x86/cpu/common.c +++ b/xen/arch/x86/cpu/common.c @@ -346,9 +346,14 @@ void __init early_cpu_init(void) c->x86_model, c->x86_model, c->x86_mask, eax); if (c->cpuid_level >= 7) - cpuid_count(7, 0, &eax, &ebx, + cpuid_count(7, 0, &eax, + &c->x86_capability[FEATURESET_7b0], &c->x86_capability[FEATURESET_7c0], &edx); + if (!(c->x86_vendor & (X86_VENDOR_AMD | X86_VENDOR_HYGON)) || + cpu_has(c, X86_FEATURE_CLFLUSHOPT)) + setup_force_cpu_cap(X86_FEATURE_CLFLUSH_NO_MFENCE); + eax = cpuid_eax(0x80000000); if ((eax >> 16) == 0x8000 && eax >= 0x80000008) { ebx = eax >= 0x8000001f ? cpuid_ebx(0x8000001f) : 0; --- a/xen/arch/x86/flushtlb.c +++ b/xen/arch/x86/flushtlb.c @@ -245,12 +245,15 @@ unsigned int flush_area_local(const void c->x86_clflush_size && c->x86_cache_size && sz && ((sz >> 10) < c->x86_cache_size) ) { - alternative("", "sfence", X86_FEATURE_CLFLUSHOPT); + alternative("mfence", , X86_FEATURE_CLFLUSH_NO_MFENCE); for ( i = 0; i < sz; i += c->x86_clflush_size ) alternative_input("ds; clflush %0", "data16 clflush %0", /* clflushopt */ X86_FEATURE_CLFLUSHOPT, "m" (((const char *)va)[i])); + alternative_2("mfence", + , X86_FEATURE_CLFLUSH_NO_MFENCE, + "sfence", X86_FEATURE_CLFLUSHOPT); flags &= ~FLUSH_CACHE; } else @@ -274,6 +277,8 @@ void cache_writeback(const void *addr, u unsigned int clflush_size = current_cpu_data.x86_clflush_size ?: 16; const void *end = addr + size; + alternative("mfence", , X86_FEATURE_CLFLUSH_NO_MFENCE); + addr -= (unsigned long)addr & (clflush_size - 1); for ( ; addr < end; addr += clflush_size ) { --- a/xen/arch/x86/include/asm/cpufeatures.h +++ b/xen/arch/x86/include/asm/cpufeatures.h @@ -24,7 +24,7 @@ XEN_CPUFEATURE(APERFMPERF, X86_SY XEN_CPUFEATURE(MFENCE_RDTSC, X86_SYNTH( 9)) /* MFENCE synchronizes RDTSC */ XEN_CPUFEATURE(XEN_SMEP, X86_SYNTH(10)) /* SMEP gets used by Xen itself */ XEN_CPUFEATURE(XEN_SMAP, X86_SYNTH(11)) /* SMAP gets used by Xen itself */ -/* Bit 12 - unused. */ +XEN_CPUFEATURE(CLFLUSH_NO_MFENCE, X86_SYNTH(12)) /* No MFENCE needed to serialize CLFLUSH */ XEN_CPUFEATURE(IND_THUNK_LFENCE, X86_SYNTH(13)) /* Use IND_THUNK_LFENCE */ XEN_CPUFEATURE(IND_THUNK_JMP, X86_SYNTH(14)) /* Use IND_THUNK_JMP */ XEN_CPUFEATURE(SC_NO_BRANCH_HARDEN, X86_SYNTH(15)) /* (Disable) Conditional branch hardening */
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |