1 /* $OpenBSD: cpu.h,v 1.97 2021/06/02 00:39:27 cheloha 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/psl.h> 77 #include <machine/reg.h> 78 #include <machine/intr.h> 79 80 #include <sys/sched.h> 81 #include <sys/srp.h> 82 83 /* 84 * The cpu_info structure is part of a 64KB structure mapped both the kernel 85 * pmap and a single locked TTE a CPUINFO_VA for that particular processor. 86 * Each processor's cpu_info is accessible at CPUINFO_VA only for that 87 * processor. Other processors can access that through an additional mapping 88 * in the kernel pmap. 89 * 90 * The 64KB page contains: 91 * 92 * cpu_info 93 * interrupt stack (all remaining space) 94 * idle PCB 95 * idle stack (STACKSPACE - sizeof(PCB)) 96 * 32KB TSB 97 */ 98 99 struct cpu_info { 100 /* 101 * SPARC cpu_info structures live at two VAs: one global 102 * VA (so each CPU can access any other CPU's cpu_info) 103 * and an alias VA CPUINFO_VA which is the same on each 104 * CPU and maps to that CPU's cpu_info. Since the alias 105 * CPUINFO_VA is how we locate our cpu_info, we have to 106 * self-reference the global VA so that we can return it 107 * in the curcpu() macro. 108 */ 109 struct cpu_info * volatile ci_self; 110 111 /* Most important fields first */ 112 struct proc *ci_curproc; 113 struct pcb *ci_cpcb; /* also initial stack */ 114 struct cpu_info *ci_next; 115 116 struct proc *ci_fpproc; 117 int ci_cpuid; 118 int ci_flags; 119 int ci_upaid; 120 #ifdef MULTIPROCESSOR 121 int ci_itid; 122 struct srp_hazard ci_srp_hazards[SRP_HAZARD_NUM]; 123 #endif 124 int ci_node; 125 u_int32_t ci_randseed; 126 struct schedstate_percpu ci_schedstate; /* scheduler state */ 127 128 int ci_want_resched; 129 int ci_handled_intr_level; 130 void *ci_intrpending[16][8]; 131 u_int64_t ci_tick; 132 struct intrhand ci_tickintr; 133 134 volatile int ci_ddb_paused; 135 #define CI_DDB_RUNNING 0 136 #define CI_DDB_SHOULDSTOP 1 137 #define CI_DDB_STOPPED 2 138 #define CI_DDB_ENTERDDB 3 139 #define CI_DDB_INDDB 4 140 141 /* Spinning up the CPU */ 142 void (*ci_spinup)(void); /* spinup routine */ 143 void *ci_initstack; 144 paddr_t ci_paddr; /* Phys addr of this structure. */ 145 146 #ifdef SUN4V 147 struct rwindow64 ci_rw; 148 u_int64_t ci_rwsp; 149 150 paddr_t ci_mmfsa; 151 paddr_t ci_cpumq; 152 paddr_t ci_devmq; 153 154 paddr_t ci_cpuset; 155 paddr_t ci_mondo; 156 #endif 157 158 int ci_pci_probe; 159 int ci_pci_fault; 160 161 #ifdef DIAGNOSTIC 162 int ci_mutex_level; 163 #endif 164 #ifdef GPROF 165 struct gmonparam *ci_gmon; 166 #endif 167 char ci_panicbuf[512]; 168 }; 169 170 #define CPUF_RUNNING 0x0001 /* CPU is running */ 171 172 extern struct cpu_info *cpus; 173 174 #ifdef MULTIPROCESSOR 175 176 register struct cpu_info *__curcpu asm ("g7"); 177 178 #define curcpu() (__curcpu->ci_self) 179 #define cpu_number() (__curcpu->ci_cpuid) 180 181 #define CPU_IS_PRIMARY(ci) ((ci)->ci_cpuid == 0) 182 #define CPU_INFO_ITERATOR int 183 #define CPU_INFO_FOREACH(cii, ci) \ 184 for (cii = 0, ci = cpus; ci != NULL; ci = ci->ci_next) 185 #define CPU_INFO_UNIT(ci) ((ci)->ci_cpuid) 186 #define MAXCPUS 256 187 188 void cpu_boot_secondary_processors(void); 189 190 void sparc64_send_ipi(int, void (*)(void), u_int64_t, u_int64_t); 191 void sparc64_broadcast_ipi(void (*)(void), u_int64_t, u_int64_t); 192 193 void cpu_unidle(struct cpu_info *); 194 195 #else /* MULTIPROCESSOR */ 196 197 #define __curcpu ((struct cpu_info *)CPUINFO_VA) 198 #define curcpu() __curcpu 199 #define cpu_number() 0 200 201 #define CPU_IS_PRIMARY(ci) 1 202 #define CPU_INFO_ITERATOR int 203 #define CPU_INFO_FOREACH(cii, ci) \ 204 for (cii = 0, ci = curcpu(); ci != NULL; ci = NULL) 205 #define CPU_INFO_UNIT(ci) 0 206 #define MAXCPUS 1 207 208 #define cpu_unidle(ci) 209 210 #endif /* MULTIPROCESSOR */ 211 212 #define curpcb __curcpu->ci_cpcb 213 #define fpproc __curcpu->ci_fpproc 214 215 static inline unsigned int 216 cpu_rnd_messybits(void) 217 { 218 u_int64_t tick; 219 220 __asm volatile("rd %%tick, %0" : "=r" (tick) :); 221 222 return ((tick >> 32) ^ tick); 223 } 224 225 /* 226 * On processors with multiple threads we force a thread switch. 227 * 228 * On UltraSPARC T2 and its successors, the optimal way to do this 229 * seems to be to do three nop reads of %ccr. This works on 230 * UltraSPARC T1 as well, even though three nop casx operations seem 231 * to be slightly more optimal. Since these instructions are 232 * effectively nops, executing them on earlier non-CMT processors is 233 * harmless, so we make this the default. 234 * 235 * On SPARC T4 and later, we can use the processor-specific pause 236 * instruction. 237 * 238 * On SPARC64 VI and its successors we execute the processor-specific 239 * sleep instruction. 240 */ 241 #define CPU_BUSY_CYCLE() \ 242 do { \ 243 __asm volatile( \ 244 "999: rd %%ccr, %%g0 \n" \ 245 " rd %%ccr, %%g0 \n" \ 246 " rd %%ccr, %%g0 \n" \ 247 " .section .sun4v_pause_patch, \"ax\" \n" \ 248 " .word 999b \n" \ 249 " .word 0xb7802080 ! pause 128 \n" \ 250 " .word 999b + 4 \n" \ 251 " nop \n" \ 252 " .word 999b + 8 \n" \ 253 " nop \n" \ 254 " .previous \n" \ 255 " .section .sun4u_mtp_patch, \"ax\" \n" \ 256 " .word 999b \n" \ 257 " .word 0x81b01060 ! sleep \n" \ 258 " .word 999b + 4 \n" \ 259 " nop \n" \ 260 " .word 999b + 8 \n" \ 261 " nop \n" \ 262 " .previous \n" \ 263 : : : "memory"); \ 264 } while (0) 265 266 /* 267 * Arguments to hardclock, softclock and gatherstats encapsulate the 268 * previous machine state in an opaque clockframe. The ipl is here 269 * as well for strayintr (see locore.s:interrupt and intr.c:strayintr). 270 */ 271 struct clockframe { 272 struct trapframe64 t; 273 int saved_intr_level; 274 }; 275 276 #define CLKF_USERMODE(framep) (((framep)->t.tf_tstate & TSTATE_PRIV) == 0) 277 #define CLKF_PC(framep) ((framep)->t.tf_pc) 278 #define CLKF_INTR(framep) ((framep)->saved_intr_level != 0) 279 280 extern void (*cpu_start_clock)(void); 281 282 #define aston(p) ((p)->p_md.md_astpending = 1) 283 284 /* 285 * Preempt the current process if in interrupt from user mode, 286 * or after the current trap/syscall if in system mode. 287 */ 288 extern void need_resched(struct cpu_info *); 289 #define clear_resched(ci) (ci)->ci_want_resched = 0 290 291 /* 292 * This is used during profiling to integrate system time. 293 */ 294 #define PROC_PC(p) ((p)->p_md.md_tf->tf_pc) 295 #define PROC_STACK(p) ((p)->p_md.md_tf->tf_out[6] + (2048-1)) /* BIAS */ 296 297 /* 298 * Give a profiling tick to the current process when the user profiling 299 * buffer pages are invalid. On the sparc, request an ast to send us 300 * through trap(), marking the proc as needing a profiling tick. 301 */ 302 #define need_proftick(p) aston(p) 303 304 void signotify(struct proc *); 305 306 /* cpu.c */ 307 int cpu_myid(void); 308 /* machdep.c */ 309 int ldcontrolb(caddr_t); 310 void dumpconf(void); 311 caddr_t reserve_dumppages(caddr_t); 312 /* clock.c */ 313 struct timeval; 314 int clockintr(void *);/* level 10 (clock) interrupt code */ 315 int statintr(void *); /* level 14 (statclock) interrupt code */ 316 /* locore.s */ 317 struct fpstate64; 318 void savefpstate(struct fpstate64 *); 319 void loadfpstate(struct fpstate64 *); 320 void clearfpstate(void); 321 u_int64_t probeget(paddr_t, int, int); 322 #define write_all_windows() __asm volatile("flushw" : : ) 323 void write_user_windows(void); 324 void proc_trampoline(void); 325 struct pcb; 326 void snapshot(struct pcb *); 327 struct frame *getfp(void); 328 int xldcontrolb(caddr_t, struct pcb *); 329 void copywords(const void *, void *, size_t); 330 void qcopy(const void *, void *, size_t); 331 void qzero(void *, size_t); 332 void switchtoctx(int); 333 /* trap.c */ 334 void pmap_unuse_final(struct proc *); 335 int rwindow_save(struct proc *); 336 /* vm_machdep.c */ 337 void fpusave_cpu(struct cpu_info *, int); 338 void fpusave_proc(struct proc *, int); 339 /* cons.c */ 340 int cnrom(void); 341 /* zs.c */ 342 void zsconsole(struct tty *, int, int, void (**)(struct tty *, int)); 343 /* fb.c */ 344 void fb_unblank(void); 345 /* tda.c */ 346 void tda_full_blast(void); 347 /* emul.c */ 348 int emul_qf(int32_t, struct proc *, union sigval, struct trapframe64 *); 349 int emul_popc(int32_t, struct proc *, union sigval, struct trapframe64 *); 350 351 /* 352 * 353 * The SPARC has a Trap Base Register (TBR) which holds the upper 20 bits 354 * of the trap vector table. The next eight bits are supplied by the 355 * hardware when the trap occurs, and the bottom four bits are always 356 * zero (so that we can shove up to 16 bytes of executable code---exactly 357 * four instructions---into each trap vector). 358 * 359 * The hardware allocates half the trap vectors to hardware and half to 360 * software. 361 * 362 * Traps have priorities assigned (lower number => higher priority). 363 */ 364 365 struct trapvec { 366 int tv_instr[8]; /* the eight instructions */ 367 }; 368 extern struct trapvec trapbase[]; /* the 256 vectors */ 369 370 extern void wzero(void *, u_int); 371 extern void wcopy(const void *, void *, u_int); 372 373 struct blink_led { 374 void (*bl_func)(void *, int); 375 void *bl_arg; 376 SLIST_ENTRY(blink_led) bl_next; 377 }; 378 379 extern void blink_led_register(struct blink_led *); 380 381 #ifdef MULTIPROCESSOR 382 #include <sys/mplock.h> 383 #endif 384 385 #endif /* _KERNEL */ 386 #endif /* _MACHINE_CPU_H_ */ 387