diff options
Diffstat (limited to 'arch/x86/kernel/cpu/amd.c')
| -rw-r--r-- | arch/x86/kernel/cpu/amd.c | 58 | 
1 files changed, 34 insertions, 24 deletions
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 12bc0a1139da..082d7875cef8 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -9,7 +9,9 @@  #include <linux/random.h>  #include <asm/processor.h>  #include <asm/apic.h> +#include <asm/cacheinfo.h>  #include <asm/cpu.h> +#include <asm/spec-ctrl.h>  #include <asm/smp.h>  #include <asm/pci-direct.h>  #include <asm/delay.h> @@ -297,7 +299,6 @@ static int nearby_node(int apicid)  }  #endif -#ifdef CONFIG_SMP  /*   * Fix up cpu_core_id for pre-F17h systems to be in the   * [0 .. cores_per_node - 1] range. Not really needed but @@ -327,6 +328,7 @@ static void amd_get_topology(struct cpuinfo_x86 *c)  	/* get information required for multi-node processors */  	if (boot_cpu_has(X86_FEATURE_TOPOEXT)) { +		int err;  		u32 eax, ebx, ecx, edx;  		cpuid(0x8000001e, &eax, &ebx, &ecx, &edx); @@ -345,21 +347,15 @@ static void amd_get_topology(struct cpuinfo_x86 *c)  		}  		/* -		 * We may have multiple LLCs if L3 caches exist, so check if we -		 * have an L3 cache by looking at the L3 cache CPUID leaf. +		 * In case leaf B is available, use it to derive +		 * topology information.  		 */ -		if (cpuid_edx(0x80000006)) { -			if (c->x86 == 0x17) { -				/* -				 * LLC is at the core complex level. -				 * Core complex id is ApicId[3]. -				 */ -				per_cpu(cpu_llc_id, cpu) = c->apicid >> 3; -			} else { -				/* LLC is at the node level. */ -				per_cpu(cpu_llc_id, cpu) = node_id; -			} -		} +		err = detect_extended_topology(c); +		if (!err) +			c->x86_coreid_bits = get_count_order(c->x86_max_cores); + +		cacheinfo_amd_init_llc_id(c, cpu, node_id); +  	} else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) {  		u64 value; @@ -375,7 +371,6 @@ static void amd_get_topology(struct cpuinfo_x86 *c)  		legacy_fixup_core_id(c);  	}  } -#endif  /*   * On a AMD dual core setup the lower bits of the APIC id distinguish the cores. @@ -383,7 +378,6 @@ static void amd_get_topology(struct cpuinfo_x86 *c)   */  static void amd_detect_cmp(struct cpuinfo_x86 *c)  { -#ifdef CONFIG_SMP  	unsigned bits;  	int cpu = smp_processor_id(); @@ -394,17 +388,11 @@ static void amd_detect_cmp(struct cpuinfo_x86 *c)  	c->phys_proc_id = c->initial_apicid >> bits;  	/* use socket ID also for last level cache */  	per_cpu(cpu_llc_id, cpu) = c->phys_proc_id; -	amd_get_topology(c); -#endif  }  u16 amd_get_nb_id(int cpu)  { -	u16 id = 0; -#ifdef CONFIG_SMP -	id = per_cpu(cpu_llc_id, cpu); -#endif -	return id; +	return per_cpu(cpu_llc_id, cpu);  }  EXPORT_SYMBOL_GPL(amd_get_nb_id); @@ -554,6 +542,26 @@ static void bsp_init_amd(struct cpuinfo_x86 *c)  		rdmsrl(MSR_FAM10H_NODE_ID, value);  		nodes_per_socket = ((value >> 3) & 7) + 1;  	} + +	if (c->x86 >= 0x15 && c->x86 <= 0x17) { +		unsigned int bit; + +		switch (c->x86) { +		case 0x15: bit = 54; break; +		case 0x16: bit = 33; break; +		case 0x17: bit = 10; break; +		default: return; +		} +		/* +		 * Try to cache the base value so further operations can +		 * avoid RMW. If that faults, do not enable SSBD. +		 */ +		if (!rdmsrl_safe(MSR_AMD64_LS_CFG, &x86_amd_ls_cfg_base)) { +			setup_force_cpu_cap(X86_FEATURE_LS_CFG_SSBD); +			setup_force_cpu_cap(X86_FEATURE_SSBD); +			x86_amd_ls_cfg_ssbd_mask = 1ULL << bit; +		} +	}  }  static void early_detect_mem_encrypt(struct cpuinfo_x86 *c) @@ -791,6 +799,7 @@ static void init_amd_bd(struct cpuinfo_x86 *c)  static void init_amd_zn(struct cpuinfo_x86 *c)  { +	set_cpu_cap(c, X86_FEATURE_ZEN);  	/*  	 * Fix erratum 1076: CPB feature bit not being set in CPUID. It affects  	 * all up to and including B1. @@ -842,6 +851,7 @@ static void init_amd(struct cpuinfo_x86 *c)  	/* Multi core CPU? */  	if (c->extended_cpuid_level >= 0x80000008) {  		amd_detect_cmp(c); +		amd_get_topology(c);  		srat_detect_node(c);  	}  | 
