xref: /titanic_44/usr/src/uts/sun4v/ml/mach_interrupt.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
5b0fc0e77Sgovinda * Common Development and Distribution License (the "License").
6b0fc0e77Sgovinda * 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/*
229d0d62adSJason Beloro * 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/thread.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/machthread.h>
357c478bd9Sstevel@tonic-gate#include <sys/machcpuvar.h>
367c478bd9Sstevel@tonic-gate#include <sys/intreg.h>
377c478bd9Sstevel@tonic-gate#include <sys/cmn_err.h>
387c478bd9Sstevel@tonic-gate#include <sys/ftrace.h>
397c478bd9Sstevel@tonic-gate#include <sys/machasi.h>
40ad559ebfSwh94709#include <sys/scb.h>
417c478bd9Sstevel@tonic-gate#include <sys/error.h>
4205d3dc4bSpaulsan#include <sys/mmu.h>
4305d3dc4bSpaulsan#include <vm/hat_sfmmu.h>
447c478bd9Sstevel@tonic-gate#define	INTR_REPORT_SIZE	64
457c478bd9Sstevel@tonic-gate
467c478bd9Sstevel@tonic-gate#ifdef TRAPTRACE
477c478bd9Sstevel@tonic-gate#include <sys/traptrace.h>
487c478bd9Sstevel@tonic-gate#endif /* TRAPTRACE */
497c478bd9Sstevel@tonic-gate
507c478bd9Sstevel@tonic-gate#if defined(lint)
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gatevoid
537c478bd9Sstevel@tonic-gatecpu_mondo(void)
547c478bd9Sstevel@tonic-gate{}
557c478bd9Sstevel@tonic-gate
567c478bd9Sstevel@tonic-gate#else	/* lint */
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate/*
607c478bd9Sstevel@tonic-gate * (TT 0x7c, TL>0) CPU Mondo Queue Handler
617c478bd9Sstevel@tonic-gate *	Globals are the Interrupt Globals.
627c478bd9Sstevel@tonic-gate */
637c478bd9Sstevel@tonic-gate	ENTRY_NP(cpu_mondo)
647c478bd9Sstevel@tonic-gate	!
657c478bd9Sstevel@tonic-gate	!	Register Usage:-
667c478bd9Sstevel@tonic-gate	!	%g5	PC for fasttrap TL>0 handler
677c478bd9Sstevel@tonic-gate	!	%g1	arg 1
687c478bd9Sstevel@tonic-gate	!	%g2	arg 2
697c478bd9Sstevel@tonic-gate	!	%g3	queue base VA
707c478bd9Sstevel@tonic-gate	!	%g4 	queue size mask
717c478bd9Sstevel@tonic-gate	!	%g6	head ptr
727c478bd9Sstevel@tonic-gate	!	%g7	tail ptr
737c478bd9Sstevel@tonic-gate	mov	CPU_MONDO_Q_HD, %g3
747c478bd9Sstevel@tonic-gate	ldxa	[%g3]ASI_QUEUE, %g6	! %g6 = head ptr
757c478bd9Sstevel@tonic-gate	mov	CPU_MONDO_Q_TL, %g4
767c478bd9Sstevel@tonic-gate	ldxa	[%g4]ASI_QUEUE, %g7	! %g7 = tail ptr
777c478bd9Sstevel@tonic-gate	cmp	%g6, %g7
7805d3dc4bSpaulsan	be,pn	%xcc, 3f		! head == tail
797c478bd9Sstevel@tonic-gate	nop
807c478bd9Sstevel@tonic-gate
817c478bd9Sstevel@tonic-gate	CPU_ADDR(%g1,%g2)
827c478bd9Sstevel@tonic-gate	add	%g1, CPU_MCPU, %g2
837c478bd9Sstevel@tonic-gate	ldx	[%g2 + MCPU_CPU_Q_BASE], %g3	! %g3 = queue base PA
847c478bd9Sstevel@tonic-gate	ldx	[%g2 + MCPU_CPU_Q_SIZE], %g4	! queue size
857c478bd9Sstevel@tonic-gate	sub	%g4, 1, %g4		! %g4 = queue size mask
867c478bd9Sstevel@tonic-gate
877c478bd9Sstevel@tonic-gate	! Load interrupt receive data registers 1 and 2 to fetch
887c478bd9Sstevel@tonic-gate	! the arguments for the fast trap handler.
897c478bd9Sstevel@tonic-gate	!
907c478bd9Sstevel@tonic-gate	! XXX - Since the data words in the interrupt report are not defined yet
917c478bd9Sstevel@tonic-gate	! we assume that the consective words contain valid data and preserve
927c478bd9Sstevel@tonic-gate	! sun4u's xcall mondo arguments.
937c478bd9Sstevel@tonic-gate	! Register usage:
947c478bd9Sstevel@tonic-gate	!	%g5	PC for fasttrap TL>0 handler
957c478bd9Sstevel@tonic-gate	!	%g1	arg 1
967c478bd9Sstevel@tonic-gate	!	%g2	arg 2
977c478bd9Sstevel@tonic-gate
987c478bd9Sstevel@tonic-gate	ldxa	[%g3 + %g6]ASI_MEM, %g5	! get PC from q base + head
997c478bd9Sstevel@tonic-gate	add	%g6, 0x8, %g6		! inc head
1007c478bd9Sstevel@tonic-gate	ldxa	[%g3 + %g6]ASI_MEM, %g1 ! read data word 1
1017c478bd9Sstevel@tonic-gate	add	%g6, 0x8, %g6		! inc head
1027c478bd9Sstevel@tonic-gate	ldxa	[%g3 + %g6]ASI_MEM, %g2	! read data word 2
1037c478bd9Sstevel@tonic-gate	add	%g6, (INTR_REPORT_SIZE - 16) , %g6 ! inc head to next record
1047c478bd9Sstevel@tonic-gate	and	%g6, %g4, %g6 		! and size mask for wrap around
1057c478bd9Sstevel@tonic-gate	mov	CPU_MONDO_Q_HD, %g3
1067c478bd9Sstevel@tonic-gate	stxa	%g6, [%g3]ASI_QUEUE	! store head pointer
1077c478bd9Sstevel@tonic-gate	membar	#Sync
1087c478bd9Sstevel@tonic-gate
1097c478bd9Sstevel@tonic-gate#ifdef TRAPTRACE
1107c478bd9Sstevel@tonic-gate	TRACE_PTR(%g4, %g6)
111*023e71deSHaik Aftandilian	GET_TRACE_TICK(%g6, %g3)
1127c478bd9Sstevel@tonic-gate	stxa	%g6, [%g4 + TRAP_ENT_TICK]%asi
1137c478bd9Sstevel@tonic-gate	TRACE_SAVE_TL_GL_REGS(%g4, %g6)
1147c478bd9Sstevel@tonic-gate	rdpr	%tt, %g6
1157c478bd9Sstevel@tonic-gate	stha	%g6, [%g4 + TRAP_ENT_TT]%asi
1167c478bd9Sstevel@tonic-gate	rdpr	%tpc, %g6
1177c478bd9Sstevel@tonic-gate	stna	%g6, [%g4 + TRAP_ENT_TPC]%asi
1187c478bd9Sstevel@tonic-gate	rdpr	%tstate, %g6
1197c478bd9Sstevel@tonic-gate	stxa	%g6, [%g4 + TRAP_ENT_TSTATE]%asi
1207c478bd9Sstevel@tonic-gate	stna	%sp, [%g4 + TRAP_ENT_SP]%asi
1217c478bd9Sstevel@tonic-gate	stna	%g5, [%g4 + TRAP_ENT_TR]%asi	! pc of the TL>0 handler
1227c478bd9Sstevel@tonic-gate	stna	%g1, [%g4 + TRAP_ENT_F1]%asi	! arg1
1237c478bd9Sstevel@tonic-gate	stna	%g2, [%g4 + TRAP_ENT_F3]%asi	! arg2
1247c478bd9Sstevel@tonic-gate	mov	CPU_MONDO_Q_HD, %g6
1257c478bd9Sstevel@tonic-gate	ldxa	[%g6]ASI_QUEUE, %g6		! new head offset
1267c478bd9Sstevel@tonic-gate	stna	%g6, [%g4 + TRAP_ENT_F2]%asi
1277c478bd9Sstevel@tonic-gate	stna	%g7, [%g4 + TRAP_ENT_F4]%asi	! tail offset
1287c478bd9Sstevel@tonic-gate	TRACE_NEXT(%g4, %g6, %g3)
1297c478bd9Sstevel@tonic-gate#endif /* TRAPTRACE */
1307c478bd9Sstevel@tonic-gate
1317c478bd9Sstevel@tonic-gate	/*
1327c478bd9Sstevel@tonic-gate	 * For now catch invalid PC being passed via cpu_mondo queue
1337c478bd9Sstevel@tonic-gate	 */
1347c478bd9Sstevel@tonic-gate	set	KERNELBASE, %g4
1357c478bd9Sstevel@tonic-gate	cmp	%g5, %g4
13605d3dc4bSpaulsan	bl,pn	%xcc, 2f		! branch if bad %pc
1377c478bd9Sstevel@tonic-gate	  nop
1387c478bd9Sstevel@tonic-gate
13905d3dc4bSpaulsan
14005d3dc4bSpaulsan	/*
14105d3dc4bSpaulsan	 * If this platform supports shared contexts and we are jumping
14205d3dc4bSpaulsan	 * to OBP code, then we need to invalidate both contexts to prevent OBP
14305d3dc4bSpaulsan	 * from corrupting the shared context registers.
14405d3dc4bSpaulsan	 *
14505d3dc4bSpaulsan	 * If shared contexts are not supported then the next two instructions
14605d3dc4bSpaulsan	 * will be patched with:
14705d3dc4bSpaulsan	 *
14805d3dc4bSpaulsan	 * jmp       %g5
14905d3dc4bSpaulsan	 * nop
15005d3dc4bSpaulsan	 *
15105d3dc4bSpaulsan	 */
15205d3dc4bSpaulsan	.global sfmmu_shctx_cpu_mondo_patch
15305d3dc4bSpaulsansfmmu_shctx_cpu_mondo_patch:
15405d3dc4bSpaulsan	set	OFW_START_ADDR, %g4	! Check if this a call into OBP?
15505d3dc4bSpaulsan	cmp	%g5, %g4
15605d3dc4bSpaulsan	bl,pt %xcc, 1f
15705d3dc4bSpaulsan	  nop
15805d3dc4bSpaulsan	set	OFW_END_ADDR, %g4
15905d3dc4bSpaulsan	cmp	%g5, %g4
16005d3dc4bSpaulsan	bg,pn %xcc, 1f
16105d3dc4bSpaulsan	  nop
16205d3dc4bSpaulsan	mov	MMU_PCONTEXT, %g3
16305d3dc4bSpaulsan	ldxa	[%g3]ASI_MMU_CTX, %g4
16405d3dc4bSpaulsan	cmp	%g4, INVALID_CONTEXT	! Check if we are in kernel mode
16505d3dc4bSpaulsan	ble,pn %xcc, 1f			! or the primary context is invalid
16605d3dc4bSpaulsan	  nop
16705d3dc4bSpaulsan	set	INVALID_CONTEXT, %g4	! Invalidate contexts - compatability
16805d3dc4bSpaulsan	stxa    %g4, [%g3]ASI_MMU_CTX	! mode ensures shared contexts are also
16905d3dc4bSpaulsan	mov     MMU_SCONTEXT, %g3	! invalidated.
17005d3dc4bSpaulsan	stxa    %g4, [%g3]ASI_MMU_CTX
17105d3dc4bSpaulsan	membar  #Sync
17205d3dc4bSpaulsan	mov	%o0, %g3		! save output regs
17305d3dc4bSpaulsan	mov	%o1, %g4
17405d3dc4bSpaulsan	mov	%o5, %g6
17505d3dc4bSpaulsan	clr	%o0			! Invalidate tsbs, set ntsb = 0
17605d3dc4bSpaulsan	clr	%o1			! and HV_TSB_INFO_PA = 0
17705d3dc4bSpaulsan	mov	MMU_TSB_CTXNON0, %o5
17805d3dc4bSpaulsan	ta	FAST_TRAP		! set TSB info for user process
17905d3dc4bSpaulsan	brnz,a,pn %o0, ptl1_panic
18005d3dc4bSpaulsan	  mov	PTL1_BAD_HCALL, %g1
18105d3dc4bSpaulsan	mov	%g3, %o0		! restore output regs
18205d3dc4bSpaulsan	mov	%g4, %o1
18305d3dc4bSpaulsan	mov	%g6, %o5
18405d3dc4bSpaulsan1:
1857c478bd9Sstevel@tonic-gate	jmp	%g5			! jump to traphandler
1867c478bd9Sstevel@tonic-gate	nop
18705d3dc4bSpaulsan2:
1887c478bd9Sstevel@tonic-gate	! invalid trap handler, discard it for now
1897c478bd9Sstevel@tonic-gate	set	cpu_mondo_inval, %g4
1907c478bd9Sstevel@tonic-gate	ldx	[%g4], %g5
1917c478bd9Sstevel@tonic-gate	inc	%g5
1927c478bd9Sstevel@tonic-gate	stx	%g5, [%g4]
19305d3dc4bSpaulsan3:
1947c478bd9Sstevel@tonic-gate	retry
1957c478bd9Sstevel@tonic-gate	/* Never Reached */
1967c478bd9Sstevel@tonic-gate	SET_SIZE(cpu_mondo)
1977c478bd9Sstevel@tonic-gate
1987c478bd9Sstevel@tonic-gate#endif /* lint */
1997c478bd9Sstevel@tonic-gate
2007c478bd9Sstevel@tonic-gate#if defined(lint)
2017c478bd9Sstevel@tonic-gate
2027c478bd9Sstevel@tonic-gatevoid
2037c478bd9Sstevel@tonic-gatedev_mondo(void)
2047c478bd9Sstevel@tonic-gate{}
2057c478bd9Sstevel@tonic-gate
2067c478bd9Sstevel@tonic-gate#else	/* lint */
2077c478bd9Sstevel@tonic-gate
2087c478bd9Sstevel@tonic-gate
2097c478bd9Sstevel@tonic-gate/*
2107c478bd9Sstevel@tonic-gate * (TT 0x7d, TL>0) Dev Mondo Queue Handler
2117c478bd9Sstevel@tonic-gate *	Globals are the Interrupt Globals.
2127c478bd9Sstevel@tonic-gate * We only process one interrupt at a time causing us to keep
2137c478bd9Sstevel@tonic-gate * taking this trap till the queue is empty.
2147c478bd9Sstevel@tonic-gate * We really should drain the whole queue for better performance
2157c478bd9Sstevel@tonic-gate * but this will do for now.
2167c478bd9Sstevel@tonic-gate */
2177c478bd9Sstevel@tonic-gate	ENTRY_NP(dev_mondo)
2187c478bd9Sstevel@tonic-gate	!
2197c478bd9Sstevel@tonic-gate	!	Register Usage:-
2207c478bd9Sstevel@tonic-gate	!	%g5	PC for fasttrap TL>0 handler
2217c478bd9Sstevel@tonic-gate	!	%g1	arg 1
2227c478bd9Sstevel@tonic-gate	!	%g2	arg 2
2237c478bd9Sstevel@tonic-gate	!	%g3	queue base PA
2247c478bd9Sstevel@tonic-gate	!	%g4 	queue size mask
2257c478bd9Sstevel@tonic-gate	!	%g6	head ptr
2267c478bd9Sstevel@tonic-gate	!	%g7	tail ptr
2277c478bd9Sstevel@tonic-gate	mov	DEV_MONDO_Q_HD, %g3
2287c478bd9Sstevel@tonic-gate	ldxa	[%g3]ASI_QUEUE, %g6	! %g6 = head ptr
2297c478bd9Sstevel@tonic-gate	mov	DEV_MONDO_Q_TL, %g4
2307c478bd9Sstevel@tonic-gate	ldxa	[%g4]ASI_QUEUE, %g7	! %g7 = tail ptr
2317c478bd9Sstevel@tonic-gate	cmp	%g6, %g7
2327c478bd9Sstevel@tonic-gate	be,pn	%xcc, 0f		! head == tail
2337c478bd9Sstevel@tonic-gate	nop
2347c478bd9Sstevel@tonic-gate
2357c478bd9Sstevel@tonic-gate	CPU_ADDR(%g1,%g2)
2367c478bd9Sstevel@tonic-gate	add	%g1, CPU_MCPU, %g2
2377c478bd9Sstevel@tonic-gate	ldx	[%g2 + MCPU_DEV_Q_BASE], %g3	! %g3 = queue base PA
2387c478bd9Sstevel@tonic-gate
2397c478bd9Sstevel@tonic-gate	! Register usage:
2407c478bd9Sstevel@tonic-gate	!	%g5 - inum
2417c478bd9Sstevel@tonic-gate	!	%g1 - cpu struct pointer used below in TRAPTRACE
2427c478bd9Sstevel@tonic-gate	!
2437c478bd9Sstevel@tonic-gate	ldxa	[%g3 + %g6]ASI_MEM, %g5	! get inum from q base + head
2447c478bd9Sstevel@tonic-gate
2457c478bd9Sstevel@tonic-gate	!
2467c478bd9Sstevel@tonic-gate	! We verify that inum is valid ( < MAXVNUM). If it is greater
247b0fc0e77Sgovinda	! than MAXVNUM, we let setvecint_tl1 take care of it.
2487c478bd9Sstevel@tonic-gate	!
2497c478bd9Sstevel@tonic-gate	set	MAXIVNUM, %g4
2507c478bd9Sstevel@tonic-gate	cmp	%g5, %g4
2517c478bd9Sstevel@tonic-gate	bgeu,a,pn	%xcc, 1f
2527c478bd9Sstevel@tonic-gate	ldx	[%g2 + MCPU_DEV_Q_SIZE], %g4	! queue size - delay slot
2537c478bd9Sstevel@tonic-gate
2547c478bd9Sstevel@tonic-gate	!
2557c478bd9Sstevel@tonic-gate	!	Copy 64-byte payload to the *iv_payload if it is not NULL
2567c478bd9Sstevel@tonic-gate	!
257b0fc0e77Sgovinda	set	intr_vec_table, %g1		! %g1 = intr_vec_table
258b0fc0e77Sgovinda	sll	%g5, CPTRSHIFT, %g7		! %g7 = offset to inum entry
259b0fc0e77Sgovinda						!       in the intr_vec_table
260b0fc0e77Sgovinda	add	%g1, %g7, %g7			! %g7 = &intr_vec_table[inum]
261b0fc0e77Sgovinda	ldn	[%g7], %g1			! %g1 = ptr to intr_vec_t (iv)
26225293bedSgovinda
26325293bedSgovinda	!
26425293bedSgovinda	! Verify the pointer to first intr_vec_t for a given inum and
26525293bedSgovinda	! it should not be NULL. If this pointer is NULL, then it is a
26625293bedSgovinda	! spurious interrupt. In this case, just call setvecint_tl1 and
26725293bedSgovinda	! it will handle this spurious interrupt.
26825293bedSgovinda	!
26925293bedSgovinda	brz,a,pn	%g1, 1f			! if %g1 is NULL
27025293bedSgovinda	ldx	[%g2 + MCPU_DEV_Q_SIZE], %g4	! queue size - delay slot
27125293bedSgovinda
272b0fc0e77Sgovinda	ldx	[%g1 + IV_PAYLOAD_BUF], %g1	! %g1 = iv->iv_payload_buf
2737c478bd9Sstevel@tonic-gate	brz,a,pt	%g1, 1f			! if it is NULL
2747c478bd9Sstevel@tonic-gate	ldx	[%g2 + MCPU_DEV_Q_SIZE], %g4	! queue size - delay slot
2757c478bd9Sstevel@tonic-gate
2767c478bd9Sstevel@tonic-gate	!
2777c478bd9Sstevel@tonic-gate	!	Now move 64 byte payload from mondo queue to buf
2787c478bd9Sstevel@tonic-gate	!
2797c478bd9Sstevel@tonic-gate	mov	%g6, %g7			! %g7 = head ptr
2807c478bd9Sstevel@tonic-gate	ldxa	[%g3 + %g7]ASI_MEM, %g4
2817c478bd9Sstevel@tonic-gate	stx	%g4, [%g1 + 0]			! byte 0 - 7
2827c478bd9Sstevel@tonic-gate	add	%g7, 8, %g7
2837c478bd9Sstevel@tonic-gate	ldxa	[%g3 + %g7]ASI_MEM, %g4
2847c478bd9Sstevel@tonic-gate	stx	%g4, [%g1 + 8]			! byte 8 - 15
2857c478bd9Sstevel@tonic-gate	add	%g7, 8, %g7
2867c478bd9Sstevel@tonic-gate	ldxa	[%g3 + %g7]ASI_MEM, %g4
2877c478bd9Sstevel@tonic-gate	stx	%g4, [%g1 + 16]			! byte 16 - 23
2887c478bd9Sstevel@tonic-gate	add	%g7, 8, %g7
2897c478bd9Sstevel@tonic-gate	ldxa	[%g3 + %g7]ASI_MEM, %g4
2907c478bd9Sstevel@tonic-gate	stx	%g4, [%g1 + 24]			! byte 24 - 31
2917c478bd9Sstevel@tonic-gate	add	%g7, 8, %g7
2927c478bd9Sstevel@tonic-gate	ldxa	[%g3 + %g7]ASI_MEM, %g4
2937c478bd9Sstevel@tonic-gate	stx	%g4, [%g1 + 32]			! byte 32 - 39
2947c478bd9Sstevel@tonic-gate	add	%g7, 8, %g7
2957c478bd9Sstevel@tonic-gate	ldxa	[%g3 + %g7]ASI_MEM, %g4
2967c478bd9Sstevel@tonic-gate	stx	%g4, [%g1 + 40]			! byte 40 - 47
2977c478bd9Sstevel@tonic-gate	add	%g7, 8, %g7
2987c478bd9Sstevel@tonic-gate	ldxa	[%g3 + %g7]ASI_MEM, %g4
2997c478bd9Sstevel@tonic-gate	stx	%g4, [%g1 + 48]			! byte 48 - 55
3007c478bd9Sstevel@tonic-gate	add	%g7, 8, %g7
3017c478bd9Sstevel@tonic-gate	ldxa	[%g3 + %g7]ASI_MEM, %g4
3027c478bd9Sstevel@tonic-gate	stx	%g4, [%g1 + 56]			! byte 56 - 63
3037c478bd9Sstevel@tonic-gate	ldx	[%g2 + MCPU_DEV_Q_SIZE], %g4	! queue size
3047c478bd9Sstevel@tonic-gate
3057c478bd9Sstevel@tonic-gate1:	sub	%g4, 1, %g4		! %g4 = queue size mask
3067c478bd9Sstevel@tonic-gate	add	%g6, INTR_REPORT_SIZE , %g6 ! inc head to next record
3077c478bd9Sstevel@tonic-gate	and	%g6, %g4, %g6 		! and mask for wrap around
3087c478bd9Sstevel@tonic-gate	mov	DEV_MONDO_Q_HD, %g3
3097c478bd9Sstevel@tonic-gate	stxa	%g6, [%g3]ASI_QUEUE	! increment head offset
3107c478bd9Sstevel@tonic-gate	membar	#Sync
3117c478bd9Sstevel@tonic-gate
3127c478bd9Sstevel@tonic-gate#ifdef TRAPTRACE
3137c478bd9Sstevel@tonic-gate	TRACE_PTR(%g4, %g6)
314*023e71deSHaik Aftandilian	GET_TRACE_TICK(%g6, %g3)
3157c478bd9Sstevel@tonic-gate	stxa	%g6, [%g4 + TRAP_ENT_TICK]%asi
3167c478bd9Sstevel@tonic-gate	TRACE_SAVE_TL_GL_REGS(%g4, %g6)
3177c478bd9Sstevel@tonic-gate	rdpr	%tt, %g6
3187c478bd9Sstevel@tonic-gate	stha	%g6, [%g4 + TRAP_ENT_TT]%asi
3197c478bd9Sstevel@tonic-gate	rdpr	%tpc, %g6
3207c478bd9Sstevel@tonic-gate	stna	%g6, [%g4 + TRAP_ENT_TPC]%asi
3217c478bd9Sstevel@tonic-gate	rdpr	%tstate, %g6
3227c478bd9Sstevel@tonic-gate	stxa	%g6, [%g4 + TRAP_ENT_TSTATE]%asi
3237c478bd9Sstevel@tonic-gate	! move head to sp
3247c478bd9Sstevel@tonic-gate	ldx	[%g2 + MCPU_DEV_Q_BASE], %g6
3257c478bd9Sstevel@tonic-gate	stna	%g6, [%g4 + TRAP_ENT_SP]%asi	! Device Queue Base PA
3267c478bd9Sstevel@tonic-gate	stna	%g5, [%g4 + TRAP_ENT_TR]%asi	! Inum
3277c478bd9Sstevel@tonic-gate	mov	DEV_MONDO_Q_HD, %g6
3287c478bd9Sstevel@tonic-gate	ldxa	[%g6]ASI_QUEUE, %g6		! New head offset
3297c478bd9Sstevel@tonic-gate	stna	%g6, [%g4 + TRAP_ENT_F1]%asi
3307c478bd9Sstevel@tonic-gate	ldx	[%g2 + MCPU_DEV_Q_SIZE], %g6
3317c478bd9Sstevel@tonic-gate	stna	%g6, [%g4 + TRAP_ENT_F2]%asi	! Q Size
3327c478bd9Sstevel@tonic-gate	stna	%g7, [%g4 + TRAP_ENT_F3]%asi	! tail offset
3337c478bd9Sstevel@tonic-gate	stna	%g0, [%g4 + TRAP_ENT_F4]%asi
3347c478bd9Sstevel@tonic-gate	TRACE_NEXT(%g4, %g6, %g3)
3357c478bd9Sstevel@tonic-gate#endif /* TRAPTRACE */
3367c478bd9Sstevel@tonic-gate
3377c478bd9Sstevel@tonic-gate	!
338b0fc0e77Sgovinda	! setvecint_tl1 will do all the work, and finish with a retry
3397c478bd9Sstevel@tonic-gate	!
340b0fc0e77Sgovinda	ba,pt	%xcc, setvecint_tl1
341b0fc0e77Sgovinda	mov	%g5, %g1		! setvecint_tl1 expects inum in %g1
3427c478bd9Sstevel@tonic-gate
3437c478bd9Sstevel@tonic-gate0:	retry
3447c478bd9Sstevel@tonic-gate
3457c478bd9Sstevel@tonic-gate	/* Never Reached */
3467c478bd9Sstevel@tonic-gate	SET_SIZE(dev_mondo)
3477c478bd9Sstevel@tonic-gate#endif /* lint */
3487c478bd9Sstevel@tonic-gate
3497c478bd9Sstevel@tonic-gate#if defined(lint)
3507c478bd9Sstevel@tonic-gateuint64_t cpu_mondo_inval;
3517c478bd9Sstevel@tonic-gate#else /* lint */
3527c478bd9Sstevel@tonic-gate	.seg	".data"
3537c478bd9Sstevel@tonic-gate	.global	cpu_mondo_inval
3547c478bd9Sstevel@tonic-gate	.align	8
3557c478bd9Sstevel@tonic-gatecpu_mondo_inval:
3567c478bd9Sstevel@tonic-gate	.skip	8
3577c478bd9Sstevel@tonic-gate
3587c478bd9Sstevel@tonic-gate	.seg	".text"
3597c478bd9Sstevel@tonic-gate#endif	/* lint */
3607c478bd9Sstevel@tonic-gate
3617c478bd9Sstevel@tonic-gate
3627c478bd9Sstevel@tonic-gate#if defined(lint)
3637c478bd9Sstevel@tonic-gate
3647c478bd9Sstevel@tonic-gatevoid
3657c478bd9Sstevel@tonic-gateresumable_error(void)
3667c478bd9Sstevel@tonic-gate{}
3677c478bd9Sstevel@tonic-gate
3687c478bd9Sstevel@tonic-gate#else	/* lint */
3697c478bd9Sstevel@tonic-gate
3707c478bd9Sstevel@tonic-gate/*
3717c478bd9Sstevel@tonic-gate * (TT 0x7e, TL>0) Resumeable Error Queue Handler
3727c478bd9Sstevel@tonic-gate *	We keep a shadow copy of the queue in kernel buf.
3737c478bd9Sstevel@tonic-gate *	Read the resumable queue head and tail offset
3747c478bd9Sstevel@tonic-gate *	If there are entries on the queue, move them to
3757c478bd9Sstevel@tonic-gate *	the kernel buf, which is next to the resumable
3767c478bd9Sstevel@tonic-gate *	queue in the memory. Call C routine to process.
3777c478bd9Sstevel@tonic-gate */
3787c478bd9Sstevel@tonic-gate	ENTRY_NP(resumable_error)
3797c478bd9Sstevel@tonic-gate	mov	CPU_RQ_HD, %g4
3807c478bd9Sstevel@tonic-gate	ldxa	[%g4]ASI_QUEUE, %g2		! %g2 = Q head offset
3817c478bd9Sstevel@tonic-gate	mov	CPU_RQ_TL, %g4
3827c478bd9Sstevel@tonic-gate	ldxa	[%g4]ASI_QUEUE, %g3		! %g3 = Q tail offset
3837c478bd9Sstevel@tonic-gate	mov	%g2, %g6			! save head in %g2
3847c478bd9Sstevel@tonic-gate
3857c478bd9Sstevel@tonic-gate	cmp	%g6, %g3
3867c478bd9Sstevel@tonic-gate	be,pn	%xcc, 0f			! head == tail
3877c478bd9Sstevel@tonic-gate	nop
3887c478bd9Sstevel@tonic-gate
3897c478bd9Sstevel@tonic-gate	CPU_ADDR(%g1, %g4)			! %g1 = cpu struct addr
3907c478bd9Sstevel@tonic-gate
3917c478bd9Sstevel@tonic-gate2:	set	CPU_RQ_BASE_OFF, %g4
3927c478bd9Sstevel@tonic-gate	ldx	[%g1 + %g4], %g4		! %g4 = queue base PA
3937c478bd9Sstevel@tonic-gate	add	%g6, %g4, %g4			! %g4 = PA of ER in Q
3947c478bd9Sstevel@tonic-gate	set	CPU_RQ_SIZE, %g7
3957c478bd9Sstevel@tonic-gate	add	%g4, %g7, %g7			! %g7=PA of ER in kernel buf
3967c478bd9Sstevel@tonic-gate
3977c478bd9Sstevel@tonic-gate	ldxa	[%g7]ASI_MEM, %g5		! %g5=first 8 byte of ER buf
3987c478bd9Sstevel@tonic-gate	cmp	0, %g5
3997c478bd9Sstevel@tonic-gate	bne,pn	%xcc, 1f			! first 8 byte is not 0
4007c478bd9Sstevel@tonic-gate	nop
4017c478bd9Sstevel@tonic-gate
4027c478bd9Sstevel@tonic-gate	/* Now we can move 64 bytes from queue to buf */
4037c478bd9Sstevel@tonic-gate	set	0, %g5
4047c478bd9Sstevel@tonic-gate	ldxa	[%g4 + %g5]ASI_MEM, %g1
4057c478bd9Sstevel@tonic-gate	stxa	%g1, [%g7 + %g5]ASI_MEM		! byte 0 - 7
4067c478bd9Sstevel@tonic-gate	add	%g5, 8, %g5
4077c478bd9Sstevel@tonic-gate	ldxa	[%g4 + %g5]ASI_MEM, %g1
4087c478bd9Sstevel@tonic-gate	stxa	%g1, [%g7 + %g5]ASI_MEM		! byte 8 - 15
4097c478bd9Sstevel@tonic-gate	add	%g5, 8, %g5
4107c478bd9Sstevel@tonic-gate	ldxa	[%g4 + %g5]ASI_MEM, %g1
4117c478bd9Sstevel@tonic-gate	stxa	%g1, [%g7 + %g5]ASI_MEM		! byte 16 - 23
4127c478bd9Sstevel@tonic-gate	add	%g5, 8, %g5
4137c478bd9Sstevel@tonic-gate	ldxa	[%g4 + %g5]ASI_MEM, %g1
4147c478bd9Sstevel@tonic-gate	stxa	%g1, [%g7 + %g5]ASI_MEM		! byte 24 - 31
4157c478bd9Sstevel@tonic-gate	add	%g5, 8, %g5
4167c478bd9Sstevel@tonic-gate	ldxa	[%g4 + %g5]ASI_MEM, %g1
4177c478bd9Sstevel@tonic-gate	stxa	%g1, [%g7 + %g5]ASI_MEM		! byte 32 - 39
4187c478bd9Sstevel@tonic-gate	add	%g5, 8, %g5
4197c478bd9Sstevel@tonic-gate	ldxa	[%g4 + %g5]ASI_MEM, %g1
4207c478bd9Sstevel@tonic-gate	stxa	%g1, [%g7 + %g5]ASI_MEM		! byte 40 - 47
4217c478bd9Sstevel@tonic-gate	add	%g5, 8, %g5
4227c478bd9Sstevel@tonic-gate	ldxa	[%g4 + %g5]ASI_MEM, %g1
4237c478bd9Sstevel@tonic-gate	stxa	%g1, [%g7 + %g5]ASI_MEM		! byte 48 - 55
4247c478bd9Sstevel@tonic-gate	add	%g5, 8, %g5
4257c478bd9Sstevel@tonic-gate	ldxa	[%g4 + %g5]ASI_MEM, %g1
4267c478bd9Sstevel@tonic-gate	stxa	%g1, [%g7 + %g5]ASI_MEM		! byte 56 - 63
4277c478bd9Sstevel@tonic-gate
4287c478bd9Sstevel@tonic-gate	set	CPU_RQ_SIZE, %g5		! %g5 = queue size
4297c478bd9Sstevel@tonic-gate	sub	%g5, 1, %g5			! %g5 = queu size mask
4307c478bd9Sstevel@tonic-gate
4317c478bd9Sstevel@tonic-gate	add	%g6, Q_ENTRY_SIZE, %g6		! increment q head to next
4327c478bd9Sstevel@tonic-gate	and	%g6, %g5, %g6			! size mask for warp around
4337c478bd9Sstevel@tonic-gate	cmp	%g6, %g3			! head == tail ??
4347c478bd9Sstevel@tonic-gate
4357c478bd9Sstevel@tonic-gate	bne,pn	%xcc, 2b			! still have more to process
4367c478bd9Sstevel@tonic-gate	nop
4377c478bd9Sstevel@tonic-gate
4387c478bd9Sstevel@tonic-gate	/*
4397c478bd9Sstevel@tonic-gate	 * head equals to tail now, we can update the queue head
4407c478bd9Sstevel@tonic-gate	 * and call sys_trap
4417c478bd9Sstevel@tonic-gate	 */
4427c478bd9Sstevel@tonic-gate	mov	CPU_RQ_HD, %g4
4437c478bd9Sstevel@tonic-gate	stxa	%g6, [%g4]ASI_QUEUE		! update head offset
4442f0fcb93SJason Beloro	membar	#Sync
4457c478bd9Sstevel@tonic-gate
4467c478bd9Sstevel@tonic-gate	/*
447f2e043f1Sdavemq	 * Call sys_trap at PIL 14 unless we're already at PIL 15. %g2.l is
448f2e043f1Sdavemq	 * head offset(arg2) and %g3 is tail
4497c478bd9Sstevel@tonic-gate	 * offset(arg3).
4507c478bd9Sstevel@tonic-gate	 */
4517c478bd9Sstevel@tonic-gate	set	process_resumable_error, %g1
452f2e043f1Sdavemq	rdpr	%pil, %g4
453f2e043f1Sdavemq	cmp	%g4, PIL_14
4547c478bd9Sstevel@tonic-gate	ba	sys_trap
455f2e043f1Sdavemq	  movl	%icc, PIL_14, %g4
4567c478bd9Sstevel@tonic-gate
4577c478bd9Sstevel@tonic-gate	/*
4587c478bd9Sstevel@tonic-gate	 * We are here because the C routine is not able to process
4597c478bd9Sstevel@tonic-gate	 * errors in time. So the first 8 bytes of ER in buf has not
4607c478bd9Sstevel@tonic-gate	 * been cleared. We update head to tail and call sys_trap to
4617c478bd9Sstevel@tonic-gate	 * print out an error message
4627c478bd9Sstevel@tonic-gate	 */
4637c478bd9Sstevel@tonic-gate
4647c478bd9Sstevel@tonic-gate1:	mov	CPU_RQ_HD, %g4
4657c478bd9Sstevel@tonic-gate	stxa	%g3, [%g4]ASI_QUEUE		! set head equal to tail
4662f0fcb93SJason Beloro	membar	#Sync
4677c478bd9Sstevel@tonic-gate
4687c478bd9Sstevel@tonic-gate	/*
4697c478bd9Sstevel@tonic-gate	 * Set %g2 to %g6, which is current head offset. %g2
4707c478bd9Sstevel@tonic-gate	 * is arg2 of the C routine. %g3 is the tail offset,
4717c478bd9Sstevel@tonic-gate	 * which is arg3 of the C routine.
472f2e043f1Sdavemq	 * Call rq_overflow at PIL 14 unless we're already at PIL 15.
4737c478bd9Sstevel@tonic-gate	 */
4747c478bd9Sstevel@tonic-gate	mov	%g6, %g2
4757c478bd9Sstevel@tonic-gate	set	rq_overflow, %g1
476f2e043f1Sdavemq	rdpr	%pil, %g4
477f2e043f1Sdavemq	cmp	%g4, PIL_14
4787c478bd9Sstevel@tonic-gate	ba	sys_trap
479f2e043f1Sdavemq	  movl	%icc, PIL_14, %g4
4807c478bd9Sstevel@tonic-gate
4817c478bd9Sstevel@tonic-gate0:	retry
4827c478bd9Sstevel@tonic-gate
4837c478bd9Sstevel@tonic-gate	/*NOTREACHED*/
4847c478bd9Sstevel@tonic-gate	SET_SIZE(resumable_error)
4857c478bd9Sstevel@tonic-gate#endif /* lint */
4867c478bd9Sstevel@tonic-gate
4877c478bd9Sstevel@tonic-gate#if defined(lint)
4887c478bd9Sstevel@tonic-gate
4897c478bd9Sstevel@tonic-gatevoid
4907c478bd9Sstevel@tonic-gatenonresumable_error(void)
4917c478bd9Sstevel@tonic-gate{}
4927c478bd9Sstevel@tonic-gate
4937c478bd9Sstevel@tonic-gate#else	/* lint */
4947c478bd9Sstevel@tonic-gate
4957c478bd9Sstevel@tonic-gate/*
4967c478bd9Sstevel@tonic-gate * (TT 0x7f, TL>0) Non-resumeable Error Queue Handler
4977c478bd9Sstevel@tonic-gate *	We keep a shadow copy of the queue in kernel buf.
4987c478bd9Sstevel@tonic-gate *	Read non-resumable queue head and tail offset
4997c478bd9Sstevel@tonic-gate *	If there are entries on the queue, move them to
5007c478bd9Sstevel@tonic-gate *	the kernel buf, which is next to the non-resumable
5017c478bd9Sstevel@tonic-gate *	queue in the memory. Call C routine to process.
5027c478bd9Sstevel@tonic-gate */
5037c478bd9Sstevel@tonic-gate	ENTRY_NP(nonresumable_error)
5047c478bd9Sstevel@tonic-gate	mov	CPU_NRQ_HD, %g4
5057c478bd9Sstevel@tonic-gate	ldxa	[%g4]ASI_QUEUE, %g2		! %g2 = Q head offset
5067c478bd9Sstevel@tonic-gate	mov	CPU_NRQ_TL, %g4
5077c478bd9Sstevel@tonic-gate	ldxa	[%g4]ASI_QUEUE, %g3		! %g3 = Q tail offset
5087c478bd9Sstevel@tonic-gate
50918aea0b1Swh94709	cmp	%g2, %g3
5107c478bd9Sstevel@tonic-gate	be,pn	%xcc, 0f			! head == tail
5117c478bd9Sstevel@tonic-gate	nop
5127c478bd9Sstevel@tonic-gate
51318aea0b1Swh94709	/* force %gl to 1 as sys_trap requires */
51418aea0b1Swh94709	wrpr	%g0, 1, %gl
51518aea0b1Swh94709	mov	CPU_NRQ_HD, %g4
51618aea0b1Swh94709	ldxa	[%g4]ASI_QUEUE, %g2		! %g2 = Q head offset
51718aea0b1Swh94709	mov	CPU_NRQ_TL, %g4
51818aea0b1Swh94709	ldxa	[%g4]ASI_QUEUE, %g3		! %g3 = Q tail offset
51918aea0b1Swh94709	mov	%g2, %g6			! save head in %g2
52018aea0b1Swh94709
52118aea0b1Swh94709	CPU_PADDR(%g1, %g4)			! %g1 = cpu struct paddr
5227c478bd9Sstevel@tonic-gate
5237c478bd9Sstevel@tonic-gate2:	set	CPU_NRQ_BASE_OFF, %g4
52418aea0b1Swh94709	ldxa	[%g1 + %g4]ASI_MEM, %g4		! %g4 = queue base PA
5257c478bd9Sstevel@tonic-gate	add	%g6, %g4, %g4			! %g4 = PA of ER in Q
5267c478bd9Sstevel@tonic-gate	set	CPU_NRQ_SIZE, %g7
5277c478bd9Sstevel@tonic-gate	add	%g4, %g7, %g7			! %g7 = PA of ER in kernel buf
5287c478bd9Sstevel@tonic-gate
5297c478bd9Sstevel@tonic-gate	ldxa	[%g7]ASI_MEM, %g5		! %g5 = first 8 byte of ER buf
5307c478bd9Sstevel@tonic-gate	cmp	0, %g5
5317c478bd9Sstevel@tonic-gate	bne,pn	%xcc, 1f			! first 8 byte is not 0
5327c478bd9Sstevel@tonic-gate	nop
5337c478bd9Sstevel@tonic-gate
5349d0d62adSJason Beloro	/* Now we can move 64 bytes from queue to buf */
5357c478bd9Sstevel@tonic-gate	set	0, %g5
5367c478bd9Sstevel@tonic-gate	ldxa	[%g4 + %g5]ASI_MEM, %g1
5377c478bd9Sstevel@tonic-gate	stxa	%g1, [%g7 + %g5]ASI_MEM		! byte 0 - 7
5387c478bd9Sstevel@tonic-gate	add	%g5, 8, %g5
5397c478bd9Sstevel@tonic-gate	ldxa	[%g4 + %g5]ASI_MEM, %g1
5407c478bd9Sstevel@tonic-gate	stxa	%g1, [%g7 + %g5]ASI_MEM		! byte 8 - 15
5417c478bd9Sstevel@tonic-gate	add	%g5, 8, %g5
5427c478bd9Sstevel@tonic-gate	ldxa	[%g4 + %g5]ASI_MEM, %g1
5437c478bd9Sstevel@tonic-gate	stxa	%g1, [%g7 + %g5]ASI_MEM		! byte 16 - 23
5449d0d62adSJason Beloro	add	%g5, 8, %g5
5457c478bd9Sstevel@tonic-gate	ldxa	[%g4 + %g5]ASI_MEM, %g1
5467c478bd9Sstevel@tonic-gate	stxa	%g1, [%g7 + %g5]ASI_MEM		! byte 24 - 31
5477c478bd9Sstevel@tonic-gate	add	%g5, 8, %g5
5487c478bd9Sstevel@tonic-gate	ldxa	[%g4 + %g5]ASI_MEM, %g1
5497c478bd9Sstevel@tonic-gate	stxa	%g1, [%g7 + %g5]ASI_MEM		! byte 32 - 39
5507c478bd9Sstevel@tonic-gate	add	%g5, 8, %g5
5517c478bd9Sstevel@tonic-gate	ldxa	[%g4 + %g5]ASI_MEM, %g1
5527c478bd9Sstevel@tonic-gate	stxa	%g1, [%g7 + %g5]ASI_MEM		! byte 40 - 47
5539d0d62adSJason Beloro	add	%g5, 8, %g5
5547c478bd9Sstevel@tonic-gate	ldxa	[%g4 + %g5]ASI_MEM, %g1
5557c478bd9Sstevel@tonic-gate	stxa	%g1, [%g7 + %g5]ASI_MEM		! byte 48 - 55
5567c478bd9Sstevel@tonic-gate	add	%g5, 8, %g5
5577c478bd9Sstevel@tonic-gate	ldxa	[%g4 + %g5]ASI_MEM, %g1
5587c478bd9Sstevel@tonic-gate	stxa	%g1, [%g7 + %g5]ASI_MEM		! byte 56 - 63
5597c478bd9Sstevel@tonic-gate
5607c478bd9Sstevel@tonic-gate	set	CPU_NRQ_SIZE, %g5		! %g5 = queue size
5617c478bd9Sstevel@tonic-gate	sub	%g5, 1, %g5			! %g5 = queu size mask
5627c478bd9Sstevel@tonic-gate
5637c478bd9Sstevel@tonic-gate	add	%g6, Q_ENTRY_SIZE, %g6		! increment q head to next
5647c478bd9Sstevel@tonic-gate	and	%g6, %g5, %g6			! size mask for warp around
5657c478bd9Sstevel@tonic-gate	cmp	%g6, %g3			! head == tail ??
5667c478bd9Sstevel@tonic-gate
5677c478bd9Sstevel@tonic-gate	bne,pn	%xcc, 2b			! still have more to process
5687c478bd9Sstevel@tonic-gate	nop
5697c478bd9Sstevel@tonic-gate
5707c478bd9Sstevel@tonic-gate	/*
5717c478bd9Sstevel@tonic-gate	 * head equals to tail now, we can update the queue head
5727c478bd9Sstevel@tonic-gate	 * and call sys_trap
5737c478bd9Sstevel@tonic-gate	 */
5747c478bd9Sstevel@tonic-gate	mov	CPU_NRQ_HD, %g4
5757c478bd9Sstevel@tonic-gate	stxa	%g6, [%g4]ASI_QUEUE		! update head offset
5762f0fcb93SJason Beloro	membar	#Sync
5772f0fcb93SJason Beloro
5782f0fcb93SJason Beloro	/*
5797c478bd9Sstevel@tonic-gate	 * Call sys_trap. %g2 is TL(arg2), %g3 is head and tail
5807c478bd9Sstevel@tonic-gate	 * offset(arg3).
5817c478bd9Sstevel@tonic-gate	 * %g3 looks like following:
5827c478bd9Sstevel@tonic-gate	 *	+--------------------+--------------------+
5837c478bd9Sstevel@tonic-gate	 *	|   tail offset      |    head offset     |
5847c478bd9Sstevel@tonic-gate	 *	+--------------------+--------------------+
5857c478bd9Sstevel@tonic-gate	 *	63                 32 31                 0
586f2e043f1Sdavemq	 *
587f2e043f1Sdavemq	 * Run at PIL 14 unless we're already at PIL 15.
5887c478bd9Sstevel@tonic-gate	 */
5899d0d62adSJason Beloro	sllx	%g3, 32, %g3			! %g3.h = tail offset
5907c478bd9Sstevel@tonic-gate	or	%g3, %g2, %g3			! %g3.l = head offset
5917c478bd9Sstevel@tonic-gate	rdpr	%tl, %g2			! %g2 = current tl
592ad559ebfSwh94709
593ad559ebfSwh94709	/*
594ad559ebfSwh94709	 * Now check if the first error that sent us here was caused
595ad559ebfSwh94709	 * in user's SPILL/FILL trap. If it was, we call sys_trap to
596ad559ebfSwh94709	 * kill the user process. Several considerations:
597ad559ebfSwh94709	 * - If multiple nonresumable errors happen, we only check the
598ad559ebfSwh94709	 *   first one. Nonresumable errors cause system either panic
599ad559ebfSwh94709	 *   or kill the user process. So the system has already
600ad559ebfSwh94709	 *   panic'ed or killed user process after processing the first
601ad559ebfSwh94709	 *   error. Therefore, no need to check if other error packet
602ad559ebfSwh94709	 *   for this type of error.
603ad559ebfSwh94709	 * - Errors happen in user's SPILL/FILL trap will bring us at
604ad559ebfSwh94709	 *   TL = 2.
605ad559ebfSwh94709	 * - We need to lower TL to 1 to get the trap type and tstate.
606ad559ebfSwh94709	 *   We don't go back to TL = 2 so no need to save states.
607ad559ebfSwh94709	 */
608ad559ebfSwh94709	cmp	%g2, 2
609ad559ebfSwh94709	bne,pt	%xcc, 3f			! if tl != 2
610ad559ebfSwh94709	nop
611ad559ebfSwh94709	/* Check to see if the trap pc is in a window spill/fill handling */
612ad559ebfSwh94709	rdpr	%tpc, %g4
613ad559ebfSwh94709	/* tpc should be in the trap table */
614ad559ebfSwh94709	set	trap_table, %g5
615ad559ebfSwh94709	cmp	%g4, %g5
616ad559ebfSwh94709	blu,pt	%xcc, 3f
617ad559ebfSwh94709	nop
618ad559ebfSwh94709	set	etrap_table, %g5
619ad559ebfSwh94709	cmp	%g4, %g5
620ad559ebfSwh94709	bgeu,pt	%xcc, 3f
621ad559ebfSwh94709	nop
622ad559ebfSwh94709	/* Set tl to 1 in order to read tt[1] and tstate[1] */
623ad559ebfSwh94709	wrpr	%g0, 1, %tl
624ad559ebfSwh94709	rdpr	%tt, %g4			! %g4 = tt[1]
625ad559ebfSwh94709	/* Check if tt[1] is a window trap */
626ad559ebfSwh94709	and	%g4, WTRAP_TTMASK, %g4
627ad559ebfSwh94709	cmp	%g4, WTRAP_TYPE
628ad559ebfSwh94709	bne,pt	%xcc, 3f
629ad559ebfSwh94709	nop
630ad559ebfSwh94709	rdpr	%tstate, %g5			! %g5 = tstate[1]
631ad559ebfSwh94709	btst	TSTATE_PRIV, %g5
632ad559ebfSwh94709	bnz	%xcc, 3f			! Is it from user code?
633ad559ebfSwh94709	nop
634ad559ebfSwh94709	/*
635ad559ebfSwh94709	 * Now we know the error happened in user's SPILL/FILL trap.
636ad559ebfSwh94709	 * Turn on the user spill/fill flag in %g2
637ad559ebfSwh94709	 */
638ad559ebfSwh94709	mov	1, %g4
639ad559ebfSwh94709	sllx	%g4, ERRH_U_SPILL_FILL_SHIFT, %g4
640ad559ebfSwh94709	or	%g2, %g4, %g2			! turn on flag in %g2
641ad559ebfSwh94709
642ad559ebfSwh947093:	sub	%g2, 1, %g2			! %g2.l = previous tl
6437c478bd9Sstevel@tonic-gate
6447c478bd9Sstevel@tonic-gate	set	process_nonresumable_error, %g1
645f2e043f1Sdavemq	rdpr	%pil, %g4
646f2e043f1Sdavemq	cmp	%g4, PIL_14
6477c478bd9Sstevel@tonic-gate	ba	sys_trap
648f2e043f1Sdavemq	  movl	%icc, PIL_14, %g4
6497c478bd9Sstevel@tonic-gate
6507c478bd9Sstevel@tonic-gate	/*
6517c478bd9Sstevel@tonic-gate	 * We are here because the C routine is not able to process
6527c478bd9Sstevel@tonic-gate	 * errors in time. So the first 8 bytes of ER in buf has not
65318aea0b1Swh94709	 * been cleared. We call sys_trap to panic.
65418aea0b1Swh94709	 * Run at PIL 14 unless we're already at PIL 15.
6557c478bd9Sstevel@tonic-gate	 */
65618aea0b1Swh947091:	set	nrq_overflow, %g1
65718aea0b1Swh94709	rdpr	%pil, %g4
65818aea0b1Swh94709	cmp	%g4, PIL_14
65918aea0b1Swh94709	ba	sys_trap
66018aea0b1Swh94709	  movl	%icc, PIL_14, %g4
6617c478bd9Sstevel@tonic-gate
6627c478bd9Sstevel@tonic-gate0:	retry
6637c478bd9Sstevel@tonic-gate
6647c478bd9Sstevel@tonic-gate	/*NOTREACHED*/
6657c478bd9Sstevel@tonic-gate	SET_SIZE(nonresumable_error)
6667c478bd9Sstevel@tonic-gate#endif /* lint */
667