Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 11fdd252 authored by Yinghai Lu's avatar Yinghai Lu Committed by Ingo Molnar
Browse files

x86: cpu make amd.c more like amd_64.c v2



1. make 32bit have early_init_amd_mc and amd_detect_cmp
2. seperate init_amd_k5/k6/k7 ...

v2: fix compiling for !CONFIG_SMP

Signed-off-by: default avatarYinghai Lu <yhlu.kernel@gmail.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 2d9cd6c2
Loading
Loading
Loading
Loading
+224 −172
Original line number Diff line number Diff line
@@ -24,55 +24,8 @@
extern void vide(void);
__asm__(".align 4\nvide: ret");

static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
static void __cpuinit init_amd_k5(struct cpuinfo_x86 *c)
{
	if (c->x86_power & (1<<8))
		set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);

	/*  Set MTRR capability flag if appropriate */
	if (c->x86_model == 13 || c->x86_model == 9 ||
	   (c->x86_model == 8 && c->x86_mask >= 8))
		set_cpu_cap(c, X86_FEATURE_K6_MTRR);
}

static void __cpuinit init_amd(struct cpuinfo_x86 *c)
{
	u32 l, h;
	int mbytes = num_physpages >> (20-PAGE_SHIFT);

#ifdef CONFIG_SMP
	unsigned long long value;

	/*
	 * Disable TLB flush filter by setting HWCR.FFDIS on K8
	 * bit 6 of msr C001_0015
	 *
	 * Errata 63 for SH-B3 steppings
	 * Errata 122 for all steppings (F+ have it disabled by default)
	 */
	if (c->x86 == 15) {
		rdmsrl(MSR_K7_HWCR, value);
		value |= 1 << 6;
		wrmsrl(MSR_K7_HWCR, value);
	}
#endif

	early_init_amd(c);

	/*
	 *	FIXME: We should handle the K5 here. Set up the write
	 *	range and also turn on MSR 83 bits 4 and 31 (write alloc,
	 *	no bus pipeline)
	 */

	/*
	 * Bit 31 in normal CPUID used for nonstandard 3DNow ID;
	 * 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway
	 */
	clear_cpu_cap(c, 0*32+31);

	switch (c->x86) {
	case 4:
/*
 * General Systems BIOSen alias the cpu frequency registers
 * of the Elan at 0x000df000. Unfortuantly, one of the Linux
@@ -86,15 +39,21 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
		if (inl (CBAR) & CBAR_ENB)
			outl (0 | CBAR_KEY, CBAR);
	}
			break;
	case 5:
}


static void __cpuinit init_amd_k6(struct cpuinfo_x86 *c)
{
	u32 l, h;
	int mbytes = num_physpages >> (20-PAGE_SHIFT);

	if (c->x86_model < 6) {
		/* Based on AMD doc 20734R - June 2000 */
		if (c->x86_model == 0) {
			clear_cpu_cap(c, X86_FEATURE_APIC);
			set_cpu_cap(c, X86_FEATURE_PGE);
		}
				break;
		return;
	}

	if (c->x86_model == 6 && c->x86_mask == 1) {
@@ -143,7 +102,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
			printk(KERN_INFO "Enabling old style K6 write allocation for %d Mb\n",
				mbytes);
		}
				break;
		return;
	}

	if ((c->x86_model == 8 && c->x86_mask > 7) ||
@@ -165,16 +124,19 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
				mbytes);
		}

				break;
		return;
	}

	if (c->x86_model == 10) {
		/* AMD Geode LX is model 10 */
		/* placeholder for any needed mods */
				break;
		return;
	}
}
			break;
	case 6: /* An Athlon/Duron */

static void __cpuinit init_amd_k7(struct cpuinfo_x86 *c)
{
	u32 l, h;

	/*
	 * Bit 15 of Athlon specific MSR 15, needs to be 0
@@ -204,62 +166,152 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
			wrmsr(MSR_K7_CLK_CTL, (l & 0x000fffff)|0x20000000, h);
		}
	}
			break;
	}

	switch (c->x86) {
	case 15:
	/* Use K8 tuning for Fam10h and Fam11h */
	case 0x10:
	case 0x11:
		set_cpu_cap(c, X86_FEATURE_K8);
		break;
	case 6:
	set_cpu_cap(c, X86_FEATURE_K7);
		break;
}
	if (c->x86 >= 6)
		set_cpu_cap(c, X86_FEATURE_FXSAVE_LEAK);

	display_cacheinfo(c);
/*
 * On a AMD dual core setup the lower bits of the APIC id distingush the cores.
 * Assumes number of cores is a power of two.
 */
static void __cpuinit amd_detect_cmp(struct cpuinfo_x86 *c)
{
#ifdef CONFIG_X86_HT
	unsigned bits;

	bits = c->x86_coreid_bits;

	if (cpuid_eax(0x80000000) >= 0x80000008)
		c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
	/* Low order bits define the core id (index of core in socket) */
	c->cpu_core_id = c->initial_apicid & ((1 << bits)-1);
	/* Convert the initial APIC ID into the socket ID */
	c->phys_proc_id = c->initial_apicid >> bits;
#endif
}

