xref: /netbsd-src/sys/arch/hppa/hppa/trap.S (revision dd6e3d87fed0060d7db97095c36e873a62686824)
1/*	$NetBSD: trap.S,v 1.75 2023/07/23 10:09:36 skrll Exp $	*/
2
3/*-
4 * Copyright (c) 2002 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Matthew Fredette.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32/*	$OpenBSD: locore.S,v 1.158 2008/07/28 19:08:46 miod Exp $	*/
33
34/*
35 * Copyright (c) 1998-2004 Michael Shalayeff
36 * All rights reserved.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 *    notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 *    notice, this list of conditions and the following disclaimer in the
45 *    documentation and/or other materials provided with the distribution.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
48 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
49 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
50 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
51 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
52 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
53 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
55 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
56 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
57 * THE POSSIBILITY OF SUCH DAMAGE.
58 *
59 * Portitions of this file are derived from other sources, see
60 * the copyrights and acknowledgements below.
61 */
62/*
63 *  (c) Copyright 1988 HEWLETT-PACKARD COMPANY
64 *
65 *  To anyone who acknowledges that this file is provided "AS IS"
66 *  without any express or implied warranty:
67 *      permission to use, copy, modify, and distribute this file
68 *  for any purpose is hereby granted without fee, provided that
69 *  the above copyright notice and this notice appears in all
70 *  copies, and that the name of Hewlett-Packard Company not be
71 *  used in advertising or publicity pertaining to distribution
72 *  of the software without specific, written prior permission.
73 *  Hewlett-Packard Company makes no representations about the
74 *  suitability of this software for any purpose.
75 */
76/*
77 * Copyright (c) 1990,1991,1992,1994 The University of Utah and
78 * the Computer Systems Laboratory (CSL).  All rights reserved.
79 *
80 * Permission to use, copy, modify and distribute this software is hereby
81 * granted provided that (1) source code retains these copyright, permission,
82 * and disclaimer notices, and (2) redistributions including binaries
83 * reproduce the notices in supporting documentation, and (3) all advertising
84 * materials mentioning features or use of this software display the following
85 * acknowledgement: ``This product includes software developed by the
86 * Computer Systems Laboratory at the University of Utah.''
87 *
88 * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
89 * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
90 * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
91 *
92 * CSL requests users of this software to return to csl-dist@cs.utah.edu any
93 * improvements that they make and grant CSL redistribution rights.
94 *
95 *	Utah $Hdr: locore.s 1.63 95/01/20$
96 */
97
98#include "opt_multiprocessor.h"
99#include "opt_cputype.h"
100
101/*
102 * NOTICE: This is not a standalone file.  To use it, #include it in
103 * your port's locore.S, like so:
104 *
105 *	#include <hppa/hppa/trap.S>
106 */
107
108	.section .data
109
110	/* Normal stack alignment */
111	.align	64
112	.export emergency_stack_start, data
113emergency_stack_start:
114	.block	32768
115	.export emergency_stack_end, data
116emergency_stack_end:
117
118	.text
119
120/*
121 * Kernel Gateway Page (must be at known address)
122 *	System Call Gate
123 *
124 * GATEway instructions have to be at a fixed known locations because their
125 * addresses are hard coded in routines such as those in the C library.
126 */
127
128	.align	NBPG
129	.export	gateway_page, entry
130gateway_page:
131	nop				/* @ 0.C0000000 (Nothing)  */
132	gate,n	bsd_syscall,%r0		/* @ 0.C0000004 (HPUX/BSD) */
133	nop				/* @ 0.C0000008 (HPOSF UNIX) */
134	nop				/* @ 0.C000000C (HPOSF Mach) */
135	nop
136	nop
137	nop
138	nop
139
140bsd_syscall:
141	/*
142	 * Set up a space register and a protection id so that we can access
143	 * kernel memory.
144	 */
145	mfctl	%eiem, %r1
146	mtctl	%r0, %eiem
147	mtsp	%r0, %sr1
148	mfctl	%pidr1, %ret0
149	ldi	HPPA_PID_KERNEL, %t2
150	mtctl	%t2, %pidr1
151
152	/*
153	 * now call the syscall handler
154	 */
155	.import syscall_entry,code
156	.call
157	ldil	L%syscall_entry, %t2
158	be	R%syscall_entry(%sr1, %t2)
159	nop ! nop ! nop ! nop
160	.size	gateway_page, .-gateway_page
161
162	.align	NBPG
163	.export	gateway_page_end, entry
164gateway_page_end:
165
166	.export syscall_entry,entry
167	.proc
168	.callinfo calls
169	.entry
170syscall_entry:
171	/*
172	 * %r1:		eiem
173	 * %ret0:	process protection id
174	 * %t1:		syscall number
175	 * %sr0, %r31:	return address
176	 * %sp:		user stack
177	 *
178	 */
179
180	/* t2 = curlwp PCB */
181	GET_CURLWP_SPACE(%sr1, %t3)
182	ldw	L_PCB(%sr1, %t3), %t2			/* XXX can use ,sl */
183
184	/*
185	 * NB: Even though t4 is a caller-saved register, we save it anyways, as
186	 * a convenience to __vfork14 and any other syscalls that absolutely
187	 * must have a register that is saved for it.
188	 */
189
190	/* calculate kernel sp, load, create kernel stack frame */
191	ldo	NBPG+TRAPFRAME_SIZEOF(%t2), %t3		/* see cpu_lwp_fork */
192
193	stw	%t4, TF_R19-TRAPFRAME_SIZEOF(%sr1, %t3)	/* t4 for vfork */
194	stw	%t1, TF_R22-TRAPFRAME_SIZEOF(%sr1, %t3)	/* syscall # */
195	copy	%sp, %t4
196
197	/* gotta save the args, in case we gonna restart */
198	stw	%arg3, TF_R23 -TRAPFRAME_SIZEOF(%sr1, %t3)
199	stw	%arg2, TF_R24 -TRAPFRAME_SIZEOF(%sr1, %t3)
200	stw	%arg1, TF_R25 -TRAPFRAME_SIZEOF(%sr1, %t3)
201	stw	%arg0, TF_R26 -TRAPFRAME_SIZEOF(%sr1, %t3)
202	stw	%r27, TF_R27 -TRAPFRAME_SIZEOF(%sr1, %t3)	/* dp */
203	stw	%sp, TF_R30 -TRAPFRAME_SIZEOF(%sr1, %t3)	/* user stack */
204	copy	%t3, %sp
205	/*
206	 * Make space for the syscall arguments.
207	 *
208	 * Match the offset from %sp to the trapframe with the offset in
209	 * TLABEL(all) for the benefit of ddb.
210	 */
211	stwm	%r0, HPPA_FRAME_SIZE+HPPA_FRAME_MAXARGS(%sr1, %sp)
212
213	/* Align correctly */
214	ldo	HPPA_FRAME_SIZE-1(%sp),%sp
215	depi	0, 31, 6, %sp
216
217	stw	%r0, HPPA_FRAME_CRP(%sr1, %sp)
218
219	GET_CURCPU_SPACE(%sr1, %t1)
220	ldw	CI_PSW(%sr1, %t1), %t1
221	stw	%r1, TF_CR15-TRAPFRAME_SIZEOF(%sr1, %t3)	/* eiem ,bc (block copy cache control hint) */
222	stw	%t1, TF_CR22-TRAPFRAME_SIZEOF(%sr1, %t3)	/* ipsw */
223
224	mfsp	%sr3, %t1
225	stw	%t1, TF_SR3-TRAPFRAME_SIZEOF(%sr1, %t3)
226	stw	%ret0, TF_CR8-TRAPFRAME_SIZEOF(%sr1, %t3)	/* pidr1 */
227
228	/* now we can allow interrupts to happen */
229	mtctl	%r1, %eiem
230
231	/*
232	 * Normally, we only have to save the caller-saved registers, because
233	 * the callee-saved registers will be naturally saved and restored by
234	 * our callee(s).  However, see the longer comment in the trap handling
235	 * code below for the reasons why we need to save and restore all of
236	 * them.
237	 */
238	stw	%r2 , TF_R2 -TRAPFRAME_SIZEOF(%sr1, %t3)
239	stw	%r3 , TF_R3 -TRAPFRAME_SIZEOF(%sr1, %t3)
240
241	/* We can now set the frame pointer */
242	copy	%t3, %r3
243
244	stw	%r4 , TF_R4 -TRAPFRAME_SIZEOF(%sr1, %t3)
245	stw	%r5 , TF_R5 -TRAPFRAME_SIZEOF(%sr1, %t3)
246	stw	%r6 , TF_R6 -TRAPFRAME_SIZEOF(%sr1, %t3)
247	stw	%r7 , TF_R7 -TRAPFRAME_SIZEOF(%sr1, %t3)
248	stw	%r8 , TF_R8 -TRAPFRAME_SIZEOF(%sr1, %t3)
249	stw	%r9 , TF_R9 -TRAPFRAME_SIZEOF(%sr1, %t3)
250	stw	%r10, TF_R10-TRAPFRAME_SIZEOF(%sr1, %t3)
251	stw	%r11, TF_R11-TRAPFRAME_SIZEOF(%sr1, %t3)
252	stw	%r12, TF_R12-TRAPFRAME_SIZEOF(%sr1, %t3)
253	stw	%r13, TF_R13-TRAPFRAME_SIZEOF(%sr1, %t3)
254	stw	%r14, TF_R14-TRAPFRAME_SIZEOF(%sr1, %t3)
255	stw	%r15, TF_R15-TRAPFRAME_SIZEOF(%sr1, %t3)
256	stw	%r16, TF_R16-TRAPFRAME_SIZEOF(%sr1, %t3)
257	stw	%r17, TF_R17-TRAPFRAME_SIZEOF(%sr1, %t3)
258	stw	%r18, TF_R18-TRAPFRAME_SIZEOF(%sr1, %t3)
259
260	stw	%r0, 0(%sr1, %t3)	/* terminate frame */
261	copy	%r0 , %r3
262	stw	%r0, HPPA_FRAME_PSP(%sr1, %sp)
263	stw	%r0, HPPA_FRAME_CRP(%sr1, %sp)
264
265	/*
266	 * Copy Arguments
267	 *
268	 * Unfortunately mmap() under bsd requires 7 words; linux is confined to
269	 * 5, and hpux to 6.  Assuming the `long' syscall it gives us the
270	 * maximum 9 words, which very much overkill for an average of 3.  We
271	 * keep it at 10, since bundling will keep it at the same speed as 9
272	 * anyway.
273	 */
274	/*
275	 * XXX fredette - possible security hole here.
276	 * What happens if the user hands us a stack
277	 * that points to nowhere, or to data that they
278	 * should not be reading?
279	 */
280	stw	%arg0, 1*4(%sr1, %t3)	/* XXX can use ,bc */
281	stw	%arg1, 2*4(%sr1, %t3)
282	stw	%arg2, 3*4(%sr1, %t3)
283	stw	%arg3, 4*4(%sr1, %t3)
284	ldw	HPPA_FRAME_ARG( 4)(%t4), %arg0
285	ldw	HPPA_FRAME_ARG( 5)(%t4), %arg1
286	ldw	HPPA_FRAME_ARG( 6)(%t4), %arg2
287	ldw	HPPA_FRAME_ARG( 7)(%t4), %arg3
288	stw	%arg0, 5*4(%sr1, %t3)
289	stw	%arg1, 6*4(%sr1, %t3)
290	stw	%arg2, 7*4(%sr1, %t3)
291	stw	%arg3, 8*4(%sr1, %t3)
292	ldw	HPPA_FRAME_ARG( 8)(%t4), %arg0
293	ldw	HPPA_FRAME_ARG( 9)(%t4), %arg1
294	stw	%arg0, 9*4(%sr1, %t3)
295	stw	%arg1,10*4(%sr1, %t3)
296
297	/*
298	 * Save the rest of the CPU context
299	 */
300
301	/* XXXNH: Should do a be 0(%sr1, %r31) instead of rfi when possible */
302	ldo	4(%r31), %arg1
303	stw	%r31, TF_IIOQH-TRAPFRAME_SIZEOF(%sr1, %t3)
304	stw	%arg1, TF_IIOQT-TRAPFRAME_SIZEOF(%sr1, %t3)
305
306	mfsp	%sr0, %arg0
307	stw	%arg0, TF_IISQH-TRAPFRAME_SIZEOF(%sr1, %t3)
308	stw	%arg0, TF_IISQT-TRAPFRAME_SIZEOF(%sr1, %t3)
309
310	stw	%arg0, TF_CR20-TRAPFRAME_SIZEOF(%sr1, %t3)
311	stw	%r31, TF_CR21-TRAPFRAME_SIZEOF(%sr1, %t3)
312
313	ldil	L%(TFF_LAST|TFF_SYS), %arg1
314	stw	%r0, TF_CR19-TRAPFRAME_SIZEOF(%sr1, %t3)	/* iir */
315	stw	%arg1, TF_FLAGS-TRAPFRAME_SIZEOF(%sr1, %t3)
316
317	/* Already done above: mfsp	%sr0, %arg0 */
318	mfsp	%sr2, %arg2
319	mfsp	%sr4, %arg3
320	stw	%arg0, TF_SR0-TRAPFRAME_SIZEOF(%sr1, %t3)
321	stw	%arg0, TF_SR1-TRAPFRAME_SIZEOF(%sr1, %t3)
322					/* we overwrote sr1 earlier */
323	stw	%arg2, TF_SR2-TRAPFRAME_SIZEOF(%sr1, %t3)
324	stw	%arg3, TF_SR4-TRAPFRAME_SIZEOF(%sr1, %t3)
325
326	mfsp	%sr5, %arg0
327	mfsp	%sr6, %arg1
328	mfsp	%sr7, %arg2
329	mfctl	%pidr2, %arg3
330	stw	%arg0, TF_SR5-TRAPFRAME_SIZEOF(%sr1, %t3)
331	stw	%arg1, TF_SR6-TRAPFRAME_SIZEOF(%sr1, %t3)
332	stw	%arg2, TF_SR7-TRAPFRAME_SIZEOF(%sr1, %t3)
333	stw	%arg3, TF_CR9-TRAPFRAME_SIZEOF(%sr1, %t3)
334
335#if pbably_not_worth_it
336	mfctl	%pidr3, %arg2
337	mfctl	%pidr4, %arg3
338	stw	%arg2, TF_CR12-TRAPFRAME_SIZEOF(%sr1, %t3)
339	stw	%arg3, TF_CR13-TRAPFRAME_SIZEOF(%sr1, %t3)
340#endif
341
342	mfctl	CR_TLS, %arg0
343	stw	%arg0, TF_CR27-TRAPFRAME_SIZEOF(%sr1, %t3)
344
345#if defined(DDB) || defined(KGDB)
346	/*
347	 * Save v2p translation table pointer
348	 */
349	mfctl	%eirr, %arg0
350	mfctl	CR_VTOP, %arg1
351	stw	%arg0, TF_CR23-TRAPFRAME_SIZEOF(%sr1, %t3)
352	stw	%arg1, TF_CR25-TRAPFRAME_SIZEOF(%sr1, %t3)
353
354	mfctl	%cr24, %arg0
355	mfctl	%cr28, %arg1
356	stw	%arg0, TF_CR24-TRAPFRAME_SIZEOF(%sr1, %t3)
357	stw	%arg1, TF_CR28-TRAPFRAME_SIZEOF(%sr1, %t3)
358#endif
359
360	/* setup kernel context */
361	mtsp	%r0, %sr0
362	mtsp	%r0, %sr1
363	mtsp	%r0, %sr2
364	mtsp	%r0, %sr3
365	mtsp	%r0, %sr4
366	mtsp	%r0, %sr5
367	mtsp	%r0, %sr6
368	mtsp	%r0, %sr7
369
370	ldo	-TRAPFRAME_SIZEOF(%t3), %arg0
371	ldo	4(%t3), %arg1
372
373	ldil	L%$global$,%dp
374	ldo	R%$global$(%dp),%dp
375
376	GET_CURLWP(%r3)
377	ldw	L_PROC(%r3), %r1
378	ldw	P_MD_SYSCALL(%r1), %r1
379
380	.call
381 	blr	%r0, %rp
382 	bv,n	%r0(%r1)
383 	nop
384
385	/* load curlwp's trapframe pointer */
386	ldw	L_MD(%r3), %t3
387
388	.exit
389	.procend
390	/* FALLTHROUGH */
391
392	.export	syscall_return, entry
393	.proc
394	.callinfo no_calls
395	.entry
396syscall_return:
397	/* t3 == VA trapframe */
398
399	/* disable interrupts, just in case */
400	mtctl	%r0, %eiem
401
402	/*
403	 * Copy the `phys' part of the frame into CPU local temporary store (see
404	 * a note for trapall).  Hopefully no page fault would happen on or after
405	 * the copy, and interrupts are disabled.
406	 */
407	GET_CURCPU(%t2)
408	ldo	CI_TRAPSAVE(%t2), %t2
409
410	ldw  0(%t3), %r1 ! ldw  4(%t3), %t1 ! stw %r1,  0(%t2) ! stw %t1,  4(%t2)
411	ldw  8(%t3), %r1 ! ldw 12(%t3), %t1 ! stw %r1,  8(%t2) ! stw %t1, 12(%t2)
412	ldw 16(%t3), %r1 ! ldw 20(%t3), %t1 ! stw %r1, 16(%t2) ! stw %t1, 20(%t2)
413	ldw 24(%t3), %r1 ! ldw 28(%t3), %t1 ! stw %r1, 24(%t2) ! stw %t1, 28(%t2)
414	ldw 32(%t3), %r1 ! ldw 36(%t3), %t1 ! stw %r1, 32(%t2) ! stw %t1, 36(%t2)
415	ldw 40(%t3), %r1 ! ldw 44(%t3), %t1 ! stw %r1, 40(%t2) ! stw %t1, 44(%t2)
416	ldw 48(%t3), %r1 ! ldw 52(%t3), %t1 ! stw %r1, 48(%t2) ! stw %t1, 52(%t2)
417	ldw 56(%t3), %r1 ! ldw 60(%t3), %t1 ! stw %r1, 56(%t2) ! stw %t1, 60(%t2)
418
419	/* 1b. restore most of the general registers */
420	ldw	TF_CR11(%t3), %t1
421	mtctl	%t1, %sar
422	ldw	TF_R1(%t3), %r1
423	ldw	TF_R2(%t3), %r2
424	ldw	TF_R3(%t3), %r3
425
426	/*
427	 * See the comment in the trap handling code below about why we need to
428	 * save and restore all general registers under these cases.
429	 */
430	ldw	TF_R4(%t3), %r4
431	ldw	TF_R5(%t3), %r5
432	ldw	TF_R6(%t3), %r6
433	ldw	TF_R7(%t3), %r7
434	ldw	TF_R8(%t3), %r8
435	ldw	TF_R9(%t3), %r9
436	ldw	TF_R10(%t3), %r10
437	ldw	TF_R11(%t3), %r11
438	ldw	TF_R12(%t3), %r12
439	ldw	TF_R13(%t3), %r13
440	ldw	TF_R14(%t3), %r14
441	ldw	TF_R15(%t3), %r15
442	ldw	TF_R16(%t3), %r16
443	ldw	TF_R17(%t3), %r17
444	ldw	TF_R18(%t3), %r18
445
446	ldw	TF_R19(%t3), %t4
447	/*	%r20(%t3) is used as a temporary and will be restored later */
448	/*	%r21(%t2) is used as a temporary and will be restored later */
449	/*	%r22(%t1) is used as a temporary and will be restored later */
450	ldw	TF_R23(%t3), %r23
451	ldw	TF_R24(%t3), %r24
452	ldw	TF_R25(%t3), %r25
453	ldw	TF_R26(%t3), %r26
454	ldw	TF_R27(%t3), %r27
455	ldw	TF_R28(%t3), %r28
456	ldw	TF_R29(%t3), %r29
457	/*	%r30 (%sp) will be restored later */
458	ldw	TF_R31(%t3), %r31
459
460	/* 2. restore all the space regs and pid regs, except sr3, pidr1 */
461	ldw	TF_SR0(%t3), %t1
462	ldw	TF_SR1(%t3), %t2
463	mtsp	%t1, %sr0
464	mtsp	%t2, %sr1
465
466	ldw	TF_SR2(%sr3, %t3), %t1
467	ldw	TF_SR4(%sr3, %t3), %t2
468	mtsp	%t1, %sr2
469	mtsp	%t2, %sr4
470
471	ldw	TF_SR5(%sr3, %t3), %t1
472	ldw	TF_SR6(%sr3, %t3), %t2
473	mtsp	%t1, %sr5
474	mtsp	%t2, %sr6
475
476	ldw	TF_SR7(%sr3, %t3), %t1
477	ldw	TF_CR9(%sr3, %t3), %t2
478	mtsp	%t1, %sr7
479	mtctl	%t2, %pidr2
480
481#if pbably_not_worth_it
482	ldw	TF_CR12(%sr3, %t3), %t1
483	ldw	TF_CR13(%sr3, %t3), %t2
484	mtctl	%t1, %pidr3
485	mtctl	%t2, %pidr4
486#endif
487	ldw	TF_CR27(%sr3, %t3), %t1
488	ldw	TF_CR30(%sr3, %t3), %t2
489	mtctl	%t1, CR_TLS
490	mtctl	%t2, CR_FPPADDR
491
492	ldw	TF_CR0(%sr3, %t3), %t1
493	mtctl	%t1, CR_RCTR
494
495	GET_CURCPU_SPACE(%sr3, %t3)
496
497	/*
498	 * Clear the system mask, this puts us back into physical mode.  Reload
499	 * the trapframe pointer with the correspondent PA value.  %sp will be
500	 * left in virtual until restored from trapframe, since we don't use it
501	 * anyway.
502	 */
503	ssm	0, %r0
504	ldo	CI_TRAPSAVE(%t3), %t3
505	nop ! nop ! nop ! nop ! nop ! nop
506	rsm	RESET_PSW, %r0
507
508	/* finally we can restore the space and offset queues and the ipsw */
509	ldw	TF_IISQH(%t3), %t1
510	ldw	TF_IISQT(%t3), %t2
511	mtctl	%t1, %pcsq
512	mtctl	%t2, %pcsq
513
514	ldw	TF_IIOQH(%t3), %t1
515	ldw	TF_IIOQT(%t3), %t2
516	mtctl	%t1, %pcoq
517	mtctl	%t2, %pcoq
518
519	ldw	TF_CR15(%t3), %t1
520	ldw	TF_CR22(%t3), %t2
521	mtctl	%t1, %eiem
522	mtctl	%t2, %ipsw
523
524	ldw	TF_SR3(%t3), %t1
525	ldw	TF_CR8(%t3), %t2
526	mtsp	%t1, %sr3
527	mtctl	%t2, %pidr1
528
529	ldw	TF_R22(%t3), %t1
530	ldw	TF_R21(%t3), %t2
531	ldw	TF_R30(%t3), %sp
532	ldw	TF_R20(%t3), %t3
533
534	rfi
535	nop
536	.exit
537	.procend
538	.size	syscall_entry, .- syscall_entry
539
540/*
541 * interrupt vector table
542 */
543#define	TLABEL(name)		__CONCAT(trap_,name)
544#define TRAPLABEL(name,num)	__CONCAT(TLABEL(name),num)
545#define	TELABEL(num)		__CONCAT(trap_ep_,num)
546
547#define TRAP(name,num) \
548	mtctl	%r1, %tr7		! \
549	.call				! \
550	.import TLABEL(name), code	! \
551	b	TLABEL(name)		! \
552	ldi	num, %r1		! \
553	.align	32
554
555#define	ATRAP(name,num) \
556	.export	TRAPLABEL(name,num), entry	! \
557	.label	TRAPLABEL(name,num)		! \
558	TRAP(all,num)				! \
559	.size	TRAPLABEL(name,num), .-TRAPLABEL(name,num)
560
561#define	CTRAP(name,num,pre) \
562	.export	TRAPLABEL(name,num), entry	! \
563	.label	TRAPLABEL(name,num)		! \
564	pre				! \
565	TRAP(name,num)			! \
566	.size	TRAPLABEL(name,num), .-TRAPLABEL(name,num)
567
568#define	STRAP(name,num,pre) \
569	.export	TRAPLABEL(name,num), entry	! \
570	.label	TRAPLABEL(name,num)		! \
571	pre				! \
572	mtctl	%r1, %tr7		! \
573	.export	TELABEL(num), entry	! \
574	.label	TELABEL(num)		! \
575	ldil	0,%r1			! \
576	ldo	0(%r1), %r1		! \
577	.call				! \
578	bv	0(%r1)			! \
579	ldi	num, %r1		! \
580	.align	32			! \
581	.size	TRAPLABEL(name,num), .-TRAPLABEL(name,num)
582
583#define	LDILDO(name)			! \
584	.export	name, entry		! \
585	.label	name			! \
586	ldil	L%TLABEL(name),%r1	! \
587	ldo	R%TLABEL(name)(%r1), %r1
588
589#ifdef HP7000_CPU
590LDILDO(itlb_x)
591LDILDO(itlbna_x)
592LDILDO(dtlb_x)
593LDILDO(dtlbna_x)
594LDILDO(tlbd_x)
595
596LDILDO(itlb_s)
597LDILDO(itlbna_s)
598LDILDO(dtlb_s)
599LDILDO(dtlbna_s)
600LDILDO(tlbd_s)
601#endif
602
603#if defined(HP7100_CPU) || defined(HP7200_CPU)
604LDILDO(itlb_t)
605LDILDO(itlbna_t)
606LDILDO(dtlb_t)
607LDILDO(dtlbna_t)
608LDILDO(tlbd_t)
609#endif
610
611#if defined(HP7100LC_CPU) || defined(HP7300LC_CPU)
612LDILDO(itlb_l)
613LDILDO(itlbna_l)
614LDILDO(dtlb_l)
615LDILDO(dtlbna_l)
616LDILDO(tlbd_l)
617#endif
618
619#if defined(HP8000_CPU) || defined(HP8200_CPU) || \
620    defined(HP8500_CPU) || defined(HP8600_CPU) || \
621    defined(HP8700_CPU)
622LDILDO(itlb_u)
623LDILDO(itlbna_u)
624LDILDO(dtlb_u)
625LDILDO(dtlbna_u)
626LDILDO(tlbd_u)
627#endif
628
629#define	ITLBPRE \
630	mfctl	%pcoq,%r9		/* Offset */			! \
631	mfctl	%pcsq,%r8		/* Space  */
632
633#define	DTLBPRE \
634	mfctl	%ior, %r9		/* Offset */			! \
635	mfctl	%isr, %r8		/* Space  */
636
637#define	HPMCPRE	\
638	nop
639
640	.align NBPG
641	.export ivaaddr, entry
642	.export os_hpmc, entry
643ivaaddr:
644	ATRAP(null,T_NONEXIST)		/*  0. invalid interrupt vector */
645os_hpmc:
646	CTRAP(hpmc,T_HPMC,HPMCPRE)	/*  1. high priority machine check */
647	ATRAP(power,T_POWERFAIL)	/*  2. power failure */
648	ATRAP(recnt,T_RECOVERY)		/*  3. recovery counter trap */
649	ATRAP(intr,T_INTERRUPT)		/*  4. external interrupt */
650	ATRAP(lpmc,T_LPMC)		/*  5. low-priority machine check */
651	STRAP(itlb,T_ITLBMISS,ITLBPRE)	/*  6. instruction TLB miss fault */
652	ATRAP(iprot,T_IPROT)		/*  7. instruction protection trap */
653	ATRAP(ill,T_ILLEGAL)		/*  8. Illegal instruction trap */
654	CTRAP(ibrk,T_IBREAK,)		/*  9. break instruction trap */
655	ATRAP(privop,T_PRIV_OP)		/* 10. privileged operation trap */
656	ATRAP(privr,T_PRIV_REG)		/* 11. privileged register trap */
657	ATRAP(ovrfl,T_OVERFLOW)		/* 12. overflow trap */
658	ATRAP(cond,T_CONDITION)		/* 13. conditional trap */
659	ATRAP(excpt,T_EXCEPTION)	/* 14. assist exception trap */
660	STRAP(dtlb,T_DTLBMISS,DTLBPRE)	/* 15. data TLB miss fault */
661	STRAP(itlbna,T_ITLBMISSNA,DTLBPRE)/* 16. ITLB non-access miss fault */
662	STRAP(dtlbna,T_DTLBMISSNA,DTLBPRE)/* 17. DTLB non-access miss fault */
663	ATRAP(dprot,T_DPROT)		/* 18. data protection trap
664					       unaligned data reference trap */
665	ATRAP(dbrk,T_DBREAK)		/* 19. data break trap */
666	STRAP(tlbd,T_TLB_DIRTY,DTLBPRE)	/* 20. TLB dirty bit trap */
667	ATRAP(pgref,T_PAGEREF)		/* 21. page reference trap */
668	CTRAP(emu,T_EMULATION,)		/* 22. assist emulation trap */
669	ATRAP(hpl,T_HIGHERPL)		/* 23. higher-privilege transfer trap*/
670	ATRAP(lpl,T_LOWERPL)		/* 24. lower-privilege transfer trap */
671	ATRAP(tknbr,T_TAKENBR)		/* 25. taken branch trap */
672	ATRAP(dacc,T_DATACC)		/* 26. data access rights trap */
673	ATRAP(dpid,T_DATAPID)		/* 27. data protection ID trap */
674	ATRAP(dalgn,T_DATALIGN)		/* 28. unaligned data ref trap */
675	ATRAP(unk,29)
676	ATRAP(unk,30)
677	ATRAP(unk,31)
678	ATRAP(unk,32)
679	ATRAP(unk,33)
680	ATRAP(unk,34)
681	ATRAP(unk,35)
682	ATRAP(unk,36)
683	ATRAP(unk,37)
684	ATRAP(unk,38)
685	ATRAP(unk,39)
686	ATRAP(unk,40)
687	ATRAP(unk,41)
688	ATRAP(unk,42)
689	ATRAP(unk,43)
690	ATRAP(unk,44)
691	ATRAP(unk,45)
692	ATRAP(unk,46)
693	ATRAP(unk,47)
694	ATRAP(unk,48)
695	ATRAP(unk,49)
696	ATRAP(unk,50)
697	ATRAP(unk,51)
698	ATRAP(unk,52)
699	ATRAP(unk,53)
700	ATRAP(unk,54)
701	ATRAP(unk,55)
702	ATRAP(unk,56)
703	ATRAP(unk,57)
704	ATRAP(unk,58)
705	ATRAP(unk,59)
706	ATRAP(unk,60)
707	ATRAP(unk,61)
708	ATRAP(unk,62)
709	ATRAP(unk,63)
710					/* 64 */
711	.size	ivaaddr, .-ivaaddr
712
713/*
714 * This is the locore support for HPMC and TOC machine checks.  In the HPMC
715 * case, this is a continuation of the HPMC handler that begins in the interrupt
716 * vector table.  In the TOC case, this is the handler installed in page zero.
717 *
718 * Notable points about the CPU state for the OS_TOC handler:
719 *
720 * - The PSW Q bit is 1, all other PSW bits are 0.
721 * - CR14 (IVA) does not point to our vector table.
722 * - CR22 (IPSW) is valid.
723 * - All other control registers HVERSION dependent.
724 * - The TLB is initialized and invalid.
725 *
726 * Notable points about the CPU state for the OS_HPMC handler:
727 *
728 * - The PSW M bit is 1, all other PSW bits are 0.
729 * - CR14 (IVA) does point to our vector table.
730 * - CR22 (IPSW) is valid.
731 * - All other control registers HVERSION dependent.
732 * - The TLB is unchanged.
733 *
734 * The TOC CPU state is actually trickier.  Whereas in the HPMC case, we can
735 * return to virtual mode right away, in the TOC case we can't return to virtual
736 * mode until the kernel mapping is reloaded into the BTLB.
737 *
738 * Otherwise, we set up the kernel context, move onto the emergency stack, and
739 * call hppa_machine_check.
740 */
741ENTRY_NOPROFILE(os_toc, 0)
742	/* This loads %arg0 and nullifies the next instruction. */
743	addi,tr	T_INTERRUPT, %r0, %arg0
744EXIT(os_toc)
745ENTRY_NOPROFILE(TLABEL(hpmc),0)
746ALTENTRY(os_hpmc_cont)
747	ldi	T_HPMC, %arg0
748
749	/* Disable interrupts. */
750	mtctl	%r0, %eiem
751
752	/* Load protection and space registers for the kernel. */
753	ldi	HPPA_PID_KERNEL, %r1
754	mtctl	%r1, %pidr1
755	ldi	HPPA_SID_KERNEL, %r1
756	mtsp	%r1, %sr0
757	mtsp	%r1, %sr1
758	mtsp	%r1, %sr2
759	mtsp	%r1, %sr3
760	mtsp	%r1, %sr4
761	mtsp	%r1, %sr5
762	mtsp	%r1, %sr6
763	mtsp	%r1, %sr7
764
765	/* Reload the Interruption Vector Address. */
766	ldil	L%ivaaddr, %r1
767	ldo	R%ivaaddr(%r1), %r1
768	mtctl	%r1, %iva
769
770	/* Reload the HPT base and mask. */
771	ldil	L%hppa_vtop, %r1
772	ldw	R%hppa_vtop(%r1), %r1
773	mtctl	%r1, CR_VTOP
774
775	/* Disable interrupts for the long haul. */
776	GET_CURCPU(%t1)
777	ldw	CI_PSW(%t1), %r1
778	depi	0, PSW_I_POS, 1, %r1
779	stw	%r1, CI_PSW(%t1)
780
781	/* Reload the global data pointer. */
782	ldil	L%$global$, %dp
783	ldo	R%$global$(%dp), %dp
784
785	/* Move onto the emergency stack. */
786	ldil	L%emergency_stack_start, %sp
787	ldo	R%emergency_stack_start(%sp), %sp
788	stwm	%r0, HPPA_FRAME_SIZE(%sp)
789	copy	%sp, %r3
790
791	/* Start stack calling convention. */
792	stw	%r0, HPPA_FRAME_CRP(%sp)
793	stw	%r0, HPPA_FRAME_PSP(%sp)
794	copy	%r3, %r1
795	copy	%sp, %r3
796	stwm	%r1, HPPA_FRAME_SIZE(%sp)
797
798	/* If this is a TOC, remap the kernel. */
799	comib,<>,n T_INTERRUPT, %arg0, L$check_do_rfi
800
801	/* Clear kernelmapped. */
802	ldil	L%kernelmapped, %r1
803	stw	%r0, R%kernelmapped(%r1)
804
805	/* Call hppa_btlb_reload. */
806	ldil	L%hppa_btlb_reload, %r1
807	ldo	R%hppa_btlb_reload(%r1), %r1
808	blr	0, %rp
809	bv	%r0(%r1)
810	nop
811
812	/* Set kernelmapped. */
813	ldil	L%kernelmapped, %r1
814	stw	%r1, R%kernelmapped(%r1)
815
816	/* Reload %arg0 (it may have been destroyed). */
817	ldi	T_INTERRUPT, %arg0
818
819	/* Disable the interrupt queues. */
820	rsm	RESET_PSW, %r0
821
822L$check_do_rfi:
823
824	/* Load IPSW. */
825	GET_CURCPU(%r1)
826	ldw	CI_PSW(%r1), %r1
827	mtctl	%r1, %ipsw
828
829	/* Get the address of hppa_machine_check. */
830	ldil	L%hppa_machine_check, %r1
831	ldo	R%hppa_machine_check(%r1), %r1
832
833	/* Load the instruction address queues. */
834	mtctl	%r1, %pcoq
835	ldo	4(%r1), %r1
836	mtctl	%r1, %pcoq
837	ldi	HPPA_SID_KERNEL, %r1
838	mtctl	%r1, %pcsq
839	mtctl	%r1, %pcsq
840
841	blr	0, %rp
842	rfi
843	nop
844	nop
845	nop
846	nop
847	nop
848
849ALTENTRY(os_hpmc_checksum)
850	nop
851ALTENTRY(os_hpmc_cont_end)
852ALTENTRY(os_toc_checksum)
853	nop
854ALTENTRY(os_toc_end)
855EXIT(TLABEL(hpmc))
856
857/*
858 * This handles all assist emulation traps.  We break these down into three
859 * categories and dispatch accordingly. The categories are:
860 *
861 *  - emulate special function unit,
862 *  - emulate non-FPU coprocessor, and
863 *  - emulate FPU coprocessor.
864 *
865 */
866	.export TLABEL(emu), entry
867LEAF_ENTRY_NOPROFILE(TLABEL(emu))
868
869	/*
870	 * Save %arg0 and load it with the instruction that caused the emulation
871	 * trap.
872	 */
873	mtctl	%arg0, %tr2
874	mfctl	%iir, %arg0
875
876	/*
877	 * If the opcode field in the instruction is 4, indicating a special
878	 * function unit SPOP instruction, branch to emulate an sfu.  If the
879	 * opcode field is 0xe, then it's an FPU instruction.
880	 */
881	extru	%arg0, 5, 6, %r1
882	comib,=,n 4, %r1, L$emulate_sfu
883	comib,=,n 0xe, %r1, hppa_fpu_emulate
884
885	/*
886	 * If the uid field in the instruction is not zero or one, indicating a
887	 * coprocessor other than an FPU, branch to emulate a non-FPU
888	 * coprocessor.
889	 */
890	extru	%arg0, 25, 3, %r1
891	comib,<<,n 1, %r1, L$emulate_coproc
892
893	/*
894	 * If we're still here, this is a FPU coprocessor instruction.  That we
895	 * trapped to emulate it means one of two things.
896	 *
897	 * If we do have a hardware FPU but it is disabled, we trapped because
898	 * the current process' state is not loaded into the FPU.  We load that
899	 * state in, possibly swapping out another process' state first.
900	 *
901	 * If we do have a hardware FPU and it is enabled, we trapped because of
902	 * an instruction that isn't supported by this FPU, and so we need to
903	 * emulate it.
904	 */
905
906hppa_fpu_emulate:
907
908	/*
909	 * We have a hardware FPU.  If it is enabled, branch to emulate the
910	 * instruction.
911	 */
912	mfctl	CR_CCR, %arg0
913	extru,= %arg0, 25, 2, %r1
914	b,n	L$emulate_fpu
915
916	/*
917	 * The hardware FPU is disabled, so we need to swap in the FPU state of
918	 * the LWP whose uspace physical address in CR_FPPADDR.  We may also
919	 * need to swap out the FPU state of any LWP whose uspace physical
920	 * address is in curcpu()->ci_fpu_state.
921	 */
922
923	/*
924	 * So far, the CTRAP() macro has saved %r1 in %tr7, and the dispatching
925	 * above has saved %arg0 in tr2.  Save the other registers that we want
926	 * to use.  hppa_fpu_swap deliberately uses only these registers and %r1
927	 * and %arg0.
928	 */
929	mtctl	%arg1, %tr4
930	mtctl	%rp, %tr5
931
932	/* Call hppa_fpu_swap. */
933	GET_CURCPU(%arg0)
934	ldw	CI_FPU_STATE(%arg0), %arg0
935	mfctl	CR_FPPADDR, %arg1
936	blr	0, %rp
937	b	hppa_fpu_swap
938	nop
939
940	/* Restore registers and rfi. */
941	mfctl	%tr5, %rp
942	mfctl	%tr4, %arg1
943	mfctl	%tr2, %arg0
944	mfctl	%tr7, %r1
945	rfi
946	nop
947
948	/*
949	 * We branch here to emulate a special function unit instruction.  On
950	 * entry, %r1 is saved in %tr7 (courtesy of CTRAP), and %arg0 is saved
951	 * in %tr2 (courtesy of the sfu/coprocessor dispatcher).
952	 */
953L$emulate_sfu:
954	/*
955	 * Currently we just restore %arg0 and trap with an illegal instruction.
956	 */
957	mfctl	%tr2, %arg0
958	b	TLABEL(all)
959	ldi	T_ILLEGAL, %r1
960
961	/*
962	 * We branch here to emulate a non-FPU coprocessor instruction.  On
963	 * entry, %r1 is saved in %tr7 (courtesy of CTRAP), and %t1 is saved in
964	 * %tr2 (courtesy of the sfu/coprocessor dispatcher).
965	 */
966L$emulate_coproc:
967	/*
968	 * Currently we just restore %arg0 and trap with an illegal instruction.
969	 */
970	mfctl	%tr2, %arg0
971	b	TLABEL(all)
972	ldi	T_ILLEGAL, %r1
973
974	/*
975	 * We branch here to emulate an FPU coprocessor instruction.  On entry,
976	 * %r1 is saved in %tr7 (courtesy of CTRAP), and %t1 is saved in %tr2
977	 * (courtesy of the sfu/coprocessor dispatcher).
978	 */
979L$emulate_fpu:
980	/*
981	 * We get back to C via the normal generic trap mechanism, as opposed to
982	 * switching to a special stack, setting up a trapframe, etc. ourselves,
983	 * for three reasons.
984	 *
985	 * One, I want to turn interrupts back on, since the emulation code
986	 * might not be fast.  Two, because the instruction to emulate might be
987	 * a load or a store, I need to turn address translation back on (i.e.,
988	 * return to virtual mode.)  Third, doing both of those plus setting up
989	 * a trapframe is a pain, and the generic trap handling already does it
990	 * all.
991	 *
992	 * To relieve trap() from having to check for sfu and non-FPU inst-
993	 * ructions again, it assumes that these kinds of instructions have
994	 * already been translated into some other trap type (as they have, by
995	 * the above L$emulate_sfu and L$emulate_coproc), and all
996	 * T_EMULATION | T_USER traps are FPU instructions that need emulating.
997	 *
998	 * So we just restore %arg0 and trap with T_EMULATION.
999	 */
1000	mfctl	%tr2, %arg0
1001	b	TLABEL(all)
1002	ldi	T_EMULATION, %r1
1003EXIT(TLABEL(emu))
1004
1005/*
1006 * void hppa_fpu_swapout(struct pcb *out);
1007 * void hppa_fpu_swap(struct fpreg *out, struct fpreg *in);
1008 */
1009LEAF_ENTRY_NOPROFILE(hppa_fpu_swapout)
1010	ldw	PCB_FPREGS(%arg0), %arg0
1011	copy	%r0, %arg1
1012
1013ALTENTRY(hppa_fpu_swap)
1014
1015	/*
1016	 * Note that this function must work in physical mode as well as virtual
1017	 * mode, because it can be called by a trap handler.  This also further
1018	 * restricts the registers we can use.  We can only use %arg0, %arg1,
1019	 * and %r1.
1020	 */
1021
1022	/*
1023	 * Assuming that out and in aren't both NULL, we will have to run co-
1024	 * processor instructions, so we'd better enable it.
1025	 *
1026	 * Also, branch if there's no FPU state to swap out.
1027	 */
1028	mfctl	CR_CCR, %r1
1029	depi	3, 25, 2, %r1
1030	comb,=	%r0, %arg0, L$fpu_swap_in
1031	mtctl	%r1, CR_CCR
1032
1033	/*
1034	 * Swap out the current FPU state.
1035	 */
1036	fstds,ma %fr0 , 8(%arg0)	/* fr0 must be saved first */
1037	fstds,ma %fr1 , 8(%arg0)
1038	fstds,ma %fr2 , 8(%arg0)
1039	fstds,ma %fr3 , 8(%arg0)
1040	fstds,ma %fr4 , 8(%arg0)
1041	fstds,ma %fr5 , 8(%arg0)
1042	fstds,ma %fr6 , 8(%arg0)
1043	fstds,ma %fr7 , 8(%arg0)
1044	fstds,ma %fr8 , 8(%arg0)
1045	fstds,ma %fr9 , 8(%arg0)
1046	fstds,ma %fr10, 8(%arg0)
1047	fstds,ma %fr11, 8(%arg0)
1048	fstds,ma %fr12, 8(%arg0)
1049	fstds,ma %fr13, 8(%arg0)
1050	fstds,ma %fr14, 8(%arg0)
1051	fstds,ma %fr15, 8(%arg0)
1052	fstds,ma %fr16, 8(%arg0)
1053	fstds,ma %fr17, 8(%arg0)
1054	fstds,ma %fr18, 8(%arg0)
1055	fstds,ma %fr19, 8(%arg0)
1056	fstds,ma %fr20, 8(%arg0)
1057	fstds,ma %fr21, 8(%arg0)
1058	fstds,ma %fr22, 8(%arg0)
1059	fstds,ma %fr23, 8(%arg0)
1060	fstds,ma %fr24, 8(%arg0)
1061	fstds,ma %fr25, 8(%arg0)
1062	fstds,ma %fr26, 8(%arg0)
1063	fstds,ma %fr27, 8(%arg0)
1064	fstds,ma %fr28, 8(%arg0)
1065	fstds,ma %fr29, 8(%arg0)
1066	fstds,ma %fr30, 8(%arg0)
1067	fstds    %fr31, 0(%arg0)
1068
1069L$fpu_swap_in:
1070
1071	/*
1072	 * Stash the incoming user structure in curcpu->ci_fpu_state.  Because
1073	 * this variable holds a physical address, this means that hppa_fpu_swap
1074	 * can only be called with a non-zero user_in from physical mode (i.e.,
1075	 * from the emulation assist trap handler).  And that's exactly what
1076	 * happens now.
1077	 *
1078	 * So stash ci->ci_fpu_state, branching past the swap-in code if it is
1079	 * zero.
1080	 */
1081	GET_CURCPU(%r1)
1082	comb,=	%r0, %arg1, L$fpu_no_swap_in
1083	stw	%arg1, CI_FPU_STATE(%r1)
1084
1085	/*
1086	 * Swap in the new FPU state.
1087	 */
1088	ldo	31*8(%arg1), %arg1
1089	fldds,ma -8(%arg1), %fr31
1090	fldds,ma -8(%arg1), %fr30
1091	fldds,ma -8(%arg1), %fr29
1092	fldds,ma -8(%arg1), %fr28
1093	fldds,ma -8(%arg1), %fr27
1094	fldds,ma -8(%arg1), %fr26
1095	fldds,ma -8(%arg1), %fr25
1096	fldds,ma -8(%arg1), %fr24
1097	fldds,ma -8(%arg1), %fr23
1098	fldds,ma -8(%arg1), %fr22
1099	fldds,ma -8(%arg1), %fr21
1100	fldds,ma -8(%arg1), %fr20
1101	fldds,ma -8(%arg1), %fr19
1102	fldds,ma -8(%arg1), %fr18
1103	fldds,ma -8(%arg1), %fr17
1104	fldds,ma -8(%arg1), %fr16
1105	fldds,ma -8(%arg1), %fr15
1106	fldds,ma -8(%arg1), %fr14
1107	fldds,ma -8(%arg1), %fr13
1108	fldds,ma -8(%arg1), %fr12
1109	fldds,ma -8(%arg1), %fr11
1110	fldds,ma -8(%arg1), %fr10
1111	fldds,ma -8(%arg1), %fr9
1112	fldds,ma -8(%arg1), %fr8
1113	fldds,ma -8(%arg1), %fr7
1114	fldds,ma -8(%arg1), %fr6
1115	fldds,ma -8(%arg1), %fr5
1116	fldds,ma -8(%arg1), %fr4
1117	fldds,ma -8(%arg1), %fr3
1118	fldds,ma -8(%arg1), %fr2
1119	fldds,ma -8(%arg1), %fr1
1120	fldds     0(%arg1), %fr0	/* fr0 must be restored last */
1121
1122L$fpu_swap_done:
1123
1124	/* Increment the switch count and return. */
1125	ldil	L%fpu_csw, %r1
1126	ldw	R%fpu_csw(%r1), %arg0
1127	ldo	1(%arg0), %arg0
1128	bv	%r0(%rp)
1129	stw	%arg0, R%fpu_csw(%r1)
1130
1131L$fpu_no_swap_in:
1132
1133	/* We didn't swap any FPU state in, so disable the FPU. */
1134	mfctl	CR_CCR, %r1
1135	depi	0, 25, 2, %r1
1136	b	L$fpu_swap_done
1137	mtctl	%r1, CR_CCR
1138EXIT(hppa_fpu_swapout)
1139
1140	/* Construct the virtual address tag. */
1141	/* NB: it is legal for off and t to be the same. */
1142#define VTAG(sp,off,t) \
1143	shd	%r0, off, 1, t		/* t[1..15] = off[0..14] */	! \
1144	dep	sp, 31, 16, t		/* put in the space id */	! \
1145	depi	1, 0, 1, t		/* and set the valid bit */
1146
1147#if 0
1148	BSS(dtlb_c, 8)
1149	BSS(tlbd_c, 8)
1150	BSS(itlb_c, 8)
1151
1152	/* XXX this touches tr5, which it should not, perhaps */
1153#define	TLB_STATS_PRE(t) \
1154	mfctl	CR_ITMR, %r17			! \
1155	mtctl	%r17, %tr5
1156
1157#define	TLB_STATS_AFT(t) \
1158	mfctl	CR_ITMR, %r16			! \
1159	mfctl	%tr5, %r17			! \
1160	ldil	L%__CONCAT(t,_c), %r25		! \
1161	ldo	R%__CONCAT(t,_c)(%r25), %r25	! \
1162	sub	%r16, %r17, %r16		! \
1163	ldw	0(%r25), %r24			! \
1164	ldw	4(%r25), %r17			! \
1165	ldo	1(%r24), %r24			! \
1166	ldo	-2(%r16), %r16 /* for mtctl */	! \
1167	add	%r16, %r17, %r17		! \
1168	stw	%r24, 0(%r25)			! \
1169	stw	%r17, 4(%r25)
1170
1171#else
1172#define	TLB_STATS_PRE(t)	/**/
1173#define	TLB_STATS_AFT(t)	/**/
1174#endif
1175
1176#define	TLB_PULL(bits,lbl)						! \
1177	/* space:pgaddr -- %r8:%r9 */					! \
1178	mfctl	CR_VTOP, %r16						! \
1179	ldwax,s	%r8(%r16), %r17		/* space -> page directory */	! \
1180	extru	%r9, 9, 10, %r25	/* r25 = r9[31..22] */		! \
1181	combt,=,n %r0, %r17, lbl					! \
1182	ldwax,s	%r25(%r17), %r24	/* page -> page table */	! \
1183	extru	%r9, 19, 10, %r16	/* r16 = r9[22..12] */		! \
1184	combt,=,n %r0, %r24, lbl					! \
1185	ldwax,s	%r16(%r24), %r17	/* va -> pa:prot */		! \
1186	sh2addl	%r16, %r24, %r25	/* r25 = r16 << 2 + r24 */	! \
1187	combt,=,n %r0, %r17, lbl					! \
1188	copy	%r17, %r16						! \
1189	depi	(bits), 21+bits, 1+bits, %r17				! \
1190	sub,=	%r16, %r17, %r0		/* do not store if unchanged */	! \
1191	stwas	%r17, 0(%r25)		/* store back w/ the bits */	! \
1192	shd	%r17, %r0, 13, %r25					! \
1193	dep	%r8, 30, 15, %r25	/* mix0r the pid from the sid */! \
1194	dep	%r0, 31, 12, %r17	/* needed ? */			! \
1195	addi	2, %r25, %r25						! \
1196	extru	%r17, 24, 25, %r17
1197
1198/*
1199 * possible optimizations:
1200 *	change pte to reduce number of shifts
1201 *	reorder to reduce stalls
1202 */
1203#define	TLB_PULL_L(bits,lbl)						! \
1204	/* space:pgaddr -- %r8:%r9 */					! \
1205	mfctl	CR_VTOP, %r16						! \
1206	ldwx,s	%r8(%r16), %r17		/* space -> page directory */	! \
1207	extru	%r9, 9, 10, %r25					! \
1208	combt,=,n %r0, %r17, lbl					! \
1209	ldwx,s	%r25(%r17), %r24	/* page -> page table */	! \
1210	extru	%r9, 19, 10, %r16					! \
1211	combt,=,n %r0, %r24, lbl					! \
1212	ldwx,s	%r16(%r24), %r17	/* va -> pa:prot */		! \
1213	sh2addl	%r16, %r24, %r25					! \
1214	combt,=,n %r0, %r17, lbl					! \
1215	copy	%r17, %r16						! \
1216	depi	(bits), 21+bits, 1+bits, %r17				! \
1217	sub,=	%r16, %r17, %r0		/* do not store if unchanged */	! \
1218	stws	%r17, 0(%r25)		/* store back w/ the bits */	! \
1219	shd	%r17, %r0, 13, %r25					! \
1220	dep	%r8, 30, 15, %r25	/* mix0r the pid from the sid */! \
1221	dep	%r0, 31, 12, %r17	/* needed ? */			! \
1222	addi	2, %r25, %r25						! \
1223	extru	%r17, 24, 25, %r17	/* tlbbtop(%r17) */		! \
1224	sync
1225
1226#if defined(HP7000_CPU) || defined(HP7100_CPU) || defined(HP7200_CPU)
1227
1228	.align	32
1229
1230/*
1231 * This is a handler for interruption 20, "TLB dirty bit trap".  It is used on
1232 * the PA7000 (PCX), PA7000 (PCX-S), and PA7100 (PCX-T).
1233 * Only shadowed registers are available, and they are:
1234 *
1235 * %r1 = C trap number
1236 * %r8 = data address space identifier.  Copied from %isr.
1237 * %r9 = data address offset.  Copied from %ior.
1238 * %r16 = undefined
1239 * %r17 = undefined
1240 * %r24 = undefined
1241 * %r25 = undefined
1242 */
1243LEAF_ENTRY_NOPROFILE(TLABEL(tlbd_s))
1244ALTENTRY(TLABEL(tlbd_t))
1245ALTENTRY(TLABEL(tlbd_x))
1246	TLB_STATS_PRE(tlbd)
1247	TLB_PULL(1, TLABEL(all))
1248	mfsp	%sr1, %r16
1249	mtsp	%r8, %sr1
1250	idtlba	%r17,(%sr1, %r9)
1251	idtlbp	%r25,(%sr1, %r9)
1252	mtsp	%r16, %sr1
1253	TLB_STATS_AFT(tlbd)
1254	rfir
1255	nop
1256EXIT(TLABEL(tlbd_s))
1257
1258/*
1259 * This is a handler for interruption 6, "Instruction TLB miss fault". It is
1260 * used on the PA7000 (PCX), PA7000 (PCX-S), PA7100 (PCX-T) and PA7200 (PCX-T')
1261 * Only shadowed registers are available, and they are:
1262 *
1263 * %r1 = C trap number
1264 * %r8 = instruction address space identifier. Copied from %pcsq.
1265 * %r9 = instruction address offset. Copied from %pcoq.
1266 * %r16 = undefined
1267 * %r17 = undefined
1268 * %r24 = undefined
1269 * %r25 = undefined
1270 */
1271LEAF_ENTRY_NOPROFILE(TLABEL(itlb_s))
1272ALTENTRY(TLABEL(itlb_t))
1273ALTENTRY(TLABEL(itlb_x))
1274	TLB_STATS_PRE(itlb)
1275	TLB_PULL(0, TLABEL(all))
1276	extru,=	%r25, 5, 1, %r0	/* gate needs a kernel pid */
1277	depi	0, 30, 15, %r25
1278	mfsp	%sr1, %r16
1279	mtsp	%r8, %sr1
1280	iitlba	%r17,(%sr1, %r9)
1281	iitlbp	%r25,(%sr1, %r9)
1282	mtsp	%r16, %sr1
1283	TLB_STATS_AFT(itlb)
1284	rfir
1285	nop
1286EXIT(TLABEL(itlb_s))
1287
1288/*
1289 * This is a handler for interruption 15, "Data TLB miss fault".  It is used on
1290 * the PA7000 (PCX), PA7000 (PCX-S), PA7100 (PCX-T) and PA7200 (PCX-T').
1291 * Only shadowed registers are available, and they are:
1292 *
1293 * %r1 = C trap number
1294 * %r8 = data address space identifier.  Copied from %isr.
1295 * %r9 = data address offset.  Copied from %ior.
1296 * %r16 = undefined
1297 * %r17 = undefined
1298 * %r24 = undefined
1299 * %r25 = undefined
1300 */
1301LEAF_ENTRY_NOPROFILE(TLABEL(dtlb_s))
1302ALTENTRY(TLABEL(dtlb_t))
1303ALTENTRY(TLABEL(dtlb_x))
1304	TLB_STATS_PRE(dtlb)
1305	TLB_PULL(0, TLABEL(all))
1306	mfsp	%sr1, %r16
1307	mtsp	%r8, %sr1
1308	idtlba	%r17,(%sr1, %r9)
1309	idtlbp	%r25,(%sr1, %r9)
1310	mtsp	%r16, %sr1
1311	TLB_STATS_AFT(dtlb)
1312	rfir
1313	nop
1314EXIT(TLABEL(dtlb_s))
1315
1316/*
1317 * This is a handler for interruption 16, "Non-access instruction TLB miss
1318 * fault", and interrupt 17, "Non-access data TLB miss fault / Non-access data
1319 * page fault".  It is used on the PA7000 (PCX), PA7000 (PCX-S), PA7100 (PCX-T)
1320 * and PA7200 (PCX-T').
1321 *
1322 * Only shadowed registers are available, and they are:
1323 *
1324 * %r1 = C trap number
1325 * %r8 = instruction address space identifier.  Copied from %isr.
1326 * %r9 = instruction address offset.  Copied from %ior.
1327 * %r16 = undefined
1328 * %r17 = undefined
1329 * %r24 = undefined
1330 * %r25 = undefined
1331 */
1332LEAF_ENTRY_NOPROFILE(TLABEL(dtlbna_s))
1333ALTENTRY(TLABEL(itlbna_s))
1334ALTENTRY(TLABEL(dtlbna_t))
1335ALTENTRY(TLABEL(itlbna_t))
1336ALTENTRY(TLABEL(dtlbna_x))
1337ALTENTRY(TLABEL(itlbna_x))
1338	TLB_STATS_PRE(dtlb)
1339	TLB_PULL(0, L$dtlbna_t_fake)
1340	mfsp	%sr1, %r16
1341	mtsp	%r8, %sr1
1342	idtlba	%r17,(%sr1, %r9)
1343	idtlbp	%r25,(%sr1, %r9)
1344	mtsp	%r16, %sr1
1345	TLB_STATS_AFT(dtlb)
1346	rfir
1347	nop
1348L$dtlbna_s_fake:
1349L$dtlbna_t_fake:
1350	/* parse prober/w insns, have to decent to trap() to set regs proper */
1351	mfctl	%iir, %r16
1352	extru	%r16, 6, 6, %r24
1353	comib,=,n 1, %r24, TLABEL(all)
1354	extru	%r16, 24, 6, %r24
1355	subi,<>	0x23, %r24, %r0
1356	b	TLABEL(all)
1357	/* otherwise generate a flush-only tlb entry */
1358	copy	%r0, %r17
1359	zdep	%r8, 30, 15, %r25
1360	depi	-13, 11, 7, %r25
1361	ldo	2(%r25), %r25   /* 3? */
1362	mfsp	%sr1, %r16
1363	mtsp	%r8, %sr1
1364	idtlba	%r17,(%sr1, %r9)
1365	idtlbp	%r25,(%sr1, %r9)
1366	mtsp	%r16, %sr1
1367	TLB_STATS_AFT(dtlb)
1368	rfir
1369	nop
1370EXIT(TLABEL(dtlbna_s))
1371
1372#endif /* defined(HP7000_CPU) || defined(HP7100_CPU) || defined(HP7200_CPU) */
1373
1374
1375#if defined(HP7100LC_CPU) || defined(HP7300LC_CPU)
1376
1377#define	IITLBAF(r)	.word	0x04000440 | ((r) << 16)
1378#define	IITLBPF(r)	.word	0x04000400 | ((r) << 16)
1379#define	IDTLBAF(r)	.word	0x04001440 | ((r) << 16)
1380#define	IDTLBPF(r)	.word	0x04001400 | ((r) << 16)
1381
1382	.align	32
1383
1384/*
1385 * This is a handler for interruption 20, "TLB dirty bit trap".  It is used on
1386 * the PA7100LC (PCX-L), PA7300LC (PCX-L2).
1387 * Only shadowed registers are available, and they are:
1388 *
1389 * %r1 = C trap number
1390 * %r8 = data address space identifier.  Copied from %ior.
1391 * %r9 = data address offset.  Copied from %isr.
1392 * %r16 = undefined
1393 * %r17 = undefined
1394 * %r24 = undefined
1395 * %r25 = undefined
1396 */
1397
1398LEAF_ENTRY_NOPROFILE(TLABEL(tlbd_l))
1399	TLB_STATS_PRE(tlbd)
1400	TLB_PULL_L(1, TLABEL(all))
1401	IDTLBAF(17)
1402	IDTLBPF(25)
1403#ifdef USE_HPT
1404	/* invalidate instead of update */
1405	mfctl	%cr28, %r17
1406	ldw	0(%r17), %r24
1407	VTAG(%r8, %r9, %r16)
1408	sub,<>	%r16, %r24, %r0
1409	stw	%r0, 0(%r17)
1410#endif
1411	TLB_STATS_AFT(tlbd)
1412	rfir
1413	nop
1414EXIT(TLABEL(tlbd_l))
1415
1416/*
1417 * This is a handler for interruption 6, "Instruction TLB miss fault".  It is
1418 * used on the PA7100LC (PCX-L), PA7300LC (PCX-L2).
1419 * Only shadowed registers are available, and they are:
1420 *
1421 * %r1 = C trap number
1422 * %r8 = instruction address space identifier.  Copied from %pcsq.
1423 * %r9 = instruction address offset.  Copied from %pcoq.
1424 * %r16 = undefined
1425 * %r17 = undefined
1426 * %r24 = undefined
1427 * %r25 = undefined
1428 */
1429
1430/*
1431 * from 7100lc ers, pg.6:
1432 * we found a post-silicon bug that makes cr28
1433 * unreliable for the itlb miss handler
1434 */
1435LEAF_ENTRY_NOPROFILE(TLABEL(itlb_l))
1436	TLB_STATS_PRE(itlb)
1437	TLB_PULL_L(0, TLABEL(all))
1438	extru,=	%r25, 5, 1, %r0	/* gate needs a kernel pid */
1439	depi	0, 30, 15, %r25
1440	IITLBAF(17)
1441	IITLBPF(25)
1442	TLB_STATS_AFT(itlb)
1443	rfir
1444	nop
1445EXIT(TLABEL(itlb_l))
1446
1447/*
1448 * This is a handler for interruption 16, "Non-access instruction TLB miss
1449 * fault", and interrupt 17, "Non-access data TLB miss fault / Non-access data
1450 * page fault".  It is used on the PA7100LC (PCX-L), PA7300LC (PCX-L2).
1451 * Only shadowed registers are available, and they are:
1452 *
1453 * %r1 = C trap number
1454 * %r8 = instruction address space identifier.  Copied from %isr.
1455 * %r9 = instruction address offset.  Copied from %ior.
1456 * %r16 = undefined
1457 * %r17 = undefined
1458 * %r24 = undefined
1459 * %r25 = undefined
1460 */
1461LEAF_ENTRY_NOPROFILE(TLABEL(dtlbna_l))
1462ALTENTRY(TLABEL(itlbna_l))
1463	TLB_STATS_PRE(dtlb)
1464	TLB_PULL_L(0, L$dtlbna_l_fake)
1465	IDTLBAF(17)
1466	IDTLBPF(25)
1467	TLB_STATS_AFT(dtlb)
1468	rfir
1469	nop
1470L$dtlbna_l_fake:
1471	/* parse prober/w insns, have to decent to trap() to set regs proper */
1472	mfctl	%iir, %r16
1473	extru	%r16, 6, 6, %r24
1474	comib,=,n 1, %r24, TLABEL(all)
1475	extru	%r16, 24, 6, %r24
1476	subi,<>	0x23, %r24, %r0
1477	b	TLABEL(all)
1478	/* otherwise generate a flush-only tlb entry */
1479	copy	%r0, %r17
1480	zdep	%r8, 30, 15, %r25
1481	depi	-13, 11, 7, %r25
1482	ldo	2(%r25), %r25   /* 3? */
1483	IDTLBAF(17)
1484	IDTLBPF(25)
1485	TLB_STATS_AFT(dtlb)
1486	rfir
1487	nop
1488EXIT(TLABEL(dtlbna_l))
1489
1490/*
1491 * This is a handler for interruption 15, "Data TLB miss fault".  It is used on
1492 * the PA7100LC (PCX-L), PA7300LC (PCX-L2).
1493 * Only shadowed registers are available, and they are:
1494 *
1495 * %r1 = C trap number
1496 * %r8 = instruction address space identifier.  Copied from %isr.
1497 * %r9 = instruction address offset.  Copied from %ior.
1498 * %r16 = undefined
1499 * %r17 = undefined
1500 * %r24 = undefined
1501 * %r25 = undefined
1502 */
1503LEAF_ENTRY_NOPROFILE(TLABEL(dtlb_l))
1504	TLB_STATS_PRE(dtlb)
1505	TLB_PULL_L(0, TLABEL(all))
1506	IDTLBAF(17)
1507	IDTLBPF(25)
1508#ifdef USE_HPT
1509	/*
1510	 * cache the next page mapping in the hpt.
1511	 *
1512	 * mapping for a page at the end of each 128k is uncachable
1513	 * in the hvt since it'd be in the tlb itself and thus there
1514	 * is no reason to cache it!
1515	 * as a side effect this avoids recomputing hpt entry and
1516	 * retraversing the whole page table each time.
1517	 */
1518
1519	ldo	PAGE_SIZE(%r9), %r9
1520	extru,<> %r9, 20, 5, %r0
1521	b,n	L$dtlb_done_l	/* skip if no simple advance */
1522	/* do not check the PT overlap since the above
1523	 * check already guaranties that */
1524
1525	/* ripped from TLB_PULL_L(0) */
1526	extru	%r9, 19, 10, %r16		/* %r24 was loaded in the TLB_PULL_L */
1527	ldwx,s	%r16(%r24), %r17		/* va -> pa:prot */
1528	sh2addl	%r16, %r24, %r25
1529	combt,=,n %r0, %r17, L$dtlb_done_l
1530	copy	%r17, %r16
1531	depi	0, 21, 1, %r17
1532	sub,=	%r16, %r17, %r0			/* do not store if unchanged */
1533	stws	%r17, 0(%r25)			/* store back w/ the bits */
1534	shd	%r17, %r0, 13, %r25
1535	dep	%r8, 30, 15, %r25		/* mix0r the pid from the sid */
1536	dep	%r0, 31, 12, %r17		/* needed ? */
1537	addi	2, %r25, %r25
1538	extru	%r17, 24, 25, %r17
1539	sync
1540
1541	mfctl	%cr28, %r24
1542	VTAG(%r8, %r9, %r16)
1543	ldo	16(%r24), %r24
1544	stw	%r16, 0(%r24)
1545	stw	%r25, 4(%r24)
1546	stw	%r17, 8(%r24)
1547L$dtlb_done_l:
1548#endif
1549	TLB_STATS_AFT(dtlb)
1550	rfir
1551	nop
1552EXIT(TLABEL(dtlb_l))
1553#endif /* defined(HP7100LC_CPU) || defined(HP7300LC_CPU) */
1554
1555#if defined(HP8000_CPU) || defined(HP8200_CPU) || \
1556    defined(HP8500_CPU) || defined(HP8600_CPU) || \
1557    defined(HP8700_CPU)
1558
1559	.level	2.0w
1560
1561	/* xlate 32bit->64bit pte */
1562#define	TLB_PCX2PCXU \
1563	extrw,u	%r25, 14, 13, %r16		! \
1564	depdi	0, 31, 32, %r17			! \
1565		/* fix io mappings */		! \
1566	extrd,s	%r17, 42, 4, %r1		! \
1567	addi,<>	1, %r1, %r0			! \
1568	depdi	-1, 38, 32, %r17		! \
1569		/* fix prom mappings */		! \
1570	extrd,s	%r17, 46, 8, %r1		! \
1571	addi,<>	0x10, %r1, %r0			! \
1572	depdi	0, 38, 4, %r17			! \
1573		/* weak ordering, dyn bp */	! \
1574	depwi	1, 31, 2, %r16			! \
1575	depdi	0, 44, 30, %r25			! \
1576	depd	%r16, 14, 15, %r25
1577
1578/*
1579 * This is a handler for interruption 20, "TLB dirty bit trap".  It is used by
1580 * the PA8000 (PCX-U), PA8200 (PCX-W), PA8500 (PCX-W), and PA8600 (PCX-W+).
1581 * Only shadowed registers are available, and they are:
1582 *
1583 * %r1 = C trap number
1584 * %r8 = data address space identifier.  Copied from %isr.
1585 * %r9 = data address offset.  Copied from %ior.
1586 * %r16 = undefined
1587 * %r17 = undefined
1588 * %r24 = undefined
1589 * %r25 = undefined
1590 */
1591LEAF_ENTRY_NOPROFILE(TLABEL(tlbd_u))
1592	TLB_STATS_PRE(tlbd)
1593	TLB_PULL_L(1, TLABEL(all))
1594	TLB_PCX2PCXU
1595	idtlbt	%r17, %r25
1596	TLB_STATS_AFT(tlbd)
1597	rfir
1598	nop
1599EXIT(TLABEL(tlbd_u))
1600
1601/*
1602 * This is a handler for interruption 6, "Instruction TLB miss fault".  It is
1603 * the PA8000 (PCX-U), PA8200 (PCX-W), PA8500 (PCX-W), and PA8600 (PCX-W+).
1604 * Only shadowed registers are available, and they are:
1605 *
1606 * %r1 = C trap number
1607 * %r8 = data address space identifier.  Copied from %isr.
1608 * %r9 = data address offset.  Copied from %ior.
1609 * %r16 = undefined
1610 * %r17 = undefined
1611 * %r24 = undefined
1612 * %r25 = undefined
1613 */
1614LEAF_ENTRY_NOPROFILE(TLABEL(itlb_u))
1615	TLB_STATS_PRE(itlb)
1616	TLB_PULL_L(0, TLABEL(all))
1617	extru,=	%r25, 5, 1, %r0	/* gate needs a kernel pid */
1618	depi	0, 30, 15, %r25
1619	TLB_PCX2PCXU
1620	iitlbt	%r17, %r25
1621	TLB_STATS_AFT(itlb)
1622	rfir
1623	nop
1624EXIT(TLABEL(itlb_u))
1625
1626
1627/*
1628 * This is a handler for interruption 16, "Non-access instruction TLB miss
1629 * fault", and interrupt 17, "Non-access data TLB miss fault / Non-access data
1630 * page fault".  It is the PA8000 (PCX-U), PA8200 (PCX-W), PA8500 (PCX-W),
1631 * and PA8600 (PCX-W+).
1632 * Only shadowed registers are available, and they are:
1633 *
1634 * %r1 = C trap number
1635 * %r8 = instruction address space identifier.  Copied from %isr.
1636 * %r9 = instruction address offset.  Copied from %ior.
1637 * %r16 = undefined
1638 * %r17 = undefined
1639 * %r24 = undefined
1640 * %r25 = undefined
1641 */
1642LEAF_ENTRY_NOPROFILE(TLABEL(dtlbna_u))
1643ALTENTRY(TLABEL(itlbna_u))
1644	TLB_STATS_PRE(dtlb)
1645	TLB_PULL_L(0, L$dtlbna_u_fake)
1646	TLB_PCX2PCXU
1647	idtlbt	%r17, %r25
1648	TLB_STATS_AFT(dtlb)
1649	rfir
1650	nop
1651L$dtlbna_u_fake:
1652	/* parse prober/w insns, have to decent to trap() to set regs proper */
1653	mfctl	%iir, %r16
1654	extru	%r16, 6, 6, %r24
1655	comib,=,n 1, %r24, TLABEL(all)
1656	extru	%r16, 24, 6, %r24
1657	subi,<>	0x23, %r24, %r0
1658	b	TLABEL(all)
1659	/* otherwise generate a flush-only tlb entry */
1660	copy	%r0, %r17
1661	zdep	%r8, 30, 15, %r25
1662	depi	-13, 11, 7, %r25
1663	ldo	2(%r25), %r25   /* 3? */
1664	idtlbt	%r17, %r25
1665	TLB_STATS_AFT(dtlb)
1666	rfir
1667	nop
1668EXIT(TLABEL(dtlbna_u))
1669
1670/*
1671 * This is a handler for interruption 15, "Data TLB miss fault".  It is the
1672 * PA8000 (PCX-U), PA8200 (PCX-W), PA8500 (PCX-W), and PA8600 (PCX-W+).
1673 * Only shadowed registers are available, and they are:
1674 *
1675 * %r1 = C trap number
1676 * %r8 = instruction address space identifier.  Copied from %isr.
1677 * %r9 = instruction address offset.  Copied from %ior.
1678 * %r16 = undefined
1679 * %r17 = undefined
1680 * %r24 = undefined
1681 * %r25 = undefined
1682 */
1683LEAF_ENTRY_NOPROFILE(TLABEL(dtlb_u))
1684	TLB_STATS_PRE(dtlb)
1685	TLB_PULL_L(0, TLABEL(all))
1686	TLB_PCX2PCXU
1687	idtlbt	%r17, %r25
1688	TLB_STATS_AFT(dtlb)
1689	rfir
1690	nop
1691EXIT(TLABEL(dtlb_u))
1692
1693	.level	1.1
1694#endif /* HP8000_CPU */
1695
1696#if defined(HP7000_CPU)
1697/*
1698 * int desidhash_s(void)
1699 * int desidhash_x(void)
1700 */
1701LEAF_ENTRY_NOPROFILE(desidhash_s)
1702ALTENTRY(desidhash_x)
1703	sync
1704	MFCPU_T(DR_CPUCFG,22)	/* %t1 */
1705	MFCPU_T(DR_CPUCFG,22)
1706	nop
1707	nop
1708	depi	0, DR0_PCXS_DHE, 3, %t1	/* 3 4 DR0_PCXS_DOMAIN|DR0_PCXS_IHE */
1709	depi	1, DR0_PCXS_EQWSTO, 1, %t1
1710	depi	0, DR0_PCXS_DHPMC, 1, %t1
1711	depi	0, DR0_PCXS_ILPMC, 1, %t1
1712	sync
1713	MTCPU_T(22,DR_CPUCFG)
1714	MTCPU_T(22,DR_CPUCFG)
1715	nop
1716	nop
1717	bv	0(%rp)
1718	extru	%t1, 4, 5, %ret0	/* return chip revision */
1719EXIT(desidhash_s)
1720#endif /* defined(HP7000_CPU) */
1721
1722#if defined(HP7100_CPU) || defined(HP7200_CPU)
1723/*
1724 * void desidhash_t(void)
1725 */
1726LEAF_ENTRY_NOPROFILE(desidhash_t)
1727	sync
1728	MFCPU_T(DR_CPUCFG,22)	/* %t1 */
1729	MFCPU_T(DR_CPUCFG,22)
1730	nop
1731	nop
1732	depi	0, DR0_PCXT_IHE, 1, %t1
1733	depi	0, DR0_PCXT_DHE, 1, %t1
1734	depi	0, DR0_PCXT_DHPMC, 1, %t1
1735	depi	0, DR0_PCXT_ILPMC, 1, %t1
1736	sync
1737	MTCPU_T(22,DR_CPUCFG)
1738	MTCPU_T(22,DR_CPUCFG)
1739	nop
1740	nop
1741	bv	0(%rp)
1742	extru	%t1, 4, 5, %ret0	/* return chip revision */
1743EXIT(desidhash_t)
1744#endif /* defined(HP7100_CPU) || defined(HP7200_CPU) */
1745
1746#if defined(HP7100LC_CPU) || defined(HP7300LC_CPU)
1747/*
1748 * int
1749 * ibtlb_l(int i, pa_space_t sp, vaddr_t va, paddr_t pa, vsize_t sz,
1750 *     u_int prot)
1751 */
1752LEAF_ENTRY_NOPROFILE(ibtlb_l)
1753	rsm	(PSW_R|PSW_I), %t4
1754	nop ! nop ! nop ! nop ! nop ! nop ! nop	/* XXXNH why? */
1755
1756	bv	0(%rp)
1757	mtsm	%t4
1758EXIT(ibtlb_l)
1759
1760/*
1761 * void
1762 * hpti_l(addr,size)
1763*/
1764LEAF_ENTRY_NOPROFILE(hpti_l)
1765	ldo	-1(%arg1), %arg1
1766	depi	0, 31, 12, %arg1
1767	ldi	0x1c0, %t1		/* cache size assumed 128k XXX */
1768	or	%arg0, %t1, %arg0
1769	sync
1770	MTCPU_C(26,DR0_PCXL2_HTLB_ADDR)
1771	MTCPU_C(25,DR0_PCXL2_HTLB_CFG)
1772	nop
1773	nop
1774	bv,n	%r0(%rp)
1775	nop
1776EXIT(hpti_l)
1777
1778/*
1779 * int
1780 * pbtlb_l(int i)
1781 */
1782LEAF_ENTRY_NOPROFILE(pbtlb_l)
1783	; DR_PAGE0
1784	rsm	(PSW_R|PSW_I), %t4
1785	nop ! nop ! nop ! nop
1786	ldil	L%0xc041, %t1
1787	ldo	R%0xc041(%t1), %t1
1788	dep	%arg0, 30, 3, %t1
1789	sync
1790	MTCPU_T(22,DR_DTLB)	/* t1 */
1791	nop
1792	nop
1793	mtsp	%r0, %sr1
1794	idtlba	%r0,(%sr1,%r0)
1795	idtlbp	%r0,(%sr1,%r0)
1796	zdepi	-1, 18, 1, %t1
1797	nop
1798	sync
1799	MTCPU_T(22,DR_DTLB)
1800	nop
1801	nop
1802	bv	0(%rp)
1803	mtsm	%t4
1804EXIT(pbtlb_l)
1805
1806/*
1807 * int desidhash_l(void)
1808 */
1809LEAF_ENTRY_NOPROFILE(desidhash_l)
1810	MFCPU_C(DR_CPUCFG,22)	/* t1 */
1811	nop
1812	nop
1813	depi	0, DR0_PCXL_L2IHASH_EN, 2, %t1	/* + DR0_PCXL_L2DHASH_EN */
1814	depi	0, DR0_PCXL_L2IHPMC, 1, %t1	/* don't reset */
1815	depi	0, DR0_PCXL_L2DHPMC, 1, %t1	/* don't reset */
1816	depi	0, DR0_PCXL_L1IHPMC, 1, %t1	/* don't reset */
1817	depi	0, DR0_PCXL_L2PARERR,1, %t1	/* don't reset */
1818	sync
1819		/* set DR0_PCXL_L1ICACHE_EN ??? */
1820	MTCPU_C(22,DR_CPUCFG)
1821	nop
1822	nop
1823	bv	0(%rp)
1824	extru	%t1, 4, 5, %ret0	/* return chip revision */
1825EXIT(desidhash_l)
1826
1827#endif /* defined(HP7100LC_CPU) || defined(HP7300LC_CPU) */
1828
1829#if defined(HP8000_CPU) || defined(HP8200_CPU) || \
1830    defined(HP8500_CPU) || defined(HP8600_CPU) || \
1831    defined(HP8700_CPU)
1832
1833	.level	2.0w
1834LEAF_ENTRY_NOPROFILE(desidhash_u)
1835	MFCPU_U(2,28)
1836	depdi	0, 54, 1, %r28
1837	MTCPU_U(28,2)
1838	bv	%r0(%rp)
1839	copy	%r0, %ret0	/* XXX dunno how to get chip rev */
1840EXIT(desidhash_u)
1841
1842LEAF_ENTRY_NOPROFILE(ibtlb_u)
1843	/* TODO insert a locked large tlb entry */
1844	bv	0(%rp)
1845	nop
1846EXIT(ibtlb_u)
1847
1848LEAF_ENTRY_NOPROFILE(pbtlb_u)
1849	/* TODO purge a locked tlb entry */
1850	bv	0(%rp)
1851	nop
1852EXIT(pbtlb_u)
1853	.level	1.1
1854#endif /* HP8000_CPU || HP8200_CPU || HP8500_CPU || HP8600_CPU || HP8700_CPU */
1855
1856	.align	64
1857	.export	TLABEL(all), entry
1858ENTRY_NOPROFILE(TLABEL(all),0)
1859	/*
1860	 * at this point we have:
1861	 *  - psw copied into ipsw
1862	 *  - psw	E(default), M(1 if HPMC, else 0), all others 0, i.e.
1863	 *		interrupts masked, absolute accesses are enabled, etc.
1864	 *  - PL	0 (highest privilege)
1865	 *  - r1, r8, r9, r16, r17, r24, r25 shadowed (maybe)
1866	 *  - r1:	trap number
1867	 *  - tr7:	old r1
1868	 */
1869
1870	mtctl	%t3, %tr2
1871
1872	GET_CURCPU(%t3)
1873
1874	stw	%t1, CI_TRAPSAVE + TF_R22(%t3)	/* use ,bc */
1875	stw	%t2, CI_TRAPSAVE + TF_R21(%t3)
1876
1877	mfctl	%tr2, %t1
1878	stw	%sp, CI_TRAPSAVE + TF_R30(%t3)	/* sp */
1879	stw	%t1, CI_TRAPSAVE + TF_R20(%t3)	/* t3 */
1880
1881	/*
1882	 * Now, save away other volatile state that prevents us from turning
1883	 * the PC queue back on, namely, the pc queue and ipsw, and the
1884	 * interrupt information.
1885	 */
1886
1887	mfctl	%eiem, %t1
1888	mfctl	%ipsw, %t2
1889	stw	%t1, CI_TRAPSAVE + TF_CR15(%t3)	/* use ,bc */
1890	stw	%t2, CI_TRAPSAVE + TF_CR22(%t3)
1891
1892	mfsp	%sr3, %t1
1893	mfctl	%pidr1, %t2
1894	stw	%t1, CI_TRAPSAVE + TF_SR3(%t3)
1895	stw	%t2, CI_TRAPSAVE + TF_CR8(%t3)
1896
1897	/* Setup kernel context */
1898	ldi	HPPA_PID_KERNEL,%t1
1899	mtctl	%t1, %pidr1
1900	mtsp	%r0, %sr3
1901
1902	/* this will enable interrupts after `cold' */
1903	GET_CURCPU(%t1)
1904	ldw	CI_PSW(%t1), %t2
1905	mtctl	%r0, %eiem
1906	mtctl	%t2, %ipsw
1907
1908	/* save interruption instruction address space queue */
1909	mfctl	%pcsq, %t1
1910	mtctl	%r0, %pcsq
1911	mfctl	%pcsq, %t2
1912	stw	%t1, CI_TRAPSAVE + TF_IISQH(%t3)	/* use ,bc */
1913	stw	%t2, CI_TRAPSAVE + TF_IISQT(%t3)
1914	mtctl	%r0, %pcsq
1915
1916	/*
1917	 * Set up the kernel stack pointer.  If the trap happened while we were
1918	 * in unprivileged code, or in privileged code in the SYSCALLGATE page,
1919	 * move to the kernel stack in curlwp's PCB; otherwise, start a new
1920	 * stack frame on whatever kernel stack we're already on.
1921	 *
1922	 * This used to check only for a trap while we were in unprivileged
1923	 * code, but this ignored the possibility that a trap could come in
1924	 * during the period between a gateway instruction to raise privilege
1925	 * and the disabling of interrupts.  During this period we're still on
1926	 * the user's stack, and we must move to the kernel stack.
1927	 */
1928	mfctl	%pcoq, %t1
1929	ldil	L%SYSCALLGATE, %t2		/* t2 = SYSCALLGATE */
1930	ldo	HPPA_FRAME_SIZE-1(%sp), %sp	/* Assumed stack align step 1 */
1931	dep	%t1, 31, PGSHIFT, %t2		/* t2 |= (pcoqh & PAGE_MASK) */
1932	dep,<>	%t1, 31, 2, %r0			/* Nullify if user mode (!0) */
1933	comb,<>	%t1, %t2, L$trap_from_kernel	/* if %t1 != %t2 => kernel */
1934	dep	%r0, 31, 6, %sp			/* Assumed stack align step 2 */
1935
1936	GET_CURLWP(%t2)
1937	depi	1, T_USER_POS, 1, %r1
1938	depi	1, TFF_LAST_POS, 1, %r1
1939	ldw	L_PCB(%t2), %sp
1940#ifdef DIAGNOSTIC
1941	b	L$trap_have_stack
1942#endif
1943	ldo	NBPG(%sp), %sp
1944
1945L$trap_from_kernel:
1946#ifdef DIAGNOSTIC
1947	/*
1948	 * Use the emergency stack if we have taken some kind
1949	 * of TLB or protection fault on the kernel stack.
1950	 */
1951	mtctl	%t1, %tr2
1952	ldw	CI_TRAPSAVE + TF_R30(%t3), %t1
1953	mfctl	%ior, %t2
1954	dep	%r0, 31, PGSHIFT, %t1
1955	dep	%r0, 31, PGSHIFT, %t2
1956	comb,=,n %t1, %t2, 0
1957	ldo	NBPG(%t1), %t1
1958	comb,<>	%t1, %t2, L$trap_have_stack
1959	mfctl	%tr2, %t1
1960	mfctl	%isr, %t2
1961	comib,<>,n HPPA_SID_KERNEL, %t2, L$trap_have_stack
1962#define _CHECK_TRAP_TYPE(tt) ldi tt, %t2 ! comb,= %r1, %t2, L$trap_kstack_fault
1963	_CHECK_TRAP_TYPE(T_ITLBMISS)
1964	_CHECK_TRAP_TYPE(T_DTLBMISS)
1965	_CHECK_TRAP_TYPE(T_ITLBMISSNA)
1966	_CHECK_TRAP_TYPE(T_DTLBMISSNA)
1967	_CHECK_TRAP_TYPE(T_DPROT)
1968	_CHECK_TRAP_TYPE(T_DATACC)
1969	_CHECK_TRAP_TYPE(T_DATAPID)
1970	ldi	T_DATALIGN, %t2
1971	comb,<>,n %r1, %t2, L$trap_have_stack
1972#undef _CHECK_TRAP_TYPE
1973L$trap_kstack_fault:
1974	ldil	L%emergency_stack_start, %sp
1975	ldo	R%emergency_stack_start(%sp), %sp
1976L$trap_have_stack:
1977#endif
1978	ldil	L%trapnowvirt, %t2
1979	ldo	R%trapnowvirt(%t2), %t2
1980	mtctl	%t2, %pcoq
1981	stw	%t1, CI_TRAPSAVE + TF_IIOQH(%t3)
1982	ldo	4(%t2), %t2
1983	mfctl	%pcoq, %t1
1984	stw	%t1, CI_TRAPSAVE + TF_IIOQT(%t3)
1985	mtctl	%t2, %pcoq
1986
1987	/* save the interruption space and offset registers */
1988	mfctl	%isr, %t1
1989	mfctl	%ior, %t2
1990	stw	%t1, CI_TRAPSAVE + TF_CR20(%t3)	/* use ,bc */
1991	stw	%t2, CI_TRAPSAVE + TF_CR21(%t3)
1992
1993	/* save the interruption instruction register */
1994	mfctl	%iir, %t2
1995	stw	%t2, CI_TRAPSAVE + TF_CR19(%t3)
1996
1997	/* save the trap type and flags */
1998	stw	%r1, CI_TRAPSAVE + TF_FLAGS(%t3)
1999
2000	/* gotta get it before R is up */
2001	mfctl	CR_RCTR, %t1
2002
2003	copy	%sp, %t3
2004	ldo	HPPA_FRAME_SIZE+TRAPFRAME_SIZEOF(%sp), %sp
2005
2006#if defined(DDB) || defined(KGDB)
2007	/*
2008	 * Match the offset from %sp for the trapframe with syscall_entry
2009	 */
2010	ldo	HPPA_FRAME_MAXARGS+HPPA_FRAME_SIZE-1(%sp),%sp
2011	depi	0, 31, 6, %sp
2012#endif
2013	rfir
2014	nop ! nop ! nop ! nop ! nop ! nop ! nop ! nop
2015trapnowvirt:
2016	/*
2017	 * %t3 contains the virtual address of the trapframe
2018	 * %sp is loaded w/ the right VA (we did not need it being physical)
2019	 */
2020
2021	mfctl	CR_CCR, %t2
2022	stw	%t1, TF_CR0(%sr3, %t3)
2023	stw	%t2, TF_CR10(%sr3, %t3)
2024
2025	mfsp	%sr0, %t1
2026	mfsp	%sr1, %t2
2027	stw	%t1, TF_SR0(%sr3, %t3)
2028	stw	%t2, TF_SR1(%sr3, %t3)
2029
2030	mfsp	%sr2, %t1
2031	mfsp	%sr4, %t2
2032	stw	%t1, TF_SR2(%sr3, %t3)
2033	stw	%t2, TF_SR4(%sr3, %t3)
2034
2035	mfsp	%sr5, %t2
2036	mfsp	%sr6, %t1
2037	stw	%t2, TF_SR5(%sr3, %t3)
2038	stw	%t1, TF_SR6(%sr3, %t3)
2039
2040	mfsp	%sr7, %t1
2041	mfctl	%pidr2, %t2
2042	stw	%t1, TF_SR7(%sr3, %t3)
2043	stw	%t2, TF_CR9(%sr3, %t3)
2044
2045	mtsp	%r0, %sr0
2046	mtsp	%r0, %sr1
2047	mtsp	%r0, %sr2
2048	mtsp	%r0, %sr4
2049	mtsp	%r0, %sr5
2050	mtsp	%r0, %sr6
2051	mtsp	%r0, %sr7
2052
2053#if pbably_not_worth_it
2054	mfctl	%pidr3, %t1
2055	mfctl	%pidr4, %t2
2056	stw	%t1, TF_CR12(%t3)
2057	stw	%t2, TF_CR13(%t3)
2058#endif
2059
2060	/*
2061	 * Save all general registers that we haven't saved already
2062	 */
2063
2064	/* XXXNH check this!!! */
2065#if defined(DDB) || defined(KGDB)
2066	stw	%rp, HPPA_FRAME_CRP(%sp)
2067	stw	%r0, -HPPA_FRAME_SIZE(%sp)
2068#endif
2069	stw	%t3, -HPPA_FRAME_SIZE+4(%sp)
2070
2071	mfctl	%sar, %t1		/* use ,bc each cache line */
2072	stw	%t1, TF_CR11(%t3)
2073	stw	%r1, TF_R1(%t3)
2074	stw	%r2, TF_R2(%t3)
2075	stw	%r3, TF_R3(%t3)
2076
2077	/*
2078	 * Copy partially saved state from the store into the frame
2079	 */
2080	GET_CURCPU(%t2)
2081	ldo	CI_TRAPSAVE(%t2), %t2
2082
2083	/* use ,bc each line */
2084	ldw  0(%t2), %r1 ! ldw  4(%t2), %t1 ! stw %r1,  0(%t3) ! stw %t1,  4(%t3)
2085	ldw  8(%t2), %r1 ! ldw 12(%t2), %t1 ! stw %r1,  8(%t3) ! stw %t1, 12(%t3)
2086	ldw 16(%t2), %r1 ! ldw 20(%t2), %t1 ! stw %r1, 16(%t3) ! stw %t1, 20(%t3)
2087	ldw 24(%t2), %r1 ! ldw 28(%t2), %t1 ! stw %r1, 24(%t3) ! stw %t1, 28(%t3)
2088	ldw 32(%t2), %r1 ! ldw 36(%t2), %t1 ! stw %r1, 32(%t3) ! stw %t1, 36(%t3)
2089	ldw 40(%t2), %r1 ! ldw 44(%t2), %t1 ! stw %r1, 40(%t3) ! stw %t1, 44(%t3)
2090	ldw 48(%t2), %r1 ! ldw 52(%t2), %t1 ! stw %r1, 48(%t3) ! stw %t1, 52(%t3)
2091	ldw 56(%t2), %r1 ! ldw 60(%t2), %t1 ! stw %r1, 56(%t3) ! stw %t1, 60(%t3)
2092
2093	/*
2094	 * Normally, we'd only have to save and restore the caller-save
2095	 * registers, because the callee-save registers will be saved and
2096	 * restored automatically by our callee(s).
2097	 *
2098	 * However, in two cases we need to save and restore all of the general
2099	 * registers in the trapframe.  One, if we're running a debugger, we
2100	 * want the debugging person to be able to see and change any and all
2101	 * general register values at the trap site.  Two, if we have an FPU
2102	 * emulator, this trap may be to emulate an instruction that needs to
2103	 * read and write any and all general registers (for example, a load
2104	 * or store instruction with a modify completer).
2105	 *
2106	 * See similar #ifdefs in the syscall entry and exit code.
2107	 */
2108	stw	%r4, TF_R4(%t3)
2109	stw	%r5, TF_R5(%t3)
2110	stw	%r6, TF_R6(%t3)
2111	stw	%r7, TF_R7(%t3)
2112	stw	%r8, TF_R8(%t3)
2113	stw	%r9, TF_R9(%t3)
2114	stw	%r10, TF_R10(%t3)
2115	stw	%r11, TF_R11(%t3)
2116	stw	%r12, TF_R12(%t3)
2117	stw	%r13, TF_R13(%t3)
2118	stw	%r14, TF_R14(%t3)
2119	stw	%r15, TF_R15(%t3)
2120	stw	%r16, TF_R16(%t3)
2121	stw	%r17, TF_R17(%t3)
2122	stw	%r18, TF_R18(%t3)
2123
2124	stw	%t4, TF_R19(%t3)
2125	stw	%r23,TF_R23(%t3)
2126	stw	%r24,TF_R24(%t3)
2127	stw	%r25,TF_R25(%t3)
2128	stw	%r26,TF_R26(%t3)
2129	stw	%r27,TF_R27(%t3)
2130	stw	%r28,TF_R28(%t3)
2131	stw	%r29,TF_R29(%t3)
2132	stw	%r31,TF_R31(%t3)
2133
2134	/*
2135	 * Save the necessary control registers that have not already saved.
2136	 */
2137#if defined(DDB) || defined(KGDB)
2138	/*
2139	 * Save v2p translation table pointer
2140	 */
2141	mfctl	%eirr, %t1
2142	mfctl	CR_VTOP, %t2
2143	stw	%t1, TF_CR23(%t3)
2144	stw	%t2, TF_CR25(%t3)
2145
2146	mfctl	%cr24, %t1
2147	mfctl	%cr28, %t2
2148	stw	%t1, TF_CR24(%t3)
2149	stw	%t2, TF_CR28(%t3)
2150
2151#endif
2152	mfctl	CR_TLS, %t1
2153	mfctl	CR_FPPADDR, %t2
2154	stw	%t1, TF_CR27(%t3)
2155	stw	%t2, TF_CR30(%t3)
2156
2157	/*
2158	 * load the global pointer for the kernel
2159	 */
2160
2161	ldil	L%$global$, %dp
2162	ldo	R%$global$(%dp), %dp
2163
2164	/*
2165	 * call the C routine trap().
2166	 * form trap type in the first argument to trap()
2167	 */
2168	ldw	TF_FLAGS(%t3), %arg0
2169	dep	%r0, 24, 25, %arg0
2170	copy	%t3, %arg1
2171
2172#if defined(DDB) || defined(KGDB)
2173	/* Mark frame pointer as NULL to indicate syscall/trap */
2174	copy	%r0, %r3
2175#endif
2176
2177	.import	trap, code
2178	CALL(trap, %t1)
2179
2180	ldw	-HPPA_FRAME_SIZE+4(%sp), %t3
2181	/* see if curlwp has changed */
2182	ldw	TF_FLAGS(%t3), %arg0
2183	bb,>=,n	%arg0, TFF_LAST_POS, L$trap_return
2184	nop
2185
2186	/* load curlwp's trapframe pointer */
2187	GET_CURLWP(%t2)
2188	ldw	L_MD(%t2), %t3
2189
2190L$trap_return:
2191	ldil	L%syscall_return, %t1
2192	ldo	R%syscall_return(%t1), %t1
2193	bv,n	%r0(%t1)
2194	nop
2195
2196EXIT(TLABEL(all))
2197
2198	.align	32
2199ENTRY_NOPROFILE(TLABEL(ibrk),0)
2200	/* If called by a user process then always pass it to trap() */
2201	mfctl	%pcoq, %r8
2202	extru,=	%r8, 31, 2, %r0
2203	b,n	L$ibrk_bad
2204
2205	/* don't accept breaks from data segments */
2206	.import etext
2207	ldil	L%etext, %r9
2208	ldo	R%etext(%r9), %r9
2209	comb,>>=,n %r8, %r9, L$ibrk_bad
2210
2211	mfctl	%iir, %r8
2212	extru	%r8, 31, 5, %r9
2213	comib,<>,n HPPA_BREAK_KERNEL, %r9, L$ibrk_bad
2214
2215	/* now process all those `break' calls we make */
2216	extru	%r8, 18, 13, %r9
2217	comib,=,n HPPA_BREAK_GET_PSW, %r9, L$ibrk_getpsw
2218	comib,=,n HPPA_BREAK_SET_PSW, %r9, L$ibrk_setpsw
2219
2220L$ibrk_bad:
2221	/* illegal (unimplemented) break entry point */
2222	b	TLABEL(all)
2223	nop
2224
2225L$ibrk_getpsw:
2226	b	L$ibrk_exit
2227	mfctl	%ipsw, %ret0
2228
2229L$ibrk_setpsw:
2230	mfctl	%ipsw, %ret0
2231	b	L$ibrk_exit
2232	mtctl	%arg0, %ipsw
2233
2234	/* insert other fast breaks here */
2235	nop ! nop
2236
2237L$ibrk_exit:
2238	/* skip the break */
2239	mtctl	%r0, %pcoq
2240	mfctl	%pcoq, %r9
2241	mtctl	%r9, %pcoq
2242	ldo	4(%r9), %r9
2243	mtctl	%r9, %pcoq
2244	rfir
2245	nop
2246EXIT(TLABEL(ibrk))
2247