From owner-freebsd-amd64@FreeBSD.ORG Thu May 19 00:07:37 2005 Return-Path: Delivered-To: freebsd-amd64@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 3FF5116A4CE; Thu, 19 May 2005 00:07:37 +0000 (GMT) Received: from anuket.mj.niksun.com (gwnew.niksun.com [65.115.46.162]) by mx1.FreeBSD.org (Postfix) with ESMTP id 7E77743D8D; Thu, 19 May 2005 00:07:36 +0000 (GMT) (envelope-from jkim@niksun.com) Received: from [10.70.0.244] (daemon.mj.niksun.com [10.70.0.244]) by anuket.mj.niksun.com (8.13.1/8.13.1) with ESMTP id j4J09R7m008757; Wed, 18 May 2005 20:09:29 -0400 (EDT) (envelope-from jkim@niksun.com) From: Jung-uk Kim Organization: Niksun, Inc. To: freebsd-amd64@freebsd.org Date: Wed, 18 May 2005 20:07:28 -0400 User-Agent: KMail/1.6.2 References: <428B6FC1.3000907@fsn.hu> <200505181453.49988.jkim@niksun.com> <200505181935.18493.jkim@niksun.com> In-Reply-To: <200505181935.18493.jkim@niksun.com> MIME-Version: 1.0 Content-Disposition: inline Content-Type: Multipart/Mixed; boundary="Boundary-00=_Aj9iC8GacVFVVEU" Message-Id: <200505182007.28631.jkim@niksun.com> X-Virus-Scanned: ClamAV 0.83/880/Mon May 16 11:00:02 2005 on anuket.mj.niksun.com X-Virus-Status: Clean cc: Pav Lucistnik Subject: Re: AMD64 multicore (Was: Re: FreeBSD on dual core Opterons - stupid buildworld test) X-BeenThere: freebsd-amd64@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Porting FreeBSD to the AMD64 platform List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 19 May 2005 00:07:37 -0000 --Boundary-00=_Aj9iC8GacVFVVEU Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Content-Disposition: inline On Wednesday 18 May 2005 07:35 pm, Jung-uk Kim wrote: > The attachment (against -CURRENT) is my attempt to 'do the right > thing' by the above manual. I did very light testing because I > don't have a dual-core proc. Can you test, please? Bah, I screwed up the diff. Please try this one. Sorry, Jung-uk Kim > Thanks, > > Jung-uk Kim --Boundary-00=_Aj9iC8GacVFVVEU Content-Type: text/x-diff; charset="utf-8"; name="multicore.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="multicore.diff" Index: sys/amd64/amd64/identcpu.c =================================================================== RCS file: /home/ncvs/src/sys/amd64/amd64/identcpu.c,v retrieving revision 1.135 diff -u -r1.135 identcpu.c --- sys/amd64/amd64/identcpu.c 21 Jan 2005 05:56:40 -0000 1.135 +++ sys/amd64/amd64/identcpu.c 18 May 2005 23:16:09 -0000 @@ -283,13 +283,53 @@ "\0403DNow" /* AMD 3DNow! */ ); } + if (amd_feature2 != 0) { + printf("\n AMD Features2=0x%b", amd_feature2, + "\020" + "\001LAHF" /* LAHF/SAHF in long mode */ + "\002CMP" /* CMP legacy */ + "\003" + "\004" + "\005CR8" /* CR8 in legacy mode */ + "\006" + "\007" + "\010" + "\011" + "\012" + "\013" + "\014" + "\015" + "\016" + "\017" + "\020" + "\021" + "\022" + "\023" + "\024" + "\025" + "\026" + "\027" + "\030" + "\031" + "\032" + "\033" + "\034" + "\035" + "\036" + "\037" + "\040" + ); + } /* * If this CPU supports hyperthreading then mention * the number of logical CPU's it contains. */ if (cpu_feature & CPUID_HTT && - (cpu_procinfo & CPUID_HTT_CORES) >> 16 > 1) + (cpu_procinfo & CPUID_HTT_CORES) >> 16 > 1 && + (strcmp(cpu_vendor, "GenuineIntel") == 0 || + (strcmp(cpu_vendor, "AuthenticAMD") == 0 && + !(amd_feature2 & AMDID2_CMP)))) printf("\n Hyperthreading: %d logical CPUs", (cpu_procinfo & CPUID_HTT_CORES) >> 16); } @@ -357,6 +397,11 @@ if (cpu_exthigh >= 0x80000001) { do_cpuid(0x80000001, regs); amd_feature = regs[3] & ~(cpu_feature & 0x0183f3ff); + amd_feature2 = regs[2] & 0x00000013; + } + if (cpu_exthigh >= 0x80000008) { + do_cpuid(0x80000008, regs); + cpu_procinfo2 = regs[2]; } /* XXX */ Index: sys/amd64/amd64/initcpu.c =================================================================== RCS file: /home/ncvs/src/sys/amd64/amd64/initcpu.c,v retrieving revision 1.48 diff -u -r1.48 initcpu.c --- sys/amd64/amd64/initcpu.c 8 Jun 2004 01:02:51 -0000 1.48 +++ sys/amd64/amd64/initcpu.c 18 May 2005 23:16:09 -0000 @@ -51,11 +51,13 @@ int cpu; /* Are we 386, 386sx, 486, etc? */ u_int cpu_feature; /* Feature flags */ u_int cpu_feature2; /* Feature flags */ -u_int amd_feature; /* Feature flags */ +u_int amd_feature; /* AMD Feature flags */ +u_int amd_feature2; /* AMD Feature flags */ u_int cpu_high; /* Highest arg to CPUID */ u_int cpu_exthigh; /* Highest arg to extended CPUID */ u_int cpu_id; /* Stepping ID */ u_int cpu_procinfo; /* HyperThreading Info / Brand Index / CLFUSH */ +u_int cpu_procinfo2; /* Multicore info */ char cpu_vendor[20]; /* CPU Origin code */ u_int cpu_fxsr; /* SSE enabled */ Index: sys/amd64/amd64/mp_machdep.c =================================================================== RCS file: /home/ncvs/src/sys/amd64/amd64/mp_machdep.c,v retrieving revision 1.255 diff -u -r1.255 mp_machdep.c --- sys/amd64/amd64/mp_machdep.c 13 May 2005 00:57:04 -0000 1.255 +++ sys/amd64/amd64/mp_machdep.c 18 May 2005 23:16:09 -0000 @@ -168,7 +168,13 @@ /* Nothing to do if there is no HTT support. */ if ((cpu_feature & CPUID_HTT) == 0) return; - logical_cpus = (cpu_procinfo & CPUID_HTT_CORES) >> 16; + if (strcmp(cpu_vendor, "AuthenticAMD") == 0) { + if (amd_feature2 & AMDID2_CMP) + logical_cpus = (cpu_procinfo2 & AMDID_CMP_CORES) + 1; + else + logical_cpus = (cpu_procinfo & CPUID_HTT_CORES) >> 16; + } else + logical_cpus = (cpu_procinfo & CPUID_HTT_CORES) >> 16; if (logical_cpus <= 1) return; group = &mp_groups[0]; @@ -353,37 +359,41 @@ * At the time of writing (May 12, 2005) the only hyperthreaded * cpus are from Intel, and Intel's dual-core processors can be * identified via the "deterministic cache parameters" cpuid - * calls. + * calls. AMD's hyperthreaded cpus can be identified via the + * "CMP legacy" cpuid call. */ - /* - * First determine if this is an Intel processor which claims - * to have hyperthreading support. - */ - if ((cpu_feature & CPUID_HTT) && - (strcmp(cpu_vendor, "GenuineIntel") == 0)) { - /* - * If the "deterministic cache parameters" cpuid calls - * are available, use them. - */ - if (cpu_high >= 4) { - /* Ask the processor about up to 32 caches. */ - for (i = 0; i < 32; i++) { - cpuid_count(4, i, p); - threads_per_cache = ((p[0] & 0x3ffc000) >> 14) + 1; - if (hyperthreading_cpus < threads_per_cache) - hyperthreading_cpus = threads_per_cache; - if ((p[0] & 0x1f) == 0) - break; + if (cpu_feature & CPUID_HTT) { + if (strcmp(cpu_vendor, "AuthenticAMD") == 0) { + if (!(amd_feature2 & AMDID2_CMP)) + hyperthreading_cpus = logical_cpus; + } else if (strcmp(cpu_vendor, "GenuineIntel") == 0) { + /* + * If the "deterministic cache parameters" cpuid + * calls are available, use them. + */ + if (cpu_high >= 4) { + /* Ask the processor about up to 32 caches. */ + for (i = 0; i < 32; i++) { + cpuid_count(4, i, p); + threads_per_cache = + ((p[0] & 0x3ffc000) >> 14) + 1; + if (hyperthreading_cpus < + threads_per_cache) + hyperthreading_cpus = + threads_per_cache; + if ((p[0] & 0x1f) == 0) + break; + } } - } - /* - * If the deterministic cache parameters are not - * available, or if no caches were reported to exist, - * just accept what the HTT flag indicated. - */ - if (hyperthreading_cpus == 0) - hyperthreading_cpus = logical_cpus; + /* + * If the deterministic cache parameters are not + * available, or if no caches were reported to exist, + * just accept what the HTT flag indicated. + */ + if (hyperthreading_cpus == 0) + hyperthreading_cpus = logical_cpus; + } } set_logical_apic_ids(); Index: sys/amd64/include/md_var.h =================================================================== RCS file: /home/ncvs/src/sys/amd64/include/md_var.h,v retrieving revision 1.75 diff -u -r1.75 md_var.h --- sys/amd64/include/md_var.h 10 Jun 2004 20:30:55 -0000 1.75 +++ sys/amd64/include/md_var.h 18 May 2005 23:16:09 -0000 @@ -43,10 +43,12 @@ extern u_int cpu_feature; extern u_int cpu_feature2; extern u_int amd_feature; +extern u_int amd_feature2; extern u_int cpu_fxsr; extern u_int cpu_high; extern u_int cpu_id; extern u_int cpu_procinfo; +extern u_int cpu_procinfo2; extern char cpu_vendor[]; extern char kstack[]; extern char sigcode[]; Index: sys/amd64/include/specialreg.h =================================================================== RCS file: /home/ncvs/src/sys/amd64/include/specialreg.h,v retrieving revision 1.30 diff -u -r1.30 specialreg.h --- sys/amd64/include/specialreg.h 8 Jun 2004 01:02:52 -0000 1.30 +++ sys/amd64/include/specialreg.h 18 May 2005 23:16:09 -0000 @@ -128,6 +128,8 @@ #define AMDID_NX 0x00100000 #define AMDID_LM 0x20000000 +#define AMDID2_CMP 0x00000002 + /* * CPUID instruction 1 ebx info */ @@ -137,6 +139,11 @@ #define CPUID_LOCAL_APIC_ID 0xff000000 /* + * AMD extended function 8000_0008h ecx info + */ +#define AMDID_CMP_CORES 0x000000ff + +/* * Model-specific registers for the i386 family */ #define MSR_P5_MC_ADDR 0x000 Index: sys/i386/i386/identcpu.c =================================================================== RCS file: /home/ncvs/src/sys/i386/i386/identcpu.c,v retrieving revision 1.143 diff -u -r1.143 identcpu.c --- sys/i386/i386/identcpu.c 16 May 2005 09:47:53 -0000 1.143 +++ sys/i386/i386/identcpu.c 18 May 2005 23:16:10 -0000 @@ -730,7 +739,10 @@ * the number of logical CPU's it contains. */ if (cpu_feature & CPUID_HTT && - (cpu_procinfo & CPUID_HTT_CORES) >> 16 > 1) + (cpu_procinfo & CPUID_HTT_CORES) >> 16 > 1 && + (strcmp(cpu_vendor, "GenuineIntel") == 0 || + (strcmp(cpu_vendor, "AuthenticAMD") == 0 && + !(amd_feature2 & AMDID2_CMP)))) printf("\n Hyperthreading: %d logical CPUs", (cpu_procinfo & CPUID_HTT_CORES) >> 16); } @@ -943,7 +955,17 @@ u_char ccr3; u_int regs[4]; - if (strcmp(cpu_vendor, "CyrixInstead") == 0) { + if (strcmp(cpu_vendor, "AuthenticAMD") == 0) { + if (cpu_exthigh >= 0x80000001) { + do_cpuid(0x80000001, regs); + amd_feature = regs[3] & ~(cpu_feature & 0x0183f3ff); + amd_feature2 = regs[2] & 0x00000013; + } + if (cpu_exthigh >= 0x80000008) { + do_cpuid(0x80000008, regs); + cpu_procinfo2 = regs[2]; + } + } else if (strcmp(cpu_vendor, "CyrixInstead") == 0) { if (cpu == CPU_486) { /* * These conditions are equivalent to: @@ -1105,48 +1127,87 @@ static void print_AMD_features(void) { - u_int regs[4]; - /* * Values taken from AMD Processor Recognition * http://www.amd.com/products/cpg/athlon/techdocs/pdf/20734.pdf */ - do_cpuid(0x80000001, regs); - printf("\n AMD Features=0x%b", regs[3] &~ cpu_feature, - "\020" /* in hex */ - "\001FPU" /* Integral FPU */ - "\002VME" /* Extended VM86 mode support */ - "\003DE" /* Debug extensions */ - "\004PSE" /* 4MByte page tables */ - "\005TSC" /* Timestamp counter */ - "\006MSR" /* Machine specific registers */ - "\007PAE" /* Physical address extension */ - "\010MCE" /* Machine Check support */ - "\011CX8" /* CMPEXCH8 instruction */ - "\012APIC" /* SMP local APIC */ - "\013" - "\014SYSCALL" /* SYSENTER/SYSEXIT instructions */ - "\015MTRR" /* Memory Type Range Registers */ - "\016PGE" /* PG_G (global bit) support */ - "\017MCA" /* Machine Check Architecture */ - "\020ICMOV" /* CMOV instruction */ - "\021PAT" /* Page attributes table */ - "\022PGE36" /* 36 bit address space support */ - "\023RSVD" /* Reserved, unknown */ - "\024MP" /* Multiprocessor Capable */ - "\025NX" /* Has EFER.NXE, NX (no execute pte bit) */ - "\026" - "\027AMIE" /* AMD MMX Instruction Extensions */ - "\030MMX" - "\031FXSAVE" /* FXSAVE/FXRSTOR */ - "\032" - "\033" - "\034" - "\035" - "\036LM" /* Long mode */ - "\037DSP" /* AMD 3DNow! Instruction Extensions */ - "\0403DNow!" /* AMD 3DNow! Instructions */ - ); + if (amd_feature != 0) + printf("\n AMD Features=0x%b", amd_feature, + "\020" /* in hex */ + "\001FPU" /* Integral FPU */ + "\002VME" /* Extended VM86 mode support */ + "\003DE" /* Debug extensions */ + "\004PSE" /* 4MByte page tables */ + "\005TSC" /* Timestamp counter */ + "\006MSR" /* Machine specific registers */ + "\007PAE" /* Physical address extension */ + "\010MCE" /* Machine Check support */ + "\011CX8" /* CMPEXCH8 instruction */ + "\012APIC" /* SMP local APIC */ + "\013" + "\014SYSCALL" /* SYSENTER/SYSEXIT instructions */ + "\015MTRR" /* Memory Type Range Registers */ + "\016PGE" /* PG_G (global bit) support */ + "\017MCA" /* Machine Check Architecture */ + "\020ICMOV" /* CMOV instruction */ + "\021PAT" /* Page attributes table */ + "\022PGE36" /* 36 bit address space support */ + "\023RSVD" /* Reserved, unknown */ + "\024MP" /* Multiprocessor Capable */ + "\025NX" /* Has EFER.NXE, NX (no execute pte bit) */ + "\026" + "\027AMIE" /* AMD MMX Instruction Extensions */ + "\030MMX" + "\031FXSAVE" /* FXSAVE/FXRSTOR */ + "\032" + "\033" + "\034" + "\035" + "\036LM" /* Long mode */ + "\037DSP" /* AMD 3DNow! Instruction Extensions */ + "\0403DNow!" /* AMD 3DNow! Instructions */ + ); + /* + * AMD64 Architecture Programmer's Manual Volume 3: + * General-Purpose and System Instructions + * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/24594.pdf + */ + if (amd_feature2 != 0) + printf("\n AMD Features2=0x%b", amd_feature2, + "\020" + "\001LAHF" /* LAHF/SAHF in long mode */ + "\002CMP" /* CMP legacy */ + "\003" + "\004" + "\005CR8" /* CR8 in legacy mode */ + "\006" + "\007" + "\010" + "\011" + "\012" + "\013" + "\014" + "\015" + "\016" + "\017" + "\020" + "\021" + "\022" + "\023" + "\024" + "\025" + "\026" + "\027" + "\030" + "\031" + "\032" + "\033" + "\034" + "\035" + "\036" + "\037" + "\040" + ); } #endif Index: sys/i386/i386/initcpu.c =================================================================== RCS file: /home/ncvs/src/sys/i386/i386/initcpu.c,v retrieving revision 1.50 diff -u -r1.50 initcpu.c --- sys/i386/i386/initcpu.c 16 May 2005 09:47:53 -0000 1.50 +++ sys/i386/i386/initcpu.c 18 May 2005 23:16:10 -0000 @@ -80,9 +80,12 @@ int cpu = 0; /* Are we 386, 386sx, 486, etc? */ u_int cpu_feature = 0; /* Feature flags */ u_int cpu_feature2 = 0; /* Feature flags */ +u_int amd_feature = 0; /* AMD Feature flags */ +u_int amd_feature2 = 0; /* AMD Feature flags */ u_int cpu_high = 0; /* Highest arg to CPUID */ u_int cpu_id = 0; /* Stepping ID */ u_int cpu_procinfo = 0; /* HyperThreading Info / Brand Index / CLFUSH */ +u_int cpu_procinfo2 = 0; /* Multicore info */ char cpu_vendor[20] = ""; /* CPU Origin code */ #ifdef CPU_ENABLE_SSE Index: sys/i386/i386/mp_machdep.c =================================================================== RCS file: /home/ncvs/src/sys/i386/i386/mp_machdep.c,v retrieving revision 1.249 diff -u -r1.249 mp_machdep.c --- sys/i386/i386/mp_machdep.c 13 May 2005 00:57:04 -0000 1.249 +++ sys/i386/i386/mp_machdep.c 18 May 2005 23:16:10 -0000 @@ -239,7 +239,13 @@ /* Nothing to do if there is no HTT support. */ if ((cpu_feature & CPUID_HTT) == 0) return; - logical_cpus = (cpu_procinfo & CPUID_HTT_CORES) >> 16; + if (strcmp(cpu_vendor, "AuthenticAMD") == 0) { + if (amd_feature2 & AMDID2_CMP) + logical_cpus = (cpu_procinfo2 & AMDID_CMP_CORES) + 1; + else + logical_cpus = (cpu_procinfo & CPUID_HTT_CORES) >> 16; + } else + logical_cpus = (cpu_procinfo & CPUID_HTT_CORES) >> 16; if (logical_cpus <= 1) return; group = &mp_groups[0]; @@ -414,37 +420,41 @@ * At the time of writing (May 12, 2005) the only hyperthreaded * cpus are from Intel, and Intel's dual-core processors can be * identified via the "deterministic cache parameters" cpuid - * calls. + * calls. AMD's hyperthreaded cpus can be identified via the + * "CMP legacy" cpuid call. */ - /* - * First determine if this is an Intel processor which claims - * to have hyperthreading support. - */ - if ((cpu_feature & CPUID_HTT) && - (strcmp(cpu_vendor, "GenuineIntel") == 0)) { - /* - * If the "deterministic cache parameters" cpuid calls - * are available, use them. - */ - if (cpu_high >= 4) { - /* Ask the processor about up to 32 caches. */ - for (i = 0; i < 32; i++) { - cpuid_count(4, i, p); - threads_per_cache = ((p[0] & 0x3ffc000) >> 14) + 1; - if (hyperthreading_cpus < threads_per_cache) - hyperthreading_cpus = threads_per_cache; - if ((p[0] & 0x1f) == 0) - break; + if (cpu_feature & CPUID_HTT) { + if (strcmp(cpu_vendor, "AuthenticAMD") == 0) { + if (!(amd_feature2 & AMDID2_CMP)) + hyperthreading_cpus = logical_cpus; + } else if (strcmp(cpu_vendor, "GenuineIntel") == 0) { + /* + * If the "deterministic cache parameters" cpuid + * calls are available, use them. + */ + if (cpu_high >= 4) { + /* Ask the processor about up to 32 caches. */ + for (i = 0; i < 32; i++) { + cpuid_count(4, i, p); + threads_per_cache = + ((p[0] & 0x3ffc000) >> 14) + 1; + if (hyperthreading_cpus < + threads_per_cache) + hyperthreading_cpus = + threads_per_cache; + if ((p[0] & 0x1f) == 0) + break; + } } - } - /* - * If the deterministic cache parameters are not - * available, or if no caches were reported to exist, - * just accept what the HTT flag indicated. - */ - if (hyperthreading_cpus == 0) - hyperthreading_cpus = logical_cpus; + /* + * If the deterministic cache parameters are not + * available, or if no caches were reported to exist, + * just accept what the HTT flag indicated. + */ + if (hyperthreading_cpus == 0) + hyperthreading_cpus = logical_cpus; + } } set_logical_apic_ids(); Index: sys/i386/include/md_var.h =================================================================== RCS file: /home/ncvs/src/sys/i386/include/md_var.h,v retrieving revision 1.71 diff -u -r1.71 md_var.h --- sys/i386/include/md_var.h 16 May 2005 09:47:53 -0000 1.71 +++ sys/i386/include/md_var.h 18 May 2005 23:16:10 -0000 @@ -46,10 +46,11 @@ extern int busdma_swi_pending; extern u_int cpu_exthigh; extern u_int cpu_feature, cpu_feature2; +extern u_int amd_feature, amd_feature2; extern u_int cpu_fxsr; extern u_int cpu_high; extern u_int cpu_id; -extern u_int cpu_procinfo; +extern u_int cpu_procinfo, cpu_procinfo2; extern char cpu_vendor[]; extern u_int cyrix_did; extern char kstack[]; Index: sys/i386/include/specialreg.h =================================================================== RCS file: /home/ncvs/src/sys/i386/include/specialreg.h,v retrieving revision 1.27 diff -u -r1.27 specialreg.h --- sys/i386/include/specialreg.h 7 Apr 2004 20:46:05 -0000 1.27 +++ sys/i386/include/specialreg.h 18 May 2005 23:16:10 -0000 @@ -108,6 +108,16 @@ #define CPUID_PBE 0x80000000 /* + * Important bits in the AMD extended cpuid flags + */ +#define AMDID_SYSCALL 0x00000800 +#define AMDID_MP 0x00080000 +#define AMDID_NX 0x00100000 +#define AMDID_LM 0x20000000 + +#define AMDID2_CMP 0x00000002 + +/* * CPUID instruction 1 ebx info */ #define CPUID_BRAND_INDEX 0x000000ff @@ -116,6 +126,11 @@ #define CPUID_LOCAL_APIC_ID 0xff000000 /* + * AMD extended function 8000_0008h ecx info + */ +#define AMDID_CMP_CORES 0x000000ff + +/* * Model-specific registers for the i386 family */ #define MSR_P5_MC_ADDR 0x000 --Boundary-00=_Aj9iC8GacVFVVEU--