#ifndef _SYS_SMP_H_
#define _SYS_SMP_H_
#ifdef _KERNEL
#ifndef LOCORE
#include <sys/types.h>
#include <sys/cpuset.h>
#include <sys/queue.h>
typedef enum {
TOPO_TYPE_DUMMY,
TOPO_TYPE_PU,
TOPO_TYPE_CORE,
TOPO_TYPE_CACHE,
TOPO_TYPE_PKG,
TOPO_TYPE_NODE,
TOPO_TYPE_GROUP,
TOPO_TYPE_SYSTEM
} topo_node_type;
typedef unsigned int hwid_t;
typedef int cpuid_t;
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;
};
struct cpu_group {
struct cpu_group *cg_parent;
struct cpu_group *cg_child;
cpuset_t cg_mask;
int32_t cg_count;
int32_t cg_first;
int32_t cg_last;
int16_t cg_children;
int8_t cg_level;
int8_t cg_flags;
};
typedef struct cpu_group *cpu_group_t;
extern cpu_group_t cpu_top;
#define CG_SHARE_NONE 0
#define CG_SHARE_L1 1
#define CG_SHARE_L2 2
#define CG_SHARE_L3 3
#define MAX_CACHE_LEVELS CG_SHARE_L3
#define CG_FLAG_HTT 0x01
#define CG_FLAG_SMT 0x02
#define CG_FLAG_THREAD (CG_FLAG_HTT | CG_FLAG_SMT)
#define CG_FLAG_NODE 0x04
#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);
enum topo_level {
TOPO_LEVEL_PKG = 0,
TOPO_LEVEL_GROUP,
TOPO_LEVEL_CACHEGROUP,
TOPO_LEVEL_CORE,
TOPO_LEVEL_THREAD,
TOPO_LEVEL_COUNT
};
struct topo_analysis {
int entities[TOPO_LEVEL_COUNT];
};
int topo_analyze(struct topo_node *topo_root, int all,
struct topo_analysis *results);
#define TOPO_FOREACH(i, root) \
for (i = root; i != NULL; i = topo_next_node(root, i))
struct cpu_group *smp_topo_1level(int l1share, int l1count, int l1flags);
struct cpu_group *smp_topo_2level(int l2share, int l2count, int l1share,
int l1count, int l1flags);
struct cpu_group *smp_topo_find(struct cpu_group *top, int cpu);
extern void (*cpustop_restartfunc)(void);
extern volatile cpuset_t resuming_cpus;
extern volatile cpuset_t started_cpus;
extern volatile cpuset_t stopped_cpus;
extern volatile cpuset_t suspended_cpus;
extern volatile cpuset_t toresume_cpus;
extern cpuset_t logical_cpus_mask;
#endif
struct cpu_group *smp_topo(void);
struct cpu_group *smp_topo_alloc(u_int count);
struct cpu_group *smp_topo_none(void);
extern u_int mp_maxid;
extern int mp_maxcpus;
extern int mp_ncores;
extern int mp_ncpus;
extern int smp_cpus;
extern volatile int smp_started;
extern int smp_threads_per_core;
extern cpuset_t all_cpus;
extern cpuset_t cpuset_domain[MAXMEMDOM];
struct pcb;
extern struct pcb *stoppcbs;
#define CPU_ABSENT(x_cpu) (!CPU_ISSET(x_cpu, &all_cpus))
#define CPU_FOREACH(i) \
for ((i) = 0; (i) <= mp_maxid; (i)++) \
if (!CPU_ABSENT((i)))
static __inline int
cpu_first(void)
{
int i;
for (i = 0;; i++)
if (!CPU_ABSENT(i))
return (i);
}
static __inline int
cpu_next(int i)
{
for (;;) {
i++;
if ((u_int)i > mp_maxid)
i = 0;
if (!CPU_ABSENT(i))
return (i);
}
}
#define CPU_FIRST() cpu_first()
#define CPU_NEXT(i) cpu_next((i))
#ifdef SMP
struct thread;
struct cpu_group *cpu_topo(void);
void cpu_mp_announce(void);
int cpu_mp_probe(void);
void cpu_mp_setmaxid(void);
void cpu_mp_start(void);
void cpu_mp_stop(void);
void forward_signal(struct thread *);
int restart_cpus(cpuset_t);
int stop_cpus(cpuset_t);
int stop_cpus_hard(cpuset_t);
#if defined(__amd64__) || defined(__i386__)
int suspend_cpus(cpuset_t);
int resume_cpus(cpuset_t);
int offline_cpus(cpuset_t);
#endif
void smp_rendezvous_action(void);
extern struct mtx smp_ipi_mtx;
#endif
int quiesce_all_cpus(const char *, int);
int quiesce_cpus(cpuset_t, const char *, int);
void quiesce_all_critical(void);
void cpus_fence_seq_cst(void);
void smp_no_rendezvous_barrier(void *);
void smp_rendezvous(void (*)(void *),
void (*)(void *),
void (*)(void *),
void *arg);
void smp_rendezvous_cpus(cpuset_t,
void (*)(void *),
void (*)(void *),
void (*)(void *),
void *arg);
void smp_rendezvous_cpu(u_int,
void (*)(void *),
void (*)(void *),
void (*)(void *),
void *arg);
struct smp_rendezvous_cpus_retry_arg {
cpuset_t cpus;
};
void smp_rendezvous_cpus_retry(cpuset_t,
void (*)(void *),
void (*)(void *),
void (*)(void *),
void (*)(void *, int),
struct smp_rendezvous_cpus_retry_arg *);
void smp_rendezvous_cpus_done(struct smp_rendezvous_cpus_retry_arg *);
#endif
#endif
#endif