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