From mboxrd@z Thu Jan 1 00:00:00 1970 From: Wei Huang Subject: Re: [PATCH][RFC][0/2] x86 SMP: enables core-pair topology detection for AMD CPUs Date: Mon, 27 Jun 2011 12:26:05 -0500 Message-ID: <4E08BD2D.9020403@amd.com> References: <4E03C386.9030009@amd.com> <4E0862520200007800049BDB@nat28.tlf.novell.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------040704000108060904050505" Return-path: In-Reply-To: <4E0862520200007800049BDB@nat28.tlf.novell.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xensource.com Errors-To: xen-devel-bounces@lists.xensource.com To: Jan Beulich Cc: George Dunlap , "xen-devel@lists.xensource.com" , Keir Fraser List-Id: xen-devel@lists.xenproject.org --------------040704000108060904050505 Content-Type: text/plain; charset="ISO-8859-1"; format=flowed Content-Transfer-Encoding: 7bit Thanks, Jan and George. I attach the latest version which fixes the indentation issues. -Wei On 06/27/2011 03:58 AM, Jan Beulich wrote: >>>> On 24.06.11 at 00:51, Wei Huang wrote: >> Hi, >> >> The following two patches enable core-pair topology detection for AMD >> CPUs. The main idea is to record compute unit information into >> cpuinfo_x86 and use it when building sibling map. The sibling map will >> be used by Xen credit scheduler to coordinate VCPU scheduling in a >> fashion similar to SMT. This code is very similar to upstream Linux kernel. >> >> Regarding the performance improvement, I saw ~8% improvement running >> kernel compilation on Dom0 with this patch. Anrea Przywara ran a POVRay >> benchmark using this patch and he saw ~5% improvement. No perf >> degradation was seen so far. >> >> Please review. > Apart from some indentation issues these look fine to me. > > Jan > >> Thanks, >> -Wei > > > --------------040704000108060904050505 Content-Type: text/plain; name="core_pair_1.txt" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="core_pair_1.txt" Content-Description: core_pair_1.txt # HG changeset patch # User Wei Huang # Date 1309193579 18000 # Node ID e6c4ff6fcb9fcbf1899463e5ec6c425bcbd683e3 # Parent d3027374a8c0d548c6ff468c4d747300e858904b SMP: consolidate cpu_core_id and phys_proc_id into cpuinfo_x86 struct This patch moves cpu_core_id and phys_proc_id into cpuinfo_x86 structure. This is similar to upstream Linux kernel's approach. Signed-off-by: Wei Huang diff -r d3027374a8c0 -r e6c4ff6fcb9f xen/arch/x86/cpu/amd.c --- a/xen/arch/x86/cpu/amd.c Mon Jun 27 14:48:57 2011 +0100 +++ b/xen/arch/x86/cpu/amd.c Mon Jun 27 11:52:59 2011 -0500 @@ -446,11 +446,11 @@ while ((1 << bits) < c->x86_max_cores) bits++; } - cpu_core_id[cpu] = phys_proc_id[cpu] & ((1<>= bits; + c->cpu_core_id = c->phys_proc_id & ((1<phys_proc_id >>= bits; if (opt_cpu_info) printk("CPU %d(%d) -> Core %d\n", - cpu, c->x86_max_cores, cpu_core_id[cpu]); + cpu, c->x86_max_cores, c->cpu_core_id); } #endif diff -r d3027374a8c0 -r e6c4ff6fcb9f xen/arch/x86/cpu/common.c --- a/xen/arch/x86/cpu/common.c Mon Jun 27 14:48:57 2011 +0100 +++ b/xen/arch/x86/cpu/common.c Mon Jun 27 11:52:59 2011 -0500 @@ -271,7 +271,7 @@ early_intel_workaround(c); #ifdef CONFIG_X86_HT - phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff; + c->phys_proc_id = (cpuid_ebx(1) >> 24) & 0xff; #endif } @@ -316,6 +316,8 @@ c->x86_max_cores = 1; c->x86_num_siblings = 1; c->x86_clflush_size = 0; + c->phys_proc_id = BAD_APICID; + c->cpu_core_id = BAD_APICID; memset(&c->x86_capability, 0, sizeof c->x86_capability); generic_identify(c); @@ -453,7 +455,6 @@ unsigned int ht_mask_width, core_plus_mask_width; unsigned int core_select_mask, core_level_siblings; unsigned int initial_apicid; - int cpu = smp_processor_id(); if ( c->cpuid_level < 0xb ) return; @@ -488,9 +489,9 @@ core_select_mask = (~(-1 << core_plus_mask_width)) >> ht_mask_width; - cpu_core_id[cpu] = phys_pkg_id(initial_apicid, ht_mask_width) + c->cpu_core_id = phys_pkg_id(initial_apicid, ht_mask_width) & core_select_mask; - phys_proc_id[cpu] = phys_pkg_id(initial_apicid, core_plus_mask_width); + c->phys_proc_id = phys_pkg_id(initial_apicid, core_plus_mask_width); c->apicid = phys_pkg_id(initial_apicid, 0); c->x86_max_cores = (core_level_siblings / c->x86_num_siblings); @@ -498,10 +499,10 @@ if ( opt_cpu_info ) { printk("CPU: Physical Processor ID: %d\n", - phys_proc_id[cpu]); + c->phys_proc_id); if ( c->x86_max_cores > 1 ) printk("CPU: Processor Core ID: %d\n", - cpu_core_id[cpu]); + c->cpu_core_id); } } @@ -510,7 +511,6 @@ { u32 eax, ebx, ecx, edx; int index_msb, core_bits; - int cpu = smp_processor_id(); cpuid(1, &eax, &ebx, &ecx, &edx); @@ -533,11 +533,11 @@ } index_msb = get_count_order(c->x86_num_siblings); - phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb); + c->phys_proc_id = phys_pkg_id((ebx >> 24) & 0xFF, index_msb); if (opt_cpu_info) printk("CPU: Physical Processor ID: %d\n", - phys_proc_id[cpu]); + c->phys_proc_id); c->x86_num_siblings = c->x86_num_siblings / c->x86_max_cores; @@ -545,12 +545,12 @@ core_bits = get_count_order(c->x86_max_cores); - cpu_core_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb) & + c->cpu_core_id = phys_pkg_id((ebx >> 24) & 0xFF, index_msb) & ((1 << core_bits) - 1); if (opt_cpu_info && c->x86_max_cores > 1) printk("CPU: Processor Core ID: %d\n", - cpu_core_id[cpu]); + c->cpu_core_id); } } #endif diff -r d3027374a8c0 -r e6c4ff6fcb9f xen/arch/x86/cpu/mcheck/mce.c --- a/xen/arch/x86/cpu/mcheck/mce.c Mon Jun 27 14:48:57 2011 +0100 +++ b/xen/arch/x86/cpu/mcheck/mce.c Mon Jun 27 11:52:59 2011 -0500 @@ -1046,9 +1046,9 @@ if (nthreads != NULL) *nthreads = 1; } else { - *chipid = phys_proc_id[cpu]; + *chipid = c->phys_proc_id; if (c->x86_max_cores > 1) - *coreid = cpu_core_id[cpu]; + *coreid = c->cpu_core_id; else *coreid = 0; *threadid = c->apicid & ((1 << (c->x86_num_siblings - 1)) - 1); diff -r d3027374a8c0 -r e6c4ff6fcb9f xen/arch/x86/smpboot.c --- a/xen/arch/x86/smpboot.c Mon Jun 27 14:48:57 2011 +0100 +++ b/xen/arch/x86/smpboot.c Mon Jun 27 11:52:59 2011 -0500 @@ -49,12 +49,6 @@ #define setup_trampoline() (bootsym_phys(trampoline_realmode_entry)) -/* Package ID of each logical CPU */ -int phys_proc_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID}; - -/* Core ID of each logical CPU */ -int cpu_core_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID}; - /* representing HT siblings of each logical CPU */ DEFINE_PER_CPU_READ_MOSTLY(cpumask_t, cpu_sibling_map); /* representing HT and core siblings of each logical CPU */ @@ -247,8 +241,8 @@ { for_each_cpu_mask ( i, cpu_sibling_setup_map ) { - if ( (phys_proc_id[cpu] == phys_proc_id[i]) && - (cpu_core_id[cpu] == cpu_core_id[i]) ) + if ( (c[cpu].phys_proc_id == c[i].phys_proc_id) && + (c[cpu].cpu_core_id == c[i].cpu_core_id) ) { cpu_set(i, per_cpu(cpu_sibling_map, cpu)); cpu_set(cpu, per_cpu(cpu_sibling_map, i)); @@ -271,7 +265,7 @@ for_each_cpu_mask ( i, cpu_sibling_setup_map ) { - if ( phys_proc_id[cpu] == phys_proc_id[i] ) + if ( c[cpu].phys_proc_id == c[i].phys_proc_id ) { cpu_set(i, per_cpu(cpu_core_map, cpu)); cpu_set(cpu, per_cpu(cpu_core_map, i)); @@ -832,8 +826,8 @@ cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling)); cpus_clear(per_cpu(cpu_sibling_map, cpu)); cpus_clear(per_cpu(cpu_core_map, cpu)); - phys_proc_id[cpu] = BAD_APICID; - cpu_core_id[cpu] = BAD_APICID; + c[cpu].phys_proc_id = BAD_APICID; + c[cpu].cpu_core_id = BAD_APICID; cpu_clear(cpu, cpu_sibling_setup_map); } diff -r d3027374a8c0 -r e6c4ff6fcb9f xen/include/asm-x86/processor.h --- a/xen/include/asm-x86/processor.h Mon Jun 27 14:48:57 2011 +0100 +++ b/xen/include/asm-x86/processor.h Mon Jun 27 11:52:59 2011 -0500 @@ -175,6 +175,8 @@ __u32 x86_max_cores; /* cpuid returned max cores value */ __u32 booted_cores; /* number of cores as seen by OS */ __u32 x86_num_siblings; /* cpuid logical cpus per chip value */ + int phys_proc_id; /* package ID of each logical CPU */ + int cpu_core_id; /* core ID of each logical CPU*/ __u32 apicid; unsigned short x86_clflush_size; } __cacheline_aligned; @@ -194,8 +196,6 @@ #endif extern u64 host_pat; -extern int phys_proc_id[NR_CPUS]; -extern int cpu_core_id[NR_CPUS]; extern bool_t opt_cpu_info; /* Maximum width of physical addresses supported by the hardware */ @@ -215,8 +215,8 @@ static always_inline void detect_ht(struct cpuinfo_x86 *c) {} #endif -#define cpu_to_core(_cpu) (cpu_core_id[_cpu]) -#define cpu_to_socket(_cpu) (phys_proc_id[_cpu]) +#define cpu_to_core(_cpu) (cpu_data[_cpu].cpu_core_id) +#define cpu_to_socket(_cpu) (cpu_data[_cpu].phys_proc_id) /* * Generic CPUID function --------------040704000108060904050505 Content-Type: text/plain; name="core_pair_2.txt" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="core_pair_2.txt" Content-Description: core_pair_2.txt # HG changeset patch # User Wei Huang # Date 1309193845 18000 # Node ID 4d928bdd56769eb8b09eefd5db80400e1c6c818a # Parent e6c4ff6fcb9fcbf1899463e5ec6c425bcbd683e3 x86: AMD core-pair topology detection code This patch is to support core-pair topology introduced by AMD CPUs, which introduces a new concept of [core, compute unit]. There is a new feature bit for topology extension in CPUID:0x80000001. Also a new CPUID 0x8000001E is introduced for CPU topology enumeration. This patch collects the sibling information from the new CPUID and will be stored in the sibling map in Xen hypervisor. Signed-off-by: Wei Huang diff -r e6c4ff6fcb9f -r 4d928bdd5676 xen/arch/x86/cpu/amd.c --- a/xen/arch/x86/cpu/amd.c Mon Jun 27 11:52:59 2011 -0500 +++ b/xen/arch/x86/cpu/amd.c Mon Jun 27 11:57:25 2011 -0500 @@ -326,6 +326,49 @@ wrmsrl(MSR_K8_SYSCFG, syscfg); } +static void __devinit amd_get_topology(struct cpuinfo_x86 *c) +{ +#ifdef CONFIG_X86_HT + int cpu; + unsigned bits; + + if (c->x86_max_cores <= 1) + return; + /* + * On a AMD multi core setup the lower bits of the APIC id + * distingush the cores. + */ + cpu = smp_processor_id(); + bits = (cpuid_ecx(0x80000008) >> 12) & 0xf; + + if (bits == 0) { + while ((1 << bits) < c->x86_max_cores) + bits++; + } + + /* Low order bits define the core id */ + c->cpu_core_id = c->phys_proc_id & ((1<phys_proc_id >>= bits; + /* Collect compute unit ID if available */ + if (cpu_has(c, X86_FEATURE_TOPOEXT)) { + u32 eax, ebx, ecx, edx; + + cpuid(0x8000001e, &eax, &ebx, &ecx, &edx); + c->compute_unit_id = ebx & 0xFF; + c->x86_num_siblings = ((ebx >> 8) & 0x3) + 1; + } + + if (opt_cpu_info) + printk("CPU %d(%d) -> Processor %d, %s %d\n", + cpu, c->x86_max_cores, c->phys_proc_id, + cpu_has(c, X86_FEATURE_TOPOEXT) ? "Compute Unit" : + "Core", + cpu_has(c, X86_FEATURE_TOPOEXT) ? c->compute_unit_id : + c->cpu_core_id); +#endif +} + static void __devinit init_amd(struct cpuinfo_x86 *c) { u32 l, h; @@ -433,26 +476,7 @@ } } -#ifdef CONFIG_X86_HT - /* - * On a AMD multi core setup the lower bits of the APIC id - * distingush the cores. - */ - if (c->x86_max_cores > 1) { - int cpu = smp_processor_id(); - unsigned bits = (cpuid_ecx(0x80000008) >> 12) & 0xf; - - if (bits == 0) { - while ((1 << bits) < c->x86_max_cores) - bits++; - } - c->cpu_core_id = c->phys_proc_id & ((1<phys_proc_id >>= bits; - if (opt_cpu_info) - printk("CPU %d(%d) -> Core %d\n", - cpu, c->x86_max_cores, c->cpu_core_id); - } -#endif + amd_get_topology(c); /* Pointless to use MWAIT on Family10 as it does not deep sleep. */ if (c->x86 >= 0x10 && !force_mwait) diff -r e6c4ff6fcb9f -r 4d928bdd5676 xen/arch/x86/cpu/common.c --- a/xen/arch/x86/cpu/common.c Mon Jun 27 11:52:59 2011 -0500 +++ b/xen/arch/x86/cpu/common.c Mon Jun 27 11:57:25 2011 -0500 @@ -318,6 +318,7 @@ c->x86_clflush_size = 0; c->phys_proc_id = BAD_APICID; c->cpu_core_id = BAD_APICID; + c->compute_unit_id = BAD_APICID; memset(&c->x86_capability, 0, sizeof c->x86_capability); generic_identify(c); diff -r e6c4ff6fcb9f -r 4d928bdd5676 xen/arch/x86/smpboot.c --- a/xen/arch/x86/smpboot.c Mon Jun 27 11:52:59 2011 -0500 +++ b/xen/arch/x86/smpboot.c Mon Jun 27 11:57:25 2011 -0500 @@ -230,6 +230,14 @@ /* CPUs for which sibling maps can be computed. */ static cpumask_t cpu_sibling_setup_map; +static void link_thread_siblings(int cpu1, int cpu2) +{ + cpu_set(cpu1, per_cpu(cpu_sibling_map, cpu2)); + cpu_set(cpu2, per_cpu(cpu_sibling_map, cpu1)); + cpu_set(cpu1, per_cpu(cpu_core_map, cpu2)); + cpu_set(cpu2, per_cpu(cpu_core_map, cpu1)); +} + static void set_cpu_sibling_map(int cpu) { int i; @@ -241,13 +249,13 @@ { for_each_cpu_mask ( i, cpu_sibling_setup_map ) { - if ( (c[cpu].phys_proc_id == c[i].phys_proc_id) && - (c[cpu].cpu_core_id == c[i].cpu_core_id) ) - { - cpu_set(i, per_cpu(cpu_sibling_map, cpu)); - cpu_set(cpu, per_cpu(cpu_sibling_map, i)); - cpu_set(i, per_cpu(cpu_core_map, cpu)); - cpu_set(cpu, per_cpu(cpu_core_map, i)); + if ( cpu_has(c, X86_FEATURE_TOPOEXT) ) { + if ( (c[cpu].phys_proc_id == c[i].phys_proc_id) && + (c[cpu].compute_unit_id == c[i].compute_unit_id) ) + link_thread_siblings(cpu, i); + } else if ( (c[cpu].phys_proc_id == c[i].phys_proc_id) && + (c[cpu].cpu_core_id == c[i].cpu_core_id) ) { + link_thread_siblings(cpu, i); } } } @@ -828,6 +836,7 @@ cpus_clear(per_cpu(cpu_core_map, cpu)); c[cpu].phys_proc_id = BAD_APICID; c[cpu].cpu_core_id = BAD_APICID; + c[cpu].compute_unit_id = BAD_APICID; cpu_clear(cpu, cpu_sibling_setup_map); } diff -r e6c4ff6fcb9f -r 4d928bdd5676 xen/include/asm-x86/processor.h --- a/xen/include/asm-x86/processor.h Mon Jun 27 11:52:59 2011 -0500 +++ b/xen/include/asm-x86/processor.h Mon Jun 27 11:57:25 2011 -0500 @@ -175,9 +175,10 @@ __u32 x86_max_cores; /* cpuid returned max cores value */ __u32 booted_cores; /* number of cores as seen by OS */ __u32 x86_num_siblings; /* cpuid logical cpus per chip value */ + __u32 apicid; int phys_proc_id; /* package ID of each logical CPU */ int cpu_core_id; /* core ID of each logical CPU*/ - __u32 apicid; + int compute_unit_id; /* AMD compute unit ID of each logical CPU */ unsigned short x86_clflush_size; } __cacheline_aligned; --------------040704000108060904050505 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel --------------040704000108060904050505--