static void __cpuinit early_init_amd_mc(struct cpuinfo_x86 *c)
{
#ifdef CONFIG_X86_HT
	/*
	 * On a AMD multi core setup the lower bits of the APIC id
	 * distinguish the cores.
	 */
	if (c->x86_max_cores > 1) {
		int cpu = smp_processor_id();
		unsigned bits = (cpuid_ecx(0x80000008) >> 12) & 0xf;
	unsigned bits, ecx;

	/* Multi core CPU? */
	if (c->extended_cpuid_level < 0x80000008)
		return;

	ecx = cpuid_ecx(0x80000008);

	c->x86_max_cores = (ecx & 0xff) + 1;

	/* CPU telling us the core id bits shift? */
	bits = (ecx >> 12) & 0xF;

	/* Otherwise recompute */
	if (bits == 0) {
		while ((1 << bits) < c->x86_max_cores)
			bits++;
	}
		c->cpu_core_id = c->phys_proc_id & ((1<<bits)-1);
		c->phys_proc_id >>= bits;
		printk(KERN_INFO "CPU %d(%d) -> Core %d\n",
		       cpu, c->x86_max_cores, c->cpu_core_id);

	c->x86_coreid_bits = bits;
#endif
}

static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
{
	early_init_amd_mc(c);

	if (c->x86_power & (1<<8))
		set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);

	/*  Set MTRR capability flag if appropriate */
	if (c->x86_model == 13 || c->x86_model == 9 ||
	   (c->x86_model == 8 && c->x86_mask >= 8))
		set_cpu_cap(c, X86_FEATURE_K6_MTRR);
}

static void __cpuinit init_amd(struct cpuinfo_x86 *c)
{
#ifdef CONFIG_SMP
	unsigned long long value;

	/*
	 * Disable TLB flush filter by setting HWCR.FFDIS on K8
	 * bit 6 of msr C001_0015
	 *
	 * Errata 63 for SH-B3 steppings
	 * Errata 122 for all steppings (F+ have it disabled by default)
	 */
	if (c->x86 == 0xf) {
		rdmsrl(MSR_K7_HWCR, value);
		value |= 1 << 6;
		wrmsrl(MSR_K7_HWCR, value);
	}
#endif

	if (cpuid_eax(0x80000000) >= 0x80000006) {
		if ((c->x86 == 0x10) && (cpuid_edx(0x80000006) & 0xf000))
			num_cache_leaves = 4;
		else
			num_cache_leaves = 3;
	early_init_amd(c);

	/*
	 *	FIXME: We should handle the K5 here. Set up the write
	 *	range and also turn on MSR 83 bits 4 and 31 (write alloc,
	 *	no bus pipeline)
	 */

	/*
	 * Bit 31 in normal CPUID used for nonstandard 3DNow ID;
	 * 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway
	 */
	clear_cpu_cap(c, 0*32+31);

	switch (c->x86) {
	case 4:
		init_amd_k5(c);
		break;
	case 5:
		init_amd_k6(c);
		break;
	case 6: /* An Athlon/Duron */
		init_amd_k7(c);
		break;
	}

	/* K6s reports MCEs but don't actually have all the MSRs */
	if (c->x86 < 6)
		clear_cpu_cap(c, X86_FEATURE_MCE);

	if (cpu_has_xmm2)
	if (c->x86 >= 6)
		set_cpu_cap(c, X86_FEATURE_FXSAVE_LEAK);

	if (!c->x86_model_id[0]) {
		switch (c->x86) {
		case 0xf:
			/* Should distinguish Models here, but this is only
			   a fallback anyways. */
			strcpy(c->x86_model_id, "Hammer");
			break;
		}
	}

	display_cacheinfo(c);

	/* Multi core CPU? */
	if (c->extended_cpuid_level >= 0x80000008)
		amd_detect_cmp(c);

	detect_ht(c);

	if (c->extended_cpuid_level >= 0x80000006) {
		if ((c->x86 >= 0x0f) && (cpuid_edx(0x80000006) & 0xf000))
			num_cache_leaves = 4;
		else
			num_cache_leaves = 3;
	}

	if (c->x86 >= 0xf && c->x86 <= 0x11)
		set_cpu_cap(c, X86_FEATURE_K8);

	if (cpu_has_xmm2) {
		/* MFENCE stops RDTSC speculation */
		set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC);
	}
}

static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 *c, unsigned int size)
{
+10 −7
Original line number Diff line number Diff line
@@ -174,17 +174,20 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
	if (c->extended_cpuid_level >= 0x80000008)
		amd_detect_cmp(c);

	if (c->extended_cpuid_level >= 0x80000006 &&
		(cpuid_edx(0x80000006) & 0xf000))
	if (c->extended_cpuid_level >= 0x80000006) {
		if ((c->x86 >= 0x0f) && (cpuid_edx(0x80000006) & 0xf000))
			num_cache_leaves = 4;
		else
			num_cache_leaves = 3;
	}

	if (c->x86 >= 0xf && c->x86 <= 0x11)
		set_cpu_cap(c, X86_FEATURE_K8);

	if (cpu_has_xmm2) {
		/* MFENCE stops RDTSC speculation */
		set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC);
	}

	if (c->x86 == 0x10) {
		/* do this for boot cpu */
+1 −1
Original line number Diff line number Diff line
@@ -629,8 +629,8 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
	c->x86_vendor_id[0] = '\0'; /* Unset */
	c->x86_model_id[0] = '\0';  /* Unset */
	c->x86_max_cores = 1;
#ifdef CONFIG_X86_64
	c->x86_coreid_bits = 0;
#ifdef CONFIG_X86_64
	c->x86_clflush_size = 64;
#else
	c->cpuid_level = -1;	/* CPUID not detected */
+1 −1
Original line number Diff line number Diff line
@@ -75,9 +75,9 @@ struct cpuinfo_x86 {
	int			 x86_tlbsize;
	__u8			x86_virt_bits;
	__u8			x86_phys_bits;
#endif
	/* CPUID returned core id bits: */
	__u8			x86_coreid_bits;
#endif
	/* Max extended CPUID function supported: */
	__u32			extended_cpuid_level;
	/* Maximum supported CPUID level, -1=no CPUID: */