diff options
Diffstat (limited to 'arch/x86/kernel/cpu/intel_cacheinfo.c')
| -rw-r--r-- | arch/x86/kernel/cpu/intel_cacheinfo.c | 75 | 
1 files changed, 55 insertions, 20 deletions
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index 93c5451bdd52..fe9edec6698a 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -538,7 +538,11 @@ __cpuinit cpuid4_cache_lookup_regs(int index,  	unsigned		edx;  	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { -		amd_cpuid4(index, &eax, &ebx, &ecx); +		if (cpu_has_topoext) +			cpuid_count(0x8000001d, index, &eax.full, +				    &ebx.full, &ecx.full, &edx); +		else +			amd_cpuid4(index, &eax, &ebx, &ecx);  		amd_init_l3_cache(this_leaf, index);  	} else {  		cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx); @@ -557,21 +561,39 @@ __cpuinit cpuid4_cache_lookup_regs(int index,  	return 0;  } -static int __cpuinit find_num_cache_leaves(void) +static int __cpuinit find_num_cache_leaves(struct cpuinfo_x86 *c)  { -	unsigned int		eax, ebx, ecx, edx; +	unsigned int		eax, ebx, ecx, edx, op;  	union _cpuid4_leaf_eax	cache_eax;  	int 			i = -1; +	if (c->x86_vendor == X86_VENDOR_AMD) +		op = 0x8000001d; +	else +		op = 4; +  	do {  		++i; -		/* Do cpuid(4) loop to find out num_cache_leaves */ -		cpuid_count(4, i, &eax, &ebx, &ecx, &edx); +		/* Do cpuid(op) loop to find out num_cache_leaves */ +		cpuid_count(op, i, &eax, &ebx, &ecx, &edx);  		cache_eax.full = eax;  	} while (cache_eax.split.type != CACHE_TYPE_NULL);  	return i;  } +void __cpuinit init_amd_cacheinfo(struct cpuinfo_x86 *c) +{ + +	if (cpu_has_topoext) { +		num_cache_leaves = find_num_cache_leaves(c); +	} else if (c->extended_cpuid_level >= 0x80000006) { +		if (cpuid_edx(0x80000006) & 0xf000) +			num_cache_leaves = 4; +		else +			num_cache_leaves = 3; +	} +} +  unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)  {  	/* Cache sizes */ @@ -588,7 +610,7 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)  		if (is_initialized == 0) {  			/* Init num_cache_leaves from boot CPU */ -			num_cache_leaves = find_num_cache_leaves(); +			num_cache_leaves = find_num_cache_leaves(c);  			is_initialized++;  		} @@ -728,37 +750,50 @@ static DEFINE_PER_CPU(struct _cpuid4_info *, ici_cpuid4_info);  static int __cpuinit cache_shared_amd_cpu_map_setup(unsigned int cpu, int index)  {  	struct _cpuid4_info *this_leaf; -	int ret, i, sibling; -	struct cpuinfo_x86 *c = &cpu_data(cpu); +	int i, sibling; -	ret = 0; -	if (index == 3) { -		ret = 1; -		for_each_cpu(i, cpu_llc_shared_mask(cpu)) { +	if (cpu_has_topoext) { +		unsigned int apicid, nshared, first, last; + +		if (!per_cpu(ici_cpuid4_info, cpu)) +			return 0; + +		this_leaf = CPUID4_INFO_IDX(cpu, index); +		nshared = this_leaf->base.eax.split.num_threads_sharing + 1; +		apicid = cpu_data(cpu).apicid; +		first = apicid - (apicid % nshared); +		last = first + nshared - 1; + +		for_each_online_cpu(i) { +			apicid = cpu_data(i).apicid; +			if ((apicid < first) || (apicid > last)) +				continue;  			if (!per_cpu(ici_cpuid4_info, i))  				continue;  			this_leaf = CPUID4_INFO_IDX(i, index); -			for_each_cpu(sibling, cpu_llc_shared_mask(cpu)) { -				if (!cpu_online(sibling)) + +			for_each_online_cpu(sibling) { +				apicid = cpu_data(sibling).apicid; +				if ((apicid < first) || (apicid > last))  					continue;  				set_bit(sibling, this_leaf->shared_cpu_map);  			}  		} -	} else if ((c->x86 == 0x15) && ((index == 1) || (index == 2))) { -		ret = 1; -		for_each_cpu(i, cpu_sibling_mask(cpu)) { +	} else if (index == 3) { +		for_each_cpu(i, cpu_llc_shared_mask(cpu)) {  			if (!per_cpu(ici_cpuid4_info, i))  				continue;  			this_leaf = CPUID4_INFO_IDX(i, index); -			for_each_cpu(sibling, cpu_sibling_mask(cpu)) { +			for_each_cpu(sibling, cpu_llc_shared_mask(cpu)) {  				if (!cpu_online(sibling))  					continue;  				set_bit(sibling, this_leaf->shared_cpu_map);  			}  		} -	} +	} else +		return 0; -	return ret; +	return 1;  }  static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)  |