ia64/xen-unstable

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>
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;