diff options
Diffstat (limited to 'arch/x86/kernel/cpu/amd.c')
| -rw-r--r-- | arch/x86/kernel/cpu/amd.c | 66 | 
1 files changed, 54 insertions, 12 deletions
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 3b9e220621f8..d58184b7cd44 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -297,13 +297,29 @@ 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 + * kept so as not to break existing setups. + */ +static void legacy_fixup_core_id(struct cpuinfo_x86 *c) +{ +	u32 cus_per_node; + +	if (c->x86 >= 0x17) +		return; + +	cus_per_node = c->x86_max_cores / nodes_per_socket; +	c->cpu_core_id %= cus_per_node; +} +  /*   * Fixup core topology information for   * (1) AMD multi-node processors   *     Assumption: Number of cores in each internal node is the same.   * (2) AMD processors supporting compute units   */ -#ifdef CONFIG_SMP  static void amd_get_topology(struct cpuinfo_x86 *c)  {  	u8 node_id; @@ -354,15 +370,9 @@ static void amd_get_topology(struct cpuinfo_x86 *c)  	} else  		return; -	/* fixup multi-node processor information */  	if (nodes_per_socket > 1) { -		u32 cus_per_node; -  		set_cpu_cap(c, X86_FEATURE_AMD_DCM); -		cus_per_node = c->x86_max_cores / nodes_per_socket; - -		/* core id has to be in the [0 .. cores_per_node - 1] range */ -		c->cpu_core_id %= cus_per_node; +		legacy_fixup_core_id(c);  	}  }  #endif @@ -548,8 +558,12 @@ static void bsp_init_amd(struct cpuinfo_x86 *c)  static void early_init_amd(struct cpuinfo_x86 *c)  { +	u32 dummy; +  	early_init_amd_mc(c); +	rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy); +  	/*  	 * c->x86_power is 8000_0007 edx. Bit 8 is TSC runs at constant rate  	 * with P/T states and does not stop in deep C-states @@ -612,6 +626,27 @@ static void early_init_amd(struct cpuinfo_x86 *c)  	 */  	if (cpu_has_amd_erratum(c, amd_erratum_400))  		set_cpu_bug(c, X86_BUG_AMD_E400); + +	/* +	 * BIOS support is required for SME. If BIOS has enabled SME then +	 * adjust x86_phys_bits by the SME physical address space reduction +	 * value. If BIOS has not enabled SME then don't advertise the +	 * feature (set in scattered.c). Also, since the SME support requires +	 * long mode, don't advertise the feature under CONFIG_X86_32. +	 */ +	if (cpu_has(c, X86_FEATURE_SME)) { +		u64 msr; + +		/* Check if SME is enabled */ +		rdmsrl(MSR_K8_SYSCFG, msr); +		if (msr & MSR_K8_SYSCFG_MEM_ENCRYPT) { +			c->x86_phys_bits -= (cpuid_ebx(0x8000001f) >> 6) & 0x3f; +			if (IS_ENABLED(CONFIG_X86_32)) +				clear_cpu_cap(c, X86_FEATURE_SME); +		} else { +			clear_cpu_cap(c, X86_FEATURE_SME); +		} +	}  }  static void init_amd_k8(struct cpuinfo_x86 *c) @@ -728,10 +763,18 @@ static void init_amd_bd(struct cpuinfo_x86 *c)  	}  } -static void init_amd(struct cpuinfo_x86 *c) +static void init_amd_zn(struct cpuinfo_x86 *c)  { -	u32 dummy; +	/* +	 * Fix erratum 1076: CPB feature bit not being set in CPUID. It affects +	 * all up to and including B1. +	 */ +	if (c->x86_model <= 1 && c->x86_mask <= 1) +		set_cpu_cap(c, X86_FEATURE_CPB); +} +static void init_amd(struct cpuinfo_x86 *c) +{  	early_init_amd(c);  	/* @@ -758,6 +801,7 @@ static void init_amd(struct cpuinfo_x86 *c)  	case 0x10: init_amd_gh(c); break;  	case 0x12: init_amd_ln(c); break;  	case 0x15: init_amd_bd(c); break; +	case 0x17: init_amd_zn(c); break;  	}  	/* Enable workaround for FXSAVE leak */ @@ -793,8 +837,6 @@ static void init_amd(struct cpuinfo_x86 *c)  	if (c->x86 > 0x11)  		set_cpu_cap(c, X86_FEATURE_ARAT); -	rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy); -  	/* 3DNow or LM implies PREFETCHW */  	if (!cpu_has(c, X86_FEATURE_3DNOWPREFETCH))  		if (cpu_has(c, X86_FEATURE_3DNOW) || cpu_has(c, X86_FEATURE_LM))  |