1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 /* 26 * General machine architecture & implementation specific 27 * assembly language routines. 28 */ 29 #if defined(lint) 30 #include <sys/types.h> 31 #include <sys/t_lock.h> 32 #else /* lint */ 33 #include "assym.h" 34 #endif /* lint */ 35 36 #define CPU_MODULE /* need it for NSEC_SHIFT used by NATIVE_TIME_TO_NSEC() */ 37 38 #include <sys/asm_linkage.h> 39 #include <sys/machsystm.h> 40 #include <sys/machthread.h> 41 #include <sys/machclock.h> 42 #include <sys/privregs.h> 43 #include <sys/cmpregs.h> 44 #include <sys/clock.h> 45 #include <sys/fpras.h> 46 #include <sys/soft_state.h> 47 48 #if defined(lint) 49 50 uint64_t 51 ultra_gettick(void) 52 { return (0); } 53 54 #else /* lint */ 55 56 /* 57 * This isn't the routine you're looking for. 58 * 59 * The routine simply returns the value of %tick on the *current* processor. 60 * Most of the time, gettick() [which in turn maps to %stick on platforms 61 * that have different CPU %tick rates] is what you want. 62 */ 63 64 ENTRY(ultra_gettick) 65 RD_TICK(%o0,%o1,%o2,__LINE__) 66 retl 67 nop 68 SET_SIZE(ultra_gettick) 69 70 #endif /* lint */ 71 72 #if defined(lint) 73 /* ARGSUSED */ 74 void 75 set_mmfsa_scratchpad(caddr_t vaddr) 76 { } 77 78 #else /* lint */ 79 80 ENTRY(set_mmfsa_scratchpad) 81 stxa %o0, [%g0]ASI_SCRATCHPAD 82 retl 83 nop 84 SET_SIZE(set_mmfsa_scratchpad) 85 #endif /* lint */ 86 87 #if defined(lint) 88 caddr_t 89 get_mmfsa_scratchpad() 90 { return (0); } 91 92 #else /* lint */ 93 94 ENTRY(get_mmfsa_scratchpad) 95 ldxa [%g0]ASI_SCRATCHPAD, %o0 96 retl 97 nop 98 SET_SIZE(get_mmfsa_scratchpad) 99 #endif /* lint */ 100 101 102 103 #if defined(lint) 104 /* ARGSUSED */ 105 void 106 cpu_intrq_unregister_powerdown(uint64_t doneflag_va) 107 {} 108 109 #else /* lint */ 110 111 /* 112 * Called from a x-trap at tl1 must use %g1 as arg 113 * and save/restore %o0-%o5 after hypervisor calls 114 */ 115 116 ENTRY(cpu_intrq_unregister_powerdown) 117 118 CPU_ADDR(%g2, %g3) 119 add %g2, CPU_MCPU, %g2 120 /* 121 * Save %o regs 122 */ 123 mov %o0, %g3 124 mov %o1, %g4 125 mov %o2, %g5 126 mov %o5, %g6 127 128 ldx [%g2 + MCPU_CPU_Q_BASE], %o1 129 mov INTR_CPU_Q, %o0 130 call hv_cpu_qconf 131 mov %g0, %o2 132 133 ldx [%g2 + MCPU_DEV_Q_BASE], %o1 134 mov INTR_DEV_Q, %o0 135 call hv_cpu_qconf 136 mov %g0, %o2 137 138 ldx [%g2 + MCPU_RQ_BASE], %o1 139 mov CPU_RQ, %o0 140 call hv_cpu_qconf 141 mov %g0, %o2 142 143 ldx [%g2 + MCPU_NRQ_BASE], %o1 144 mov CPU_NRQ, %o0 145 call hv_cpu_qconf 146 mov %g0, %o2 147 148 /* 149 * set done flag to 0 150 */ 151 stub %g0, [%g1] 152 153 /* 154 * Restore %o regs 155 */ 156 mov %g3, %o0 157 mov %g4, %o1 158 mov %g5, %o2 159 mov %g6, %o5 160 161 /* 162 * This CPU is on its way out. Spin here 163 * until the DR unconfigure code stops it. 164 * Returning would put it back in the OS 165 * where it might grab resources like locks, 166 * causing some nastiness to occur. 167 */ 168 0: 169 ba,a 0b 170 171 SET_SIZE(cpu_intrq_unregister_powerdown) 172 #endif /* lint */ 173 174 175 #if defined(lint) 176 /* ARGSUSED */ 177 int 178 getprocessorid(void) 179 { return (0); } 180 181 #else /* lint */ 182 183 /* 184 * Get the processor ID. 185 * === MID reg as specified in 15dec89 sun4u spec, sec 5.4.3 186 */ 187 188 ENTRY(getprocessorid) 189 CPU_INDEX(%o0, %o1) 190 retl 191 nop 192 SET_SIZE(getprocessorid) 193 194 #endif /* lint */ 195 196 #if defined(lint) || defined(__lint) 197 198 /* ARGSUSED */ 199 hrtime_t 200 tick2ns(hrtime_t tick, uint_t cpuid) 201 { return 0; } 202 203 #else /* lint */ 204 205 ENTRY_NP(tick2ns) 206 ! 207 ! Use nsec_scale for sun4v which is based on %stick 208 ! 209 NATIVE_TIME_TO_NSEC(%o0, %o2, %o3) 210 retl 211 nop 212 SET_SIZE(tick2ns) 213 214 #endif /* lint */ 215 216 #if defined(lint) 217 218 /* ARGSUSED */ 219 void 220 set_cmp_error_steering(void) 221 {} 222 223 #else /* lint */ 224 225 ENTRY(set_cmp_error_steering) 226 retl 227 nop 228 SET_SIZE(set_cmp_error_steering) 229 230 #endif /* lint */ 231 232 #if defined(lint) 233 234 /* ARGSUSED */ 235 uint64_t 236 ultra_getver(void) 237 { 238 return (0); 239 } 240 241 #else /* lint */ 242 243 ENTRY(ultra_getver) 244 retl 245 mov -1, %o0 ! XXXQ no version available 246 SET_SIZE(ultra_getver) 247 248 #endif /* lint */ 249 250 #if defined(lint) 251 252 int 253 fpras_chkfn_type1(void) 254 { return 0; } 255 256 #else /* lint */ 257 258 /* 259 * Check instructions using just the AX pipelines, designed by 260 * C.B. Liaw of PNP. 261 * 262 * This function must match a struct fpras_chkfn and must be 263 * block aligned. A zero return means all was well. These 264 * instructions are chosen to be sensitive to bit corruptions 265 * on the fpras rewrite, so if a bit corruption still produces 266 * a valid instruction we should still get an incorrect result 267 * here. This function is never called directly - it is copied 268 * into per-cpu and per-operation buffers; it must therefore 269 * be absolutely position independent. If an illegal instruction 270 * is encountered then the trap handler trampolines to the final 271 * three instructions of this function. 272 * 273 * We want two instructions that are complements of one another, 274 * and which can perform a calculation with a known result. 275 * 276 * SETHI: 277 * 278 * | 0 0 | rd | 1 0 0 | imm22 | 279 * 31 30 29 25 24 22 21 0 280 * 281 * ADDCCC with two source registers: 282 * 283 * | 1 0 | rd | 0 1 1 0 0 0 | rs1 | 0 | - | rs2 | 284 * 31 30 29 25 24 19 18 14 13 12 5 4 0 285 * 286 * We can choose rd and imm2 of the SETHI and rd, rs1 and rs2 of 287 * the ADDCCC to obtain instructions that are complements in all but 288 * bit 30. 289 * 290 * Registers are numbered as follows: 291 * 292 * r[31] %i7 293 * r[30] %i6 294 * r[29] %i5 295 * r[28] %i4 296 * r[27] %i3 297 * r[26] %i2 298 * r[25] %i1 299 * r[24] %i0 300 * r[23] %l7 301 * r[22] %l6 302 * r[21] %l5 303 * r[20] %l4 304 * r[19] %l3 305 * r[18] %l2 306 * r[17] %l1 307 * r[16] %l0 308 * r[15] %o7 309 * r[14] %o6 310 * r[13] %o5 311 * r[12] %o4 312 * r[11] %o3 313 * r[10] %o2 314 * r[9] %o1 315 * r[8] %o0 316 * r[7] %g7 317 * r[6] %g6 318 * r[5] %g5 319 * r[4] %g4 320 * r[3] %g3 321 * r[2] %g2 322 * r[1] %g1 323 * r[0] %g0 324 * 325 * For register r[n], register r[31-n] is the complement. We must 326 * avoid use of %i6/%i7 and %o6/%o7 as well as %g7. Clearly we need 327 * to use a local or input register as one half of the pair, which 328 * requires us to obtain our own register window or take steps 329 * to preserve any local or input we choose to use. We choose 330 * %o1 as rd for the SETHI, so rd of the ADDCCC must be %l6. 331 * We'll use %o1 as rs1 and %l6 as rs2 of the ADDCCC, which then 332 * requires that imm22 be 0b111 10110 1 11111111 01001 or 0x3dbfe9, 333 * or %hi(0xf6ffa400). This determines the value of the constant 334 * CBV2 below. 335 * 336 * The constant CBV1 is chosen such that an initial subcc %g0, CBV1 337 * will set the carry bit and every addccc thereafter will continue 338 * to generate a carry. Other values are possible for CBV1 - this 339 * is just one that works this way. 340 * 341 * Finally CBV3 is the expected answer when we perform our repeated 342 * calculations on CBV1 and CBV2 - it is not otherwise specially 343 * derived. If this result is not obtained then a corruption has 344 * occured during the FPRAS_REWRITE of one of the two blocks of 345 * 16 instructions. A corruption could also result in an illegal 346 * instruction or other unexpected trap - we catch illegal 347 * instruction traps in the PC range and trampoline to the 348 * last instructions of the function to return a failure indication. 349 * 350 */ 351 352 #define CBV1 0xc11 353 #define CBV2 0xf6ffa400 354 #define CBV3 0x66f9d800 355 #define CBR1 %o1 356 #define CBR2 %l6 357 #define CBO2 %o2 358 #define SETHI_CBV2_CBR1 sethi %hi(CBV2), CBR1 359 #define ADDCCC_CBR1_CBR2_CBR2 addccc CBR1, CBR2, CBR2 360 361 .align 64 362 ENTRY_NP(fpras_chkfn_type1) 363 mov CBR2, CBO2 ! 1, preserve CBR2 of (callers) window 364 mov FPRAS_OK, %o0 ! 2, default return value 365 ba,pt %icc, 1f ! 3 366 subcc %g0, CBV1, CBR2 ! 4 367 ! 5 - 16 368 .align 64 369 1: SETHI_CBV2_CBR1 ! 1 370 ADDCCC_CBR1_CBR2_CBR2 ! 2 371 SETHI_CBV2_CBR1 ! 3 372 ADDCCC_CBR1_CBR2_CBR2 ! 4 373 SETHI_CBV2_CBR1 ! 5 374 ADDCCC_CBR1_CBR2_CBR2 ! 6 375 SETHI_CBV2_CBR1 ! 7 376 ADDCCC_CBR1_CBR2_CBR2 ! 8 377 SETHI_CBV2_CBR1 ! 9 378 ADDCCC_CBR1_CBR2_CBR2 ! 10 379 SETHI_CBV2_CBR1 ! 11 380 ADDCCC_CBR1_CBR2_CBR2 ! 12 381 SETHI_CBV2_CBR1 ! 13 382 ADDCCC_CBR1_CBR2_CBR2 ! 14 383 SETHI_CBV2_CBR1 ! 15 384 ADDCCC_CBR1_CBR2_CBR2 ! 16 385 386 ADDCCC_CBR1_CBR2_CBR2 ! 1 387 SETHI_CBV2_CBR1 ! 2 388 ADDCCC_CBR1_CBR2_CBR2 ! 3 389 SETHI_CBV2_CBR1 ! 4 390 ADDCCC_CBR1_CBR2_CBR2 ! 5 391 SETHI_CBV2_CBR1 ! 6 392 ADDCCC_CBR1_CBR2_CBR2 ! 7 393 SETHI_CBV2_CBR1 ! 8 394 ADDCCC_CBR1_CBR2_CBR2 ! 9 395 SETHI_CBV2_CBR1 ! 10 396 ADDCCC_CBR1_CBR2_CBR2 ! 11 397 SETHI_CBV2_CBR1 ! 12 398 ADDCCC_CBR1_CBR2_CBR2 ! 13 399 SETHI_CBV2_CBR1 ! 14 400 ADDCCC_CBR1_CBR2_CBR2 ! 15 401 SETHI_CBV2_CBR1 ! 16 402 403 addc CBR1, CBR2, CBR2 ! 1 404 sethi %hi(CBV3), CBR1 ! 2 405 cmp CBR1, CBR2 ! 3 406 movnz %icc, FPRAS_BADCALC, %o0! 4, how detected 407 retl ! 5 408 mov CBO2, CBR2 ! 6, restore borrowed register 409 .skip 4*(13-7+1) ! 7 - 13 410 ! 411 ! illegal instr'n trap comes here 412 ! 413 mov CBO2, CBR2 ! 14, restore borrowed register 414 retl ! 15 415 mov FPRAS_BADTRAP, %o0 ! 16, how detected 416 SET_SIZE(fpras_chkfn_type1) 417 #endif /* lint */ 418 419 #if defined(lint) 420 char soft_state_message_strings[SOLARIS_SOFT_STATE_MSG_CNT][SSM_SIZE]; 421 #else /* lint */ 422 .seg ".data" 423 .global soft_state_message_strings 424 425 .align SSM_SIZE 426 soft_state_message_strings: 427 .asciz SOLARIS_SOFT_STATE_BOOT_MSG_STR 428 .align SSM_SIZE 429 .asciz SOLARIS_SOFT_STATE_RUN_MSG_STR 430 .align SSM_SIZE 431 .asciz SOLARIS_SOFT_STATE_HALT_MSG_STR 432 .align SSM_SIZE 433 .asciz SOLARIS_SOFT_STATE_POWER_MSG_STR 434 .align SSM_SIZE 435 .asciz SOLARIS_SOFT_STATE_PANIC_MSG_STR 436 .align SSM_SIZE 437 .asciz SOLARIS_SOFT_STATE_REBOOT_MSG_STR 438 .align SSM_SIZE 439 .asciz SOLARIS_SOFT_STATE_DEBUG_MSG_STR 440 .align SSM_SIZE 441 .skip SSM_SIZE /* saved message */ 442 .nword 0 443 444 .seg ".text" 445 #endif /* lint */