From owner-svn-src-head@freebsd.org Tue Apr 5 10:36:41 2016 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 630E4B0132D; Tue, 5 Apr 2016 10:36:41 +0000 (UTC) (envelope-from avg@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 251DA12D4; Tue, 5 Apr 2016 10:36:41 +0000 (UTC) (envelope-from avg@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u35Aae12057424; Tue, 5 Apr 2016 10:36:40 GMT (envelope-from avg@FreeBSD.org) Received: (from avg@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u35AaelA057422; Tue, 5 Apr 2016 10:36:40 GMT (envelope-from avg@FreeBSD.org) Message-Id: <201604051036.u35AaelA057422@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: avg set sender to avg@FreeBSD.org using -f From: Andriy Gapon Date: Tue, 5 Apr 2016 10:36:40 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r297577 - in head/sys: kern x86/x86 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 05 Apr 2016 10:36:41 -0000 Author: avg Date: Tue Apr 5 10:36:40 2016 New Revision: 297577 URL: https://svnweb.freebsd.org/changeset/base/297577 Log: x86 topo: add some comments, descriptions and references to documentation Plus a minor cosmetic change. MFC after: 1 month Modified: head/sys/kern/subr_smp.c head/sys/x86/x86/mp_x86.c Modified: head/sys/kern/subr_smp.c ============================================================================== --- head/sys/kern/subr_smp.c Tue Apr 5 09:20:52 2016 (r297576) +++ head/sys/kern/subr_smp.c Tue Apr 5 10:36:40 2016 (r297577) @@ -53,9 +53,7 @@ __FBSDID("$FreeBSD$"); #ifdef SMP MALLOC_DEFINE(M_TOPO, "toponodes", "SMP topology data"); -#endif -#ifdef SMP volatile cpuset_t stopped_cpus; volatile cpuset_t started_cpus; volatile cpuset_t suspended_cpus; @@ -895,6 +893,10 @@ topo_init_root(struct topo_node *root) root->type = TOPO_TYPE_SYSTEM; } +/* + * Add a child node with the given ID under the given parent. + * Do nothing if there is already a child with that ID. + */ struct topo_node * topo_add_node_by_hwid(struct topo_node *parent, int hwid, topo_node_type type, uintptr_t subtype) @@ -921,6 +923,9 @@ topo_add_node_by_hwid(struct topo_node * return (node); } +/* + * Find a child node with the given ID under the given parent. + */ struct topo_node * topo_find_node_by_hwid(struct topo_node *parent, int hwid, topo_node_type type, uintptr_t subtype) @@ -938,6 +943,12 @@ topo_find_node_by_hwid(struct topo_node return (NULL); } +/* + * Given a node change the order of its parent's child nodes such + * that the node becomes the firt child while preserving the cyclic + * order of the children. In other words, the given node is promoted + * by rotation. + */ void topo_promote_child(struct topo_node *child) { @@ -959,6 +970,10 @@ topo_promote_child(struct topo_node *chi } } +/* + * Iterate to the next node in the depth-first search (traversal) of + * the topology tree. + */ struct topo_node * topo_next_node(struct topo_node *top, struct topo_node *node) { @@ -977,6 +992,10 @@ topo_next_node(struct topo_node *top, st return (NULL); } +/* + * Iterate to the next node in the depth-first search of the topology tree, + * but without descending below the current node. + */ struct topo_node * topo_next_nonchild_node(struct topo_node *top, struct topo_node *node) { @@ -992,6 +1011,10 @@ topo_next_nonchild_node(struct topo_node return (NULL); } +/* + * Assign the given ID to the given topology node that represents a logical + * processor. + */ void topo_set_pu_id(struct topo_node *node, cpuid_t id) { @@ -1013,6 +1036,14 @@ topo_set_pu_id(struct topo_node *node, c } } +/* + * Check if the topology is uniform, that is, each package has the same number + * of cores in it and each core has the same number of threads (logical + * processors) in it. If so, calculate the number of package, the number of + * cores per package and the number of logical processors per core. + * 'all' parameter tells whether to include administratively disabled logical + * processors into the analysis. + */ int topo_analyze(struct topo_node *topo_root, int all, int *pkg_count, int *cores_per_pkg, int *thrs_per_core) Modified: head/sys/x86/x86/mp_x86.c ============================================================================== --- head/sys/x86/x86/mp_x86.c Tue Apr 5 09:20:52 2016 (r297576) +++ head/sys/x86/x86/mp_x86.c Tue Apr 5 10:36:40 2016 (r297577) @@ -176,6 +176,9 @@ mask_width(u_int x) return (fls(x << (1 - powerof2(x))) - 1); } +/* + * Add a cache level to the cache topology description. + */ static int add_deterministic_cache(int type, int level, int share_count) { @@ -217,6 +220,16 @@ add_deterministic_cache(int type, int le return (1); } +/* + * Determine topology of processing units and caches for AMD CPUs. + * See: + * - AMD CPUID Specification (Publication # 25481) + * - BKDG For AMD Family 10h Processors (Publication # 31116), section 2.15 + * - BKDG for AMD NPT Family 0Fh Processors (Publication # 32559) + * XXX At the moment the code does not recognize grouping of AMD CMT threads, + * if supported, into cores, so each thread is treated as being in its own + * core. In other words, each logical CPU is considered to be a core. + */ static void topo_probe_amd(void) { @@ -277,6 +290,15 @@ topo_probe_amd(void) } } +/* + * Determine topology of processing units for Intel CPUs + * using CPUID Leaf 1 and Leaf 4, if supported. + * See: + * - Intel 64 Architecture Processor Topology Enumeration + * - Intel 64 and IA-32 ArchitecturesSoftware Developer’s Manual, + * Volume 3A: System Programming Guide, PROGRAMMING CONSIDERATIONS + * FOR HARDWARE MULTI-THREADING CAPABLE PROCESSORS + */ static void topo_probe_intel_0x4(void) { @@ -302,6 +324,15 @@ topo_probe_intel_0x4(void) pkg_id_shift = core_id_shift + mask_width(max_cores); } +/* + * Determine topology of processing units for Intel CPUs + * using CPUID Leaf 11, if supported. + * See: + * - Intel 64 Architecture Processor Topology Enumeration + * - Intel 64 and IA-32 ArchitecturesSoftware Developer’s Manual, + * Volume 3A: System Programming Guide, PROGRAMMING CONSIDERATIONS + * FOR HARDWARE MULTI-THREADING CAPABLE PROCESSORS + */ static void topo_probe_intel_0xb(void) { @@ -342,6 +373,14 @@ topo_probe_intel_0xb(void) } } +/* + * Determine topology of caches for Intel CPUs. + * See: + * - Intel 64 Architecture Processor Topology Enumeration + * - Intel 64 and IA-32 Architectures Software Developer’s Manual + * Volume 2A: Instruction Set Reference, A-M, + * CPUID instruction + */ static void topo_probe_intel_caches(void) { @@ -376,14 +415,16 @@ topo_probe_intel_caches(void) } } +/* + * Determine topology of processing units and caches for Intel CPUs. + * See: + * - Intel 64 Architecture Processor Topology Enumeration + */ static void topo_probe_intel(void) { /* - * See Intel(R) 64 Architecture Processor - * Topology Enumeration article for details. - * * Note that 0x1 <= cpu_high < 4 case should be * compatible with topo_probe_intel_0x4() logic when * CPUID.1:EBX[23:16] > 0 (cpu_cores will be 1) @@ -640,6 +681,12 @@ cpu_mp_announce(void) } } +/* + * Add a scheduling group, a group of logical processors sharing + * a particular cache (and, thus having an affinity), to the scheduling + * topology. + * This function recursively works on lower level caches. + */ static void x86topo_add_sched_group(struct topo_node *root, struct cpu_group *cg_root) { @@ -657,6 +704,11 @@ x86topo_add_sched_group(struct topo_node else cg_root->cg_level = root->subtype; + /* + * Check how many core nodes we have under the given root node. + * If we have multiple logical processors, but not multiple + * cores, then those processors must be hardware threads. + */ ncores = 0; node = root; while (node != NULL) { @@ -673,6 +725,13 @@ x86topo_add_sched_group(struct topo_node root->cpu_count > 1 && ncores < 2) cg_root->cg_flags = CG_FLAG_SMT; + /* + * Find out how many cache nodes we have under the given root node. + * We ignore cache nodes that cover all the same processors as the + * root node. Also, we do not descend below found cache nodes. + * That is, we count top-level "non-redundant" caches under the root + * node. + */ nchildren = 0; node = root; while (node != NULL) { @@ -689,6 +748,10 @@ x86topo_add_sched_group(struct topo_node cg_root->cg_child = smp_topo_alloc(nchildren); cg_root->cg_children = nchildren; + /* + * Now find again the same cache nodes as above and recursively + * build scheduling topologies for them. + */ node = root; i = 0; while (node != NULL) { @@ -705,6 +768,9 @@ x86topo_add_sched_group(struct topo_node } } +/* + * Build the MI scheduling topology from the discovered hardware topology. + */ struct cpu_group * cpu_topo(void) { @@ -719,6 +785,9 @@ cpu_topo(void) } +/* + * Add a logical CPU to the topology. + */ void cpu_add(u_int apic_id, char boot_cpu) {