xref: /onnv-gate/usr/src/uts/sun4v/ml/mach_xc.s (revision 11172:a792f425ae2e)
10Sstevel@tonic-gate/*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*11172SHaik.Aftandilian@Sun.COM * Common Development and Distribution License (the "License").
6*11172SHaik.Aftandilian@Sun.COM * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate/*
22*11172SHaik.Aftandilian@Sun.COM * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate#if defined(lint)
270Sstevel@tonic-gate#include <sys/types.h>
280Sstevel@tonic-gate#include <sys/cpuvar.h>
290Sstevel@tonic-gate#else	/*lint */
300Sstevel@tonic-gate#include "assym.h"
310Sstevel@tonic-gate#endif	/* lint */
320Sstevel@tonic-gate
330Sstevel@tonic-gate#include <sys/asm_linkage.h>
340Sstevel@tonic-gate#include <sys/privregs.h>
350Sstevel@tonic-gate#include <sys/x_call.h>
360Sstevel@tonic-gate#include <sys/xc_impl.h>
370Sstevel@tonic-gate#include <sys/machthread.h>
380Sstevel@tonic-gate#include <sys/hypervisor_api.h>
390Sstevel@tonic-gate
400Sstevel@tonic-gate#ifdef TRAPTRACE
410Sstevel@tonic-gate#include <sys/traptrace.h>
420Sstevel@tonic-gate#endif /* TRAPTRACE */
430Sstevel@tonic-gate
440Sstevel@tonic-gate
450Sstevel@tonic-gate#if defined(lint)
460Sstevel@tonic-gate
470Sstevel@tonic-gate/* ARGSUSED */
480Sstevel@tonic-gatevoid
490Sstevel@tonic-gateself_xcall(struct cpu *cpu, uint64_t arg1, uint64_t arg2, xcfunc_t *func)
500Sstevel@tonic-gate{}
510Sstevel@tonic-gate
520Sstevel@tonic-gate#else
530Sstevel@tonic-gate
540Sstevel@tonic-gate/*
550Sstevel@tonic-gate * Entered by the software trap (TT=ST_SELFXCALL, TL>0) thru send_self_xcall().
560Sstevel@tonic-gate * Emulate the mondo handler - vec_interrupt().
570Sstevel@tonic-gate *
580Sstevel@tonic-gate * Global registers are the Alternate Globals.
590Sstevel@tonic-gate * Arguments:
600Sstevel@tonic-gate * 	%o0 - CPU
610Sstevel@tonic-gate * 	ILP32 kernel:
620Sstevel@tonic-gate * 		%o5 - function to call
630Sstevel@tonic-gate * 		%o1, %o2, %o3, %o4  - arguments
640Sstevel@tonic-gate * 	LP64 kernel:
650Sstevel@tonic-gate * 		%o3 - function to call
660Sstevel@tonic-gate * 		%o1, %o2 - arguments
670Sstevel@tonic-gate */
680Sstevel@tonic-gate	ENTRY_NP(self_xcall)
690Sstevel@tonic-gate	!
700Sstevel@tonic-gate	! TL>0 handlers are expected to do "retry"
710Sstevel@tonic-gate	! prepare their return PC and nPC now
720Sstevel@tonic-gate	!
730Sstevel@tonic-gate	rdpr	%tnpc, %g1
740Sstevel@tonic-gate	wrpr	%g1, %tpc			!  PC <- TNPC[TL]
750Sstevel@tonic-gate 	add	%g1, 4, %g1
760Sstevel@tonic-gate	wrpr	%g1, %tnpc			! nPC <- TNPC[TL] + 4
770Sstevel@tonic-gate
780Sstevel@tonic-gate#ifdef TRAPTRACE
790Sstevel@tonic-gate	TRACE_PTR(%g4, %g6)
80*11172SHaik.Aftandilian@Sun.COM	GET_TRACE_TICK(%g6, %g3)
810Sstevel@tonic-gate	stxa	%g6, [%g4 + TRAP_ENT_TICK]%asi
820Sstevel@tonic-gate	rdpr	%tl, %g6
830Sstevel@tonic-gate	stha	%g6, [%g4 + TRAP_ENT_TL]%asi
840Sstevel@tonic-gate	rdpr	%tt, %g6
850Sstevel@tonic-gate	stha	%g6, [%g4 + TRAP_ENT_TT]%asi
860Sstevel@tonic-gate	stna	%o3, [%g4 + TRAP_ENT_TR]%asi ! pc of the TL>0 handler
870Sstevel@tonic-gate	rdpr	%tpc, %g6
880Sstevel@tonic-gate	stna	%g6, [%g4 + TRAP_ENT_TPC]%asi
890Sstevel@tonic-gate	rdpr	%tstate, %g6
900Sstevel@tonic-gate	stxa	%g6, [%g4 + TRAP_ENT_TSTATE]%asi
910Sstevel@tonic-gate	stna	%sp, [%g4 + TRAP_ENT_SP]%asi
920Sstevel@tonic-gate	stna	%o1, [%g4 + TRAP_ENT_F1]%asi ! arg 1
930Sstevel@tonic-gate	stna	%o2, [%g4 + TRAP_ENT_F2]%asi ! arg 2
940Sstevel@tonic-gate	stna	%g0, [%g4 + TRAP_ENT_F3]%asi
950Sstevel@tonic-gate	stna	%g0, [%g4 + TRAP_ENT_F4]%asi
960Sstevel@tonic-gate	TRACE_NEXT(%g4, %g6, %g3)
970Sstevel@tonic-gate#endif /* TRAPTRACE */
980Sstevel@tonic-gate	!
990Sstevel@tonic-gate	! Load the arguments for the fast trap handler.
1000Sstevel@tonic-gate	!
1010Sstevel@tonic-gate	mov	%o1, %g1
1020Sstevel@tonic-gate	jmp	%o3				! call the fast trap handler
1030Sstevel@tonic-gate	mov	%o2, %g2
1040Sstevel@tonic-gate	/* Not Reached */
1050Sstevel@tonic-gate	SET_SIZE(self_xcall)
1060Sstevel@tonic-gate
1070Sstevel@tonic-gate#endif	/* lint */
1080Sstevel@tonic-gate
1090Sstevel@tonic-gate#ifdef  TRAPTRACE
1100Sstevel@tonic-gate#if defined(lint)
1110Sstevel@tonic-gate
1120Sstevel@tonic-gate/* ARGSUSED */
1130Sstevel@tonic-gatevoid
1140Sstevel@tonic-gatexc_trace(u_int traptype, cpuset_t *cpu_set, xcfunc_t *func,
1150Sstevel@tonic-gate	uint64_t arg1, uint64_t arg2)
1160Sstevel@tonic-gate{}
1170Sstevel@tonic-gate
1180Sstevel@tonic-gate#else	/* lint */
1190Sstevel@tonic-gate	ENTRY(xc_trace)
1200Sstevel@tonic-gate	rdpr	%pstate, %g1
1210Sstevel@tonic-gate	andn	%g1, PSTATE_IE | PSTATE_AM, %g2
1220Sstevel@tonic-gate	wrpr	%g0, %g2, %pstate			/* disable interrupts */
1230Sstevel@tonic-gate	TRACE_PTR(%g3, %g4)
124*11172SHaik.Aftandilian@Sun.COM	GET_TRACE_TICK(%g6, %g4)
1250Sstevel@tonic-gate	stxa	%g6, [%g3 + TRAP_ENT_TICK]%asi
1260Sstevel@tonic-gate	stha	%g0, [%g3 + TRAP_ENT_TL]%asi
1270Sstevel@tonic-gate	set	TT_XCALL, %g2
1280Sstevel@tonic-gate	or	%o0, %g2, %g4
1290Sstevel@tonic-gate	stha	%g4, [%g3 + TRAP_ENT_TT]%asi
1300Sstevel@tonic-gate	stna	%o7, [%g3 + TRAP_ENT_TPC]%asi
1310Sstevel@tonic-gate	ldn	[%o1], %g2
1320Sstevel@tonic-gate	stna	%g2, [%g3 + TRAP_ENT_SP]%asi		/* sp = cpuset */
1330Sstevel@tonic-gate	stna	%o2, [%g3 + TRAP_ENT_TR]%asi		/* tr = func */
1340Sstevel@tonic-gate	stna	%o3, [%g3 + TRAP_ENT_F1]%asi		/* f1 = arg1 */
1350Sstevel@tonic-gate	stna	%o4, [%g3 + TRAP_ENT_F2]%asi		/* f2 = arg2 */
1360Sstevel@tonic-gate	stna	%g0, [%g3 + TRAP_ENT_F3]%asi		/* f3 = 0 */
1370Sstevel@tonic-gate	stna	%i7, [%g3 + TRAP_ENT_F4]%asi		/* f4 = xcall caller */
1380Sstevel@tonic-gate	stxa	%g1, [%g3 + TRAP_ENT_TSTATE]%asi	/* tstate = pstate */
1390Sstevel@tonic-gate	TRACE_NEXT(%g2, %g3, %g4)
1400Sstevel@tonic-gate/*
1410Sstevel@tonic-gate * In the case of a cpuset of greater size than a long we
1420Sstevel@tonic-gate * grab extra trace buffers just to store the cpuset.
1430Sstevel@tonic-gate * Seems like a waste but popular opinion opted for this
1440Sstevel@tonic-gate * rather than increase the size of the buffer.
1450Sstevel@tonic-gate */
1460Sstevel@tonic-gate#if CPUSET_SIZE > CLONGSIZE
1470Sstevel@tonic-gate	add	%o1, CPUSET_SIZE, %g5			/* end of cpuset */
1480Sstevel@tonic-gate	clr	%o2
1490Sstevel@tonic-gate1:
1500Sstevel@tonic-gate	TRACE_PTR(%g3, %g4)
1510Sstevel@tonic-gate	stha	%g0, [%g3 + TRAP_ENT_TL]%asi
1520Sstevel@tonic-gate	set	TT_XCALL_CONT, %g2
1530Sstevel@tonic-gate	or	%g2, %o2, %g2				/* continuation # */
1540Sstevel@tonic-gate	stha	%g2, [%g3 + TRAP_ENT_TT]%asi
1550Sstevel@tonic-gate	stxa	%g6, [%g3 + TRAP_ENT_TICK]%asi		/* same tick */
1560Sstevel@tonic-gate	stna	%g0, [%g3 + TRAP_ENT_TPC]%asi		/* clr unused fields */
1570Sstevel@tonic-gate	stna	%g0, [%g3 + TRAP_ENT_SP]%asi
1580Sstevel@tonic-gate	stna	%g0, [%g3 + TRAP_ENT_TR]%asi
1590Sstevel@tonic-gate	stxa	%g0, [%g3 + TRAP_ENT_TSTATE]%asi
1600Sstevel@tonic-gate	stna	%g0, [%g3 + TRAP_ENT_F2]%asi
1610Sstevel@tonic-gate	stna	%g0, [%g3 + TRAP_ENT_F3]%asi
1620Sstevel@tonic-gate	stna	%g0, [%g3 + TRAP_ENT_F4]%asi
1630Sstevel@tonic-gate	ldn	[%o1], %g2
1640Sstevel@tonic-gate	stna	%g2, [%g3 + TRAP_ENT_F1]%asi
1650Sstevel@tonic-gate	add	%o1, CLONGSIZE, %o1
1660Sstevel@tonic-gate	cmp	%o1, %g5
1670Sstevel@tonic-gate	bge	2f
1680Sstevel@tonic-gate	ldn	[%o1], %g2
1690Sstevel@tonic-gate	stna	%g2, [%g3 + TRAP_ENT_F2]%asi
1700Sstevel@tonic-gate	add	%o1, CLONGSIZE, %o1
1710Sstevel@tonic-gate	cmp	%o1, %g5
1720Sstevel@tonic-gate	bge	2f
1730Sstevel@tonic-gate	ldn	[%o1], %g2
1740Sstevel@tonic-gate	stna	%g2, [%g3 + TRAP_ENT_F3]%asi
1750Sstevel@tonic-gate	add	%o1, CLONGSIZE, %o1
1760Sstevel@tonic-gate	cmp	%o1, %g5
1770Sstevel@tonic-gate	bge	2f
1780Sstevel@tonic-gate	ldn	[%o1], %g2
1790Sstevel@tonic-gate	stna	%g2, [%g3 + TRAP_ENT_F4]%asi
1800Sstevel@tonic-gate	add	%o1, CLONGSIZE, %o1
1810Sstevel@tonic-gate2:
1820Sstevel@tonic-gate	TRACE_NEXT(%g2, %g3, %g4)
1830Sstevel@tonic-gate	cmp	%o1, %g5
1840Sstevel@tonic-gate	bl	1b
1850Sstevel@tonic-gate	inc	%o2
1860Sstevel@tonic-gate#endif	/* CPUSET_SIZE */
1870Sstevel@tonic-gate	retl
1880Sstevel@tonic-gate	wrpr	%g0, %g1, %pstate			/* enable interrupts */
1890Sstevel@tonic-gate	SET_SIZE(xc_trace)
1900Sstevel@tonic-gate
1910Sstevel@tonic-gate#endif	/* lint */
1920Sstevel@tonic-gate#endif	/* TRAPTRACE */
1930Sstevel@tonic-gate
1940Sstevel@tonic-gate#if defined(lint)
1950Sstevel@tonic-gate
1960Sstevel@tonic-gate/*ARGSUSED*/
1970Sstevel@tonic-gatevoid
1980Sstevel@tonic-gateinit_mondo(xcfunc_t *func, uint64_t arg1, uint64_t arg2)
1990Sstevel@tonic-gate{}
2000Sstevel@tonic-gate
2010Sstevel@tonic-gate/*ARGSUSED*/
2020Sstevel@tonic-gateint
2030Sstevel@tonic-gateshipit(int n, uint64_t cpuid)
2040Sstevel@tonic-gate{ return(0); }
2050Sstevel@tonic-gate
2060Sstevel@tonic-gate#else	/* lint */
2070Sstevel@tonic-gate/*
2080Sstevel@tonic-gate * Setup interrupt dispatch data registers
2090Sstevel@tonic-gate * Entry:
2100Sstevel@tonic-gate *	%o0 - function or inumber to call
2110Sstevel@tonic-gate *	%o1, %o2 - arguments (2 uint64_t's)
2120Sstevel@tonic-gate */
2130Sstevel@tonic-gate	ENTRY(init_mondo)
2140Sstevel@tonic-gate	ALTENTRY(init_mondo_nocheck)
2150Sstevel@tonic-gate	CPU_ADDR(%g1, %g4)			! load CPU struct addr
2160Sstevel@tonic-gate	add	%g1, CPU_MCPU, %g1
2170Sstevel@tonic-gate	ldx	[%g1 + MCPU_MONDO_DATA], %g1
2180Sstevel@tonic-gate	stx	%o0, [%g1]
2190Sstevel@tonic-gate	stx	%o1, [%g1+8]
2200Sstevel@tonic-gate	stx	%o2, [%g1+0x10]
2210Sstevel@tonic-gate	stx	%g0, [%g1+0x18]
2220Sstevel@tonic-gate	stx	%g0, [%g1+0x20]
2230Sstevel@tonic-gate	stx	%g0, [%g1+0x28]
2240Sstevel@tonic-gate	stx	%g0, [%g1+0x30]
2250Sstevel@tonic-gate	stx	%g0, [%g1+0x38]
2260Sstevel@tonic-gate	retl
2270Sstevel@tonic-gate	membar	#Sync			! allowed to be in the delay slot
2280Sstevel@tonic-gate	SET_SIZE(init_mondo)
2290Sstevel@tonic-gate
2300Sstevel@tonic-gate/*
2310Sstevel@tonic-gate * Ship mondo to cpuid
2320Sstevel@tonic-gate */
2330Sstevel@tonic-gate	ENTRY_NP(shipit)
2340Sstevel@tonic-gate	/* For now use dummy interface:  cpu# func arg1 arg2 */
2350Sstevel@tonic-gate	CPU_ADDR(%g1, %g4)
2360Sstevel@tonic-gate	add	%g1, CPU_MCPU, %g1
2370Sstevel@tonic-gate	ldx	[%g1 + MCPU_MONDO_DATA_RA],	%o2
2380Sstevel@tonic-gate	mov	HV_INTR_SEND, %o5
2390Sstevel@tonic-gate	ta	FAST_TRAP
2400Sstevel@tonic-gate	retl
2410Sstevel@tonic-gate	membar	#Sync
2420Sstevel@tonic-gate	SET_SIZE(shipit)
2430Sstevel@tonic-gate
2440Sstevel@tonic-gate#endif	/* lint */
2450Sstevel@tonic-gate
2460Sstevel@tonic-gate#if defined(lint)
2470Sstevel@tonic-gate
2480Sstevel@tonic-gate/*ARGSUSED*/
2490Sstevel@tonic-gateuint64_t
2500Sstevel@tonic-gateget_cpuaddr(uint64_t reg, uint64_t scr)
2510Sstevel@tonic-gate{ return (0);}
2520Sstevel@tonic-gate
2530Sstevel@tonic-gate#else	/* lint */
2540Sstevel@tonic-gate/*
2550Sstevel@tonic-gate * Get cpu structure
2560Sstevel@tonic-gate * Entry:
2570Sstevel@tonic-gate *      %o0 - register for CPU_ADDR macro
2580Sstevel@tonic-gate *      %o1 - scratch for CPU_ADDR macro
2590Sstevel@tonic-gate */
2600Sstevel@tonic-gate	ENTRY(get_cpuaddr)
2610Sstevel@tonic-gate	CPU_ADDR(%o0, %o1)	! %o0 == CPU struct addr
2620Sstevel@tonic-gate	retl
2630Sstevel@tonic-gate	nop
2640Sstevel@tonic-gate	SET_SIZE(get_cpuaddr)
2650Sstevel@tonic-gate
2660Sstevel@tonic-gate#endif	/* lint */
2670Sstevel@tonic-gate
2680Sstevel@tonic-gate#if defined(lint)
2690Sstevel@tonic-gate/* ARGSUSED */
2700Sstevel@tonic-gatevoid
2710Sstevel@tonic-gatext_sync_tl1(uint64_t *cpu_sync_addr)
2720Sstevel@tonic-gate{}
2730Sstevel@tonic-gate
2740Sstevel@tonic-gate#else /* lint */
2750Sstevel@tonic-gate/*
2760Sstevel@tonic-gate * This is to ensure that previously called xtrap handlers have executed on
2770Sstevel@tonic-gate * sun4v. We zero out the byte corresponding to its cpuid in the
2780Sstevel@tonic-gate * array passed to us from xt_sync(), so the sender knows the previous
2790Sstevel@tonic-gate * mondo has been executed.
2800Sstevel@tonic-gate * Register:
2810Sstevel@tonic-gate *		%g1 - Addr of the cpu_sync array.
2820Sstevel@tonic-gate */
2830Sstevel@tonic-gate	ENTRY_NP(xt_sync_tl1)
2840Sstevel@tonic-gate	CPU_INDEX(%g3, %g4)		/* %g3 = cpu id */
2850Sstevel@tonic-gate	stb	%g0, [%g1 + %g3]
2860Sstevel@tonic-gate	retry
2870Sstevel@tonic-gate	SET_SIZE(xt_sync_tl1)
2880Sstevel@tonic-gate
2890Sstevel@tonic-gate#endif  /* lint */
290