| 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_ */ |