1 /* $OpenBSD: cpu.h,v 1.82 2024/10/23 07:41:44 mpi Exp $ */ 2 /* 3 * Copyright (c) 1996 Nivas Madhur 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This software was developed by the Computer Systems Engineering group 8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 9 * contributed to Berkeley. 10 * 11 * All advertising materials mentioning features or use of this software 12 * must display the following acknowledgement: 13 * This product includes software developed by the University of 14 * California, Lawrence Berkeley Laboratory. 15 * 16 * Redistribution and use in source and binary forms, with or without 17 * modification, are permitted provided that the following conditions 18 * are met: 19 * 1. Redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer. 21 * 2. Redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution. 24 * 3. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 */ 40 41 #ifndef _M88K_CPU_H_ 42 #define _M88K_CPU_H_ 43 44 /* 45 * CTL_MACHDEP definitions. 46 */ 47 #define CPU_CONSDEV 1 /* dev_t: console terminal device */ 48 #define CPU_CPUTYPE 2 /* int: cpu type */ 49 #define CPU_MAXID 3 /* number of valid machdep ids */ 50 51 #define CTL_MACHDEP_NAMES { \ 52 { 0, 0 }, \ 53 { "console_device", CTLTYPE_STRUCT }, \ 54 { "cputype", CTLTYPE_INT }, \ 55 } 56 57 #ifdef _KERNEL 58 59 #include <machine/atomic.h> 60 #include <machine/pcb.h> 61 #include <machine/psl.h> 62 #include <machine/intr.h> 63 #include <sys/clockintr.h> 64 #include <sys/queue.h> 65 #include <sys/sched.h> 66 #include <sys/srp.h> 67 #include <uvm/uvm_percpu.h> 68 69 #if defined(MULTIPROCESSOR) 70 #if !defined(MAX_CPUS) || MAX_CPUS > 4 71 #undef MAX_CPUS 72 #define MAX_CPUS 4 73 #endif 74 #else 75 #if !defined(MAX_CPUS) 76 #undef MAX_CPUS 77 #define MAX_CPUS 1 78 #endif 79 #endif 80 81 #ifndef _LOCORE 82 83 #include <machine/lock.h> 84 85 /* 86 * Per-CPU data structure 87 */ 88 89 struct pmap; 90 91 struct cpu_info { 92 volatile u_int ci_flags; 93 #define CIF_ALIVE 0x01 /* cpu initialized */ 94 #define CIF_PRIMARY 0x02 /* primary cpu */ 95 96 struct proc *ci_curproc; /* current process... */ 97 struct pcb *ci_curpcb; /* ...its pcb... */ 98 struct pmap *ci_curpmap; /* ...and its pmap */ 99 100 u_int ci_cpuid; /* cpu number */ 101 102 /* 103 * Function pointers used within mplock to ensure 104 * non-interruptability. 105 */ 106 uint32_t (*ci_mp_atomic_begin) 107 (__cpu_simple_lock_t *lock, uint *csr); 108 void (*ci_mp_atomic_end) 109 (uint32_t psr, __cpu_simple_lock_t *lock, uint csr); 110 111 /* 112 * Other processor-dependent routines 113 */ 114 void (*ci_zeropage)(vaddr_t); 115 void (*ci_copypage)(vaddr_t, vaddr_t); 116 117 /* 118 * The following fields are used differently depending on 119 * the processor type. Think of them as an anonymous union 120 * of two anonymous structs. 121 */ 122 u_int ci_cpudep0; 123 u_int ci_cpudep1; 124 u_int ci_cpudep2; 125 u_int ci_cpudep3; 126 u_int ci_cpudep4; 127 u_int ci_cpudep5; 128 u_int ci_cpudep6; 129 u_int ci_cpudep7; 130 131 /* 88100 fields */ 132 #define ci_pfsr_i0 ci_cpudep0 /* instruction... */ 133 #define ci_pfsr_i1 ci_cpudep1 134 #define ci_pfsr_d0 ci_cpudep2 /* ...and data CMMU PFSRs */ 135 #define ci_pfsr_d1 ci_cpudep3 136 137 /* 88110 fields */ 138 #define ci_ipi_arg1 ci_cpudep0 /* Complex IPI arguments */ 139 #define ci_ipi_arg2 ci_cpudep1 140 #define ci_h_sxip ci_cpudep2 /* trapframe values */ 141 #define ci_h_epsr ci_cpudep3 /* for hardclock */ 142 #define ci_s_sxip ci_cpudep4 /* and softclock */ 143 #define ci_s_epsr ci_cpudep5 144 145 struct schedstate_percpu 146 ci_schedstate; /* scheduling state */ 147 int ci_want_resched; /* need_resched() invoked */ 148 149 u_int ci_idepth; /* interrupt depth */ 150 151 int ci_ddb_state; /* ddb status */ 152 #define CI_DDB_RUNNING 0 153 #define CI_DDB_ENTERDDB 1 154 #define CI_DDB_INDDB 2 155 #define CI_DDB_PAUSE 3 156 157 u_int32_t ci_randseed; /* per-cpu random seed */ 158 159 int ci_ipi; /* pending ipis */ 160 #define CI_IPI_NOTIFY 0x00000001 161 #define CI_IPI_HARDCLOCK 0x00000002 162 #define CI_IPI_STATCLOCK 0x00000004 163 #define CI_IPI_DDB 0x00000008 164 /* 88110 simple ipi */ 165 #define CI_IPI_TLB_FLUSH_KERNEL 0x00000010 166 #define CI_IPI_TLB_FLUSH_USER 0x00000020 167 /* 88110 complex ipi */ 168 #define CI_IPI_CACHE_FLUSH 0x00000040 169 #define CI_IPI_ICACHE_FLUSH 0x00000080 170 #define CI_IPI_DMA_CACHECTL 0x00000100 171 void (*ci_softipi_cb)(void); /* 88110 softipi callback */ 172 173 #if defined(MULTIPROCESSOR) 174 struct srp_hazard ci_srp_hazards[SRP_HAZARD_NUM]; 175 #define __HAVE_UVM_PERCPU 176 struct uvm_pmr_cache ci_uvm; /* [o] page cache */ 177 #endif 178 #ifdef DIAGNOSTIC 179 int ci_mutex_level; 180 #endif 181 #ifdef GPROF 182 struct gmonparam *ci_gmon; 183 struct clockintr ci_gmonclock; 184 #endif 185 struct clockqueue ci_queue; 186 char ci_panicbuf[512]; 187 }; 188 189 extern cpuid_t master_cpu; 190 extern struct cpu_info m88k_cpus[MAX_CPUS]; 191 192 #define CPU_INFO_ITERATOR cpuid_t 193 #define CPU_INFO_FOREACH(cii, ci) \ 194 for ((cii) = 0; (cii) < MAX_CPUS; (cii)++) \ 195 if (((ci) = &m88k_cpus[cii])->ci_flags & CIF_ALIVE) 196 #define CPU_INFO_UNIT(ci) ((ci)->ci_cpuid) 197 #define MAXCPUS MAX_CPUS 198 199 #if defined(MULTIPROCESSOR) 200 201 static __inline__ struct cpu_info * 202 curcpu(void) 203 { 204 struct cpu_info *cpuptr; 205 206 __asm__ volatile ("ldcr %0, %%cr17" : "=r" (cpuptr)); 207 return cpuptr; 208 } 209 210 #define CPU_IS_PRIMARY(ci) ((ci)->ci_flags & CIF_PRIMARY) 211 #define CPU_IS_RUNNING(ci) ((ci)->ci_flags & CIF_ALIVE) 212 213 void cpu_boot_secondary_processors(void); 214 void cpu_unidle(struct cpu_info *); 215 void m88k_send_ipi(int, cpuid_t); 216 void m88k_broadcast_ipi(int); 217 218 #else /* MULTIPROCESSOR */ 219 220 #define curcpu() (&m88k_cpus[0]) 221 #define cpu_unidle(ci) do { /* nothing */ } while (0) 222 #define CPU_IS_PRIMARY(ci) 1 223 #define CPU_IS_RUNNING(ci) 1 224 225 #endif /* MULTIPROCESSOR */ 226 227 #define CPU_BUSY_CYCLE() __asm volatile ("" ::: "memory") 228 229 struct cpu_info *set_cpu_number(cpuid_t); 230 231 /* 232 * The md code may hardcode this in some very specific situations. 233 */ 234 #if !defined(cpu_number) 235 #define cpu_number() curcpu()->ci_cpuid 236 #endif 237 238 #define curpcb curcpu()->ci_curpcb 239 240 unsigned int cpu_rnd_messybits(void); 241 242 #endif /* _LOCORE */ 243 244 /* 245 * definitions of cpu-dependent requirements 246 * referenced in generic code 247 */ 248 249 #define cpu_idle_enter() do { /* nothing */ } while (0) 250 #define cpu_idle_cycle() do { /* nothing */ } while (0) 251 #define cpu_idle_leave() do { /* nothing */ } while (0) 252 253 #if defined(MULTIPROCESSOR) 254 #include <sys/mplock.h> 255 #endif 256 257 /* 258 * Arguments to clockintr_dispatch encapsulate the previous 259 * machine state in an opaque clockframe. CLKF_INTR is only valid 260 * if the process is in kernel mode. Clockframe is really trapframe, 261 * so pointer to clockframe can be safely cast into a pointer to 262 * trapframe. 263 */ 264 struct clockframe { 265 struct trapframe tf; 266 }; 267 268 #define CLKF_USERMODE(framep) (((framep)->tf.tf_epsr & PSR_MODE) == 0) 269 #define CLKF_PC(framep) ((framep)->tf.tf_sxip & XIP_ADDR) 270 #define CLKF_INTR(framep) \ 271 (((struct cpu_info *)(framep)->tf.tf_cpu)->ci_idepth > 1) 272 273 #define aston(p) ((p)->p_md.md_astpending = 1) 274 275 /* 276 * This is used during profiling to integrate system time. 277 */ 278 #define PC_REGS(regs) \ 279 (CPU_IS88110 ? ((regs)->exip & XIP_ADDR) : \ 280 ((regs)->sxip & XIP_V ? (regs)->sxip & XIP_ADDR : \ 281 ((regs)->snip & NIP_V ? (regs)->snip & NIP_ADDR : \ 282 (regs)->sfip & FIP_ADDR))) 283 #define PROC_PC(p) PC_REGS((struct reg *)((p)->p_md.md_tf)) 284 #define PROC_STACK(p) ((p)->p_md.md_tf->tf_sp) 285 286 #define clear_resched(ci) (ci)->ci_want_resched = 0 287 288 /* 289 * Give a profiling tick to the current process when the user profiling 290 * buffer pages are invalid. On the m88k, request an ast to send us 291 * through trap(), marking the proc as needing a profiling tick. 292 */ 293 #define need_proftick(p) aston(p) 294 295 void need_resched(struct cpu_info *); 296 void signotify(struct proc *); 297 void softipi(void); 298 299 int badaddr(vaddr_t addr, int size); 300 void set_vbr(register_t); 301 extern register_t kernel_vbr; 302 303 #define copyinsn(p, v, ip) copyin32((v), (ip)) 304 305 #endif /* _KERNEL */ 306 #endif /* _M88K_CPU_H_ */ 307