diff options
author | avg <avg@FreeBSD.org> | 2016-04-04 16:09:29 +0000 |
---|---|---|
committer | avg <avg@FreeBSD.org> | 2016-04-04 16:09:29 +0000 |
commit | 14341afcfcb81fa4ee5ea9e38596d59bbaef36c7 (patch) | |
tree | 23a3eef0c6e2364cf57f22cbc0dd5be2e47b7e33 /sys/sys/smp.h | |
parent | b6c01ffbf517baa5a9a91cc3281fd91013b806df (diff) | |
download | FreeBSD-src-14341afcfcb81fa4ee5ea9e38596d59bbaef36c7.zip FreeBSD-src-14341afcfcb81fa4ee5ea9e38596d59bbaef36c7.tar.gz |
new x86 smp topology detection code
Previously, the code determined a topology of processing units
(hardware threads, cores, packages) and then deduced a cache topology
using certain assumptions. The new code builds a topology that
includes both processing units and caches using the information
provided by the hardware.
At the moment, the discovered full topology is used only to creeate
a scheduling topology for SCHED_ULE.
There is no KPI for other kernel uses.
Summary:
- based on APIC ID derivation rules for Intel and AMD CPUs
- can handle non-uniform topologies
- requires homogeneous APIC ID assignment (same bit widths for ID
components)
- topology for dual-node AMD CPUs may not be optimal
- topology for latest AMD CPU models may not be optimal as the code is
several years old
- supports only thread/package/core/cache nodes
Todo:
- AMD dual-node processors
- latest AMD processors
- NUMA nodes
- checking for homogeneity of the APIC ID assignment across packages
- more flexible cache placement within topology
- expose topology to userland, e.g., via sysctl nodes
Long term todo:
- KPI for CPU sharing and affinity with respect to various resources
(e.g., two logical processors may share the same FPU, etc)
Reviewed by: mav
Tested by: mav
MFC after: 1 month
Differential Revision: https://reviews.freebsd.org/D2728
Diffstat (limited to 'sys/sys/smp.h')
-rw-r--r-- | sys/sys/smp.h | 68 |
1 files changed, 66 insertions, 2 deletions
diff --git a/sys/sys/smp.h b/sys/sys/smp.h index 58b1754..904b9f7 100644 --- a/sys/sys/smp.h +++ b/sys/sys/smp.h @@ -17,9 +17,52 @@ #ifndef LOCORE #include <sys/cpuset.h> +#include <sys/queue.h> /* - * Topology of a NUMA or HTT system. + * Types of nodes in the topological tree. + */ +typedef enum { + /* No node has this type; can be used in topo API calls. */ + TOPO_TYPE_DUMMY, + /* Processing unit aka computing unit aka logical CPU. */ + TOPO_TYPE_PU, + /* Physical subdivision of a package. */ + TOPO_TYPE_CORE, + /* CPU L1/L2/L3 cache. */ + TOPO_TYPE_CACHE, + /* Package aka chip, equivalent to socket. */ + TOPO_TYPE_PKG, + /* NUMA node. */ + TOPO_TYPE_NODE, + /* Other logical or physical grouping of PUs. */ + /* E.g. PUs on the same dye, or PUs sharing an FPU. */ + TOPO_TYPE_GROUP, + /* The whole system. */ + TOPO_TYPE_SYSTEM +} topo_node_type; + +/* Hardware indenitifier of a topology component. */ +typedef unsigned int hwid_t; +/* Logical CPU idenitifier. */ +typedef int cpuid_t; + +/* A node in the topology. */ +struct topo_node { + struct topo_node *parent; + TAILQ_HEAD(topo_children, topo_node) children; + TAILQ_ENTRY(topo_node) siblings; + cpuset_t cpuset; + topo_node_type type; + uintptr_t subtype; + hwid_t hwid; + cpuid_t id; + int nchildren; + int cpu_count; +}; + +/* + * Scheduling topology of a NUMA or SMP system. * * The top level topology is an array of pointers to groups. Each group * contains a bitmask of cpus in its group or subgroups. It may also @@ -52,6 +95,8 @@ typedef struct cpu_group *cpu_group_t; #define CG_SHARE_L2 2 #define CG_SHARE_L3 3 +#define MAX_CACHE_LEVELS CG_SHARE_L3 + /* * Behavior modifiers for load balancing and affinity. */ @@ -60,10 +105,29 @@ typedef struct cpu_group *cpu_group_t; #define CG_FLAG_THREAD (CG_FLAG_HTT | CG_FLAG_SMT) /* Any threading. */ /* - * Convenience routines for building topologies. + * Convenience routines for building and traversing topologies. */ #ifdef SMP +void topo_init_node(struct topo_node *node); +void topo_init_root(struct topo_node *root); +struct topo_node * topo_add_node_by_hwid(struct topo_node *parent, int hwid, + topo_node_type type, uintptr_t subtype); +struct topo_node * topo_find_node_by_hwid(struct topo_node *parent, int hwid, + topo_node_type type, uintptr_t subtype); +void topo_promote_child(struct topo_node *child); +struct topo_node * topo_next_node(struct topo_node *top, + struct topo_node *node); +struct topo_node * topo_next_nonchild_node(struct topo_node *top, + struct topo_node *node); +void topo_set_pu_id(struct topo_node *node, cpuid_t id); +int topo_analyze(struct topo_node *topo_root, int all, int *pkg_count, + int *cores_per_pkg, int *thrs_per_core); + +#define TOPO_FOREACH(i, root) \ + for (i = root; i != NULL; i = topo_next_node(root, i)) + struct cpu_group *smp_topo(void); +struct cpu_group *smp_topo_alloc(u_int count); struct cpu_group *smp_topo_none(void); struct cpu_group *smp_topo_1level(int l1share, int l1count, int l1flags); struct cpu_group *smp_topo_2level(int l2share, int l2count, int l1share, |