1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 1614 jb145095 * Common Development and Distribution License (the "License"). 6 1614 jb145095 * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 0 stevel /* 22 8803 Jonathan * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 0 stevel * Use is subject to license terms. 24 0 stevel */ 25 0 stevel 26 0 stevel #if !defined(lint) 27 0 stevel #include "assym.h" 28 0 stevel #endif 29 0 stevel 30 0 stevel /* 31 0 stevel * General assembly language routines. 32 0 stevel * It is the intent of this file to contain routines that are 33 0 stevel * specific to cpu architecture. 34 0 stevel */ 35 0 stevel 36 0 stevel /* 37 0 stevel * WARNING: If you add a fast trap handler which can be invoked by a 38 0 stevel * non-privileged user, you may have to use the FAST_TRAP_DONE macro 39 0 stevel * instead of "done" instruction to return back to the user mode. See 40 0 stevel * comments for the "fast_trap_done" entry point for more information. 41 0 stevel */ 42 0 stevel #define FAST_TRAP_DONE \ 43 0 stevel ba,a fast_trap_done 44 0 stevel 45 11172 Haik #include <sys/machclock.h> 46 0 stevel #include <sys/clock.h> 47 0 stevel 48 0 stevel #if defined(lint) 49 0 stevel #include <sys/types.h> 50 0 stevel #include <sys/scb.h> 51 0 stevel #include <sys/systm.h> 52 0 stevel #include <sys/regset.h> 53 0 stevel #include <sys/sunddi.h> 54 0 stevel #include <sys/lockstat.h> 55 0 stevel #endif /* lint */ 56 0 stevel 57 0 stevel 58 0 stevel #include <sys/asm_linkage.h> 59 0 stevel #include <sys/privregs.h> 60 2241 huah #include <vm/hat_sfmmu.h> 61 0 stevel #include <sys/machparam.h> /* To get SYSBASE and PAGESIZE */ 62 0 stevel #include <sys/machthread.h> 63 0 stevel #include <sys/clock.h> 64 0 stevel #include <sys/intreg.h> 65 0 stevel #include <sys/psr_compat.h> 66 0 stevel #include <sys/isa_defs.h> 67 0 stevel #include <sys/dditypes.h> 68 0 stevel #include <sys/intr.h> 69 0 stevel #include <sys/hypervisor_api.h> 70 0 stevel 71 0 stevel #if !defined(lint) 72 0 stevel #include "assym.h" 73 0 stevel #endif 74 0 stevel 75 0 stevel #define ICACHE_FLUSHSZ 0x20 76 0 stevel 77 0 stevel #if defined(lint) 78 0 stevel /* 79 0 stevel * Softint generated when counter field of tick reg matches value field 80 0 stevel * of tick_cmpr reg 81 0 stevel */ 82 0 stevel /*ARGSUSED*/ 83 0 stevel void 84 0 stevel tickcmpr_set(uint64_t clock_cycles) 85 0 stevel {} 86 0 stevel 87 0 stevel #else /* lint */ 88 0 stevel 89 0 stevel ENTRY_NP(tickcmpr_set) 90 0 stevel ! get 64-bit clock_cycles interval 91 0 stevel mov %o0, %o2 92 0 stevel mov 8, %o3 ! A reasonable initial step size 93 0 stevel 1: 94 0 stevel WR_TICKCMPR(%o2,%o4,%o5,__LINE__) ! Write to TICK_CMPR 95 0 stevel 96 11172 Haik GET_NATIVE_TIME(%o0,%o4,%o5,__LINE__) ! Read %tick to confirm the 97 11172 Haik ! value we wrote was in the 98 11172 Haik ! future. 99 0 stevel 100 0 stevel cmp %o2, %o0 ! If the value we wrote was in the 101 0 stevel bg,pt %xcc, 2f ! future, then blow out of here. 102 2241 huah sllx %o3, 1, %o3 ! If not, then double our step size, 103 0 stevel ba,pt %xcc, 1b ! and take another lap. 104 2241 huah add %o0, %o3, %o2 ! 105 0 stevel 2: 106 0 stevel retl 107 2241 huah nop 108 0 stevel SET_SIZE(tickcmpr_set) 109 0 stevel 110 0 stevel #endif /* lint */ 111 0 stevel 112 0 stevel #if defined(lint) 113 0 stevel 114 0 stevel void 115 0 stevel tickcmpr_disable(void) 116 0 stevel {} 117 0 stevel 118 0 stevel #else 119 0 stevel 120 0 stevel ENTRY_NP(tickcmpr_disable) 121 0 stevel mov 1, %g1 122 0 stevel sllx %g1, TICKINT_DIS_SHFT, %o0 123 0 stevel WR_TICKCMPR(%o0,%o4,%o5,__LINE__) ! Write to TICK_CMPR 124 0 stevel retl 125 2241 huah nop 126 0 stevel SET_SIZE(tickcmpr_disable) 127 0 stevel 128 0 stevel #endif 129 0 stevel 130 0 stevel #if defined(lint) 131 0 stevel 132 0 stevel /* 133 0 stevel * tick_write_delta() increments %tick by the specified delta. This should 134 0 stevel * only be called after a CPR event to assure that gethrtime() continues to 135 0 stevel * increase monotonically. Obviously, writing %tick needs to de done very 136 0 stevel * carefully to avoid introducing unnecessary %tick skew across CPUs. For 137 0 stevel * this reason, we make sure we're i-cache hot before actually writing to 138 0 stevel * %tick. 139 0 stevel * 140 0 stevel * NOTE: No provision for this on sun4v right now. 141 0 stevel */ 142 0 stevel 143 0 stevel /*ARGSUSED*/ 144 0 stevel void 145 0 stevel tick_write_delta(uint64_t delta) 146 0 stevel {} 147 0 stevel 148 0 stevel #else /* lint */ 149 0 stevel 150 0 stevel .seg ".text" 151 0 stevel tick_write_delta_panic: 152 0 stevel .asciz "tick_write_delta: not supported" 153 0 stevel 154 0 stevel ENTRY_NP(tick_write_delta) 155 0 stevel sethi %hi(tick_write_delta_panic), %o1 156 0 stevel save %sp, -SA(MINFRAME), %sp ! get a new window to preserve caller 157 0 stevel call panic 158 2241 huah or %i1, %lo(tick_write_delta_panic), %o0 159 0 stevel /*NOTREACHED*/ 160 0 stevel retl 161 2241 huah nop 162 0 stevel #endif 163 0 stevel 164 0 stevel #if defined(lint) 165 0 stevel /* 166 0 stevel * return 1 if disabled 167 0 stevel */ 168 0 stevel 169 0 stevel int 170 0 stevel tickcmpr_disabled(void) 171 0 stevel { return (0); } 172 0 stevel 173 0 stevel #else /* lint */ 174 0 stevel 175 0 stevel ENTRY_NP(tickcmpr_disabled) 176 11172 Haik RD_TICKCMPR(%g1,%o0,%o1,__LINE__) 177 0 stevel retl 178 2241 huah srlx %g1, TICKINT_DIS_SHFT, %o0 179 0 stevel SET_SIZE(tickcmpr_disabled) 180 0 stevel 181 0 stevel #endif /* lint */ 182 0 stevel 183 0 stevel /* 184 0 stevel * Get current tick 185 0 stevel */ 186 0 stevel #if defined(lint) 187 0 stevel 188 0 stevel u_longlong_t 189 0 stevel gettick(void) 190 0 stevel { return (0); } 191 0 stevel 192 0 stevel #else /* lint */ 193 0 stevel 194 0 stevel ENTRY(gettick) 195 11172 Haik GET_NATIVE_TIME(%o0,%o2,%o3,__LINE__) 196 0 stevel retl 197 2241 huah nop 198 0 stevel SET_SIZE(gettick) 199 0 stevel 200 0 stevel #endif /* lint */ 201 11172 Haik 202 11172 Haik /* 203 11172 Haik * Get current tick. For trapstat use only. 204 11172 Haik */ 205 11172 Haik #if defined (lint) 206 11172 Haik 207 11172 Haik hrtime_t 208 11172 Haik rdtick() 209 11172 Haik { return (0); } 210 11172 Haik 211 11172 Haik #else 212 11172 Haik ENTRY(rdtick) 213 11172 Haik retl 214 11172 Haik RD_TICK_PHYSICAL(%o0) 215 11172 Haik SET_SIZE(rdtick) 216 11172 Haik #endif /* lint */ 217 0 stevel 218 0 stevel 219 0 stevel /* 220 0 stevel * Return the counter portion of the tick register. 221 0 stevel */ 222 0 stevel 223 0 stevel #if defined(lint) 224 0 stevel 225 0 stevel uint64_t 226 0 stevel gettick_counter(void) 227 0 stevel { return(0); } 228 0 stevel 229 11172 Haik uint64_t 230 11172 Haik gettick_npt(void) 231 11172 Haik { return(0); } 232 11172 Haik 233 11172 Haik uint64_t 234 11172 Haik getstick_npt(void) 235 11172 Haik { return(0); } 236 11172 Haik 237 0 stevel #else /* lint */ 238 0 stevel 239 0 stevel ENTRY_NP(gettick_counter) 240 11172 Haik RD_TICK(%o0,%o1,%o2,__LINE__) 241 0 stevel retl 242 11172 Haik nop 243 0 stevel SET_SIZE(gettick_counter) 244 11172 Haik 245 11172 Haik ENTRY_NP(gettick_npt) 246 11172 Haik RD_TICK_PHYSICAL(%o0) 247 11172 Haik retl 248 11172 Haik srlx %o0, 63, %o0 249 11172 Haik SET_SIZE(gettick_npt) 250 11172 Haik 251 11172 Haik ENTRY_NP(getstick_npt) 252 11172 Haik RD_STICK_PHYSICAL(%o0) 253 11172 Haik retl 254 11172 Haik srlx %o0, 63, %o0 255 11172 Haik SET_SIZE(getstick_npt) 256 0 stevel #endif /* lint */ 257 0 stevel 258 0 stevel /* 259 0 stevel * Provide a C callable interface to the trap that reads the hi-res timer. 260 0 stevel * Returns 64-bit nanosecond timestamp in %o0 and %o1. 261 0 stevel */ 262 0 stevel 263 0 stevel #if defined(lint) 264 0 stevel 265 0 stevel hrtime_t 266 0 stevel gethrtime(void) 267 0 stevel { 268 0 stevel return ((hrtime_t)0); 269 0 stevel } 270 0 stevel 271 0 stevel hrtime_t 272 0 stevel gethrtime_unscaled(void) 273 0 stevel { 274 0 stevel return ((hrtime_t)0); 275 0 stevel } 276 0 stevel 277 0 stevel hrtime_t 278 0 stevel gethrtime_max(void) 279 0 stevel { 280 0 stevel return ((hrtime_t)0); 281 0 stevel } 282 0 stevel 283 0 stevel void 284 0 stevel scalehrtime(hrtime_t *hrt) 285 0 stevel { 286 0 stevel *hrt = 0; 287 0 stevel } 288 0 stevel 289 0 stevel void 290 0 stevel gethrestime(timespec_t *tp) 291 0 stevel { 292 0 stevel tp->tv_sec = 0; 293 0 stevel tp->tv_nsec = 0; 294 0 stevel } 295 0 stevel 296 0 stevel time_t 297 0 stevel gethrestime_sec(void) 298 0 stevel { 299 0 stevel return (0); 300 0 stevel } 301 0 stevel 302 0 stevel void 303 0 stevel gethrestime_lasttick(timespec_t *tp) 304 0 stevel { 305 0 stevel tp->tv_sec = 0; 306 0 stevel tp->tv_nsec = 0; 307 0 stevel } 308 0 stevel 309 0 stevel /*ARGSUSED*/ 310 0 stevel void 311 0 stevel hres_tick(void) 312 0 stevel { 313 0 stevel } 314 0 stevel 315 0 stevel void 316 0 stevel panic_hres_tick(void) 317 0 stevel { 318 0 stevel } 319 0 stevel 320 0 stevel #else /* lint */ 321 0 stevel 322 0 stevel ENTRY_NP(gethrtime) 323 11172 Haik GET_HRTIME(%g1,%o0,%o1,%o2,%o3,%o4,%o5,%g2,__LINE__) 324 0 stevel ! %g1 = hrtime 325 0 stevel retl 326 2241 huah mov %g1, %o0 327 0 stevel SET_SIZE(gethrtime) 328 0 stevel 329 0 stevel ENTRY_NP(gethrtime_unscaled) 330 11172 Haik GET_NATIVE_TIME(%g1,%o2,%o3,__LINE__) ! %g1 = native time 331 0 stevel retl 332 2241 huah mov %g1, %o0 333 0 stevel SET_SIZE(gethrtime_unscaled) 334 0 stevel 335 0 stevel ENTRY_NP(gethrtime_waitfree) 336 0 stevel ALTENTRY(dtrace_gethrtime) 337 11172 Haik GET_NATIVE_TIME(%g1,%o2,%o3,__LINE__) ! %g1 = native time 338 0 stevel NATIVE_TIME_TO_NSEC(%g1, %o2, %o3) 339 0 stevel retl 340 2241 huah mov %g1, %o0 341 0 stevel SET_SIZE(dtrace_gethrtime) 342 0 stevel SET_SIZE(gethrtime_waitfree) 343 0 stevel 344 0 stevel ENTRY(gethrtime_max) 345 0 stevel NATIVE_TIME_MAX(%g1) 346 0 stevel NATIVE_TIME_TO_NSEC(%g1, %o0, %o1) 347 0 stevel 348 0 stevel ! hrtime_t's are signed, max hrtime_t must be positive 349 0 stevel mov -1, %o2 350 0 stevel brlz,a %g1, 1f 351 2241 huah srlx %o2, 1, %g1 352 0 stevel 1: 353 0 stevel retl 354 2241 huah mov %g1, %o0 355 0 stevel SET_SIZE(gethrtime_max) 356 0 stevel 357 0 stevel ENTRY(scalehrtime) 358 0 stevel ldx [%o0], %o1 359 0 stevel NATIVE_TIME_TO_NSEC(%o1, %o2, %o3) 360 0 stevel retl 361 2241 huah stx %o1, [%o0] 362 0 stevel SET_SIZE(scalehrtime) 363 0 stevel 364 0 stevel /* 365 0 stevel * Fast trap to return a timestamp, uses trap window, leaves traps 366 0 stevel * disabled. Returns a 64-bit nanosecond timestamp in %o0 and %o1. 367 0 stevel * 368 0 stevel * This is the handler for the ST_GETHRTIME trap. 369 0 stevel */ 370 0 stevel 371 0 stevel ENTRY_NP(get_timestamp) 372 11172 Haik GET_HRTIME(%g1,%g2,%g3,%g4,%g5,%o0,%o1,%o2,__LINE__) 373 11172 Haik ! %g1 = hrtime 374 0 stevel srlx %g1, 32, %o0 ! %o0 = hi32(%g1) 375 0 stevel srl %g1, 0, %o1 ! %o1 = lo32(%g1) 376 0 stevel FAST_TRAP_DONE 377 0 stevel SET_SIZE(get_timestamp) 378 0 stevel 379 0 stevel /* 380 0 stevel * Macro to convert GET_HRESTIME() bits into a timestamp. 381 0 stevel * 382 0 stevel * We use two separate macros so that the platform-dependent GET_HRESTIME() 383 0 stevel * can be as small as possible; CONV_HRESTIME() implements the generic part. 384 0 stevel */ 385 0 stevel #define CONV_HRESTIME(hrestsec, hrestnsec, adj, nslt, nano) \ 386 0 stevel brz,pt adj, 3f; /* no adjustments, it's easy */ \ 387 0 stevel add hrestnsec, nslt, hrestnsec; /* hrest.tv_nsec += nslt */ \ 388 0 stevel brlz,pn adj, 2f; /* if hrestime_adj negative */ \ 389 2399 cth srlx nslt, ADJ_SHIFT, nslt; /* delay: nslt >>= 4 */ \ 390 0 stevel subcc adj, nslt, %g0; /* hrestime_adj - nslt/16 */ \ 391 0 stevel movg %xcc, nslt, adj; /* adj by min(adj, nslt/16) */ \ 392 0 stevel ba 3f; /* go convert to sec/nsec */ \ 393 2241 huah add hrestnsec, adj, hrestnsec; /* delay: apply adjustment */ \ 394 0 stevel 2: addcc adj, nslt, %g0; /* hrestime_adj + nslt/16 */ \ 395 0 stevel bge,a,pt %xcc, 3f; /* is adj less negative? */ \ 396 2241 huah add hrestnsec, adj, hrestnsec; /* yes: hrest.nsec += adj */ \ 397 0 stevel sub hrestnsec, nslt, hrestnsec; /* no: hrest.nsec -= nslt/16 */ \ 398 0 stevel 3: cmp hrestnsec, nano; /* more than a billion? */ \ 399 0 stevel bl,pt %xcc, 4f; /* if not, we're done */ \ 400 2241 huah nop; /* delay: do nothing :( */ \ 401 0 stevel add hrestsec, 1, hrestsec; /* hrest.tv_sec++; */ \ 402 0 stevel sub hrestnsec, nano, hrestnsec; /* hrest.tv_nsec -= NANOSEC; */ \ 403 2399 cth ba,a 3b; /* check >= billion again */ \ 404 0 stevel 4: 405 0 stevel 406 0 stevel ENTRY_NP(gethrestime) 407 11172 Haik GET_HRESTIME(%o1,%o2,%o3,%o4,%o5,%g1,%g2,%g3,%g4,__LINE__) 408 0 stevel CONV_HRESTIME(%o1, %o2, %o3, %o4, %o5) 409 0 stevel stn %o1, [%o0] 410 0 stevel retl 411 2241 huah stn %o2, [%o0 + CLONGSIZE] 412 0 stevel SET_SIZE(gethrestime) 413 0 stevel 414 0 stevel /* 415 0 stevel * Similar to gethrestime(), but gethrestime_sec() returns current hrestime 416 0 stevel * seconds. 417 0 stevel */ 418 0 stevel ENTRY_NP(gethrestime_sec) 419 11172 Haik GET_HRESTIME(%o0,%o2,%o3,%o4,%o5,%g1,%g2,%g3,%g4,__LINE__) 420 0 stevel CONV_HRESTIME(%o0, %o2, %o3, %o4, %o5) 421 0 stevel retl ! %o0 current hrestime seconds 422 2241 huah nop 423 0 stevel SET_SIZE(gethrestime_sec) 424 0 stevel 425 0 stevel /* 426 0 stevel * Returns the hrestime on the last tick. This is simpler than gethrestime() 427 0 stevel * and gethrestime_sec(): no conversion is required. gethrestime_lasttick() 428 0 stevel * follows the same locking algorithm as GET_HRESTIME and GET_HRTIME, 429 0 stevel * outlined in detail in clock.h. (Unlike GET_HRESTIME/GET_HRTIME, we don't 430 0 stevel * rely on load dependencies to effect the membar #LoadLoad, instead declaring 431 0 stevel * it explicitly.) 432 0 stevel */ 433 0 stevel ENTRY_NP(gethrestime_lasttick) 434 0 stevel sethi %hi(hres_lock), %o1 435 0 stevel 0: 436 0 stevel lduw [%o1 + %lo(hres_lock)], %o2 ! Load lock value 437 0 stevel membar #LoadLoad ! Load of lock must complete 438 0 stevel andn %o2, 1, %o2 ! Mask off lowest bit 439 0 stevel ldn [%o1 + %lo(hrestime)], %g1 ! Seconds. 440 0 stevel add %o1, %lo(hrestime), %o4 441 0 stevel ldn [%o4 + CLONGSIZE], %g2 ! Nanoseconds. 442 0 stevel membar #LoadLoad ! All loads must complete 443 0 stevel lduw [%o1 + %lo(hres_lock)], %o3 ! Reload lock value 444 0 stevel cmp %o3, %o2 ! If lock is locked or has 445 0 stevel bne 0b ! changed, retry. 446 2241 huah stn %g1, [%o0] ! Delay: store seconds 447 0 stevel retl 448 2241 huah stn %g2, [%o0 + CLONGSIZE] ! Delay: store nanoseconds 449 0 stevel SET_SIZE(gethrestime_lasttick) 450 0 stevel 451 0 stevel /* 452 0 stevel * Fast trap for gettimeofday(). Returns a timestruc_t in %o0 and %o1. 453 0 stevel * 454 0 stevel * This is the handler for the ST_GETHRESTIME trap. 455 0 stevel */ 456 0 stevel 457 0 stevel ENTRY_NP(get_hrestime) 458 11172 Haik GET_HRESTIME(%o0,%o1,%g1,%g2,%g3,%g4,%g5,%o2,%o3,__LINE__) 459 0 stevel CONV_HRESTIME(%o0, %o1, %g1, %g2, %g3) 460 0 stevel FAST_TRAP_DONE 461 0 stevel SET_SIZE(get_hrestime) 462 0 stevel 463 0 stevel /* 464 0 stevel * Fast trap to return lwp virtual time, uses trap window, leaves traps 465 0 stevel * disabled. Returns a 64-bit number in %o0:%o1, which is the number 466 0 stevel * of nanoseconds consumed. 467 0 stevel * 468 0 stevel * This is the handler for the ST_GETHRVTIME trap. 469 0 stevel * 470 0 stevel * Register usage: 471 0 stevel * %o0, %o1 = return lwp virtual time 472 0 stevel * %o2 = CPU/thread 473 0 stevel * %o3 = lwp 474 0 stevel * %g1 = scratch 475 0 stevel * %g5 = scratch 476 0 stevel */ 477 0 stevel ENTRY_NP(get_virtime) 478 11172 Haik GET_NATIVE_TIME(%g5,%g1,%g2,__LINE__) ! %g5 = native time in ticks 479 0 stevel CPU_ADDR(%g2, %g3) ! CPU struct ptr to %g2 480 0 stevel ldn [%g2 + CPU_THREAD], %g2 ! thread pointer to %g2 481 0 stevel ldn [%g2 + T_LWP], %g3 ! lwp pointer to %g3 482 0 stevel 483 0 stevel /* 484 0 stevel * Subtract start time of current microstate from time 485 0 stevel * of day to get increment for lwp virtual time. 486 0 stevel */ 487 0 stevel ldx [%g3 + LWP_STATE_START], %g1 ! ms_state_start 488 0 stevel sub %g5, %g1, %g5 489 0 stevel 490 0 stevel /* 491 0 stevel * Add current value of ms_acct[LMS_USER] 492 0 stevel */ 493 0 stevel ldx [%g3 + LWP_ACCT_USER], %g1 ! ms_acct[LMS_USER] 494 0 stevel add %g5, %g1, %g5 495 0 stevel NATIVE_TIME_TO_NSEC(%g5, %g1, %o0) 496 0 stevel 497 0 stevel srl %g5, 0, %o1 ! %o1 = lo32(%g5) 498 0 stevel srlx %g5, 32, %o0 ! %o0 = hi32(%g5) 499 0 stevel 500 0 stevel FAST_TRAP_DONE 501 0 stevel SET_SIZE(get_virtime) 502 0 stevel 503 0 stevel 504 0 stevel 505 0 stevel .seg ".text" 506 0 stevel hrtime_base_panic: 507 0 stevel .asciz "hrtime_base stepping back" 508 0 stevel 509 0 stevel 510 0 stevel ENTRY_NP(hres_tick) 511 0 stevel save %sp, -SA(MINFRAME), %sp ! get a new window 512 0 stevel 513 0 stevel sethi %hi(hrestime), %l4 514 0 stevel ldstub [%l4 + %lo(hres_lock + HRES_LOCK_OFFSET)], %l5 ! try locking 515 0 stevel 7: tst %l5 516 0 stevel bz,pt %xcc, 8f ! if we got it, drive on 517 2241 huah ld [%l4 + %lo(nsec_scale)], %l5 ! delay: %l5 = scaling factor 518 0 stevel ldub [%l4 + %lo(hres_lock + HRES_LOCK_OFFSET)], %l5 519 0 stevel 9: tst %l5 520 0 stevel bz,a,pn %xcc, 7b 521 2241 huah ldstub [%l4 + %lo(hres_lock + HRES_LOCK_OFFSET)], %l5 522 0 stevel ba,pt %xcc, 9b 523 2241 huah ldub [%l4 + %lo(hres_lock + HRES_LOCK_OFFSET)], %l5 524 0 stevel 8: 525 0 stevel membar #StoreLoad|#StoreStore 526 0 stevel 527 0 stevel ! 528 0 stevel ! update hres_last_tick. %l5 has the scaling factor (nsec_scale). 529 0 stevel ! 530 0 stevel ldx [%l4 + %lo(hrtime_base)], %g1 ! load current hrtime_base 531 11172 Haik GET_NATIVE_TIME(%l0,%l3,%l6,__LINE__) ! current native time 532 0 stevel stx %l0, [%l4 + %lo(hres_last_tick)]! prev = current 533 0 stevel ! convert native time to nsecs 534 0 stevel NATIVE_TIME_TO_NSEC_SCALE(%l0, %l5, %l2, NSEC_SHIFT) 535 0 stevel 536 0 stevel sub %l0, %g1, %i1 ! get accurate nsec delta 537 0 stevel 538 0 stevel ldx [%l4 + %lo(hrtime_base)], %l1 539 0 stevel cmp %l1, %l0 540 0 stevel bg,pn %xcc, 9f 541 2241 huah nop 542 0 stevel 543 0 stevel stx %l0, [%l4 + %lo(hrtime_base)] ! update hrtime_base 544 0 stevel 545 0 stevel ! 546 0 stevel ! apply adjustment, if any 547 0 stevel ! 548 0 stevel ldx [%l4 + %lo(hrestime_adj)], %l0 ! %l0 = hrestime_adj 549 0 stevel brz %l0, 2f 550 0 stevel ! hrestime_adj == 0 ? 551 0 stevel ! yes, skip adjustments 552 2241 huah clr %l5 ! delay: set adj to zero 553 0 stevel tst %l0 ! is hrestime_adj >= 0 ? 554 0 stevel bge,pt %xcc, 1f ! yes, go handle positive case 555 2241 huah srl %i1, ADJ_SHIFT, %l5 ! delay: %l5 = adj 556 0 stevel 557 0 stevel addcc %l0, %l5, %g0 ! hrestime_adj < -adj ? 558 0 stevel bl,pt %xcc, 2f ! yes, use current adj 559 2241 huah neg %l5 ! delay: %l5 = -adj 560 0 stevel ba,pt %xcc, 2f 561 2241 huah mov %l0, %l5 ! no, so set adj = hrestime_adj 562 0 stevel 1: 563 0 stevel subcc %l0, %l5, %g0 ! hrestime_adj < adj ? 564 0 stevel bl,a,pt %xcc, 2f ! yes, set adj = hrestime_adj 565 2241 huah mov %l0, %l5 ! delay: adj = hrestime_adj 566 0 stevel 2: 567 0 stevel ldx [%l4 + %lo(timedelta)], %l0 ! %l0 = timedelta 568 0 stevel sub %l0, %l5, %l0 ! timedelta -= adj 569 0 stevel 570 0 stevel stx %l0, [%l4 + %lo(timedelta)] ! store new timedelta 571 0 stevel stx %l0, [%l4 + %lo(hrestime_adj)] ! hrestime_adj = timedelta 572 0 stevel 573 0 stevel or %l4, %lo(hrestime), %l2 574 0 stevel ldn [%l2], %i2 ! %i2:%i3 = hrestime sec:nsec 575 0 stevel ldn [%l2 + CLONGSIZE], %i3 576 0 stevel add %i3, %l5, %i3 ! hrestime.nsec += adj 577 0 stevel add %i3, %i1, %i3 ! hrestime.nsec += nslt 578 0 stevel 579 0 stevel set NANOSEC, %l5 ! %l5 = NANOSEC 580 0 stevel cmp %i3, %l5 581 0 stevel bl,pt %xcc, 5f ! if hrestime.tv_nsec < NANOSEC 582 2241 huah sethi %hi(one_sec), %i1 ! delay 583 0 stevel add %i2, 0x1, %i2 ! hrestime.tv_sec++ 584 0 stevel sub %i3, %l5, %i3 ! hrestime.tv_nsec - NANOSEC 585 0 stevel mov 0x1, %l5 586 0 stevel st %l5, [%i1 + %lo(one_sec)] 587 0 stevel 5: 588 0 stevel stn %i2, [%l2] 589 0 stevel stn %i3, [%l2 + CLONGSIZE] ! store the new hrestime 590 0 stevel 591 0 stevel membar #StoreStore 592 0 stevel 593 0 stevel ld [%l4 + %lo(hres_lock)], %i1 594 0 stevel inc %i1 ! release lock 595 0 stevel st %i1, [%l4 + %lo(hres_lock)] ! clear hres_lock 596 0 stevel 597 0 stevel ret 598 0 stevel restore 599 0 stevel 600 0 stevel 9: 601 0 stevel ! 602 0 stevel ! release hres_lock 603 0 stevel ! 604 0 stevel ld [%l4 + %lo(hres_lock)], %i1 605 0 stevel inc %i1 606 0 stevel st %i1, [%l4 + %lo(hres_lock)] 607 0 stevel 608 0 stevel sethi %hi(hrtime_base_panic), %o0 609 0 stevel call panic 610 2241 huah or %o0, %lo(hrtime_base_panic), %o0 611 0 stevel 612 0 stevel SET_SIZE(hres_tick) 613 0 stevel 614 0 stevel #endif /* lint */ 615 0 stevel 616 0 stevel #if !defined(lint) && !defined(__lint) 617 0 stevel 618 0 stevel .seg ".text" 619 0 stevel kstat_q_panic_msg: 620 0 stevel .asciz "kstat_q_exit: qlen == 0" 621 0 stevel 622 0 stevel ENTRY(kstat_q_panic) 623 0 stevel save %sp, -SA(MINFRAME), %sp 624 0 stevel sethi %hi(kstat_q_panic_msg), %o0 625 0 stevel call panic 626 2241 huah or %o0, %lo(kstat_q_panic_msg), %o0 627 0 stevel /*NOTREACHED*/ 628 0 stevel SET_SIZE(kstat_q_panic) 629 0 stevel 630 0 stevel #define BRZPN brz,pn 631 0 stevel #define BRZPT brz,pt 632 0 stevel 633 0 stevel #define KSTAT_Q_UPDATE(QOP, QBR, QZERO, QRETURN, QTYPE) \ 634 0 stevel ld [%o0 + QTYPE/**/CNT], %o1; /* %o1 = old qlen */ \ 635 0 stevel QOP %o1, 1, %o2; /* %o2 = new qlen */ \ 636 0 stevel QBR %o1, QZERO; /* done if qlen == 0 */ \ 637 0 stevel st %o2, [%o0 + QTYPE/**/CNT]; /* delay: save qlen */ \ 638 0 stevel ldx [%o0 + QTYPE/**/LASTUPDATE], %o3; \ 639 0 stevel ldx [%o0 + QTYPE/**/TIME], %o4; /* %o4 = old time */ \ 640 0 stevel ldx [%o0 + QTYPE/**/LENTIME], %o5; /* %o5 = old lentime */ \ 641 0 stevel sub %g1, %o3, %o2; /* %o2 = time delta */ \ 642 0 stevel mulx %o1, %o2, %o3; /* %o3 = cur lentime */ \ 643 0 stevel add %o4, %o2, %o4; /* %o4 = new time */ \ 644 0 stevel add %o5, %o3, %o5; /* %o5 = new lentime */ \ 645 0 stevel stx %o4, [%o0 + QTYPE/**/TIME]; /* save time */ \ 646 0 stevel stx %o5, [%o0 + QTYPE/**/LENTIME]; /* save lentime */ \ 647 0 stevel QRETURN; \ 648 0 stevel stx %g1, [%o0 + QTYPE/**/LASTUPDATE]; /* lastupdate = now */ 649 0 stevel 650 0 stevel .align 16 651 0 stevel ENTRY(kstat_waitq_enter) 652 11172 Haik GET_NATIVE_TIME(%g1,%g2,%g3,__LINE__) 653 0 stevel KSTAT_Q_UPDATE(add, BRZPT, 1f, 1:retl, KSTAT_IO_W) 654 0 stevel SET_SIZE(kstat_waitq_enter) 655 0 stevel 656 0 stevel .align 16 657 0 stevel ENTRY(kstat_waitq_exit) 658 11172 Haik GET_NATIVE_TIME(%g1,%g2,%g3,__LINE__) 659 0 stevel KSTAT_Q_UPDATE(sub, BRZPN, kstat_q_panic, retl, KSTAT_IO_W) 660 0 stevel SET_SIZE(kstat_waitq_exit) 661 0 stevel 662 0 stevel .align 16 663 0 stevel ENTRY(kstat_runq_enter) 664 11172 Haik GET_NATIVE_TIME(%g1,%g2,%g3,__LINE__) 665 0 stevel KSTAT_Q_UPDATE(add, BRZPT, 1f, 1:retl, KSTAT_IO_R) 666 0 stevel SET_SIZE(kstat_runq_enter) 667 0 stevel 668 0 stevel .align 16 669 0 stevel ENTRY(kstat_runq_exit) 670 11172 Haik GET_NATIVE_TIME(%g1,%g2,%g3,__LINE__) 671 0 stevel KSTAT_Q_UPDATE(sub, BRZPN, kstat_q_panic, retl, KSTAT_IO_R) 672 0 stevel SET_SIZE(kstat_runq_exit) 673 0 stevel 674 0 stevel .align 16 675 0 stevel ENTRY(kstat_waitq_to_runq) 676 11172 Haik GET_NATIVE_TIME(%g1,%g2,%g3,__LINE__) 677 0 stevel KSTAT_Q_UPDATE(sub, BRZPN, kstat_q_panic, 1:, KSTAT_IO_W) 678 0 stevel KSTAT_Q_UPDATE(add, BRZPT, 1f, 1:retl, KSTAT_IO_R) 679 0 stevel SET_SIZE(kstat_waitq_to_runq) 680 0 stevel 681 0 stevel .align 16 682 0 stevel ENTRY(kstat_runq_back_to_waitq) 683 11172 Haik GET_NATIVE_TIME(%g1,%g2,%g3,__LINE__) 684 0 stevel KSTAT_Q_UPDATE(sub, BRZPN, kstat_q_panic, 1:, KSTAT_IO_R) 685 0 stevel KSTAT_Q_UPDATE(add, BRZPT, 1f, 1:retl, KSTAT_IO_W) 686 0 stevel SET_SIZE(kstat_runq_back_to_waitq) 687 0 stevel 688 0 stevel #endif /* lint */ 689 0 stevel 690 0 stevel #ifdef lint 691 0 stevel 692 0 stevel int64_t timedelta; 693 0 stevel hrtime_t hres_last_tick; 694 4551 sudheer volatile timestruc_t hrestime; 695 0 stevel int64_t hrestime_adj; 696 4551 sudheer volatile int hres_lock; 697 0 stevel uint_t nsec_scale; 698 0 stevel hrtime_t hrtime_base; 699 0 stevel int traptrace_use_stick; 700 0 stevel 701 0 stevel #else 702 0 stevel /* 703 0 stevel * -- WARNING -- 704 0 stevel * 705 0 stevel * The following variables MUST be together on a 128-byte boundary. 706 0 stevel * In addition to the primary performance motivation (having them all 707 0 stevel * on the same cache line(s)), code here and in the GET*TIME() macros 708 0 stevel * assumes that they all have the same high 22 address bits (so 709 0 stevel * there's only one sethi). 710 0 stevel */ 711 0 stevel .seg ".data" 712 0 stevel .global timedelta, hres_last_tick, hrestime, hrestime_adj 713 0 stevel .global hres_lock, nsec_scale, hrtime_base, traptrace_use_stick 714 11172 Haik .global nsec_shift, adj_shift, native_tick_offset, native_stick_offset 715 0 stevel 716 0 stevel /* XXX - above comment claims 128-bytes is necessary */ 717 0 stevel .align 64 718 0 stevel timedelta: 719 0 stevel .word 0, 0 /* int64_t */ 720 0 stevel hres_last_tick: 721 0 stevel .word 0, 0 /* hrtime_t */ 722 0 stevel hrestime: 723 0 stevel .nword 0, 0 /* 2 longs */ 724 0 stevel hrestime_adj: 725 0 stevel .word 0, 0 /* int64_t */ 726 0 stevel hres_lock: 727 0 stevel .word 0 728 0 stevel nsec_scale: 729 0 stevel .word 0 730 0 stevel hrtime_base: 731 0 stevel .word 0, 0 732 0 stevel traptrace_use_stick: 733 0 stevel .word 0 734 0 stevel nsec_shift: 735 0 stevel .word NSEC_SHIFT 736 0 stevel adj_shift: 737 0 stevel .word ADJ_SHIFT 738 11172 Haik .align 8 739 11172 Haik native_tick_offset: 740 11172 Haik .word 0, 0 741 11172 Haik .align 8 742 11172 Haik native_stick_offset: 743 11172 Haik .word 0, 0 744 0 stevel 745 0 stevel #endif 746 0 stevel 747 0 stevel 748 0 stevel /* 749 0 stevel * drv_usecwait(clock_t n) [DDI/DKI - section 9F] 750 0 stevel * usec_delay(int n) [compatibility - should go one day] 751 0 stevel * Delay by spinning. 752 0 stevel * 753 0 stevel * delay for n microseconds. numbers <= 0 delay 1 usec 754 0 stevel * 755 0 stevel * With UltraSPARC-III the combination of supporting mixed-speed CPUs 756 0 stevel * and variable clock rate for power management requires that we 757 0 stevel * use %stick to implement this routine. 758 0 stevel */ 759 0 stevel 760 0 stevel #if defined(lint) 761 0 stevel 762 0 stevel /*ARGSUSED*/ 763 0 stevel void 764 0 stevel drv_usecwait(clock_t n) 765 0 stevel {} 766 0 stevel 767 0 stevel /*ARGSUSED*/ 768 0 stevel void 769 0 stevel usec_delay(int n) 770 0 stevel {} 771 0 stevel 772 0 stevel #else /* lint */ 773 0 stevel 774 0 stevel ENTRY(drv_usecwait) 775 0 stevel ALTENTRY(usec_delay) 776 0 stevel brlez,a,pn %o0, 0f 777 2241 huah mov 1, %o0 778 0 stevel 0: 779 0 stevel sethi %hi(sticks_per_usec), %o1 780 0 stevel lduw [%o1 + %lo(sticks_per_usec)], %o1 781 0 stevel mulx %o1, %o0, %o1 ! Scale usec to ticks 782 0 stevel inc %o1 ! We don't start on a tick edge 783 11172 Haik GET_NATIVE_TIME(%o2,%o3,%o4,__LINE__) 784 0 stevel add %o1, %o2, %o1 785 0 stevel 786 0 stevel 1: cmp %o1, %o2 787 11172 Haik GET_NATIVE_TIME(%o2,%o3,%o4,__LINE__) 788 0 stevel bgeu,pt %xcc, 1b 789 2241 huah nop 790 0 stevel retl 791 2241 huah nop 792 0 stevel SET_SIZE(usec_delay) 793 0 stevel SET_SIZE(drv_usecwait) 794 0 stevel #endif /* lint */ 795 0 stevel 796 0 stevel #if defined(lint) 797 0 stevel 798 0 stevel /* ARGSUSED */ 799 0 stevel void 800 0 stevel pil14_interrupt(int level) 801 0 stevel {} 802 0 stevel 803 0 stevel #else 804 0 stevel 805 0 stevel /* 806 0 stevel * Level-14 interrupt prologue. 807 0 stevel */ 808 0 stevel ENTRY_NP(pil14_interrupt) 809 0 stevel CPU_ADDR(%g1, %g2) 810 0 stevel rdpr %pil, %g6 ! %g6 = interrupted PIL 811 0 stevel stn %g6, [%g1 + CPU_PROFILE_PIL] ! record interrupted PIL 812 0 stevel rdpr %tstate, %g6 813 0 stevel rdpr %tpc, %g5 814 0 stevel btst TSTATE_PRIV, %g6 ! trap from supervisor mode? 815 0 stevel bnz,a,pt %xcc, 1f 816 2241 huah stn %g5, [%g1 + CPU_PROFILE_PC] ! if so, record kernel PC 817 0 stevel stn %g5, [%g1 + CPU_PROFILE_UPC] ! if not, record user PC 818 0 stevel ba pil_interrupt_common ! must be large-disp branch 819 2241 huah stn %g0, [%g1 + CPU_PROFILE_PC] ! zero kernel PC 820 0 stevel 1: ba pil_interrupt_common ! must be large-disp branch 821 2241 huah stn %g0, [%g1 + CPU_PROFILE_UPC] ! zero user PC 822 0 stevel SET_SIZE(pil14_interrupt) 823 0 stevel 824 0 stevel ENTRY_NP(tick_rtt) 825 0 stevel ! 826 0 stevel ! Load TICK_COMPARE into %o5; if bit 63 is set, then TICK_COMPARE is 827 0 stevel ! disabled. If TICK_COMPARE is enabled, we know that we need to 828 0 stevel ! reenqueue the interrupt request structure. We'll then check TICKINT 829 0 stevel ! in SOFTINT; if it's set, then we know that we were in a TICK_COMPARE 830 0 stevel ! interrupt. In this case, TICK_COMPARE may have been rewritten 831 0 stevel ! recently; we'll compare %o5 to the current time to verify that it's 832 0 stevel ! in the future. 833 0 stevel ! 834 0 stevel ! Note that %o5 is live until after 1f. 835 0 stevel ! XXX - there is a subroutine call while %o5 is live! 836 0 stevel ! 837 11172 Haik RD_TICKCMPR(%o5,%g1,%g2,__LINE__) 838 0 stevel srlx %o5, TICKINT_DIS_SHFT, %g1 839 0 stevel brnz,pt %g1, 2f 840 2241 huah nop 841 0 stevel 842 0 stevel rdpr %pstate, %g5 843 0 stevel andn %g5, PSTATE_IE, %g1 844 0 stevel wrpr %g0, %g1, %pstate ! Disable vec interrupts 845 0 stevel 846 0 stevel sethi %hi(cbe_level14_inum), %o1 847 2973 govinda ldx [%o1 + %lo(cbe_level14_inum)], %o1 848 0 stevel call intr_enqueue_req ! preserves %o5 and %g5 849 2241 huah mov PIL_14, %o0 850 0 stevel 851 0 stevel ! Check SOFTINT for TICKINT/STICKINT 852 0 stevel rd SOFTINT, %o4 853 0 stevel set (TICK_INT_MASK | STICK_INT_MASK), %o0 854 0 stevel andcc %o4, %o0, %g0 855 0 stevel bz,a,pn %icc, 2f 856 2241 huah wrpr %g0, %g5, %pstate ! Enable vec interrupts 857 0 stevel 858 0 stevel ! clear TICKINT/STICKINT 859 0 stevel wr %o0, CLEAR_SOFTINT 860 0 stevel 861 0 stevel ! 862 0 stevel ! Now that we've cleared TICKINT, we can reread %tick and confirm 863 0 stevel ! that the value we programmed is still in the future. If it isn't, 864 0 stevel ! we need to reprogram TICK_COMPARE to fire as soon as possible. 865 0 stevel ! 866 11172 Haik GET_NATIVE_TIME(%o0,%g1,%g2,__LINE__) ! %o0 = tick 867 0 stevel cmp %o5, %o0 ! In the future? 868 0 stevel bg,a,pt %xcc, 2f ! Yes, drive on. 869 2241 huah wrpr %g0, %g5, %pstate ! delay: enable vec intr 870 0 stevel 871 0 stevel ! 872 0 stevel ! If we're here, then we have programmed TICK_COMPARE with a %tick 873 0 stevel ! which is in the past; we'll now load an initial step size, and loop 874 0 stevel ! until we've managed to program TICK_COMPARE to fire in the future. 875 0 stevel ! 876 0 stevel mov 8, %o4 ! 8 = arbitrary inital step 877 0 stevel 1: add %o0, %o4, %o5 ! Add the step 878 0 stevel WR_TICKCMPR(%o5,%g1,%g2,__LINE__) ! Write to TICK_CMPR 879 11172 Haik GET_NATIVE_TIME(%o0,%g1,%g2,__LINE__) ! %o0 = tick 880 0 stevel cmp %o5, %o0 ! In the future? 881 0 stevel bg,a,pt %xcc, 2f ! Yes, drive on. 882 2241 huah wrpr %g0, %g5, %pstate ! delay: enable vec intr 883 0 stevel ba 1b ! No, try again. 884 2241 huah sllx %o4, 1, %o4 ! delay: double step size 885 0 stevel 886 0 stevel 2: ba current_thread_complete 887 2241 huah nop 888 0 stevel SET_SIZE(tick_rtt) 889 0 stevel 890 0 stevel #endif /* lint */ 891 8803 Jonathan 892 8803 Jonathan #if defined(lint) 893 8803 Jonathan 894 8803 Jonathan /* ARGSUSED */ 895 8803 Jonathan void 896 8803 Jonathan pil15_interrupt(int level) 897 8803 Jonathan {} 898 8803 Jonathan 899 8803 Jonathan #else /* lint */ 900 8803 Jonathan 901 8803 Jonathan /* 902 8803 Jonathan * Level-15 interrupt prologue. 903 8803 Jonathan */ 904 8803 Jonathan ENTRY_NP(pil15_interrupt) 905 8803 Jonathan CPU_ADDR(%g1, %g2) 906 8803 Jonathan rdpr %tstate, %g6 907 8803 Jonathan rdpr %tpc, %g5 908 8803 Jonathan btst TSTATE_PRIV, %g6 ! trap from supervisor mode? 909 8803 Jonathan bnz,a,pt %xcc, 1f 910 8803 Jonathan stn %g5, [%g1 + CPU_CPCPROFILE_PC] ! if so, record kernel PC 911 8803 Jonathan stn %g5, [%g1 + CPU_CPCPROFILE_UPC] ! if not, record user PC 912 8803 Jonathan ba pil15_epilogue ! must be large-disp branch 913 8803 Jonathan stn %g0, [%g1 + CPU_CPCPROFILE_PC] ! zero kernel PC 914 8803 Jonathan 1: ba pil15_epilogue ! must be large-disp branch 915 8803 Jonathan stn %g0, [%g1 + CPU_CPCPROFILE_UPC] ! zero user PC 916 8803 Jonathan SET_SIZE(pil15_interrupt) 917 8803 Jonathan 918 8803 Jonathan #endif /* lint */ 919 0 stevel 920 0 stevel #if defined(lint) 921 0 stevel /* 922 0 stevel * Prefetch a page_t for write or read, this assumes a linear 923 0 stevel * scan of sequential page_t's. 924 0 stevel */ 925 0 stevel /*ARGSUSED*/ 926 0 stevel void 927 0 stevel prefetch_page_w(void *pp) 928 0 stevel {} 929 0 stevel 930 0 stevel /*ARGSUSED*/ 931 0 stevel void 932 0 stevel prefetch_page_r(void *pp) 933 0 stevel {} 934 0 stevel #else /* lint */ 935 0 stevel 936 0 stevel /* XXXQ These should be inline templates, not functions */ 937 0 stevel ENTRY(prefetch_page_w) 938 0 stevel retl 939 2241 huah nop 940 0 stevel SET_SIZE(prefetch_page_w) 941 0 stevel 942 0 stevel ENTRY(prefetch_page_r) 943 0 stevel retl 944 2241 huah nop 945 0 stevel SET_SIZE(prefetch_page_r) 946 0 stevel 947 0 stevel #endif /* lint */ 948 0 stevel 949 0 stevel #if defined(lint) 950 0 stevel /* 951 0 stevel * Prefetch struct smap for write. 952 0 stevel */ 953 0 stevel /*ARGSUSED*/ 954 0 stevel void 955 0 stevel prefetch_smap_w(void *smp) 956 0 stevel {} 957 0 stevel #else /* lint */ 958 0 stevel 959 0 stevel /* XXXQ These should be inline templates, not functions */ 960 0 stevel ENTRY(prefetch_smap_w) 961 0 stevel retl 962 2241 huah nop 963 0 stevel SET_SIZE(prefetch_smap_w) 964 0 stevel 965 0 stevel #endif /* lint */ 966 0 stevel 967 0 stevel /* 968 0 stevel * Generic sun4v MMU and Cache operations. 969 0 stevel */ 970 0 stevel 971 0 stevel #if defined(lint) 972 0 stevel 973 0 stevel /*ARGSUSED*/ 974 0 stevel void 975 2241 huah vtag_flushpage(caddr_t vaddr, uint64_t sfmmup) 976 0 stevel {} 977 0 stevel 978 0 stevel /*ARGSUSED*/ 979 0 stevel void 980 0 stevel vtag_flushall(void) 981 0 stevel {} 982 0 stevel 983 0 stevel /*ARGSUSED*/ 984 0 stevel void 985 0 stevel vtag_unmap_perm_tl1(uint64_t vaddr, uint64_t ctxnum) 986 0 stevel {} 987 0 stevel 988 0 stevel /*ARGSUSED*/ 989 0 stevel void 990 2241 huah vtag_flushpage_tl1(uint64_t vaddr, uint64_t sfmmup) 991 0 stevel {} 992 0 stevel 993 0 stevel /*ARGSUSED*/ 994 0 stevel void 995 2241 huah vtag_flush_pgcnt_tl1(uint64_t vaddr, uint64_t sfmmup_pgcnt) 996 0 stevel {} 997 0 stevel 998 0 stevel /*ARGSUSED*/ 999 0 stevel void 1000 0 stevel vtag_flushall_tl1(uint64_t dummy1, uint64_t dummy2) 1001 0 stevel {} 1002 0 stevel 1003 0 stevel /*ARGSUSED*/ 1004 0 stevel void 1005 0 stevel vac_flushpage(pfn_t pfnum, int vcolor) 1006 0 stevel {} 1007 0 stevel 1008 0 stevel /*ARGSUSED*/ 1009 0 stevel void 1010 0 stevel vac_flushpage_tl1(uint64_t pfnum, uint64_t vcolor) 1011 0 stevel {} 1012 0 stevel 1013 0 stevel /*ARGSUSED*/ 1014 0 stevel void 1015 0 stevel flush_instr_mem(caddr_t vaddr, size_t len) 1016 0 stevel {} 1017 0 stevel 1018 0 stevel #else /* lint */ 1019 0 stevel 1020 0 stevel ENTRY_NP(vtag_flushpage) 1021 0 stevel /* 1022 0 stevel * flush page from the tlb 1023 0 stevel * 1024 0 stevel * %o0 = vaddr 1025 2241 huah * %o1 = sfmmup 1026 0 stevel */ 1027 2241 huah SFMMU_CPU_CNUM(%o1, %g1, %g2) /* %g1 = sfmmu cnum on this CPU */ 1028 2241 huah 1029 2241 huah mov %g1, %o1 1030 0 stevel mov MAP_ITLB | MAP_DTLB, %o2 1031 0 stevel ta MMU_UNMAP_ADDR 1032 0 stevel brz,pt %o0, 1f 1033 2241 huah nop 1034 0 stevel ba panic_bad_hcall 1035 2241 huah mov MMU_UNMAP_ADDR, %o1 1036 0 stevel 1: 1037 0 stevel retl 1038 2241 huah nop 1039 0 stevel SET_SIZE(vtag_flushpage) 1040 0 stevel 1041 0 stevel ENTRY_NP(vtag_flushall) 1042 0 stevel mov %g0, %o0 ! XXX no cpu list yet 1043 0 stevel mov %g0, %o1 ! XXX no cpu list yet 1044 0 stevel mov MAP_ITLB | MAP_DTLB, %o2 1045 0 stevel mov MMU_DEMAP_ALL, %o5 1046 0 stevel ta FAST_TRAP 1047 0 stevel brz,pt %o0, 1f 1048 2241 huah nop 1049 0 stevel ba panic_bad_hcall 1050 2241 huah mov MMU_DEMAP_ALL, %o1 1051 0 stevel 1: 1052 0 stevel retl 1053 2241 huah nop 1054 0 stevel SET_SIZE(vtag_flushall) 1055 0 stevel 1056 0 stevel ENTRY_NP(vtag_unmap_perm_tl1) 1057 0 stevel /* 1058 0 stevel * x-trap to unmap perm map entry 1059 0 stevel * %g1 = vaddr 1060 2241 huah * %g2 = ctxnum (KCONTEXT only) 1061 0 stevel */ 1062 0 stevel mov %o0, %g3 1063 0 stevel mov %o1, %g4 1064 0 stevel mov %o2, %g5 1065 0 stevel mov %o5, %g6 1066 0 stevel mov %g1, %o0 1067 0 stevel mov %g2, %o1 1068 0 stevel mov MAP_ITLB | MAP_DTLB, %o2 1069 0 stevel mov UNMAP_PERM_ADDR, %o5 1070 0 stevel ta FAST_TRAP 1071 0 stevel brz,pt %o0, 1f 1072 0 stevel nop 1073 1991 heppo 1074 0 stevel mov PTL1_BAD_HCALL, %g1 1075 1991 heppo 1076 1991 heppo cmp %o0, H_ENOMAP 1077 1991 heppo move %xcc, PTL1_BAD_HCALL_UNMAP_PERM_ENOMAP, %g1 1078 1991 heppo 1079 1991 heppo cmp %o0, H_EINVAL 1080 1991 heppo move %xcc, PTL1_BAD_HCALL_UNMAP_PERM_EINVAL, %g1 1081 1991 heppo 1082 1991 heppo ba,a ptl1_panic 1083 0 stevel 1: 1084 0 stevel mov %g6, %o5 1085 0 stevel mov %g5, %o2 1086 0 stevel mov %g4, %o1 1087 0 stevel mov %g3, %o0 1088 0 stevel retry 1089 0 stevel SET_SIZE(vtag_unmap_perm_tl1) 1090 0 stevel 1091 0 stevel ENTRY_NP(vtag_flushpage_tl1) 1092 0 stevel /* 1093 0 stevel * x-trap to flush page from tlb and tsb 1094 0 stevel * 1095 0 stevel * %g1 = vaddr, zero-extended on 32-bit kernel 1096 2241 huah * %g2 = sfmmup 1097 0 stevel * 1098 0 stevel * assumes TSBE_TAG = 0 1099 0 stevel */ 1100 0 stevel srln %g1, MMU_PAGESHIFT, %g1 1101 0 stevel slln %g1, MMU_PAGESHIFT, %g1 /* g1 = vaddr */ 1102 0 stevel mov %o0, %g3 1103 0 stevel mov %o1, %g4 1104 0 stevel mov %o2, %g5 1105 2241 huah mov %g1, %o0 /* vaddr */ 1106 2241 huah 1107 2241 huah SFMMU_CPU_CNUM(%g2, %o1, %g6) /* %o1 = sfmmu cnum on this CPU */ 1108 2241 huah 1109 0 stevel mov MAP_ITLB | MAP_DTLB, %o2 1110 0 stevel ta MMU_UNMAP_ADDR 1111 0 stevel brz,pt %o0, 1f 1112 0 stevel nop 1113 2241 huah ba ptl1_panic 1114 0 stevel mov PTL1_BAD_HCALL, %g1 1115 0 stevel 1: 1116 0 stevel mov %g5, %o2 1117 0 stevel mov %g4, %o1 1118 0 stevel mov %g3, %o0 1119 0 stevel membar #Sync 1120 0 stevel retry 1121 0 stevel SET_SIZE(vtag_flushpage_tl1) 1122 0 stevel 1123 0 stevel ENTRY_NP(vtag_flush_pgcnt_tl1) 1124 0 stevel /* 1125 0 stevel * x-trap to flush pgcnt MMU_PAGESIZE pages from tlb 1126 0 stevel * 1127 0 stevel * %g1 = vaddr, zero-extended on 32-bit kernel 1128 2241 huah * %g2 = <sfmmup58|pgcnt6>, (pgcnt - 1) is pass'ed in via pgcnt6 bits. 1129 0 stevel * 1130 0 stevel * NOTE: this handler relies on the fact that no 1131 0 stevel * interrupts or traps can occur during the loop 1132 0 stevel * issuing the TLB_DEMAP operations. It is assumed 1133 0 stevel * that interrupts are disabled and this code is 1134 0 stevel * fetching from the kernel locked text address. 1135 0 stevel * 1136 0 stevel * assumes TSBE_TAG = 0 1137 0 stevel */ 1138 0 stevel srln %g1, MMU_PAGESHIFT, %g1 1139 0 stevel slln %g1, MMU_PAGESHIFT, %g1 /* g1 = vaddr */ 1140 0 stevel mov %o0, %g3 1141 0 stevel mov %o1, %g4 1142 0 stevel mov %o2, %g5 1143 0 stevel 1144 2241 huah and %g2, SFMMU_PGCNT_MASK, %g7 /* g7 = pgcnt - 1 */ 1145 2241 huah add %g7, 1, %g7 /* g7 = pgcnt */ 1146 0 stevel 1147 2241 huah andn %g2, SFMMU_PGCNT_MASK, %o0 /* %o0 = sfmmup */ 1148 2241 huah 1149 2241 huah SFMMU_CPU_CNUM(%o0, %g2, %g6) /* %g2 = sfmmu cnum on this CPU */ 1150 2241 huah 1151 2241 huah set MMU_PAGESIZE, %g6 /* g6 = pgsize */ 1152 2241 huah 1153 2241 huah 1: 1154 2241 huah mov %g1, %o0 /* vaddr */ 1155 2241 huah mov %g2, %o1 /* cnum */ 1156 0 stevel mov MAP_ITLB | MAP_DTLB, %o2 1157 0 stevel ta MMU_UNMAP_ADDR 1158 0 stevel brz,pt %o0, 2f 1159 2241 huah nop 1160 0 stevel ba ptl1_panic 1161 2241 huah mov PTL1_BAD_HCALL, %g1 1162 0 stevel 2: 1163 0 stevel deccc %g7 /* decr pgcnt */ 1164 0 stevel bnz,pt %icc,1b 1165 2241 huah add %g1, %g6, %g1 /* go to nextpage */ 1166 0 stevel 1167 0 stevel mov %g5, %o2 1168 0 stevel mov %g4, %o1 1169 0 stevel mov %g3, %o0 1170 0 stevel membar #Sync 1171 0 stevel retry 1172 0 stevel SET_SIZE(vtag_flush_pgcnt_tl1) 1173 0 stevel 1174 0 stevel ! Not implemented on US1/US2 1175 0 stevel ENTRY_NP(vtag_flushall_tl1) 1176 0 stevel mov %o0, %g3 1177 0 stevel mov %o1, %g4 1178 0 stevel mov %o2, %g5 1179 0 stevel mov %o3, %g6 ! XXXQ not used? 1180 0 stevel mov %o5, %g7 1181 0 stevel mov %g0, %o0 ! XXX no cpu list yet 1182 0 stevel mov %g0, %o1 ! XXX no cpu list yet 1183 0 stevel mov MAP_ITLB | MAP_DTLB, %o2 1184 0 stevel mov MMU_DEMAP_ALL, %o5 1185 0 stevel ta FAST_TRAP 1186 0 stevel brz,pt %o0, 1f 1187 2241 huah nop 1188 0 stevel ba ptl1_panic 1189 2241 huah mov PTL1_BAD_HCALL, %g1 1190 0 stevel 1: 1191 0 stevel mov %g7, %o5 1192 0 stevel mov %g6, %o3 ! XXXQ not used? 1193 0 stevel mov %g5, %o2 1194 0 stevel mov %g4, %o1 1195 0 stevel mov %g3, %o0 1196 0 stevel retry 1197 0 stevel SET_SIZE(vtag_flushall_tl1) 1198 0 stevel 1199 0 stevel /* 1200 0 stevel * flush_instr_mem: 1201 0 stevel * Flush a portion of the I-$ starting at vaddr 1202 0 stevel * %o0 vaddr 1203 0 stevel * %o1 bytes to be flushed 1204 0 stevel */ 1205 0 stevel 1206 0 stevel ENTRY(flush_instr_mem) 1207 0 stevel membar #StoreStore ! Ensure the stores 1208 0 stevel ! are globally visible 1209 0 stevel 1: 1210 0 stevel flush %o0 1211 0 stevel subcc %o1, ICACHE_FLUSHSZ, %o1 ! bytes = bytes-0x20 1212 0 stevel bgu,pt %ncc, 1b 1213 2241 huah add %o0, ICACHE_FLUSHSZ, %o0 ! vaddr = vaddr+0x20 1214 0 stevel 1215 0 stevel retl 1216 2241 huah nop 1217 0 stevel SET_SIZE(flush_instr_mem) 1218 0 stevel 1219 0 stevel #endif /* !lint */ 1220 1614 jb145095 1221 7718 Jason #if !defined(CUSTOM_FPZERO) 1222 7718 Jason 1223 1614 jb145095 /* 1224 1614 jb145095 * fp_zero() - clear all fp data registers and the fsr 1225 1614 jb145095 */ 1226 1614 jb145095 1227 1614 jb145095 #if defined(lint) || defined(__lint) 1228 1614 jb145095 1229 1614 jb145095 void 1230 1614 jb145095 fp_zero(void) 1231 1614 jb145095 {} 1232 1614 jb145095 1233 1614 jb145095 #else /* lint */ 1234 1614 jb145095 1235 1614 jb145095 .global fp_zero_zero 1236 1614 jb145095 .align 8 1237 1614 jb145095 fp_zero_zero: 1238 1614 jb145095 .xword 0 1239 1614 jb145095 1240 1614 jb145095 ENTRY_NP(fp_zero) 1241 1614 jb145095 sethi %hi(fp_zero_zero), %o0 1242 7718 Jason ldx [%o0 + %lo(fp_zero_zero)], %fsr 1243 1614 jb145095 ldd [%o0 + %lo(fp_zero_zero)], %f0 1244 1614 jb145095 fmovd %f0, %f2 1245 1614 jb145095 fmovd %f0, %f4 1246 1614 jb145095 fmovd %f0, %f6 1247 1614 jb145095 fmovd %f0, %f8 1248 1614 jb145095 fmovd %f0, %f10 1249 1614 jb145095 fmovd %f0, %f12 1250 1614 jb145095 fmovd %f0, %f14 1251 1614 jb145095 fmovd %f0, %f16 1252 1614 jb145095 fmovd %f0, %f18 1253 1614 jb145095 fmovd %f0, %f20 1254 1614 jb145095 fmovd %f0, %f22 1255 1614 jb145095 fmovd %f0, %f24 1256 1614 jb145095 fmovd %f0, %f26 1257 1614 jb145095 fmovd %f0, %f28 1258 1614 jb145095 fmovd %f0, %f30 1259 1614 jb145095 fmovd %f0, %f32 1260 1614 jb145095 fmovd %f0, %f34 1261 1614 jb145095 fmovd %f0, %f36 1262 1614 jb145095 fmovd %f0, %f38 1263 1614 jb145095 fmovd %f0, %f40 1264 1614 jb145095 fmovd %f0, %f42 1265 1614 jb145095 fmovd %f0, %f44 1266 1614 jb145095 fmovd %f0, %f46 1267 1614 jb145095 fmovd %f0, %f48 1268 1614 jb145095 fmovd %f0, %f50 1269 1614 jb145095 fmovd %f0, %f52 1270 1614 jb145095 fmovd %f0, %f54 1271 1614 jb145095 fmovd %f0, %f56 1272 1614 jb145095 fmovd %f0, %f58 1273 1614 jb145095 fmovd %f0, %f60 1274 1614 jb145095 retl 1275 1614 jb145095 fmovd %f0, %f62 1276 1614 jb145095 SET_SIZE(fp_zero) 1277 1614 jb145095 1278 1614 jb145095 #endif /* lint */ 1279 7718 Jason #endif /* CUSTOM_FPZERO */ 1280