1 /* $OpenBSD: psl.h,v 1.26 2009/03/15 19:40:40 miod Exp $ */ 2 /* $NetBSD: psl.h,v 1.20 2001/04/13 23:30:05 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 * @(#)psl.h 8.1 (Berkeley) 6/11/93 42 */ 43 44 #ifndef _SPARC64_PSL_ 45 #define _SPARC64_PSL_ 46 47 /* Interesting spl()s */ 48 #define PIL_SCSI 3 49 #define PIL_FDSOFT 4 50 #define PIL_AUSOFT 4 51 #define PIL_BIO 5 52 #define PIL_VIDEO 5 53 #define PIL_TTY 6 54 #define PIL_LPT 6 55 #define PIL_NET 6 56 #define PIL_VM 7 57 #define PIL_AUD 8 58 #define PIL_CLOCK 10 59 #define PIL_FD 11 60 #define PIL_SER 12 61 #define PIL_STATCLOCK 14 62 #define PIL_HIGH 15 63 #define PIL_SCHED PIL_STATCLOCK 64 #define PIL_LOCK PIL_HIGH 65 66 /* 67 * SPARC V9 CCR register 68 */ 69 70 #define ICC_C 0x01L 71 #define ICC_V 0x02L 72 #define ICC_Z 0x04L 73 #define ICC_N 0x08L 74 #define XCC_SHIFT 4 75 #define XCC_C (ICC_C<<XCC_SHIFT) 76 #define XCC_V (ICC_V<<XCC_SHIFT) 77 #define XCC_Z (ICC_Z<<XCC_SHIFT) 78 #define XCC_N (ICC_N<<XCC_SHIFT) 79 80 81 /* 82 * SPARC V9 PSTATE register (what replaces the PSR in V9) 83 * 84 * Here's the layout: 85 * 86 * 11 10 9 8 7 6 5 4 3 2 1 0 87 * +------------------------------------------------------------+ 88 * | IG | MG | CLE | TLE | MM | RED | PEF | AM | PRIV | IE | AG | 89 * +------------------------------------------------------------+ 90 */ 91 92 #define PSTATE_IG 0x800 /* enable spitfire interrupt globals */ 93 #define PSTATE_MG 0x400 /* enable spitfire MMU globals */ 94 #define PSTATE_CLE 0x200 /* current little endian */ 95 #define PSTATE_TLE 0x100 /* traps little endian */ 96 #define PSTATE_MM 0x0c0 /* memory model */ 97 #define PSTATE_MM_TSO 0x000 /* total store order */ 98 #define PSTATE_MM_PSO 0x040 /* partial store order */ 99 #define PSTATE_MM_RMO 0x080 /* Relaxed memory order */ 100 #define PSTATE_RED 0x020 /* RED state */ 101 #define PSTATE_PEF 0x010 /* enable floating point */ 102 #define PSTATE_AM 0x008 /* 32-bit address masking */ 103 #define PSTATE_PRIV 0x004 /* privileged mode */ 104 #define PSTATE_IE 0x002 /* interrupt enable */ 105 #define PSTATE_AG 0x001 /* enable alternate globals */ 106 107 #define PSTATE_BITS "\20\14IG\13MG\12CLE\11TLE\10\7MM\6RED\5PEF\4AM\3PRIV\2IE\1AG" 108 109 110 /* 111 * 32-bit code requires TSO or at best PSO since that's what's supported on 112 * SPARC V8 and earlier machines. 113 * 114 * 64-bit code sets the memory model in the ELF header. 115 * 116 * We're running kernel code in TSO for the moment so we don't need to worry 117 * about possible memory barrier bugs. 118 */ 119 120 #define PSTATE_PROM (PSTATE_MM_TSO|PSTATE_PRIV) 121 #define PSTATE_NUCLEUS (PSTATE_MM_TSO|PSTATE_PRIV|PSTATE_AG) 122 #define PSTATE_KERN (PSTATE_MM_TSO|PSTATE_PRIV) 123 #define PSTATE_INTR (PSTATE_KERN|PSTATE_IE) 124 #define PSTATE_USER32 (PSTATE_MM_TSO|PSTATE_AM|PSTATE_IE) 125 #define PSTATE_USER (PSTATE_MM_RMO|PSTATE_IE) 126 127 128 /* 129 * SPARC V9 TSTATE register 130 * 131 * 39 32 31 24 23 18 17 8 7 5 4 0 132 * +-----+-----+-----+--------+---+-----+ 133 * | CCR | ASI | - | PSTATE | - | CWP | 134 * +-----+-----+-----+--------+---+-----+ 135 */ 136 137 #define TSTATE_CWP 0x01f 138 #define TSTATE_PSTATE 0x6ff00 139 #define TSTATE_PSTATE_SHIFT 8 140 #define TSTATE_ASI 0xff000000LL 141 #define TSTATE_ASI_SHIFT 24 142 #define TSTATE_CCR 0xff00000000LL 143 #define TSTATE_CCR_SHIFT 32 144 145 /* Leftover SPARC V8 PSTATE stuff */ 146 #define PSR_ICC 0x00f00000 147 #define PSRCC_TO_TSTATE(x) (((int64_t)(x)&PSR_ICC)<<(TSTATE_CCR_SHIFT-19)) 148 #define TSTATECCR_TO_PSR(x) (((x)&TSTATE_CCR)>>(TSTATE_CCR_SHIFT-19)) 149 150 /* 151 * These are here to simplify life. 152 */ 153 #define TSTATE_IG (PSTATE_IG<<TSTATE_PSTATE_SHIFT) 154 #define TSTATE_MG (PSTATE_MG<<TSTATE_PSTATE_SHIFT) 155 #define TSTATE_CLE (PSTATE_CLE<<TSTATE_PSTATE_SHIFT) 156 #define TSTATE_TLE (PSTATE_TLE<<TSTATE_PSTATE_SHIFT) 157 #define TSTATE_MM (PSTATE_MM<<TSTATE_PSTATE_SHIFT) 158 #define TSTATE_MM_TSO (PSTATE_MM_TSO<<TSTATE_PSTATE_SHIFT) 159 #define TSTATE_MM_PSO (PSTATE_MM_PSO<<TSTATE_PSTATE_SHIFT) 160 #define TSTATE_MM_RMO (PSTATE_MM_RMO<<TSTATE_PSTATE_SHIFT) 161 #define TSTATE_RED (PSTATE_RED<<TSTATE_PSTATE_SHIFT) 162 #define TSTATE_PEF (PSTATE_PEF<<TSTATE_PSTATE_SHIFT) 163 #define TSTATE_AM (PSTATE_AM<<TSTATE_PSTATE_SHIFT) 164 #define TSTATE_PRIV (PSTATE_PRIV<<TSTATE_PSTATE_SHIFT) 165 #define TSTATE_IE (PSTATE_IE<<TSTATE_PSTATE_SHIFT) 166 #define TSTATE_AG (PSTATE_AG<<TSTATE_PSTATE_SHIFT) 167 168 #define TSTATE_BITS "\20\14IG\13MG\12CLE\11TLE\10\7MM\6RED\5PEF\4AM\3PRIV\2IE\1AG" 169 170 #define TSTATE_KERN ((PSTATE_KERN)<<TSTATE_PSTATE_SHIFT) 171 #define TSTATE_USER ((PSTATE_USER)<<TSTATE_PSTATE_SHIFT) 172 /* 173 * SPARC V9 VER version register. 174 * 175 * 63 48 47 32 31 24 23 16 15 8 7 5 4 0 176 * +-------+------+------+-----+-------+---+--------+ 177 * | manuf | impl | mask | - | maxtl | - | maxwin | 178 * +-------+------+------+-----+-------+---+--------+ 179 * 180 */ 181 182 #define VER_MANUF 0xffff000000000000ULL 183 #define VER_MANUF_SHIFT 48 184 #define VER_IMPL 0x0000ffff00000000ULL 185 #define VER_IMPL_SHIFT 32 186 #define VER_MASK 0x00000000ff000000ULL 187 #define VER_MASK_SHIFT 24 188 #define VER_MAXTL 0x000000000000ff00ULL 189 #define VER_MAXTL_SHIFT 8 190 #define VER_MAXWIN 0x000000000000001fULL 191 192 #define IMPL_SPARC64 0x01 /* SPARC64 */ 193 #define IMPL_SPARC64_II 0x02 /* SPARC64-II */ 194 #define IMPL_SPARC64_III 0x03 /* SPARC64-III */ 195 #define IMPL_SPARC64_IV 0x04 /* SPARC64-IV */ 196 #define IMPL_ZEUS 0x05 /* SPARC64-V */ 197 #define IMPL_OLYMPUS_C 0x06 /* SPARC64-VI */ 198 #define IMPL_JUPITER 0x07 /* SPARC64-VII */ 199 #define IMPL_SPITFIRE 0x10 /* UltraSPARC */ 200 #define IMPL_BLACKBIRD 0x11 /* UltraSPARC-II */ 201 #define IMPL_SABRE 0x12 /* UltraSPARC-IIi */ 202 #define IMPL_HUMMINGBIRD 0x13 /* UltraSPARC-IIe */ 203 #define IMPL_CHEETAH 0x14 /* UltraSPARC-III */ 204 #define IMPL_CHEETAH_PLUS 0x15 /* UltraSPARC-III+ */ 205 #define IMPL_JALAPENO 0x16 /* UltraSPARC-IIIi */ 206 #define IMPL_JAGUAR 0x18 /* UltraSPARC-IV */ 207 #define IMPL_PANTHER 0x19 /* UltraSPARC-IV+ */ 208 #define IMPL_SERRANO 0x22 /* UltraSPARC-IIIi+ */ 209 210 /* 211 * Here are a few things to help us transition between user and kernel mode: 212 */ 213 214 /* Memory models */ 215 #define KERN_MM PSTATE_MM_TSO 216 #define USER_MM PSTATE_MM_RMO 217 218 /* 219 * Register window handlers. These point to generic routines that check the 220 * stack pointer and then vector to the real handler. We could optimize this 221 * if we could guarantee only 32-bit or 64-bit stacks. 222 */ 223 #define WSTATE_KERN 027 224 #define WSTATE_USER 022 225 226 #define CWP 0x01f 227 228 /* 64-byte alignment -- this seems the best place to put this. */ 229 #define BLOCK_SIZE 64 230 #define BLOCK_ALIGN 0x3f 231 232 #if defined(_KERNEL) && !defined(_LOCORE) 233 234 extern u_int64_t ver; /* Copy of v9 version register. We need to read this only once, in locore.s. */ 235 #ifndef SPLDEBUG 236 extern __inline void splx(int); 237 #endif 238 239 #ifdef DIAGNOSTIC 240 /* 241 * Although this function is implemented in MI code, it must be in this MD 242 * header because we don't want this header to include MI includes. 243 */ 244 void splassert_fail(int, int, const char *); 245 extern int splassert_ctl; 246 void splassert_check(int, const char *); 247 #define splassert(__wantipl) do { \ 248 if (splassert_ctl > 0) { \ 249 splassert_check(__wantipl, __func__); \ 250 } \ 251 } while (0) 252 #define splsoftassert(wantipl) splassert(wantipl) 253 #else 254 #define splassert(wantipl) do { /* nada */ } while (0) 255 #define splsoftassert(wantipl) do { /* nada */ } while (0) 256 #endif 257 258 /* 259 * GCC pseudo-functions for manipulating privileged registers 260 */ 261 extern __inline u_int64_t getpstate(void); 262 extern __inline 263 u_int64_t getpstate() 264 { 265 return (sparc_rdpr(pstate)); 266 } 267 268 extern __inline void setpstate(u_int64_t); 269 extern __inline void setpstate(u_int64_t newpstate) 270 { 271 sparc_wrpr(pstate, newpstate, 0); 272 } 273 274 extern __inline int getcwp(void); 275 extern __inline 276 int getcwp() 277 { 278 return (sparc_rdpr(cwp)); 279 } 280 281 extern __inline void setcwp(u_int64_t); 282 extern __inline void 283 setcwp(u_int64_t newcwp) 284 { 285 sparc_wrpr(cwp, newcwp, 0); 286 } 287 288 extern __inline u_int64_t getver(void); 289 extern __inline 290 u_int64_t getver() 291 { 292 return (sparc_rdpr(ver)); 293 } 294 295 extern __inline u_int64_t intr_disable(void); 296 extern __inline u_int64_t 297 intr_disable() 298 { 299 u_int64_t s; 300 301 s = sparc_rdpr(pstate); 302 sparc_wrpr(pstate, s & ~PSTATE_IE, 0); 303 return (s); 304 } 305 306 extern __inline void intr_restore(u_int64_t); 307 extern __inline void 308 intr_restore(u_int64_t s) 309 { 310 sparc_wrpr(pstate, s, 0); 311 } 312 313 extern __inline void stxa_sync(u_int64_t, u_int64_t, u_int64_t); 314 extern __inline void 315 stxa_sync(u_int64_t va, u_int64_t asi, u_int64_t val) 316 { 317 u_int64_t s = intr_disable(); 318 stxa_nc(va, asi, val); 319 membar(Sync); 320 intr_restore(s); 321 } 322 323 /* 324 * GCC pseudo-functions for manipulating PIL 325 */ 326 327 #ifdef SPLDEBUG 328 void prom_printf(const char *fmt, ...); 329 extern int printspl; 330 #define SPLPRINT(x) if(printspl) { int i=10000000; prom_printf x ; while(i--); } 331 #define SPL(name, newpil) \ 332 extern __inline int name##X(const char *, int); \ 333 extern __inline int name##X(const char *file, int line) \ 334 { \ 335 u_int64_t oldpil = sparc_rdpr(pil); \ 336 SPLPRINT(("{%s:%d %d=>%d}", file, line, oldpil, newpil)); \ 337 sparc_wrpr(pil, newpil, 0); \ 338 return (oldpil); \ 339 } 340 /* A non-priority-decreasing version of SPL */ 341 #define SPLHOLD(name, newpil) \ 342 extern __inline int name##X(const char *, int); \ 343 extern __inline int name##X(const char * file, int line) \ 344 { \ 345 int oldpil = sparc_rdpr(pil); \ 346 if (__predict_false((u_int64_t)newpil <= oldpil)) \ 347 return (oldpil); \ 348 SPLPRINT(("{%s:%d %d->!d}", file, line, oldpil, newpil)); \ 349 sparc_wrpr(pil, newpil, 0); \ 350 return (oldpil); \ 351 } 352 353 #else 354 #define SPLPRINT(x) 355 #define SPL(name, newpil) \ 356 extern __inline int name(void); \ 357 extern __inline int name() \ 358 { \ 359 int oldpil; \ 360 __asm __volatile(" rdpr %%pil, %0 \n" \ 361 " wrpr %%g0, %1, %%pil \n" \ 362 : "=&r" (oldpil) \ 363 : "n" (newpil) \ 364 : "%g0"); \ 365 __asm __volatile("" : : : "memory"); \ 366 return (oldpil); \ 367 } 368 /* A non-priority-decreasing version of SPL */ 369 #define SPLHOLD(name, newpil) \ 370 extern __inline int name(void); \ 371 extern __inline int name() \ 372 { \ 373 int oldpil; \ 374 \ 375 if (newpil <= 1) { \ 376 __asm __volatile(" rdpr %%pil, %0 \n" \ 377 " brnz,pn %0, 1f \n" \ 378 " nop \n" \ 379 " wrpr %%g0, %1, %%pil \n" \ 380 "1: \n" \ 381 : "=&r" (oldpil) \ 382 : "I" (newpil) \ 383 : "%g0"); \ 384 } else { \ 385 __asm __volatile(" rdpr %%pil, %0 \n" \ 386 " cmp %0, %1 - 1 \n" \ 387 " bgu,pn %%xcc, 1f \n" \ 388 " nop \n" \ 389 " wrpr %%g0, %1, %%pil \n" \ 390 "1: \n" \ 391 : "=&r" (oldpil) \ 392 : "I" (newpil) \ 393 : "cc"); \ 394 } \ 395 __asm __volatile("" : : : "memory"); \ 396 return (oldpil); \ 397 } 398 #endif 399 400 SPL(spl0, 0) 401 402 SPLHOLD(splsoftint, 1) 403 #define splsoftclock splsoftint 404 #define splsoftnet splsoftint 405 406 /* audio software interrupts are at software level 4 */ 407 SPLHOLD(splausoft, PIL_AUSOFT) 408 409 /* floppy software interrupts are at software level 4 too */ 410 SPLHOLD(splfdsoft, PIL_FDSOFT) 411 412 /* Block devices */ 413 SPLHOLD(splbio, PIL_BIO) 414 415 /* network hardware interrupts are at level 6 */ 416 SPLHOLD(splnet, PIL_NET) 417 418 /* tty input runs at software level 6 */ 419 SPLHOLD(spltty, PIL_TTY) 420 421 /* parallel port runs at software level 6 */ 422 SPLHOLD(spllpt, PIL_LPT) 423 424 /* 425 * Memory allocation (must be as high as highest network, tty, or disk device) 426 */ 427 SPLHOLD(splvm, PIL_VM) 428 429 SPLHOLD(splclock, PIL_CLOCK) 430 431 /* fd hardware interrupts are at level 11 */ 432 SPLHOLD(splfd, PIL_FD) 433 434 /* zs hardware interrupts are at level 12 */ 435 SPLHOLD(splzs, PIL_SER) 436 SPLHOLD(splserial, PIL_SER) 437 438 /* audio hardware interrupts are at level 13 */ 439 SPLHOLD(splaudio, PIL_AUD) 440 441 /* second sparc timer interrupts at level 14 */ 442 SPLHOLD(splstatclock, PIL_STATCLOCK) 443 444 SPLHOLD(splsched, PIL_SCHED) 445 SPLHOLD(spllock, PIL_LOCK) 446 447 SPLHOLD(splhigh, PIL_HIGH) 448 449 /* splx does not have a return value */ 450 #ifdef SPLDEBUG 451 452 #define spl0() spl0X(__FILE__, __LINE__) 453 #define splsoftint() splsoftintX(__FILE__, __LINE__) 454 #define splausoft() splausoftX(__FILE__, __LINE__) 455 #define splfdsoft() splfdsoftX(__FILE__, __LINE__) 456 #define splbio() splbioX(__FILE__, __LINE__) 457 #define splnet() splnetX(__FILE__, __LINE__) 458 #define spltty() splttyX(__FILE__, __LINE__) 459 #define spllpt() spllptX(__FILE__, __LINE__) 460 #define splvm() splvmX(__FILE__, __LINE__) 461 #define splclock() splclockX(__FILE__, __LINE__) 462 #define splfd() splfdX(__FILE__, __LINE__) 463 #define splzs() splzsX(__FILE__, __LINE__) 464 #define splserial() splzerialX(__FILE__, __LINE__) 465 #define splaudio() splaudioX(__FILE__, __LINE__) 466 #define splstatclock() splstatclockX(__FILE__, __LINE__) 467 #define splsched() splschedX(__FILE__, __LINE__) 468 #define spllock() spllockX(__FILE__, __LINE__) 469 #define splhigh() splhighX(__FILE__, __LINE__) 470 #define splx(x) splxX((x),__FILE__, __LINE__) 471 472 extern __inline void splxX(u_int64_t, const char *, int); 473 extern __inline void 474 splxX(u_int64_t newpil, const char *file, int line) 475 #else 476 extern __inline void splx(int newpil) 477 #endif 478 { 479 #ifdef SPLDEBUG 480 u_int64_t oldpil = sparc_rdpr(pil); 481 SPLPRINT(("{%d->%d}", oldpil, newpil)); 482 #endif 483 sparc_wrpr(pil, newpil, 0); 484 } 485 #endif /* KERNEL && !_LOCORE */ 486 487 #endif /* _SPARC64_PSL_ */ 488