aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2005-01-11 01:48:01 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-01-11 01:48:01 -0800
commitb9662b21dd274ff9c9d1ddbc85b90f7cebf38d03 (patch)
treea4af078170950ba7873a9c64c5e02be8d81d7f28 /arch
parente77da0004873c55d33962075b2625e728f1568eb (diff)
downloadhistory-b9662b21dd274ff9c9d1ddbc85b90f7cebf38d03.tar.gz
[PATCH] i386: AMD dual core support for i386
AMD dual core support for i386 Run HT initialization on AMD dual core CPUs on i386. They fake being HT CPUs. This patch makes the HT detection run on AMD CPUs too. I moved the HT detection code into a common file from intel.c for that. It would be actually better to run HT detection always on all CPUs but this would need a second callback afterwards to AMD code, which I avoided for now. It adds a cpuinfo->x86_num_cores field. This sets up the phys_proc_id[] array. This overloads this array with HT, but when smp_num_siblings is 1 It is currently only used for /proc/cpuinfo printing. The reason we want to behave this like SMT is that there are some license managers in user space that license according to number of physical CPUs, and when they handle HT they should handle CMP with this hack too. Another reason we need this is that the powernow k8 driver needs this information to properly manage dual core CPUs. When there are ever dual core HT CPUs this will need small changes in smpboot.c. I didn't do this for now to keep the patch simple. Then we set smp_num_siblings to 1 on these systems again to prevent the scheduler from setting up HT scheduling (which is not a very good match for dual core). This is a port of the CMP support code from x86-64 (minus the NUMA bits) Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/i386/kernel/cpu/amd.c17
-rw-r--r--arch/i386/kernel/cpu/common.c48
-rw-r--r--arch/i386/kernel/cpu/intel.c43
3 files changed, 66 insertions, 42 deletions
diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c
index 091b98ae93b672..ae94585d044513 100644
--- a/arch/i386/kernel/cpu/amd.c
+++ b/arch/i386/kernel/cpu/amd.c
@@ -188,6 +188,23 @@ static void __init init_amd(struct cpuinfo_x86 *c)
}
display_cacheinfo(c);
+ detect_ht(c);
+
+#ifdef CONFIG_X86_HT
+ /* AMD dual core looks like HT but isn't really. Hide it from the
+ scheduler. This works around problems with the domain scheduler.
+ Also probably gives slightly better scheduling and disables
+ SMT nice which is harmful on dual core.
+ TBD tune the domain scheduler for dual core. */
+ if (cpu_has(c, X86_FEATURE_CMP_LEGACY))
+ smp_num_siblings = 1;
+#endif
+
+ if (cpuid_eax(0x80000000) >= 0x80000008) {
+ c->x86_num_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
+ if (c->x86_num_cores & (c->x86_num_cores - 1))
+ c->x86_num_cores = 1;
+ }
}
static unsigned int amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index 35f37a3d39546d..5761150d84e071 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -10,6 +10,11 @@
#include <asm/msr.h>
#include <asm/io.h>
#include <asm/mmu_context.h>
+#ifdef CONFIG_X86_LOCAL_APIC
+#include <asm/mpspec.h>
+#include <asm/apic.h>
+#include <mach_apic.h>
+#endif
#include "cpu.h"
@@ -323,6 +328,7 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
c->x86_model = c->x86_mask = 0; /* So far unknown... */
c->x86_vendor_id[0] = '\0'; /* Unset */
c->x86_model_id[0] = '\0'; /* Unset */
+ c->x86_num_cores = 1;
memset(&c->x86_capability, 0, sizeof c->x86_capability);
if (!have_cpuid_p()) {
@@ -431,6 +437,48 @@ void __init dodgy_tsc(void)
cpu_devs[X86_VENDOR_CYRIX]->c_init(&boot_cpu_data);
}
+void __init detect_ht(struct cpuinfo_x86 *c)
+{
+ u32 eax, ebx, ecx, edx;
+ int index_lsb, index_msb, tmp;
+ int cpu = smp_processor_id();
+
+ if (!cpu_has(c, X86_FEATURE_HT))
+ return;
+
+ cpuid(1, &eax, &ebx, &ecx, &edx);
+ smp_num_siblings = (ebx & 0xff0000) >> 16;
+
+ if (smp_num_siblings == 1) {
+ printk(KERN_INFO "CPU: Hyper-Threading is disabled\n");
+ } else if (smp_num_siblings > 1 ) {
+ index_lsb = 0;
+ index_msb = 31;
+
+ if (smp_num_siblings > NR_CPUS) {
+ printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings);
+ smp_num_siblings = 1;
+ return;
+ }
+ tmp = smp_num_siblings;
+ while ((tmp & 1) == 0) {
+ tmp >>=1 ;
+ index_lsb++;
+ }
+ tmp = smp_num_siblings;
+ while ((tmp & 0x80000000 ) == 0) {
+ tmp <<=1 ;
+ index_msb--;
+ }
+ if (index_lsb != index_msb )
+ index_msb++;
+ phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb);
+
+ printk(KERN_INFO "CPU: Physical Processor ID: %d\n",
+ phys_proc_id[cpu]);
+ }
+}
+
void __init print_cpu_info(struct cpuinfo_x86 *c)
{
char *vendor = NULL;
diff --git a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c
index eb145ed88d6a55..ec3858cf4c5a05 100644
--- a/arch/i386/kernel/cpu/intel.c
+++ b/arch/i386/kernel/cpu/intel.c
@@ -140,48 +140,7 @@ static void __init init_intel(struct cpuinfo_x86 *c)
strcpy(c->x86_model_id, p);
#ifdef CONFIG_X86_HT
- if (cpu_has(c, X86_FEATURE_HT)) {
- extern int phys_proc_id[NR_CPUS];
-
- u32 eax, ebx, ecx, edx;
- int index_lsb, index_msb, tmp;
- int cpu = smp_processor_id();
-
- cpuid(1, &eax, &ebx, &ecx, &edx);
- smp_num_siblings = (ebx & 0xff0000) >> 16;
-
- if (smp_num_siblings == 1) {
- printk(KERN_INFO "CPU: Hyper-Threading is disabled\n");
- } else if (smp_num_siblings > 1 ) {
- index_lsb = 0;
- index_msb = 31;
-
- if (smp_num_siblings > NR_CPUS) {
- printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings);
- smp_num_siblings = 1;
- goto too_many_siblings;
- }
- tmp = smp_num_siblings;
- while ((tmp & 1) == 0) {
- tmp >>=1 ;
- index_lsb++;
- }
- tmp = smp_num_siblings;
- while ((tmp & 0x80000000 ) == 0) {
- tmp <<=1 ;
- index_msb--;
- }
- if (index_lsb != index_msb )
- index_msb++;
- phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb);
-
- printk(KERN_INFO "CPU: Physical Processor ID: %d\n",
- phys_proc_id[cpu]);
- }
-
- }
-too_many_siblings:
-
+ detect_ht(c);
#endif
/* Work around errata */