direct-io.hg
changeset 5509:dd6990776fcc
bitkeeper revision 1.1718.1.5 (42b59f7dHnuJ9AFj24zaneKCDkFTCg)
This patch adds dual-core support to xen, and improves HT detection.
Adapted from linux 2.6.12.
Signed-off-by: Nguyen Anh Quynh <aquynh@gmail.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
This patch adds dual-core support to xen, and improves HT detection.
Adapted from linux 2.6.12.
Signed-off-by: Nguyen Anh Quynh <aquynh@gmail.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
author | kaf24@firebug.cl.cam.ac.uk |
---|---|
date | Sun Jun 19 16:38:21 2005 +0000 (2005-06-19) |
parents | 85fab828d6ff |
children | acf30d736a08 |
files | xen/arch/x86/cpu/amd.c xen/arch/x86/cpu/common.c xen/arch/x86/cpu/cpu.h xen/arch/x86/cpu/intel.c xen/arch/x86/dom0_ops.c xen/arch/x86/setup.c xen/arch/x86/smpboot.c xen/common/dom0_ops.c xen/include/asm-x86/processor.h xen/include/asm-x86/smp.h xen/include/xen/smp.h |
line diff
1.1 --- a/xen/arch/x86/cpu/amd.c Sun Jun 19 16:17:17 2005 +0000 1.2 +++ b/xen/arch/x86/cpu/amd.c Sun Jun 19 16:38:21 2005 +0000 1.3 @@ -193,23 +193,30 @@ static void __init init_amd(struct cpuin 1.4 } 1.5 1.6 display_cacheinfo(c); 1.7 - detect_ht(c); 1.8 - 1.9 -#ifdef CONFIG_X86_HT 1.10 - /* AMD dual core looks like HT but isn't really. Hide it from the 1.11 - scheduler. This works around problems with the domain scheduler. 1.12 - Also probably gives slightly better scheduling and disables 1.13 - SMT nice which is harmful on dual core. 1.14 - TBD tune the domain scheduler for dual core. */ 1.15 - if (cpu_has(c, X86_FEATURE_CMP_LEGACY)) 1.16 - smp_num_siblings = 1; 1.17 -#endif 1.18 1.19 if (cpuid_eax(0x80000000) >= 0x80000008) { 1.20 c->x86_num_cores = (cpuid_ecx(0x80000008) & 0xff) + 1; 1.21 if (c->x86_num_cores & (c->x86_num_cores - 1)) 1.22 c->x86_num_cores = 1; 1.23 } 1.24 + 1.25 +#ifdef CONFIG_X86_HT 1.26 + /* 1.27 + * On a AMD dual core setup the lower bits of the APIC id 1.28 + * distingush the cores. Assumes number of cores is a power 1.29 + * of two. 1.30 + */ 1.31 + if (c->x86_num_cores > 1) { 1.32 + int cpu = smp_processor_id(); 1.33 + unsigned bits = 0; 1.34 + while ((1 << bits) < c->x86_num_cores) 1.35 + bits++; 1.36 + cpu_core_id[cpu] = phys_proc_id[cpu] & ((1<<bits)-1); 1.37 + phys_proc_id[cpu] >>= bits; 1.38 + printk(KERN_INFO "CPU %d(%d) -> Core %d\n", 1.39 + cpu, c->x86_num_cores, cpu_core_id[cpu]); 1.40 + } 1.41 +#endif 1.42 } 1.43 1.44 static unsigned int amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
2.1 --- a/xen/arch/x86/cpu/common.c Sun Jun 19 16:17:17 2005 +0000 2.2 +++ b/xen/arch/x86/cpu/common.c Sun Jun 19 16:38:21 2005 +0000 2.3 @@ -186,7 +186,7 @@ static inline int flag_is_changeable_p(u 2.4 2.5 2.6 /* Probe for the CPUID instruction */ 2.7 -int __init have_cpuid_p(void) 2.8 +static int __init have_cpuid_p(void) 2.9 { 2.10 return flag_is_changeable_p(X86_EFLAGS_ID); 2.11 } 2.12 @@ -194,7 +194,7 @@ int __init have_cpuid_p(void) 2.13 /* Do minimum CPU detection early. 2.14 Fields really needed: vendor, cpuid_level, family, model, mask, cache alignment. 2.15 The others are not touched to avoid unwanted side effects. */ 2.16 -void __init early_cpu_detect(void) 2.17 +static void __init early_cpu_detect(void) 2.18 { 2.19 struct cpuinfo_x86 *c = &boot_cpu_data; 2.20 2.21 @@ -228,6 +228,10 @@ void __init early_cpu_detect(void) 2.22 } 2.23 2.24 early_intel_workaround(c); 2.25 + 2.26 +#ifdef CONFIG_X86_HT 2.27 + phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff; 2.28 +#endif 2.29 } 2.30 2.31 void __init generic_identify(struct cpuinfo_x86 * c) 2.32 @@ -416,25 +420,15 @@ void __init identify_cpu(struct cpuinfo_ 2.33 mcheck_init(c); 2.34 #endif 2.35 } 2.36 -/* 2.37 - * Perform early boot up checks for a valid TSC. See arch/i386/kernel/time.c 2.38 - */ 2.39 - 2.40 -void __init dodgy_tsc(void) 2.41 -{ 2.42 - if (( boot_cpu_data.x86_vendor == X86_VENDOR_CYRIX ) || 2.43 - ( boot_cpu_data.x86_vendor == X86_VENDOR_NSC )) 2.44 - cpu_devs[X86_VENDOR_CYRIX]->c_init(&boot_cpu_data); 2.45 -} 2.46 2.47 #ifdef CONFIG_X86_HT 2.48 void __init detect_ht(struct cpuinfo_x86 *c) 2.49 { 2.50 u32 eax, ebx, ecx, edx; 2.51 - int index_lsb, index_msb, tmp; 2.52 + int index_msb, tmp; 2.53 int cpu = smp_processor_id(); 2.54 2.55 - if (!cpu_has(c, X86_FEATURE_HT)) 2.56 + if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY)) 2.57 return; 2.58 2.59 cpuid(1, &eax, &ebx, &ecx, &edx); 2.60 @@ -443,7 +437,6 @@ void __init detect_ht(struct cpuinfo_x86 2.61 if (smp_num_siblings == 1) { 2.62 printk(KERN_INFO "CPU: Hyper-Threading is disabled\n"); 2.63 } else if (smp_num_siblings > 1 ) { 2.64 - index_lsb = 0; 2.65 index_msb = 31; 2.66 2.67 if (smp_num_siblings > NR_CPUS) { 2.68 @@ -452,21 +445,34 @@ void __init detect_ht(struct cpuinfo_x86 2.69 return; 2.70 } 2.71 tmp = smp_num_siblings; 2.72 - while ((tmp & 1) == 0) { 2.73 - tmp >>=1 ; 2.74 - index_lsb++; 2.75 - } 2.76 - tmp = smp_num_siblings; 2.77 while ((tmp & 0x80000000 ) == 0) { 2.78 tmp <<=1 ; 2.79 index_msb--; 2.80 } 2.81 - if (index_lsb != index_msb ) 2.82 + if (smp_num_siblings & (smp_num_siblings - 1)) 2.83 index_msb++; 2.84 phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb); 2.85 2.86 printk(KERN_INFO "CPU: Physical Processor ID: %d\n", 2.87 phys_proc_id[cpu]); 2.88 + 2.89 + smp_num_siblings = smp_num_siblings / c->x86_num_cores; 2.90 + 2.91 + tmp = smp_num_siblings; 2.92 + index_msb = 31; 2.93 + while ((tmp & 0x80000000) == 0) { 2.94 + tmp <<=1 ; 2.95 + index_msb--; 2.96 + } 2.97 + 2.98 + if (smp_num_siblings & (smp_num_siblings - 1)) 2.99 + index_msb++; 2.100 + 2.101 + cpu_core_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb); 2.102 + 2.103 + if (c->x86_num_cores > 1) 2.104 + printk(KERN_INFO "CPU: Processor Core ID: %d\n", 2.105 + cpu_core_id[cpu]); 2.106 } 2.107 } 2.108 #endif 2.109 @@ -511,7 +517,6 @@ extern int amd_init_cpu(void); 2.110 extern int centaur_init_cpu(void); 2.111 extern int transmeta_init_cpu(void); 2.112 extern int rise_init_cpu(void); 2.113 -void early_cpu_detect(void); 2.114 2.115 void __init early_cpu_init(void) 2.116 {
3.1 --- a/xen/arch/x86/cpu/cpu.h Sun Jun 19 16:17:17 2005 +0000 3.2 +++ b/xen/arch/x86/cpu/cpu.h Sun Jun 19 16:38:21 2005 +0000 3.3 @@ -25,7 +25,6 @@ extern int get_model_name(struct cpuinfo 3.4 extern void display_cacheinfo(struct cpuinfo_x86 *c); 3.5 3.6 extern void generic_identify(struct cpuinfo_x86 * c); 3.7 -extern int have_cpuid_p(void); 3.8 3.9 extern void early_intel_workaround(struct cpuinfo_x86 *c); 3.10
4.1 --- a/xen/arch/x86/cpu/intel.c Sun Jun 19 16:17:17 2005 +0000 4.2 +++ b/xen/arch/x86/cpu/intel.c Sun Jun 19 16:38:21 2005 +0000 4.3 @@ -74,6 +74,27 @@ static void __init Intel_errata_workarou 4.4 } 4.5 4.6 4.7 +/* 4.8 + * find out the number of processor cores on the die 4.9 + */ 4.10 +static int __init num_cpu_cores(struct cpuinfo_x86 *c) 4.11 +{ 4.12 + unsigned int eax; 4.13 + 4.14 + if (c->cpuid_level < 4) 4.15 + return 1; 4.16 + 4.17 + __asm__("cpuid" 4.18 + : "=a" (eax) 4.19 + : "0" (4), "c" (0) 4.20 + : "bx", "dx"); 4.21 + 4.22 + if (eax & 0x1f) 4.23 + return ((eax >> 26) + 1); 4.24 + else 4.25 + return 1; 4.26 +} 4.27 + 4.28 static void __init init_intel(struct cpuinfo_x86 *c) 4.29 { 4.30 unsigned int l2 = 0; 4.31 @@ -136,6 +157,8 @@ static void __init init_intel(struct cpu 4.32 if ( p ) 4.33 strcpy(c->x86_model_id, p); 4.34 4.35 + c->x86_num_cores = num_cpu_cores(c); 4.36 + 4.37 detect_ht(c); 4.38 4.39 /* Work around errata */
5.1 --- a/xen/arch/x86/dom0_ops.c Sun Jun 19 16:17:17 2005 +0000 5.2 +++ b/xen/arch/x86/dom0_ops.c Sun Jun 19 16:38:21 2005 +0000 5.3 @@ -179,8 +179,8 @@ long arch_do_dom0_op(dom0_op_t *op, dom0 5.4 { 5.5 dom0_physinfo_t *pi = &op->u.physinfo; 5.6 5.7 - pi->ht_per_core = ht_per_core; 5.8 - pi->cores = num_online_cpus() / ht_per_core; 5.9 + pi->ht_per_core = smp_num_siblings; 5.10 + pi->cores = boot_cpu_data.x86_num_cores; 5.11 pi->total_pages = max_page; 5.12 pi->free_pages = avail_domheap_pages(); 5.13 pi->cpu_khz = cpu_khz;
6.1 --- a/xen/arch/x86/setup.c Sun Jun 19 16:17:17 2005 +0000 6.2 +++ b/xen/arch/x86/setup.c Sun Jun 19 16:38:21 2005 +0000 6.3 @@ -66,7 +66,6 @@ boolean_param("noapic", skip_ioapic_setu 6.4 6.5 int early_boot = 1; 6.6 6.7 -int ht_per_core = 1; 6.8 cpumask_t cpu_present_map; 6.9 6.10 /* Limits of Xen heap, used to initialise the allocator. */
7.1 --- a/xen/arch/x86/smpboot.c Sun Jun 19 16:17:17 2005 +0000 7.2 +++ b/xen/arch/x86/smpboot.c Sun Jun 19 16:38:21 2005 +0000 7.3 @@ -62,6 +62,8 @@ static int __initdata smp_b_stepping; 7.4 int smp_num_siblings = 1; 7.5 int phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */ 7.6 EXPORT_SYMBOL(phys_proc_id); 7.7 +int cpu_core_id[NR_CPUS]; /* Core ID of each logical CPU */ 7.8 +EXPORT_SYMBOL(cpu_core_id); 7.9 7.10 /* bitmap of online cpus */ 7.11 cpumask_t cpu_online_map; 7.12 @@ -923,6 +925,8 @@ static int boot_cpu_logical_apicid; 7.13 void *xquad_portio; 7.14 7.15 cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned; 7.16 +cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned; 7.17 +EXPORT_SYMBOL(cpu_core_map); 7.18 7.19 static void __init smp_boot_cpus(unsigned int max_cpus) 7.20 { 7.21 @@ -947,6 +951,9 @@ static void __init smp_boot_cpus(unsigne 7.22 cpus_clear(cpu_sibling_map[0]); 7.23 cpu_set(0, cpu_sibling_map[0]); 7.24 7.25 + cpus_clear(cpu_core_map[0]); 7.26 + cpu_set(0, cpu_core_map[0]); 7.27 + 7.28 /* 7.29 * If we couldn't find an SMP configuration at boot time, 7.30 * get out of here now! 7.31 @@ -959,6 +966,8 @@ static void __init smp_boot_cpus(unsigne 7.32 printk(KERN_NOTICE "Local APIC not detected." 7.33 " Using dummy APIC emulation.\n"); 7.34 map_cpu_to_logical_apicid(); 7.35 + cpu_set(0, cpu_sibling_map[0]); 7.36 + cpu_set(0, cpu_core_map[0]); 7.37 return; 7.38 } 7.39 7.40 @@ -1079,10 +1088,13 @@ static void __init smp_boot_cpus(unsigne 7.41 * construct cpu_sibling_map[], so that we can tell sibling CPUs 7.42 * efficiently. 7.43 */ 7.44 - for (cpu = 0; cpu < NR_CPUS; cpu++) 7.45 + for (cpu = 0; cpu < NR_CPUS; cpu++) { 7.46 cpus_clear(cpu_sibling_map[cpu]); 7.47 + cpus_clear(cpu_core_map[cpu]); 7.48 + } 7.49 7.50 for (cpu = 0; cpu < NR_CPUS; cpu++) { 7.51 + struct cpuinfo_x86 *c = cpu_data + cpu; 7.52 int siblings = 0; 7.53 int i; 7.54 if (!cpu_isset(cpu, cpu_callout_map)) 7.55 @@ -1092,7 +1104,7 @@ static void __init smp_boot_cpus(unsigne 7.56 for (i = 0; i < NR_CPUS; i++) { 7.57 if (!cpu_isset(i, cpu_callout_map)) 7.58 continue; 7.59 - if (phys_proc_id[cpu] == phys_proc_id[i]) { 7.60 + if (cpu_core_id[cpu] == cpu_core_id[i]) { 7.61 siblings++; 7.62 cpu_set(i, cpu_sibling_map[cpu]); 7.63 } 7.64 @@ -1102,8 +1114,22 @@ static void __init smp_boot_cpus(unsigne 7.65 cpu_set(cpu, cpu_sibling_map[cpu]); 7.66 } 7.67 7.68 - if (siblings != smp_num_siblings) 7.69 + if (siblings != smp_num_siblings) { 7.70 printk(KERN_WARNING "WARNING: %d siblings found for CPU%d, should be %d\n", siblings, cpu, smp_num_siblings); 7.71 + smp_num_siblings = siblings; 7.72 + } 7.73 + 7.74 + if (c->x86_num_cores > 1) { 7.75 + for (i = 0; i < NR_CPUS; i++) { 7.76 + if (!cpu_isset(i, cpu_callout_map)) 7.77 + continue; 7.78 + if (phys_proc_id[cpu] == phys_proc_id[i]) { 7.79 + cpu_set(i, cpu_core_map[cpu]); 7.80 + } 7.81 + } 7.82 + } else { 7.83 + cpu_core_map[cpu] = cpu_sibling_map[cpu]; 7.84 + } 7.85 } 7.86 7.87 if (nmi_watchdog == NMI_LOCAL_APIC)
8.1 --- a/xen/common/dom0_ops.c Sun Jun 19 16:17:17 2005 +0000 8.2 +++ b/xen/common/dom0_ops.c Sun Jun 19 16:38:21 2005 +0000 8.3 @@ -184,8 +184,8 @@ long do_dom0_op(dom0_op_t *u_dom0_op) 8.4 * domains will all share the second HT of each CPU. Since dom0 is on 8.5 * CPU 0, we favour high numbered CPUs in the event of a tie. 8.6 */ 8.7 - pro = ht_per_core - 1; 8.8 - for ( i = pro; i < num_online_cpus(); i += ht_per_core ) 8.9 + pro = smp_num_siblings - 1; 8.10 + for ( i = pro; i < num_online_cpus(); i += smp_num_siblings ) 8.11 if ( cnt[i] <= cnt[pro] ) 8.12 pro = i; 8.13
9.1 --- a/xen/include/asm-x86/processor.h Sun Jun 19 16:17:17 2005 +0000 9.2 +++ b/xen/include/asm-x86/processor.h Sun Jun 19 16:38:21 2005 +0000 9.3 @@ -181,6 +181,7 @@ extern struct cpuinfo_x86 cpu_data[]; 9.4 #endif 9.5 9.6 extern int phys_proc_id[NR_CPUS]; 9.7 +extern int cpu_core_id[NR_CPUS]; 9.8 9.9 extern void identify_cpu(struct cpuinfo_x86 *); 9.10 extern void print_cpu_info(struct cpuinfo_x86 *);
10.1 --- a/xen/include/asm-x86/smp.h Sun Jun 19 16:17:17 2005 +0000 10.2 +++ b/xen/include/asm-x86/smp.h Sun Jun 19 16:38:21 2005 +0000 10.3 @@ -8,6 +8,7 @@ 10.4 #include <xen/config.h> 10.5 #include <xen/kernel.h> 10.6 #include <xen/cpumask.h> 10.7 +#include <asm/current.h> 10.8 #endif 10.9 10.10 #ifdef CONFIG_X86_LOCAL_APIC 10.11 @@ -34,6 +35,7 @@ extern void smp_alloc_memory(void); 10.12 extern int pic_mode; 10.13 extern int smp_num_siblings; 10.14 extern cpumask_t cpu_sibling_map[]; 10.15 +extern cpumask_t cpu_core_map[]; 10.16 10.17 extern void smp_flush_tlb(void); 10.18 extern void smp_invalidate_rcv(void); /* Process an NMI */
11.1 --- a/xen/include/xen/smp.h Sun Jun 19 16:17:17 2005 +0000 11.2 +++ b/xen/include/xen/smp.h Sun Jun 19 16:38:21 2005 +0000 11.3 @@ -58,8 +58,6 @@ static inline int on_each_cpu(void (*fun 11.4 return ret; 11.5 } 11.6 11.7 -extern int ht_per_core; 11.8 - 11.9 extern volatile unsigned long smp_msg_data; 11.10 extern volatile int smp_src_cpu; 11.11 extern volatile int smp_msg_id;