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