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 2008 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #if defined(lint) || defined(DS_DDICT)
  27 #include <sys/types.h>
  28 #include <sys/param.h>
  29 #else
  30 #include "assym.h"      /* Determine value of CPU_THREAD */
  31 #include <sys/asm_linkage.h>
  32 #endif
  33 
  34 #ifdef DS_DDICT
  35 #define uint8_t uchar_t
  36 #endif
  37 
  38 
  39 /*
  40  * Special support routines that can't be done with C
  41  * x86 variant
  42  */
  43 
  44 /*
  45  * uint8_t nsc_ldstub(uint8_t *cp)
  46  *
  47  * Store 0xFF at the specified location, and return its previous content.
  48  */
  49 
  50 #if defined(lint) || defined(DS_DDICT)
  51 uint8_t
  52 nsc_ldstub(uint8_t *cp)
  53 {
  54         uint8_t rv;
  55         rv = *cp;
  56         *cp = 0xFF;
  57         return (rv);
  58 }
  59 #else
  60         ENTRY(nsc_ldstub)
  61 #if defined(__amd64)
  62         movl    $0xff,%eax 
  63         lock
  64         xchgb   %al, (%rdi)             /* rdi = lock addr */
  65         ret
  66 #elif defined(__i386)
  67         movl    4(%esp), %ecx           /* ecx = lock addr */
  68         movl    $0xff, %eax             /* eax = 0xff */
  69         lock
  70         xchgb   %al, (%ecx)             /* atomic swap eax <-> *ecx */
  71         ret
  72 #else
  73 #error  "port this routine"
  74 #endif
  75         SET_SIZE(nsc_ldstub)
  76 #endif
  77 
  78 /*
  79  * nsc_membar_stld(void)
  80  *
  81  * On SPARC this is a C callable interface to SPARC asm membar instruction.
  82  * For x86 we brute force it with a #LOCK instruction.
  83  */
  84 
  85 #if defined(lint) || defined(DS_DDICT)
  86 void
  87 nsc_membar_stld(void)
  88 {}
  89 #else
  90 
  91         ENTRY(nsc_membar_stld)
  92 #if defined(__amd64)
  93         mfence
  94         ret
  95 #elif defined(__i386)
  96         lock
  97         xorl    $0, (%esp)
  98         ret
  99 #else
 100 #error  "port this routine"
 101 #endif
 102         SET_SIZE(nsc_membar_stld)
 103 
 104 #endif  /* lint || DS_DDICT */
 105 
 106 
 107 /*
 108  * if a() calls b() calls nsc_caller(),
 109  * nsc_caller() returns return address in a().
 110  */
 111 
 112 #if defined(lint) || defined(DS_DDICT)
 113 caddr_t
 114 nsc_caller(void)
 115 {
 116         return (0);
 117 }
 118 #else
 119 
 120         ENTRY(nsc_caller)
 121 #if defined(__amd64)
 122         movq    8(%rbp), %rax           /* b()'s return pc, in a() */
 123         ret
 124 #elif defined(__i386)
 125         movl    4(%ebp), %eax           /* b()'s return pc, in a() */
 126         ret
 127 #else
 128 #error  "port this routine"
 129 #endif
 130         SET_SIZE(nsc_caller)
 131 
 132 #endif  /* lint || DS_DDICT */
 133 
 134 
 135 /*
 136  * if a() calls nsc_callee(), nsc_callee() returns the
 137  * return address in a();
 138  */
 139 
 140 #if defined(lint) || defined(DS_DDICT)
 141 caddr_t
 142 nsc_callee(void)
 143 {
 144         return (0);
 145 }
 146 #else
 147 
 148         ENTRY(nsc_callee)
 149 #if defined(__amd64)
 150         movq    (%rsp), %rax            /* callee()'s return pc, in a() */
 151         ret
 152 #elif defined(__i386)
 153         movl    (%esp), %eax            /* callee()'s return pc, in a() */
 154         ret
 155 #else
 156 #error  "port this routine"
 157 #endif
 158         SET_SIZE(nsc_callee)
 159 
 160 #endif  /* lint || DS_DDICT */
 161 
 162 
 163 /*
 164  * nsc_threadp(void)
 165  *
 166  * C callable interface to get the current thread pointer.
 167  */
 168  
 169 #if defined(lint) || defined(DS_DDICT)
 170 void *
 171 nsc_threadp(void)
 172 {
 173         return (NULL);
 174 }
 175 #else
 176 
 177         ENTRY(nsc_threadp)
 178 #if defined(__amd64)
 179         movq    %gs:CPU_THREAD, %rax
 180         ret
 181 #elif defined(__i386)
 182         movl %gs:CPU_THREAD,%eax
 183         ret
 184 #else
 185 #error  "port this routine"
 186 #endif
 187         SET_SIZE(nsc_threadp)
 188 
 189 #endif /* lint || DS_DDICT */