diff options
Diffstat (limited to 'arch/x86/kernel/cpu/amd.c')
-rw-r--r-- | arch/x86/kernel/cpu/amd.c | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index bcb75dc97d44..ea831c858195 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c | |||
@@ -829,8 +829,32 @@ static void init_amd(struct cpuinfo_x86 *c) | |||
829 | set_cpu_cap(c, X86_FEATURE_K8); | 829 | set_cpu_cap(c, X86_FEATURE_K8); |
830 | 830 | ||
831 | if (cpu_has(c, X86_FEATURE_XMM2)) { | 831 | if (cpu_has(c, X86_FEATURE_XMM2)) { |
832 | /* MFENCE stops RDTSC speculation */ | 832 | unsigned long long val; |
833 | set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC); | 833 | int ret; |
834 | |||
835 | /* | ||
836 | * A serializing LFENCE has less overhead than MFENCE, so | ||
837 | * use it for execution serialization. On families which | ||
838 | * don't have that MSR, LFENCE is already serializing. | ||
839 | * msr_set_bit() uses the safe accessors, too, even if the MSR | ||
840 | * is not present. | ||
841 | */ | ||
842 | msr_set_bit(MSR_F10H_DECFG, | ||
843 | MSR_F10H_DECFG_LFENCE_SERIALIZE_BIT); | ||
844 | |||
845 | /* | ||
846 | * Verify that the MSR write was successful (could be running | ||
847 | * under a hypervisor) and only then assume that LFENCE is | ||
848 | * serializing. | ||
849 | */ | ||
850 | ret = rdmsrl_safe(MSR_F10H_DECFG, &val); | ||
851 | if (!ret && (val & MSR_F10H_DECFG_LFENCE_SERIALIZE)) { | ||
852 | /* A serializing LFENCE stops RDTSC speculation */ | ||
853 | set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); | ||
854 | } else { | ||
855 | /* MFENCE stops RDTSC speculation */ | ||
856 | set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC); | ||
857 | } | ||
834 | } | 858 | } |
835 | 859 | ||
836 | /* | 860 | /* |