xref: /titanic_50/usr/src/uts/sun4u/ml/mach_xc.s (revision 023e71de9e5670cebc23dd51162833661d3d2d3b)
17c478bd9Sstevel@tonic-gate/*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*023e71deSHaik Aftandilian * Common Development and Distribution License (the "License").
6*023e71deSHaik Aftandilian * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate/*
22*023e71deSHaik Aftandilian * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate#if defined(lint)
277c478bd9Sstevel@tonic-gate#include <sys/types.h>
287c478bd9Sstevel@tonic-gate#include <sys/cpuvar.h>
297c478bd9Sstevel@tonic-gate#else	/*lint */
307c478bd9Sstevel@tonic-gate#include "assym.h"
317c478bd9Sstevel@tonic-gate#endif	/* lint */
327c478bd9Sstevel@tonic-gate
337c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h>
347c478bd9Sstevel@tonic-gate#include <sys/privregs.h>
357c478bd9Sstevel@tonic-gate#include <sys/x_call.h>
367c478bd9Sstevel@tonic-gate#include <sys/xc_impl.h>
377c478bd9Sstevel@tonic-gate
387c478bd9Sstevel@tonic-gate#ifdef TRAPTRACE
397c478bd9Sstevel@tonic-gate#include <sys/traptrace.h>
407c478bd9Sstevel@tonic-gate#endif /* TRAPTRACE */
417c478bd9Sstevel@tonic-gate
427c478bd9Sstevel@tonic-gate
437c478bd9Sstevel@tonic-gate#if defined(lint)
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate/* ARGSUSED */
467c478bd9Sstevel@tonic-gatevoid
477c478bd9Sstevel@tonic-gateself_xcall(struct cpu *cpu, uint64_t arg1, uint64_t arg2, xcfunc_t *func)
487c478bd9Sstevel@tonic-gate{}
497c478bd9Sstevel@tonic-gate
507c478bd9Sstevel@tonic-gate#else
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate/*
537c478bd9Sstevel@tonic-gate * Entered by the software trap (TT=ST_SELFXCALL, TL>0) thru send_self_xcall().
547c478bd9Sstevel@tonic-gate * Emulate the mondo handler - vec_interrupt().
557c478bd9Sstevel@tonic-gate *
567c478bd9Sstevel@tonic-gate * Global registers are the Alternate Globals.
577c478bd9Sstevel@tonic-gate * Arguments:
587c478bd9Sstevel@tonic-gate * 	%o0 - CPU
597c478bd9Sstevel@tonic-gate * 	ILP32 kernel:
607c478bd9Sstevel@tonic-gate * 		%o5 - function to call
617c478bd9Sstevel@tonic-gate * 		%o1, %o2, %o3, %o4  - arguments
627c478bd9Sstevel@tonic-gate * 	LP64 kernel:
637c478bd9Sstevel@tonic-gate * 		%o3 - function to call
647c478bd9Sstevel@tonic-gate * 		%o1, %o2 - arguments
657c478bd9Sstevel@tonic-gate */
667c478bd9Sstevel@tonic-gate	ENTRY_NP(self_xcall)
677c478bd9Sstevel@tonic-gate	!
687c478bd9Sstevel@tonic-gate	! TL>0 handlers are expected to do "retry"
697c478bd9Sstevel@tonic-gate	! prepare their return PC and nPC now
707c478bd9Sstevel@tonic-gate	!
717c478bd9Sstevel@tonic-gate	rdpr	%tnpc, %g1
727c478bd9Sstevel@tonic-gate	wrpr	%g1, %tpc			!  PC <- TNPC[TL]
737c478bd9Sstevel@tonic-gate 	add	%g1, 4, %g1
747c478bd9Sstevel@tonic-gate	wrpr	%g1, %tnpc			! nPC <- TNPC[TL] + 4
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gate#ifdef TRAPTRACE
777c478bd9Sstevel@tonic-gate	TRACE_PTR(%g4, %g6)
78*023e71deSHaik Aftandilian	GET_TRACE_TICK(%g6, %g3)
797c478bd9Sstevel@tonic-gate	stxa	%g6, [%g4 + TRAP_ENT_TICK]%asi
807c478bd9Sstevel@tonic-gate	rdpr	%tl, %g6
817c478bd9Sstevel@tonic-gate	stha	%g6, [%g4 + TRAP_ENT_TL]%asi
827c478bd9Sstevel@tonic-gate	rdpr	%tt, %g6
837c478bd9Sstevel@tonic-gate	stha	%g6, [%g4 + TRAP_ENT_TT]%asi
847c478bd9Sstevel@tonic-gate	stna	%o3, [%g4 + TRAP_ENT_TR]%asi ! pc of the TL>0 handler
857c478bd9Sstevel@tonic-gate	rdpr	%tpc, %g6
867c478bd9Sstevel@tonic-gate	stna	%g6, [%g4 + TRAP_ENT_TPC]%asi
877c478bd9Sstevel@tonic-gate	rdpr	%tstate, %g6
887c478bd9Sstevel@tonic-gate	stxa	%g6, [%g4 + TRAP_ENT_TSTATE]%asi
897c478bd9Sstevel@tonic-gate	stna	%sp, [%g4 + TRAP_ENT_SP]%asi
907c478bd9Sstevel@tonic-gate	stna	%o1, [%g4 + TRAP_ENT_F1]%asi ! arg 1
917c478bd9Sstevel@tonic-gate	stna	%o2, [%g4 + TRAP_ENT_F2]%asi ! arg 2
927c478bd9Sstevel@tonic-gate	stna	%g0, [%g4 + TRAP_ENT_F3]%asi
937c478bd9Sstevel@tonic-gate	stna	%g0, [%g4 + TRAP_ENT_F4]%asi
947c478bd9Sstevel@tonic-gate	TRACE_NEXT(%g4, %g6, %g3)
957c478bd9Sstevel@tonic-gate#endif /* TRAPTRACE */
967c478bd9Sstevel@tonic-gate	!
977c478bd9Sstevel@tonic-gate	! Load the arguments for the fast trap handler.
987c478bd9Sstevel@tonic-gate	!
997c478bd9Sstevel@tonic-gate	mov	%o1, %g1
1007c478bd9Sstevel@tonic-gate	jmp	%o3				! call the fast trap handler
1017c478bd9Sstevel@tonic-gate	mov	%o2, %g2
1027c478bd9Sstevel@tonic-gate	/* Not Reached */
1037c478bd9Sstevel@tonic-gate	SET_SIZE(self_xcall)
1047c478bd9Sstevel@tonic-gate
1057c478bd9Sstevel@tonic-gate#endif	/* lint */
1067c478bd9Sstevel@tonic-gate
1077c478bd9Sstevel@tonic-gate#ifdef  TRAPTRACE
1087c478bd9Sstevel@tonic-gate#if defined(lint)
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate/* ARGSUSED */
1117c478bd9Sstevel@tonic-gatevoid
1127c478bd9Sstevel@tonic-gatexc_trace(u_int traptype, cpuset_t *cpu_set, xcfunc_t *func,
1137c478bd9Sstevel@tonic-gate	uint64_t arg1, uint64_t arg2)
1147c478bd9Sstevel@tonic-gate{}
1157c478bd9Sstevel@tonic-gate
1167c478bd9Sstevel@tonic-gate#else	/* lint */
1177c478bd9Sstevel@tonic-gate	ENTRY(xc_trace)
1187c478bd9Sstevel@tonic-gate	rdpr	%pstate, %g1
1197c478bd9Sstevel@tonic-gate	andn	%g1, PSTATE_IE | PSTATE_AM, %g2
1207c478bd9Sstevel@tonic-gate	wrpr	%g0, %g2, %pstate			/* disable interrupts */
1217c478bd9Sstevel@tonic-gate	TRACE_PTR(%g3, %g4)
122*023e71deSHaik Aftandilian	GET_TRACE_TICK(%g6, %g4)
1237c478bd9Sstevel@tonic-gate	stxa	%g6, [%g3 + TRAP_ENT_TICK]%asi
1247c478bd9Sstevel@tonic-gate	stha	%g0, [%g3 + TRAP_ENT_TL]%asi
1257c478bd9Sstevel@tonic-gate	set	TT_XCALL, %g2
1267c478bd9Sstevel@tonic-gate	or	%o0, %g2, %g4
1277c478bd9Sstevel@tonic-gate	stha	%g4, [%g3 + TRAP_ENT_TT]%asi
1287c478bd9Sstevel@tonic-gate	stna	%o7, [%g3 + TRAP_ENT_TPC]%asi
1297c478bd9Sstevel@tonic-gate	ldn	[%o1], %g2
1307c478bd9Sstevel@tonic-gate	stna	%g2, [%g3 + TRAP_ENT_SP]%asi		/* sp = cpuset */
1317c478bd9Sstevel@tonic-gate	stna	%o2, [%g3 + TRAP_ENT_TR]%asi		/* tr = func */
1327c478bd9Sstevel@tonic-gate	stna	%o3, [%g3 + TRAP_ENT_F1]%asi		/* f1 = arg1 */
1337c478bd9Sstevel@tonic-gate	stna	%o4, [%g3 + TRAP_ENT_F2]%asi		/* f2 = arg2 */
1347c478bd9Sstevel@tonic-gate	stna	%g0, [%g3 + TRAP_ENT_F3]%asi		/* f3 = 0 */
1357c478bd9Sstevel@tonic-gate	stna	%i7, [%g3 + TRAP_ENT_F4]%asi		/* f4 = xcall caller */
1367c478bd9Sstevel@tonic-gate	stxa	%g1, [%g3 + TRAP_ENT_TSTATE]%asi	/* tstate = pstate */
1377c478bd9Sstevel@tonic-gate	TRACE_NEXT(%g2, %g3, %g4)
1387c478bd9Sstevel@tonic-gate/*
1397c478bd9Sstevel@tonic-gate * In the case of a cpuset of greater size than a long we
1407c478bd9Sstevel@tonic-gate * grab extra trace buffers just to store the cpuset.
1417c478bd9Sstevel@tonic-gate * Seems like a waste but popular opinion opted for this
1427c478bd9Sstevel@tonic-gate * rather than increase the size of the buffer.
1437c478bd9Sstevel@tonic-gate */
1447c478bd9Sstevel@tonic-gate#if CPUSET_SIZE > CLONGSIZE
1457c478bd9Sstevel@tonic-gate	add	%o1, CPUSET_SIZE, %g5			/* end of cpuset */
1467c478bd9Sstevel@tonic-gate	clr	%o2
1477c478bd9Sstevel@tonic-gate1:
1487c478bd9Sstevel@tonic-gate	TRACE_PTR(%g3, %g4)
1497c478bd9Sstevel@tonic-gate	stha	%g0, [%g3 + TRAP_ENT_TL]%asi
1507c478bd9Sstevel@tonic-gate	set	TT_XCALL_CONT, %g2
1517c478bd9Sstevel@tonic-gate	or	%g2, %o2, %g2				/* continuation # */
1527c478bd9Sstevel@tonic-gate	stha	%g2, [%g3 + TRAP_ENT_TT]%asi
1537c478bd9Sstevel@tonic-gate	stxa	%g6, [%g3 + TRAP_ENT_TICK]%asi		/* same tick */
1547c478bd9Sstevel@tonic-gate	stna	%g0, [%g3 + TRAP_ENT_TPC]%asi		/* clr unused fields */
1557c478bd9Sstevel@tonic-gate	stna	%g0, [%g3 + TRAP_ENT_SP]%asi
1567c478bd9Sstevel@tonic-gate	stna	%g0, [%g3 + TRAP_ENT_TR]%asi
1577c478bd9Sstevel@tonic-gate	stxa	%g0, [%g3 + TRAP_ENT_TSTATE]%asi
1587c478bd9Sstevel@tonic-gate	stna	%g0, [%g3 + TRAP_ENT_F2]%asi
1597c478bd9Sstevel@tonic-gate	stna	%g0, [%g3 + TRAP_ENT_F3]%asi
1607c478bd9Sstevel@tonic-gate	stna	%g0, [%g3 + TRAP_ENT_F4]%asi
1617c478bd9Sstevel@tonic-gate	ldn	[%o1], %g2
1627c478bd9Sstevel@tonic-gate	stna	%g2, [%g3 + TRAP_ENT_F1]%asi
1637c478bd9Sstevel@tonic-gate	add	%o1, CLONGSIZE, %o1
1647c478bd9Sstevel@tonic-gate	cmp	%o1, %g5
1657c478bd9Sstevel@tonic-gate	bge	2f
1667c478bd9Sstevel@tonic-gate	ldn	[%o1], %g2
1677c478bd9Sstevel@tonic-gate	stna	%g2, [%g3 + TRAP_ENT_F2]%asi
1687c478bd9Sstevel@tonic-gate	add	%o1, CLONGSIZE, %o1
1697c478bd9Sstevel@tonic-gate	cmp	%o1, %g5
1707c478bd9Sstevel@tonic-gate	bge	2f
1717c478bd9Sstevel@tonic-gate	ldn	[%o1], %g2
1727c478bd9Sstevel@tonic-gate	stna	%g2, [%g3 + TRAP_ENT_F3]%asi
1737c478bd9Sstevel@tonic-gate	add	%o1, CLONGSIZE, %o1
1747c478bd9Sstevel@tonic-gate	cmp	%o1, %g5
1757c478bd9Sstevel@tonic-gate	bge	2f
1767c478bd9Sstevel@tonic-gate	ldn	[%o1], %g2
1777c478bd9Sstevel@tonic-gate	stna	%g2, [%g3 + TRAP_ENT_F4]%asi
1787c478bd9Sstevel@tonic-gate	add	%o1, CLONGSIZE, %o1
1797c478bd9Sstevel@tonic-gate2:
1807c478bd9Sstevel@tonic-gate	TRACE_NEXT(%g2, %g3, %g4)
1817c478bd9Sstevel@tonic-gate	cmp	%o1, %g5
1827c478bd9Sstevel@tonic-gate	bl	1b
1837c478bd9Sstevel@tonic-gate	inc	%o2
1847c478bd9Sstevel@tonic-gate#endif	/* CPUSET_SIZE */
1857c478bd9Sstevel@tonic-gate	retl
1867c478bd9Sstevel@tonic-gate	wrpr	%g0, %g1, %pstate			/* enable interrupts */
1877c478bd9Sstevel@tonic-gate	SET_SIZE(xc_trace)
1887c478bd9Sstevel@tonic-gate
1897c478bd9Sstevel@tonic-gate#endif	/* lint */
1907c478bd9Sstevel@tonic-gate#endif	/* TRAPTRACE */
1917c478bd9Sstevel@tonic-gate
1927c478bd9Sstevel@tonic-gate#if defined(lint)
1937c478bd9Sstevel@tonic-gate
1947c478bd9Sstevel@tonic-gate/* ARGSUSED */
1957c478bd9Sstevel@tonic-gatevoid
1967c478bd9Sstevel@tonic-gatext_sync_tl1(uint64_t *cpu_sync_addr)
1977c478bd9Sstevel@tonic-gate{}
1987c478bd9Sstevel@tonic-gate
1997c478bd9Sstevel@tonic-gate#else
2007c478bd9Sstevel@tonic-gate/*
2017c478bd9Sstevel@tonic-gate * This dummy tl1 function is there to ensure that previously called
2027c478bd9Sstevel@tonic-gate * xtrap handlers have exececuted. The hardware (mondo dispatch
2037c478bd9Sstevel@tonic-gate * mechanism) is such that return from xtrap doesn't guarantee execution
2047c478bd9Sstevel@tonic-gate * of xtrap handler. So, callers can call this xtrap-handler to ensure
2057c478bd9Sstevel@tonic-gate * that the previous one is complete. This is because the hardware only
2067c478bd9Sstevel@tonic-gate * can handle 1 mondo at a time - when this mondo is handled, we are sure
2077c478bd9Sstevel@tonic-gate * that the mondo for the previous xtrap must have been handled.
2087c478bd9Sstevel@tonic-gate */
2097c478bd9Sstevel@tonic-gate	ENTRY_NP(xt_sync_tl1)
2107c478bd9Sstevel@tonic-gate	retry
2117c478bd9Sstevel@tonic-gate	SET_SIZE(xt_sync_tl1)
2127c478bd9Sstevel@tonic-gate
2137c478bd9Sstevel@tonic-gate#endif  /* lint */
214