Home | History | Annotate | Download | only in ml
      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 */
    290