1139825Simp/*-
225164Speter * ----------------------------------------------------------------------------
325164Speter * "THE BEER-WARE LICENSE" (Revision 42):
425164Speter * <phk@FreeBSD.org> wrote this file.  As long as you retain this notice you
525164Speter * can do whatever you want with this stuff. If we meet some day, and you think
625164Speter * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
725164Speter * ----------------------------------------------------------------------------
825164Speter *
950477Speter * $FreeBSD$
1025164Speter */
1125164Speter
1276078Sjhb#ifndef _SYS_SMP_H_
1376078Sjhb#define _SYS_SMP_H_
1425164Speter
1555205Speter#ifdef _KERNEL
1625164Speter
1776078Sjhb#ifndef LOCORE
1825517Sfsmp
19222813Sattilio#include <sys/cpuset.h>
20222813Sattilio
21117005Sjeff/*
22117005Sjeff * Topology of a NUMA or HTT system.
23117005Sjeff *
24117005Sjeff * The top level topology is an array of pointers to groups.  Each group
25117005Sjeff * contains a bitmask of cpus in its group or subgroups.  It may also
26117005Sjeff * contain a pointer to an array of child groups.
27117005Sjeff *
28117005Sjeff * The bitmasks at non leaf groups may be used by consumers who support
29117005Sjeff * a smaller depth than the hardware provides.
30117005Sjeff *
31117005Sjeff * The topology may be omitted by systems where all CPUs are equal.
32117005Sjeff */
33117005Sjeff
34117005Sjeffstruct cpu_group {
35176734Sjeff	struct cpu_group *cg_parent;	/* Our parent group. */
36176734Sjeff	struct cpu_group *cg_child;	/* Optional children groups. */
37222813Sattilio	cpuset_t	cg_mask;	/* Mask of cpus in this group. */
38222200Sattilio	int32_t		cg_count;	/* Count of cpus in this group. */
39222200Sattilio	int16_t		cg_children;	/* Number of children groups. */
40176734Sjeff	int8_t		cg_level;	/* Shared cache level. */
41176734Sjeff	int8_t		cg_flags;	/* Traversal modifiers. */
42117005Sjeff};
43117005Sjeff
44215159Snwhitehorntypedef struct cpu_group *cpu_group_t;
45215159Snwhitehorn
46176734Sjeff/*
47176734Sjeff * Defines common resources for CPUs in the group.  The highest level
48176734Sjeff * resource should be used when multiple are shared.
49176734Sjeff */
50176734Sjeff#define	CG_SHARE_NONE	0
51176734Sjeff#define	CG_SHARE_L1	1
52176734Sjeff#define	CG_SHARE_L2	2
53176734Sjeff#define	CG_SHARE_L3	3
54117005Sjeff
55176734Sjeff/*
56176734Sjeff * Behavior modifiers for load balancing and affinity.
57176734Sjeff */
58176734Sjeff#define	CG_FLAG_HTT	0x01		/* Schedule the alternate core last. */
59191643Sjeff#define	CG_FLAG_SMT	0x02		/* New age htt, less crippled. */
60191643Sjeff#define	CG_FLAG_THREAD	(CG_FLAG_HTT | CG_FLAG_SMT)	/* Any threading. */
61176734Sjeff
62176734Sjeff/*
63176734Sjeff * Convenience routines for building topologies.
64176734Sjeff */
65215159Snwhitehorn#ifdef SMP
66176734Sjeffstruct cpu_group *smp_topo(void);
67176734Sjeffstruct cpu_group *smp_topo_none(void);
68176734Sjeffstruct cpu_group *smp_topo_1level(int l1share, int l1count, int l1flags);
69176734Sjeffstruct cpu_group *smp_topo_2level(int l2share, int l2count, int l1share,
70176734Sjeff    int l1count, int l1flags);
71176734Sjeffstruct cpu_group *smp_topo_find(struct cpu_group *top, int cpu);
72176734Sjeff
7376078Sjhbextern void (*cpustop_restartfunc)(void);
7476078Sjhbextern int smp_active;
7576078Sjhbextern int smp_cpus;
76222813Sattilioextern volatile cpuset_t started_cpus;
77222813Sattilioextern volatile cpuset_t stopped_cpus;
78236772Siwasakiextern volatile cpuset_t suspended_cpus;
79222813Sattilioextern cpuset_t hlt_cpus_mask;
80222813Sattilioextern cpuset_t logical_cpus_mask;
81123125Sjhb#endif /* SMP */
82123125Sjhb
8391673Sjeffextern u_int mp_maxid;
84134689Sjulianextern int mp_maxcpus;
85123125Sjhbextern int mp_ncpus;
86123125Sjhbextern volatile int smp_started;
8727728Sfsmp
88222813Sattilioextern cpuset_t all_cpus;
89134591Sjulian
9027002Sfsmp/*
9180779Sbmilekic * Macro allowing us to determine whether a CPU is absent at any given
9280779Sbmilekic * time, thus permitting us to configure sparse maps of cpuid-dependent
9380779Sbmilekic * (per-CPU) structures.
9480779Sbmilekic */
95222813Sattilio#define	CPU_ABSENT(x_cpu)	(!CPU_ISSET(x_cpu, &all_cpus))
9680779Sbmilekic
97209050Sjhb/*
98209050Sjhb * Macros to iterate over non-absent CPUs.  CPU_FOREACH() takes an
99209050Sjhb * integer iterator and iterates over the available set of CPUs.
100209050Sjhb * CPU_FIRST() returns the id of the first non-absent CPU.  CPU_NEXT()
101209050Sjhb * returns the id of the next non-absent CPU.  It will wrap back to
102209050Sjhb * CPU_FIRST() once the end of the list is reached.  The iterators are
103209050Sjhb * currently implemented via inline functions.
104209050Sjhb */
105209050Sjhb#define	CPU_FOREACH(i)							\
106209050Sjhb	for ((i) = 0; (i) <= mp_maxid; (i)++)				\
107209050Sjhb		if (!CPU_ABSENT((i)))
108209050Sjhb
109209050Sjhbstatic __inline int
110209050Sjhbcpu_first(void)
111209050Sjhb{
112209050Sjhb	int i;
113209050Sjhb
114209050Sjhb	for (i = 0;; i++)
115209050Sjhb		if (!CPU_ABSENT(i))
116209050Sjhb			return (i);
117209050Sjhb}
118209050Sjhb
119209050Sjhbstatic __inline int
120209050Sjhbcpu_next(int i)
121209050Sjhb{
122209050Sjhb
123209050Sjhb	for (;;) {
124209050Sjhb		i++;
125209050Sjhb		if (i > mp_maxid)
126209050Sjhb			i = 0;
127209050Sjhb		if (!CPU_ABSENT(i))
128209050Sjhb			return (i);
129209050Sjhb	}
130209050Sjhb}
131209050Sjhb
132209050Sjhb#define	CPU_FIRST()	cpu_first()
133209050Sjhb#define	CPU_NEXT(i)	cpu_next((i))
134209050Sjhb
135123125Sjhb#ifdef SMP
13680779Sbmilekic/*
13776078Sjhb * Machine dependent functions used to initialize MP support.
13876078Sjhb *
13976078Sjhb * The cpu_mp_probe() should check to see if MP support is present and return
14076078Sjhb * zero if it is not or non-zero if it is.  If MP support is present, then
14176078Sjhb * cpu_mp_start() will be called so that MP can be enabled.  This function
14276078Sjhb * should do things such as startup secondary processors.  It should also
14376078Sjhb * setup mp_ncpus, all_cpus, and smp_cpus.  It should also ensure that
14476078Sjhb * smp_active and smp_started are initialized at the appropriate time.
14576078Sjhb * Once cpu_mp_start() returns, machine independent MP startup code will be
14676078Sjhb * executed and a simple message will be output to the console.  Finally,
14776078Sjhb * cpu_mp_announce() will be called so that machine dependent messages about
14876078Sjhb * the MP support may be output to the console if desired.
149122947Sjhb *
150122947Sjhb * The cpu_setmaxid() function is called very early during the boot process
151122947Sjhb * so that the MD code may set mp_maxid to provide an upper bound on CPU IDs
152122947Sjhb * that other subsystems may use.  If a platform is not able to determine
153123126Sjhb * the exact maximum ID that early, then it may set mp_maxid to MAXCPU - 1.
15427002Sfsmp */
15596999Sjakestruct thread;
15696999Sjake
157176734Sjeffstruct cpu_group *cpu_topo(void);
15876078Sjhbvoid	cpu_mp_announce(void);
15976078Sjhbint	cpu_mp_probe(void);
160122947Sjhbvoid	cpu_mp_setmaxid(void);
16176078Sjhbvoid	cpu_mp_start(void);
16227002Sfsmp
16383366Sjulianvoid	forward_signal(struct thread *);
164222813Sattilioint	restart_cpus(cpuset_t);
165222813Sattilioint	stop_cpus(cpuset_t);
166222813Sattilioint	stop_cpus_hard(cpuset_t);
167235622Siwasaki#if defined(__amd64__) || defined(__i386__)
168222813Sattilioint	suspend_cpus(cpuset_t);
169255726Sgibbsint	resume_cpus(cpuset_t);
170189903Sjkim#endif
171243046Sjeff
17276078Sjhbvoid	smp_rendezvous_action(void);
173134416Sobrienextern	struct mtx smp_ipi_mtx;
174145727Sdwhite
175123125Sjhb#endif /* SMP */
176243046Sjeff
177243046Sjeffint	quiesce_all_cpus(const char *, int);
178243046Sjeffint	quiesce_cpus(cpuset_t, const char *, int);
179179230Sjbvoid	smp_no_rendevous_barrier(void *);
18076078Sjhbvoid	smp_rendezvous(void (*)(void *),
18176078Sjhb		       void (*)(void *),
18276078Sjhb		       void (*)(void *),
18376078Sjhb		       void *arg);
184222813Sattiliovoid	smp_rendezvous_cpus(cpuset_t,
185179230Sjb		       void (*)(void *),
186179230Sjb		       void (*)(void *),
187179230Sjb		       void (*)(void *),
188179230Sjb		       void *arg);
18927728Sfsmp#endif /* !LOCORE */
19055205Speter#endif /* _KERNEL */
19176078Sjhb#endif /* _SYS_SMP_H_ */
192