Home | History | Annotate | Line # | Download | only in sys
      1 /*	$NetBSD: cpu_data.h,v 1.57 2025/03/29 17:29:20 kre Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2004, 2006, 2007, 2008, 2019, 2020 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26  * POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 /*
     30  * based on arch/i386/include/cpu.h:
     31  *	NetBSD: cpu.h,v 1.115 2004/05/16 12:32:53 yamt Exp
     32  */
     33 
     34 #ifndef _SYS_CPU_DATA_H_
     35 #define	_SYS_CPU_DATA_H_
     36 
     37 struct callout;
     38 struct lwp;
     39 
     40 #include <sys/sched.h>	/* for schedstate_percpu */
     41 #include <sys/condvar.h>
     42 #include <sys/pcu.h>
     43 #include <sys/percpu_types.h>
     44 #include <sys/queue.h>
     45 #include <sys/kcpuset.h>
     46 #include <sys/ipi.h>
     47 #include <sys/intr.h>
     48 
     49 /* Per-CPU counters.  New elements must be added in blocks of 8. */
     50 enum cpu_count {
     51 	CPU_COUNT_NSWTCH,		/* 0 */
     52 	CPU_COUNT_NSYSCALL,
     53 	CPU_COUNT_NTRAP,
     54 	CPU_COUNT_NINTR,
     55 	CPU_COUNT_NSOFT,
     56 	CPU_COUNT_FORKS,
     57 	CPU_COUNT_FORKS_PPWAIT,
     58 	CPU_COUNT_FORKS_SHAREVM,
     59 	CPU_COUNT_COLORHIT,		/* 8 */
     60 	CPU_COUNT_COLORMISS,
     61 	CPU_COUNT__UNUSED3,
     62 	CPU_COUNT__UNUSED4,
     63 	CPU_COUNT_CPUHIT,
     64 	CPU_COUNT_CPUMISS,
     65 	CPU_COUNT_FREEPAGES,
     66 	CPU_COUNT__UNUSED5,
     67 	CPU_COUNT_PAGEINS,		/* 16 */
     68 	CPU_COUNT_FLTUP,
     69 	CPU_COUNT_FLTNOUP,
     70 	CPU_COUNT_FLTPGWAIT,
     71 	CPU_COUNT_FLTRELCK,
     72 	CPU_COUNT_FLTRELCKOK,
     73 	CPU_COUNT__UNUSED1,
     74 	CPU_COUNT__UNUSED2,
     75 	CPU_COUNT_NFAULT,		/* 24 */
     76 	CPU_COUNT_FLT_ACOW,
     77 	CPU_COUNT_FLT_ANON,
     78 	CPU_COUNT_FLT_OBJ,
     79 	CPU_COUNT_FLT_PRCOPY,
     80 	CPU_COUNT_FLT_PRZERO,
     81 	CPU_COUNT_FLTAMCOPY,
     82 	CPU_COUNT_FLTANGET,
     83 	CPU_COUNT_FLTANRETRY,		/* 32 */
     84 	CPU_COUNT_FLTGET,
     85 	CPU_COUNT_FLTLGET,
     86 	CPU_COUNT_FLTNAMAP,
     87 	CPU_COUNT_FLTNOMAP,
     88 	CPU_COUNT_FLTNOANON,
     89 	CPU_COUNT_FLTNORAM,
     90 	CPU_COUNT_FLTPGRELE,
     91 	CPU_COUNT_ANONUNKNOWN,		/* 40 */
     92 	CPU_COUNT_ANONCLEAN,
     93 	CPU_COUNT_ANONDIRTY,
     94 	CPU_COUNT_FILEUNKNOWN,
     95 	CPU_COUNT_FILECLEAN,
     96 	CPU_COUNT_FILEDIRTY,
     97 	CPU_COUNT_EXECPAGES,
     98 	CPU_COUNT_SYNC,
     99 	CPU_COUNT_MAX			/* 48 */
    100 };
    101 
    102 /*
    103  * MI per-cpu data
    104  *
    105  * this structure is intended to be included in MD cpu_info structure.
    106  *	struct cpu_info {
    107  *		struct cpu_data ci_data;
    108  *	}
    109  *
    110  * note that cpu_data is not expected to contain much data,
    111  * as cpu_info is size-limited on most ports.
    112  */
    113 
    114 struct lockdebug;
    115 
    116 enum cpu_rel {
    117 	/*
    118 	 * This is a circular list of peer CPUs in the same core (SMT /
    119 	 * Hyperthreading).  It always includes the CPU it is referenced
    120 	 * from as the last entry.
    121 	 */
    122 	CPUREL_CORE,
    123 
    124 	/*
    125 	 * This is a circular list of peer CPUs in the same physical
    126 	 * package.  It always includes the CPU it is referenced from as
    127 	 * the last entry.
    128 	 */
    129 	CPUREL_PACKAGE,
    130 
    131 	/*
    132 	 * This is a circular list of the first CPUs in each physical
    133 	 * package.  It may or may not include the CPU it is referenced
    134 	 * from.
    135 	 */
    136 	CPUREL_PACKAGE1ST,
    137 
    138 	/* Terminator. */
    139 	CPUREL_COUNT
    140 };
    141 
    142 struct cpu_data {
    143 	/*
    144 	 * The first section is likely to be touched by other CPUs -
    145 	 * it is cache hot.
    146 	 */
    147 	u_int		cpu_index;		/* CPU index */
    148 	lwp_t		*cpu_biglock_wanted;	/* LWP spinning on biglock */
    149 	kcondvar_t	cpu_xcall;		/* cross-call support */
    150 	int		cpu_xcall_pending;	/* cross-call support */
    151 	u_int		cpu_psz_read_depth;	/* pserialize(9) read depth */
    152 	uint32_t	cpu_ipipend[IPI_BITWORDS];	/* pending IPIs */
    153 	struct schedstate_percpu cpu_schedstate; /* scheduler state */
    154 
    155 	/* Basic topology information.  May be fake. */
    156 	u_int		cpu_package_id;
    157 	u_int		cpu_core_id;
    158 	u_int		cpu_smt_id;
    159 	u_int		cpu_numa_id;
    160 	bool		cpu_is_slow;
    161 	u_int		cpu_nsibling[CPUREL_COUNT];
    162 	struct cpu_info	*cpu_sibling[CPUREL_COUNT];
    163 	struct cpu_info *cpu_package1st;	/* 1st CPU in our package */
    164 
    165 	/*
    166 	 * This section is mostly CPU-private.
    167 	 */
    168 	lwp_t		*cpu_idlelwp __aligned(64);/* idle lwp */
    169 	void		*cpu_lockstat;		/* lockstat private tables */
    170 	u_int		cpu_biglock_count;	/* # recursive holds */
    171 	u_int		cpu_spin_locks;		/* # of spinlockmgr locks */
    172 	u_int		cpu_simple_locks;	/* # of simple locks held */
    173 	u_int		cpu_spin_locks2;	/* # of spin locks held XXX */
    174 	u_int		cpu_lkdebug_recurse;	/* LOCKDEBUG recursion */
    175 	u_int		cpu_softints;		/* pending (slow) softints */
    176 	struct uvm_cpu	*cpu_uvm;		/* uvm per-cpu data */
    177 	u_int		cpu_faultrng;		/* counter for fault rng */
    178 	void		*cpu_callout;		/* per-CPU callout state */
    179 	void		*cpu_softcpu;		/* soft interrupt table */
    180 	TAILQ_HEAD(,buf) cpu_biodone;		/* finished block xfers */
    181 	percpu_cpu_t	cpu_percpu;		/* per-cpu data */
    182 	struct selcluster *cpu_selcluster;	/* per-CPU select() info */
    183 	void		*cpu_nch;		/* per-cpu vfs_cache data */
    184 	_TAILQ_HEAD(,struct lockdebug,volatile) cpu_ld_locks;/* !: lockdebug */
    185 	__cpu_simple_lock_t cpu_ld_lock;	/* lockdebug */
    186 	uint64_t	cpu_cc_freq;		/* cycle counter frequency */
    187 	int64_t		cpu_cc_skew;		/* counter skew vs cpu0 */
    188 	char		cpu_name[8];		/* eg, "cpu4" */
    189 	kcpuset_t	*cpu_kcpuset;		/* kcpuset_t of this cpu only */
    190 	struct lwp * volatile cpu_pcu_curlwp[PCU_UNIT_COUNT];
    191 	int64_t		cpu_counts[CPU_COUNT_MAX];/* per-CPU counts */
    192 
    193 	unsigned	cpu_heartbeat_count;		/* # of heartbeats */
    194 	unsigned	cpu_heartbeat_uptime_cache;	/* last time_uptime */
    195 	unsigned	cpu_heartbeat_uptime_stamp;	/* heartbeats since
    196 							 * uptime changed */
    197 	unsigned	cpu_heartbeat_suspend;		/* suspend depth */
    198 };
    199 
    200 #define	ci_schedstate		ci_data.cpu_schedstate
    201 #define	ci_index		ci_data.cpu_index
    202 #define	ci_biglock_count	ci_data.cpu_biglock_count
    203 #define	ci_biglock_wanted	ci_data.cpu_biglock_wanted
    204 #define	ci_cpuname		ci_data.cpu_name
    205 #define	ci_spin_locks		ci_data.cpu_spin_locks
    206 #define	ci_simple_locks		ci_data.cpu_simple_locks
    207 #define	ci_lockstat		ci_data.cpu_lockstat
    208 #define	ci_spin_locks2		ci_data.cpu_spin_locks2
    209 #define	ci_lkdebug_recurse	ci_data.cpu_lkdebug_recurse
    210 #define	ci_pcu_curlwp		ci_data.cpu_pcu_curlwp
    211 #define	ci_kcpuset		ci_data.cpu_kcpuset
    212 #define	ci_ipipend		ci_data.cpu_ipipend
    213 #define	ci_psz_read_depth	ci_data.cpu_psz_read_depth
    214 
    215 #define	ci_package_id		ci_data.cpu_package_id
    216 #define	ci_core_id		ci_data.cpu_core_id
    217 #define	ci_smt_id		ci_data.cpu_smt_id
    218 #define	ci_numa_id		ci_data.cpu_numa_id
    219 #define	ci_is_slow		ci_data.cpu_is_slow
    220 #define	ci_nsibling		ci_data.cpu_nsibling
    221 #define	ci_sibling		ci_data.cpu_sibling
    222 #define	ci_package1st		ci_data.cpu_package1st
    223 #define	ci_faultrng		ci_data.cpu_faultrng
    224 #define	ci_counts		ci_data.cpu_counts
    225 
    226 #define	ci_heartbeat_count		ci_data.cpu_heartbeat_count
    227 #define	ci_heartbeat_uptime_cache	ci_data.cpu_heartbeat_uptime_cache
    228 #define	ci_heartbeat_uptime_stamp	ci_data.cpu_heartbeat_uptime_stamp
    229 #define	ci_heartbeat_suspend		ci_data.cpu_heartbeat_suspend
    230 
    231 #define	cpu_nsyscall		cpu_counts[CPU_COUNT_NSYSCALL]
    232 #define	cpu_ntrap		cpu_counts[CPU_COUNT_NTRAP]
    233 #define	cpu_nswtch		cpu_counts[CPU_COUNT_NSWTCH]
    234 #define	cpu_nintr		cpu_counts[CPU_COUNT_NINTR]
    235 #define	cpu_nsoft		cpu_counts[CPU_COUNT_NSOFT]
    236 #define	cpu_nfault		cpu_counts[CPU_COUNT_NFAULT]
    237 
    238 void	mi_cpu_init(void);
    239 int	mi_cpu_attach(struct cpu_info *);
    240 
    241 /*
    242  * Adjust a count with preemption already disabled.  If the counter being
    243  * adjusted can be updated from interrupt context, SPL must be raised.
    244  */
    245 #define	CPU_COUNT(idx, d)					\
    246 do {								\
    247 	extern bool kpreempt_disabled(void);			\
    248 	KASSERT(kpreempt_disabled());				\
    249 	KASSERT((unsigned)(idx) < CPU_COUNT_MAX);		\
    250 	curcpu()->ci_counts[(idx)] += (d);			\
    251 } while (0)
    252 
    253 /*
    254  * Fetch a potentially stale count - cheap, use as often as you like.
    255  */
    256 static inline int64_t
    257 cpu_count_get(enum cpu_count idx)
    258 {
    259 	extern int64_t cpu_counts[];
    260 	return cpu_counts[idx];
    261 }
    262 
    263 void	cpu_count(enum cpu_count, int64_t);
    264 void	cpu_count_sync(bool);
    265 
    266 #endif /* _SYS_CPU_DATA_H_ */
    267