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