1 /* $OpenBSD: cpu.h,v 1.109 2024/11/06 12:06:15 miod Exp $ */ 2 /* $NetBSD: cpu.h,v 1.28 2001/06/14 22:56:58 thorpej Exp $ */ 3 4 /* 5 * Copyright (c) 1992, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This software was developed by the Computer Systems Engineering group 9 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 10 * contributed to Berkeley. 11 * 12 * All advertising materials mentioning features or use of this software 13 * must display the following acknowledgement: 14 * This product includes software developed by the University of 15 * California, Lawrence Berkeley Laboratory. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions 19 * are met: 20 * 1. Redistributions of source code must retain the above copyright 21 * notice, this list of conditions and the following disclaimer. 22 * 2. Redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in the 24 * documentation and/or other materials provided with the distribution. 25 * 3. Neither the name of the University nor the names of its contributors 26 * may be used to endorse or promote products derived from this software 27 * without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * SUCH DAMAGE. 40 * 41 * @(#)cpu.h 8.4 (Berkeley) 1/5/94 42 */ 43 44 #ifndef _MACHINE_CPU_H_ 45 #define _MACHINE_CPU_H_ 46 47 /* 48 * CTL_MACHDEP definitions. 49 */ 50 /* 1 formerly: booted kernel name */ 51 #define CPU_LED_BLINK 2 /* int: blink leds? */ 52 #define CPU_ALLOWAPERTURE 3 /* allow xf86 operations */ 53 #define CPU_CPUTYPE 4 /* cpu type */ 54 #define CPU_CECCERRORS 5 /* Correctable ECC errors */ 55 #define CPU_CECCLAST 6 /* Correctable ECC last fault addr */ 56 /* 7 formerly: soft reset via keyboard */ 57 #define CPU_MAXID 8 /* number of valid machdep ids */ 58 59 #define CTL_MACHDEP_NAMES { \ 60 { 0, 0 }, \ 61 { 0, 0 }, \ 62 { "led_blink", CTLTYPE_INT }, \ 63 { "allowaperture", CTLTYPE_INT }, \ 64 { "cputype", CTLTYPE_INT }, \ 65 { "ceccerrs", CTLTYPE_INT }, \ 66 { "cecclast", CTLTYPE_QUAD }, \ 67 { 0, 0 }, \ 68 } 69 70 #ifdef _KERNEL 71 /* 72 * Exported definitions unique to SPARC cpu support. 73 */ 74 75 #include <machine/ctlreg.h> 76 #include <machine/frame.h> 77 #include <machine/intr.h> 78 #include <machine/psl.h> 79 #include <machine/reg.h> 80 81 #include <sys/clockintr.h> 82 #include <sys/sched.h> 83 #include <sys/srp.h> 84 #include <uvm/uvm_percpu.h> 85 86 /* 87 * The cpu_info structure is part of a 64KB structure mapped both the kernel 88 * pmap and a single locked TTE a CPUINFO_VA for that particular processor. 89 * Each processor's cpu_info is accessible at CPUINFO_VA only for that 90 * processor. Other processors can access that through an additional mapping 91 * in the kernel pmap. 92 * 93 * The 64KB page contains: 94 * 95 * cpu_info 96 * interrupt stack (all remaining space) 97 * idle PCB 98 * idle stack (STACKSPACE - sizeof(PCB)) 99 * 32KB TSB 100 */ 101 102 struct cpu_info { 103 /* 104 * SPARC cpu_info structures live at two VAs: one global 105 * VA (so each CPU can access any other CPU's cpu_info) 106 * and an alias VA CPUINFO_VA which is the same on each 107 * CPU and maps to that CPU's cpu_info. Since the alias 108 * CPUINFO_VA is how we locate our cpu_info, we have to 109 * self-reference the global VA so that we can return it 110 * in the curcpu() macro. 111 */ 112 struct cpu_info * volatile ci_self; 113 114 /* Most important fields first */ 115 struct proc *ci_curproc; 116 struct pcb *ci_cpcb; /* also initial stack */ 117 paddr_t ci_cpcbpaddr; 118 struct cpu_info *ci_next; 119 120 struct proc *ci_fpproc; 121 int ci_cpuid; 122 int ci_flags; 123 int ci_upaid; 124 #ifdef MULTIPROCESSOR 125 int ci_itid; 126 struct srp_hazard ci_srp_hazards[SRP_HAZARD_NUM]; 127 #define __HAVE_UVM_PERCPU 128 struct uvm_pmr_cache ci_uvm; /* [o] page cache */ 129 #endif 130 int ci_node; 131 u_int32_t ci_randseed; 132 struct schedstate_percpu ci_schedstate; /* scheduler state */ 133 134 int ci_want_resched; 135 int ci_handled_intr_level; 136 int ci_idepth; 137 struct intrhand *ci_intrpending[16]; 138 struct clockqueue ci_queue; 139 struct intrhand ci_tickintr; 140 141 volatile int ci_ddb_paused; 142 #define CI_DDB_RUNNING 0 143 #define CI_DDB_SHOULDSTOP 1 144 #define CI_DDB_STOPPED 2 145 #define CI_DDB_ENTERDDB 3 146 #define CI_DDB_INDDB 4 147 148 /* Spinning up the CPU */ 149 void (*ci_spinup)(void); /* spinup routine */ 150 void *ci_initstack; 151 paddr_t ci_paddr; /* Phys addr of this structure. */ 152 153 #ifdef SUN4V 154 struct rwindow ci_rw; 155 u_int64_t ci_rwsp; 156 157 paddr_t ci_mmfsa; 158 paddr_t ci_cpumq; 159 paddr_t ci_devmq; 160 161 paddr_t ci_cpuset; 162 paddr_t ci_mondo; 163 #endif 164 165 int ci_pci_probe; 166 int ci_pci_fault; 167 168 #ifdef DIAGNOSTIC 169 int ci_mutex_level; 170 #endif 171 #ifdef GPROF 172 struct gmonparam *ci_gmon; 173 struct clockintr ci_gmonclock; 174 #endif 175 char ci_panicbuf[512]; 176 }; 177 178 #define CPUF_RUNNING 0x0001 /* CPU is running */ 179 180 extern struct cpu_info *cpus; 181 182 #ifdef MULTIPROCESSOR 183 184 register struct cpu_info *__curcpu asm ("g7"); 185 186 #define curcpu() (__curcpu->ci_self) 187 #define cpu_number() (__curcpu->ci_cpuid) 188 189 #define CPU_IS_PRIMARY(ci) ((ci)->ci_cpuid == 0) 190 #define CPU_IS_RUNNING(ci) 1 191 #define CPU_INFO_ITERATOR int 192 #define CPU_INFO_FOREACH(cii, ci) \ 193 for (cii = 0, ci = cpus; ci != NULL; ci = ci->ci_next) 194 #define CPU_INFO_UNIT(ci) ((ci)->ci_cpuid) 195 #define MAXCPUS 256 196 197 void cpu_boot_secondary_processors(void); 198 199 void sparc64_send_ipi(int, void (*)(void), u_int64_t, u_int64_t); 200 void sparc64_broadcast_ipi(void (*)(void), u_int64_t, u_int64_t); 201 202 void cpu_unidle(struct cpu_info *); 203 204 #else /* MULTIPROCESSOR */ 205 206 #define __curcpu ((struct cpu_info *)CPUINFO_VA) 207 #define curcpu() __curcpu 208 #define cpu_number() 0 209 210 #define CPU_IS_PRIMARY(ci) 1 211 #define CPU_IS_RUNNING(ci) 1 212 #define CPU_INFO_ITERATOR int 213 #define CPU_INFO_FOREACH(cii, ci) \ 214 for (cii = 0, ci = curcpu(); ci != NULL; ci = NULL) 215 #define CPU_INFO_UNIT(ci) 0 216 #define MAXCPUS 1 217 218 #define cpu_unidle(ci) 219 220 #endif /* MULTIPROCESSOR */ 221 222 #define curpcb __curcpu->ci_cpcb 223 #define fpproc __curcpu->ci_fpproc 224 225 static inline unsigned int 226 cpu_rnd_messybits(void) 227 { 228 u_int64_t tick; 229 230 __asm volatile("rd %%tick, %0" : "=r" (tick) :); 231 232 return ((tick >> 32) ^ tick); 233 } 234 235 /* 236 * On processors with multiple threads we force a thread switch. 237 * 238 * On UltraSPARC T2 and its successors, the optimal way to do this 239 * seems to be to do three nop reads of %ccr. This works on 240 * UltraSPARC T1 as well, even though three nop casx operations seem 241 * to be slightly more optimal. Since these instructions are 242 * effectively nops, executing them on earlier non-CMT processors is 243 * harmless, so we make this the default. 244 * 245 * On SPARC T4 and later, we can use the processor-specific pause 246 * instruction. 247 * 248 * On SPARC64 VI and its successors we execute the processor-specific 249 * sleep instruction. 250 */ 251 #define CPU_BUSY_CYCLE() \ 252 do { \ 253 __asm volatile( \ 254 "999: rd %%ccr, %%g0 \n" \ 255 " rd %%ccr, %%g0 \n" \ 256 " rd %%ccr, %%g0 \n" \ 257 " .section .sun4v_pause_patch, \"ax\" \n" \ 258 " .word 999b \n" \ 259 " .word 0xb7802080 ! pause 128 \n" \ 260 " .word 999b + 4 \n" \ 261 " nop \n" \ 262 " .word 999b + 8 \n" \ 263 " nop \n" \ 264 " .previous \n" \ 265 " .section .sun4u_mtp_patch, \"ax\" \n" \ 266 " .word 999b \n" \ 267 " .word 0x81b01060 ! sleep \n" \ 268 " .word 999b + 4 \n" \ 269 " nop \n" \ 270 " .word 999b + 8 \n" \ 271 " nop \n" \ 272 " .previous \n" \ 273 : : : "memory"); \ 274 } while (0) 275 276 /* 277 * Arguments to clockintr_dispatch encapsulate the 278 * previous machine state in an opaque clockframe. 279 */ 280 struct clockframe { 281 struct trapframe t; 282 int saved_intr_level; 283 }; 284 285 #define CLKF_USERMODE(framep) (((framep)->t.tf_tstate & TSTATE_PRIV) == 0) 286 #define CLKF_PC(framep) ((framep)->t.tf_pc) 287 #define CLKF_INTR(framep) ((framep)->saved_intr_level != 0) 288 289 extern void (*cpu_start_clock)(void); 290 291 #define aston(p) ((p)->p_md.md_astpending = 1) 292 293 /* 294 * Preempt the current process if in interrupt from user mode, 295 * or after the current trap/syscall if in system mode. 296 */ 297 extern void need_resched(struct cpu_info *); 298 #define clear_resched(ci) (ci)->ci_want_resched = 0 299 300 /* 301 * This is used during profiling to integrate system time. 302 */ 303 #define PROC_PC(p) ((p)->p_md.md_tf->tf_pc) 304 #define PROC_STACK(p) ((p)->p_md.md_tf->tf_out[6] + (2048-1)) /* BIAS */ 305 306 /* 307 * Give a profiling tick to the current process when the user profiling 308 * buffer pages are invalid. On the sparc, request an ast to send us 309 * through trap(), marking the proc as needing a profiling tick. 310 */ 311 #define need_proftick(p) aston(p) 312 313 void signotify(struct proc *); 314 315 /* cpu.c */ 316 int cpu_myid(void); 317 /* machdep.c */ 318 void dumpconf(void); 319 caddr_t reserve_dumppages(caddr_t); 320 /* clock.c */ 321 struct timeval; 322 int clockintr(void *);/* level 10 (clock) interrupt code */ 323 /* locore.s */ 324 struct fpstate; 325 void savefpstate(struct fpstate *); 326 void loadfpstate(struct fpstate *); 327 void clearfpstate(void); 328 u_int64_t probeget(paddr_t, int, int); 329 #define write_all_windows() __asm volatile("flushw" : : ) 330 void write_user_windows(void); 331 void proc_trampoline(void); 332 struct pcb; 333 void snapshot(struct pcb *); 334 struct frame *getfp(void); 335 void switchtoctx(int); 336 /* trap.c */ 337 void pmap_unuse_final(struct proc *); 338 int rwindow_save(struct proc *); 339 /* vm_machdep.c */ 340 void fpusave_cpu(struct cpu_info *, int); 341 void fpusave_proc(struct proc *, int); 342 /* fb.c */ 343 void fb_unblank(void); 344 /* ltc.c */ 345 void ltc_full_blast(void); 346 /* tda.c */ 347 void tda_full_blast(void); 348 /* emul.c */ 349 int emul_qf(int32_t, struct proc *, union sigval, struct trapframe *); 350 int emul_popc(int32_t, struct proc *, union sigval, struct trapframe *); 351 352 /* 353 * 354 * The SPARC has a Trap Base Register (TBR) which holds the upper 20 bits 355 * of the trap vector table. The next eight bits are supplied by the 356 * hardware when the trap occurs, and the bottom four bits are always 357 * zero (so that we can shove up to 16 bytes of executable code---exactly 358 * four instructions---into each trap vector). 359 * 360 * The hardware allocates half the trap vectors to hardware and half to 361 * software. 362 * 363 * Traps have priorities assigned (lower number => higher priority). 364 */ 365 366 struct trapvec { 367 int tv_instr[8]; /* the eight instructions */ 368 }; 369 extern struct trapvec trapbase[]; /* the 256 vectors */ 370 371 struct blink_led { 372 void (*bl_func)(void *, int); 373 void *bl_arg; 374 SLIST_ENTRY(blink_led) bl_next; 375 }; 376 377 extern void blink_led_register(struct blink_led *); 378 379 #ifdef MULTIPROCESSOR 380 #include <sys/mplock.h> 381 #endif 382 383 #endif /* _KERNEL */ 384 #endif /* _MACHINE_CPU_H_ */ 385