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 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #if defined(lint)
  27 #include <sys/types.h>
  28 #include <sys/cpuvar.h>
  29 #else   /*lint */
  30 #include "assym.h"
  31 #endif  /* lint */
  32 
  33 #include <sys/asm_linkage.h>
  34 #include <sys/privregs.h>
  35 #include <sys/x_call.h>
  36 #include <sys/xc_impl.h>
  37 #include <sys/machthread.h>
  38 #include <sys/hypervisor_api.h>
  39 
  40 #ifdef TRAPTRACE
  41 #include <sys/traptrace.h>
  42 #endif /* TRAPTRACE */
  43 
  44 
  45 #if defined(lint)
  46 
  47 /* ARGSUSED */
  48 void
  49 self_xcall(struct cpu *cpu, uint64_t arg1, uint64_t arg2, xcfunc_t *func)
  50 {}
  51 
  52 #else
  53 
  54 /*
  55  * Entered by the software trap (TT=ST_SELFXCALL, TL>0) thru send_self_xcall().
  56  * Emulate the mondo handler - vec_interrupt().
  57  *
  58  * Global registers are the Alternate Globals.
  59  * Arguments:
  60  *      %o0 - CPU
  61  *      ILP32 kernel:
  62  *              %o5 - function to call
  63  *              %o1, %o2, %o3, %o4  - arguments
  64  *      LP64 kernel:
  65  *              %o3 - function to call
  66  *              %o1, %o2 - arguments
  67  */
  68         ENTRY_NP(self_xcall)
  69         !
  70         ! TL>0 handlers are expected to do "retry"
  71         ! prepare their return PC and nPC now
  72         !
  73         rdpr    %tnpc, %g1
  74         wrpr    %g1, %tpc                       !  PC <- TNPC[TL]
  75         add     %g1, 4, %g1
  76         wrpr    %g1, %tnpc                      ! nPC <- TNPC[TL] + 4
  77 
  78 #ifdef TRAPTRACE
  79         TRACE_PTR(%g4, %g6)
  80         GET_TRACE_TICK(%g6, %g3)
  81         stxa    %g6, [%g4 + TRAP_ENT_TICK]%asi
  82         rdpr    %tl, %g6
  83         stha    %g6, [%g4 + TRAP_ENT_TL]%asi
  84         rdpr    %tt, %g6
  85         stha    %g6, [%g4 + TRAP_ENT_TT]%asi
  86         stna    %o3, [%g4 + TRAP_ENT_TR]%asi ! pc of the TL>0 handler
  87         rdpr    %tpc, %g6
  88         stna    %g6, [%g4 + TRAP_ENT_TPC]%asi
  89         rdpr    %tstate, %g6
  90         stxa    %g6, [%g4 + TRAP_ENT_TSTATE]%asi
  91         stna    %sp, [%g4 + TRAP_ENT_SP]%asi
  92         stna    %o1, [%g4 + TRAP_ENT_F1]%asi ! arg 1
  93         stna    %o2, [%g4 + TRAP_ENT_F2]%asi ! arg 2
  94         stna    %g0, [%g4 + TRAP_ENT_F3]%asi
  95         stna    %g0, [%g4 + TRAP_ENT_F4]%asi
  96         TRACE_NEXT(%g4, %g6, %g3)
  97 #endif /* TRAPTRACE */
  98         !
  99         ! Load the arguments for the fast trap handler.
 100         !
 101         mov     %o1, %g1
 102         jmp     %o3                             ! call the fast trap handler
 103         mov     %o2, %g2
 104         /* Not Reached */
 105         SET_SIZE(self_xcall)
 106 
 107 #endif  /* lint */
 108 
 109 #ifdef  TRAPTRACE
 110 #if defined(lint)
 111 
 112 /* ARGSUSED */
 113 void
 114 xc_trace(u_int traptype, cpuset_t *cpu_set, xcfunc_t *func,
 115         uint64_t arg1, uint64_t arg2)
 116 {}
 117 
 118 #else   /* lint */
 119         ENTRY(xc_trace)
 120         rdpr    %pstate, %g1
 121         andn    %g1, PSTATE_IE | PSTATE_AM, %g2
 122         wrpr    %g0, %g2, %pstate                       /* disable interrupts */
 123         TRACE_PTR(%g3, %g4)
 124         GET_TRACE_TICK(%g6, %g4)
 125         stxa    %g6, [%g3 + TRAP_ENT_TICK]%asi
 126         stha    %g0, [%g3 + TRAP_ENT_TL]%asi
 127         set     TT_XCALL, %g2
 128         or      %o0, %g2, %g4
 129         stha    %g4, [%g3 + TRAP_ENT_TT]%asi
 130         stna    %o7, [%g3 + TRAP_ENT_TPC]%asi
 131         ldn     [%o1], %g2
 132         stna    %g2, [%g3 + TRAP_ENT_SP]%asi            /* sp = cpuset */
 133         stna    %o2, [%g3 + TRAP_ENT_TR]%asi            /* tr = func */
 134         stna    %o3, [%g3 + TRAP_ENT_F1]%asi            /* f1 = arg1 */
 135         stna    %o4, [%g3 + TRAP_ENT_F2]%asi            /* f2 = arg2 */
 136         stna    %g0, [%g3 + TRAP_ENT_F3]%asi            /* f3 = 0 */
 137         stna    %i7, [%g3 + TRAP_ENT_F4]%asi            /* f4 = xcall caller */
 138         stxa    %g1, [%g3 + TRAP_ENT_TSTATE]%asi        /* tstate = pstate */
 139         TRACE_NEXT(%g2, %g3, %g4)
 140 /*
 141  * In the case of a cpuset of greater size than a long we
 142  * grab extra trace buffers just to store the cpuset.
 143  * Seems like a waste but popular opinion opted for this 
 144  * rather than increase the size of the buffer.
 145  */
 146 #if CPUSET_SIZE > CLONGSIZE
 147         add     %o1, CPUSET_SIZE, %g5                   /* end of cpuset */
 148         clr     %o2
 149 1:
 150         TRACE_PTR(%g3, %g4)
 151         stha    %g0, [%g3 + TRAP_ENT_TL]%asi
 152         set     TT_XCALL_CONT, %g2
 153         or      %g2, %o2, %g2                           /* continuation # */
 154         stha    %g2, [%g3 + TRAP_ENT_TT]%asi
 155         stxa    %g6, [%g3 + TRAP_ENT_TICK]%asi          /* same tick */
 156         stna    %g0, [%g3 + TRAP_ENT_TPC]%asi           /* clr unused fields */
 157         stna    %g0, [%g3 + TRAP_ENT_SP]%asi
 158         stna    %g0, [%g3 + TRAP_ENT_TR]%asi
 159         stxa    %g0, [%g3 + TRAP_ENT_TSTATE]%asi
 160         stna    %g0, [%g3 + TRAP_ENT_F2]%asi
 161         stna    %g0, [%g3 + TRAP_ENT_F3]%asi
 162         stna    %g0, [%g3 + TRAP_ENT_F4]%asi
 163         ldn     [%o1], %g2
 164         stna    %g2, [%g3 + TRAP_ENT_F1]%asi
 165         add     %o1, CLONGSIZE, %o1
 166         cmp     %o1, %g5
 167         bge     2f
 168         ldn     [%o1], %g2
 169         stna    %g2, [%g3 + TRAP_ENT_F2]%asi
 170         add     %o1, CLONGSIZE, %o1
 171         cmp     %o1, %g5
 172         bge     2f
 173         ldn     [%o1], %g2
 174         stna    %g2, [%g3 + TRAP_ENT_F3]%asi
 175         add     %o1, CLONGSIZE, %o1
 176         cmp     %o1, %g5
 177         bge     2f
 178         ldn     [%o1], %g2
 179         stna    %g2, [%g3 + TRAP_ENT_F4]%asi
 180         add     %o1, CLONGSIZE, %o1
 181 2:      
 182         TRACE_NEXT(%g2, %g3, %g4)
 183         cmp     %o1, %g5
 184         bl      1b
 185         inc     %o2
 186 #endif  /* CPUSET_SIZE */
 187         retl
 188         wrpr    %g0, %g1, %pstate                       /* enable interrupts */
 189         SET_SIZE(xc_trace)
 190 
 191 #endif  /* lint */
 192 #endif  /* TRAPTRACE */
 193 
 194 #if defined(lint)
 195 
 196 /*ARGSUSED*/
 197 void
 198 init_mondo(xcfunc_t *func, uint64_t arg1, uint64_t arg2)
 199 {}
 200 
 201 /*ARGSUSED*/
 202 int
 203 shipit(int n, uint64_t cpuid)
 204 { return(0); }
 205 
 206 #else   /* lint */
 207 /*
 208  * Setup interrupt dispatch data registers
 209  * Entry:
 210  *      %o0 - function or inumber to call
 211  *      %o1, %o2 - arguments (2 uint64_t's)
 212  */
 213         ENTRY(init_mondo)
 214         ALTENTRY(init_mondo_nocheck)
 215         CPU_ADDR(%g1, %g4)                      ! load CPU struct addr
 216         add     %g1, CPU_MCPU, %g1
 217         ldx     [%g1 + MCPU_MONDO_DATA], %g1
 218         stx     %o0, [%g1]
 219         stx     %o1, [%g1+8]
 220         stx     %o2, [%g1+0x10]
 221         stx     %g0, [%g1+0x18]
 222         stx     %g0, [%g1+0x20]
 223         stx     %g0, [%g1+0x28]
 224         stx     %g0, [%g1+0x30]
 225         stx     %g0, [%g1+0x38]
 226         retl
 227         membar  #Sync                   ! allowed to be in the delay slot
 228         SET_SIZE(init_mondo)
 229 
 230 /*
 231  * Ship mondo to cpuid
 232  */
 233         ENTRY_NP(shipit)
 234         /* For now use dummy interface:  cpu# func arg1 arg2 */
 235         CPU_ADDR(%g1, %g4)
 236         add     %g1, CPU_MCPU, %g1
 237         ldx     [%g1 + MCPU_MONDO_DATA_RA],     %o2
 238         mov     HV_INTR_SEND, %o5
 239         ta      FAST_TRAP
 240         retl
 241         membar  #Sync
 242         SET_SIZE(shipit)
 243 
 244 #endif  /* lint */
 245 
 246 #if defined(lint)
 247 
 248 /*ARGSUSED*/
 249 uint64_t
 250 get_cpuaddr(uint64_t reg, uint64_t scr)
 251 { return (0);}
 252 
 253 #else   /* lint */
 254 /*
 255  * Get cpu structure
 256  * Entry:
 257  *      %o0 - register for CPU_ADDR macro
 258  *      %o1 - scratch for CPU_ADDR macro
 259  */
 260         ENTRY(get_cpuaddr)
 261         CPU_ADDR(%o0, %o1)      ! %o0 == CPU struct addr
 262         retl
 263         nop
 264         SET_SIZE(get_cpuaddr)
 265 
 266 #endif  /* lint */
 267 
 268 #if defined(lint)
 269 /* ARGSUSED */
 270 void
 271 xt_sync_tl1(uint64_t *cpu_sync_addr)
 272 {}
 273 
 274 #else /* lint */
 275 /*
 276  * This is to ensure that previously called xtrap handlers have executed on
 277  * sun4v. We zero out the byte corresponding to its cpuid in the
 278  * array passed to us from xt_sync(), so the sender knows the previous
 279  * mondo has been executed.
 280  * Register:
 281  *              %g1 - Addr of the cpu_sync array.
 282  */
 283         ENTRY_NP(xt_sync_tl1)
 284         CPU_INDEX(%g3, %g4)             /* %g3 = cpu id */
 285         stb     %g0, [%g1 + %g3] 
 286         retry
 287         SET_SIZE(xt_sync_tl1)
 288 
 289 #endif  /* lint */