smp.h revision 331910
1/*- 2 * ---------------------------------------------------------------------------- 3 * "THE BEER-WARE LICENSE" (Revision 42): 4 * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you 5 * can do whatever you want with this stuff. If we meet some day, and you think 6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 7 * ---------------------------------------------------------------------------- 8 * 9 * $FreeBSD: stable/10/sys/sys/smp.h 331910 2018-04-03 07:52:06Z avg $ 10 */ 11 12#ifndef _SYS_SMP_H_ 13#define _SYS_SMP_H_ 14 15#ifdef _KERNEL 16 17#ifndef LOCORE 18 19#include <sys/cpuset.h> 20 21/* 22 * Topology of a NUMA or HTT system. 23 * 24 * The top level topology is an array of pointers to groups. Each group 25 * contains a bitmask of cpus in its group or subgroups. It may also 26 * contain a pointer to an array of child groups. 27 * 28 * The bitmasks at non leaf groups may be used by consumers who support 29 * a smaller depth than the hardware provides. 30 * 31 * The topology may be omitted by systems where all CPUs are equal. 32 */ 33 34struct cpu_group { 35 struct cpu_group *cg_parent; /* Our parent group. */ 36 struct cpu_group *cg_child; /* Optional children groups. */ 37 cpuset_t cg_mask; /* Mask of cpus in this group. */ 38 int32_t cg_count; /* Count of cpus in this group. */ 39 int16_t cg_children; /* Number of children groups. */ 40 int8_t cg_level; /* Shared cache level. */ 41 int8_t cg_flags; /* Traversal modifiers. */ 42}; 43 44typedef struct cpu_group *cpu_group_t; 45 46/* 47 * Defines common resources for CPUs in the group. The highest level 48 * resource should be used when multiple are shared. 49 */ 50#define CG_SHARE_NONE 0 51#define CG_SHARE_L1 1 52#define CG_SHARE_L2 2 53#define CG_SHARE_L3 3 54 55/* 56 * Behavior modifiers for load balancing and affinity. 57 */ 58#define CG_FLAG_HTT 0x01 /* Schedule the alternate core last. */ 59#define CG_FLAG_SMT 0x02 /* New age htt, less crippled. */ 60#define CG_FLAG_THREAD (CG_FLAG_HTT | CG_FLAG_SMT) /* Any threading. */ 61 62/* 63 * Convenience routines for building topologies. 64 */ 65#ifdef SMP 66struct cpu_group *smp_topo(void); 67struct cpu_group *smp_topo_none(void); 68struct cpu_group *smp_topo_1level(int l1share, int l1count, int l1flags); 69struct cpu_group *smp_topo_2level(int l2share, int l2count, int l1share, 70 int l1count, int l1flags); 71struct cpu_group *smp_topo_find(struct cpu_group *top, int cpu); 72 73extern void (*cpustop_restartfunc)(void); 74extern int smp_cpus; 75/* The suspend/resume cpusets are x86 only, but minimize ifdefs. */ 76extern volatile cpuset_t resuming_cpus; /* woken up cpus in suspend pen */ 77extern volatile cpuset_t started_cpus; /* cpus to let out of stop pen */ 78extern volatile cpuset_t stopped_cpus; /* cpus in stop pen */ 79extern volatile cpuset_t suspended_cpus; /* cpus [near] sleeping in susp pen */ 80extern volatile cpuset_t toresume_cpus; /* cpus to let out of suspend pen */ 81extern cpuset_t hlt_cpus_mask; /* XXX 'mask' is detail in old impl */ 82extern cpuset_t logical_cpus_mask; 83#endif /* SMP */ 84 85extern u_int mp_maxid; 86extern int mp_maxcpus; 87extern int mp_ncpus; 88extern volatile int smp_started; 89 90extern cpuset_t all_cpus; 91 92/* 93 * Macro allowing us to determine whether a CPU is absent at any given 94 * time, thus permitting us to configure sparse maps of cpuid-dependent 95 * (per-CPU) structures. 96 */ 97#define CPU_ABSENT(x_cpu) (!CPU_ISSET(x_cpu, &all_cpus)) 98 99/* 100 * Macros to iterate over non-absent CPUs. CPU_FOREACH() takes an 101 * integer iterator and iterates over the available set of CPUs. 102 * CPU_FIRST() returns the id of the first non-absent CPU. CPU_NEXT() 103 * returns the id of the next non-absent CPU. It will wrap back to 104 * CPU_FIRST() once the end of the list is reached. The iterators are 105 * currently implemented via inline functions. 106 */ 107#define CPU_FOREACH(i) \ 108 for ((i) = 0; (i) <= mp_maxid; (i)++) \ 109 if (!CPU_ABSENT((i))) 110 111static __inline int 112cpu_first(void) 113{ 114 int i; 115 116 for (i = 0;; i++) 117 if (!CPU_ABSENT(i)) 118 return (i); 119} 120 121static __inline int 122cpu_next(int i) 123{ 124 125 for (;;) { 126 i++; 127 if (i > mp_maxid) 128 i = 0; 129 if (!CPU_ABSENT(i)) 130 return (i); 131 } 132} 133 134#define CPU_FIRST() cpu_first() 135#define CPU_NEXT(i) cpu_next((i)) 136 137#ifdef SMP 138/* 139 * Machine dependent functions used to initialize MP support. 140 * 141 * The cpu_mp_probe() should check to see if MP support is present and return 142 * zero if it is not or non-zero if it is. If MP support is present, then 143 * cpu_mp_start() will be called so that MP can be enabled. This function 144 * should do things such as startup secondary processors. It should also 145 * setup mp_ncpus, all_cpus, and smp_cpus. It should also ensure that 146 * smp_started is initialized at the appropriate time. 147 * Once cpu_mp_start() returns, machine independent MP startup code will be 148 * executed and a simple message will be output to the console. Finally, 149 * cpu_mp_announce() will be called so that machine dependent messages about 150 * the MP support may be output to the console if desired. 151 * 152 * The cpu_setmaxid() function is called very early during the boot process 153 * so that the MD code may set mp_maxid to provide an upper bound on CPU IDs 154 * that other subsystems may use. If a platform is not able to determine 155 * the exact maximum ID that early, then it may set mp_maxid to MAXCPU - 1. 156 */ 157struct thread; 158 159struct cpu_group *cpu_topo(void); 160void cpu_mp_announce(void); 161int cpu_mp_probe(void); 162void cpu_mp_setmaxid(void); 163void cpu_mp_start(void); 164 165void forward_signal(struct thread *); 166int restart_cpus(cpuset_t); 167int stop_cpus(cpuset_t); 168int stop_cpus_hard(cpuset_t); 169#if defined(__amd64__) || defined(__i386__) 170int suspend_cpus(cpuset_t); 171int resume_cpus(cpuset_t); 172#endif 173 174void smp_rendezvous_action(void); 175extern struct mtx smp_ipi_mtx; 176 177#endif /* SMP */ 178 179int quiesce_all_cpus(const char *, int); 180int quiesce_cpus(cpuset_t, const char *, int); 181void smp_no_rendevous_barrier(void *); 182void smp_rendezvous(void (*)(void *), 183 void (*)(void *), 184 void (*)(void *), 185 void *arg); 186void smp_rendezvous_cpus(cpuset_t, 187 void (*)(void *), 188 void (*)(void *), 189 void (*)(void *), 190 void *arg); 191#endif /* !LOCORE */ 192#endif /* _KERNEL */ 193#endif /* _SYS_SMP_H_ */ 194