1/*	$OpenBSD: locore.S,v 1.207 2023/12/12 07:37:20 deraadt Exp $	*/
2
3/*
4 * Copyright (c) 1998-2004 Michael Shalayeff
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26 * THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Portitions of this file are derived from other sources, see
29 * the copyrights and acknowledgements below.
30 */
31/*
32 *  (c) Copyright 1988 HEWLETT-PACKARD COMPANY
33 *
34 *  To anyone who acknowledges that this file is provided "AS IS"
35 *  without any express or implied warranty:
36 *      permission to use, copy, modify, and distribute this file
37 *  for any purpose is hereby granted without fee, provided that
38 *  the above copyright notice and this notice appears in all
39 *  copies, and that the name of Hewlett-Packard Company not be
40 *  used in advertising or publicity pertaining to distribution
41 *  of the software without specific, written prior permission.
42 *  Hewlett-Packard Company makes no representations about the
43 *  suitability of this software for any purpose.
44 */
45/*
46 * Copyright (c) 1990,1991,1992,1994 The University of Utah and
47 * the Computer Systems Laboratory (CSL).  All rights reserved.
48 *
49 * Permission to use, copy, modify and distribute this software is hereby
50 * granted provided that (1) source code retains these copyright, permission,
51 * and disclaimer notices, and (2) redistributions including binaries
52 * reproduce the notices in supporting documentation, and (3) all advertising
53 * materials mentioning features or use of this software display the following
54 * acknowledgement: ``This product includes software developed by the
55 * Computer Systems Laboratory at the University of Utah.''
56 *
57 * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
58 * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
59 * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
60 *
61 * CSL requests users of this software to return to csl-dist@cs.utah.edu any
62 * improvements that they make and grant CSL redistribution rights.
63 *
64 *	Utah $Hdr: locore.s 1.63 95/01/20$
65 */
66
67#include <sys/reboot.h>
68#include <machine/param.h>
69#include <machine/asm.h>
70#include <machine/psl.h>
71#include <machine/trap.h>
72#include <machine/iomod.h>
73#include <machine/pdc.h>
74#include <machine/frame.h>
75#include <machine/reg.h>
76#include "assym.h"
77
78/*
79 * hw-specific instructions
80 */
81
82/* source: mklinux cache.s */
83#define	MFCPU_C_PCXST(r,x)	.word	0x14001a00 | ((r) << 21) | ((x) << 16)
84#define	MTCPU_PCXST(x,r)	.word	0x14001600 | ((r) << 21) | ((x) << 16)
85
86/* source: PCXL and PCXL2 ERS */
87/* Use MFCPU_C for DR0-8; MFCPU_T for DR25,27,28,29 */
88#define	MFCPU_C_PCXL(r,x)	.word	0x14000600 | ((r) << 21) | ((x) << 16)
89#define	MFCPU_T_PCXL(r,x)	.word	0x14001800 | ((r) << 21) | ((x))
90#define	MTCPU_PCXL(x,r)		.word	0x14000240 | ((r) << 21) | ((x) << 16)
91#define	DR_PAGE0_PCXL		.word	0x14000e00
92#define	DR_PAGE1_PCXL		.word	0x14000e40
93
94#define	MFCPU_PCXU(r,x)		.word	0x140008a0 | ((r) << 21) | ((x))
95#define	MTCPU_PCXU(x,r)		.word	0x14001840 | ((r) << 21) | ((x) << 16)
96
97	.import	$global$, data
98	.import pdc, data
99	.import cpu_info, data
100	.import	panic, code
101
102LEAF_ENTRY($kernel_setup)
103
104	/*
105	 * disable interrupts and turn off all bits in the psw so that
106	 * we start in a known state.
107	 */
108	rsm	RESET_PSL, r0
109	nop ! nop ! nop ! nop ! nop ! nop
110
111	/* get things ready for the kernel to run in virtual mode */
112	ldi	HPPA_PID_KERNEL, r1
113	mtctl	r1, pidr1
114	mtctl	r1, pidr2
115#if pbably_not_worth_it
116	mtctl	r0, pidr3
117	mtctl	r0, pidr4
118#endif
119	mtsp	r0, sr0
120	mtsp	r0, sr1
121	mtsp	r0, sr2
122	mtsp	r0, sr3
123	mtsp	r0, sr4
124	mtsp	r0, sr5
125	mtsp	r0, sr6
126	mtsp	r0, sr7
127
128	/*
129	 * to keep the spl() routines consistent we need to put the correct
130	 * spl level into eiem, and reset any pending interrupts
131	 */
132	ldi	-1, r1
133	mtctl	r0, eiem
134	mtctl	r1, eirr
135
136	/*
137	 * load address of interrupt vector table
138	 */
139	ldil	L%$ivaaddr, t2
140	ldo	R%$ivaaddr(t2), t2
141	mtctl	t2, iva
142
143	/*
144	 * set up the dp pointer so that we can do quick references off of it
145	 */
146	ldil	L%$global$,dp
147	ldo	R%$global$(dp),dp
148
149	/*
150	 * Create a stack frame for us to call C with. Clear out the previous
151	 * sp marker to mark that this is the first frame on the stack.
152	 */
153	copy	arg1, sp
154	ldo	0(arg1), r3
155	stw,ma	r0, HPPA_FRAME_SIZE(sp)
156	stw	r0, HPPA_FRAME_CRP(sp)
157	stw	r0, HPPA_FRAME_PSP(sp)
158
159	/*
160	 * We need to set the Q bit so that we can take TLB misses after we
161	 * turn on virtual memory.
162	 */
163	mtctl	r0, pcsq
164	mtctl	r0, pcsq
165	mtctl	rp, pcoq
166	ldo	4(rp), rp
167	mtctl	rp, pcoq
168	mtctl	arg2, ipsw
169	rfi
170	nop
171	nop
172EXIT($kernel_setup)
173
174/* int
175 * pdc_call(func, pdc_flag, ...)
176 *	iodcio_t func;
177 *	int pdc_flag;
178 */
179ENTRY(pdc_call,160)
180
181	mfctl	eiem, t1
182	mtctl	r0, eiem
183	stw	rp, HPPA_FRAME_CRP(sp)
184	copy	arg0, r31
185	copy	sp, ret1
186
187	ldil	L%kernelmapped, ret0
188	ldw	R%kernelmapped(ret0), ret0
189	comb,=	r0, ret0, pdc_call_unmapped1
190	nop
191	ldil	L%pdc_stack, ret1
192	ldw	R%pdc_stack(ret1), ret1
193
194pdc_call_unmapped1
195	copy	sp, r1
196	ldo	HPPA_FRAME_SIZE+24*4(ret1), sp
197
198	stw	r1, HPPA_FRAME_PSP(sp)
199
200	/* save kernelmapped and eiem */
201	stw	ret0, HPPA_FRAME_ARG(21)(sp)
202	stw	t1, HPPA_FRAME_ARG(22)(sp)
203
204	/* copy arguments */
205	copy	arg2, arg0
206	copy	arg3, arg1
207	ldw	HPPA_FRAME_ARG(4)(r1), arg2
208	ldw	HPPA_FRAME_ARG(5)(r1), arg3
209	ldw	HPPA_FRAME_ARG(6)(r1), t1
210	ldw	HPPA_FRAME_ARG(7)(r1), t2
211	ldw	HPPA_FRAME_ARG(8)(r1), t3
212	ldw	HPPA_FRAME_ARG(9)(r1), t4
213	stw	t1, HPPA_FRAME_ARG(4)(sp)	/* XXX can use ,bc */
214	stw	t2, HPPA_FRAME_ARG(5)(sp)
215	stw	t3, HPPA_FRAME_ARG(6)(sp)
216	stw	t4, HPPA_FRAME_ARG(7)(sp)
217	ldw	HPPA_FRAME_ARG(10)(r1), t1
218	ldw	HPPA_FRAME_ARG(11)(r1), t2
219	ldw	HPPA_FRAME_ARG(12)(r1), t3
220	ldw	HPPA_FRAME_ARG(13)(r1), t4
221	stw	t1, HPPA_FRAME_ARG(8)(sp)
222	stw	t2, HPPA_FRAME_ARG(9)(sp)
223	stw	t3, HPPA_FRAME_ARG(10)(sp)
224	stw	t4, HPPA_FRAME_ARG(11)(sp)
225
226	/* save temp control regs */
227	mfctl	cr24, t1
228	mfctl	cr25, t2
229	mfctl	cr26, t3
230	mfctl	cr27, t4
231	stw	t1, HPPA_FRAME_ARG(12)(sp)	/* XXX can use ,bc */
232	stw	t2, HPPA_FRAME_ARG(13)(sp)
233	stw	t3, HPPA_FRAME_ARG(14)(sp)
234	stw	t4, HPPA_FRAME_ARG(15)(sp)
235	mfctl	cr28, t1
236	mfctl	cr29, t2
237	mfctl	cr30, t3
238	mfctl	cr31, t4
239	stw	t1, HPPA_FRAME_ARG(16)(sp)
240	stw	t2, HPPA_FRAME_ARG(17)(sp)
241	stw	t3, HPPA_FRAME_ARG(18)(sp)
242	stw	t4, HPPA_FRAME_ARG(19)(sp)
243
244	comb,=	r0, ret0, pdc_call_unmapped2
245	nop
246
247	copy	arg0, t4
248	ldi	PSL_Q, arg0 /* (!pdc_flag && args[0] == PDC_PIM)? PSL_M:0) */
249	break	HPPA_BREAK_KERNEL, HPPA_BREAK_SET_PSW
250	stw	ret0, HPPA_FRAME_ARG(23)(sp)
251	copy	t4, arg0
252
253pdc_call_unmapped2
254	.call
255	blr	r0, rp
256	bv,n	(r31)
257	nop
258
259	/* load temp control regs */
260	ldw	HPPA_FRAME_ARG(12)(sp), t1
261	ldw	HPPA_FRAME_ARG(13)(sp), t2
262	ldw	HPPA_FRAME_ARG(14)(sp), t3
263	ldw	HPPA_FRAME_ARG(15)(sp), t4
264	mtctl	t1, cr24
265	mtctl	t2, cr25
266	mtctl	t3, cr26
267	mtctl	t4, cr27
268	ldw	HPPA_FRAME_ARG(16)(sp), t1
269	ldw	HPPA_FRAME_ARG(17)(sp), t2
270	ldw	HPPA_FRAME_ARG(18)(sp), t3
271	ldw	HPPA_FRAME_ARG(19)(sp), t4
272	mtctl	t1, cr28
273	mtctl	t2, cr29
274	mtctl	t3, cr30
275	mtctl	t4, cr31
276
277	ldw	HPPA_FRAME_ARG(21)(sp), t1
278	ldw	HPPA_FRAME_ARG(22)(sp), t2
279	comb,=	r0, t1, pdc_call_unmapped3
280	nop
281
282	copy	ret0, t3
283	ldw	HPPA_FRAME_ARG(23)(sp), arg0
284	break	HPPA_BREAK_KERNEL, HPPA_BREAK_SET_PSW
285	copy	t3, ret0
286
287pdc_call_unmapped3
288	ldw	HPPA_FRAME_PSP(sp), sp
289	ldw	HPPA_FRAME_CRP(sp), rp
290	bv	r0(rp)
291	mtctl	t2, eiem
292EXIT(pdc_call)
293
294/*
295 * Kernel Gateway Page (must be at known address)
296 *	System Call Gate
297 *	Signal Return Gate
298 *
299 * GATEway instructions have to be at a fixed known locations
300 * because their addresses are hard coded in routines such as
301 * those in the C library.
302 */
303	.align	NBPG
304	.export	gateway_page, entry
305gateway_page
306	nop				/* @ 0.C0000000 (Nothing)  */
307	gate,n	$bsd_syscall,r0		/* @ 0.C0000004 (HPUX/BSD) */
308	nop				/* @ 0.C0000008 (HPOSF UNIX) */
309	nop				/* @ 0.C000000C (HPOSF Mach) */
310	nop
311	nop
312	nop
313	nop
314
315$bsd_syscall
316	/*
317	 * set up a space register and a protection id so that
318	 * we can access kernel memory
319	 */
320	mfctl	eiem, r1
321	mtctl	r0, eiem
322	mtsp	r0, sr1
323	mfctl	pidr1, ret0
324	ldi	HPPA_PID_KERNEL, t2
325	mtctl	t2, pidr1
326
327	.import $syscall,code
328	.call
329	ldil	L%$syscall, t2
330	be	R%$syscall(sr1, t2)
331	nop ! nop ! nop ! nop
332
333	.size	gateway_page, .-gateway_page
334	.align	NBPG
335	.export	gateway_page_end, entry
336gateway_page_end
337
338	.export $syscall,entry
339	.proc
340	.callinfo calls
341	.entry
342$syscall
343	/*
344	 *
345	 * t1:	syscall number
346	 * t2:	user
347	 * t3:	args
348	 * t4:	user stack
349	 *
350	 */
351	mfctl	cr29, t2
352	ldw	CI_CURPROC(sr1, t2), t2
353	ldw	P_ADDR(sr1, t2), t3	/* XXX can use ,sl */
354
355	/* calculate kernel sp, load, create kernel stack frame */
356	ldo	NBPG(t3), t3
357	stw	t3, P_MD_REGS(sr1, t2)
358	ldo	TRAPFRAME_SIZEOF(t3), t3
359	stw	t4, TF_R19 -TRAPFRAME_SIZEOF(sr1, t3)	/* t4 for vfork() */
360	stw	t1, TF_R22 -TRAPFRAME_SIZEOF(sr1, t3)	/* syscall # */
361	/* gotta save the args, in case we gonna restart */
362	stw	arg3, TF_R23-TRAPFRAME_SIZEOF(sr1, t3)
363	stw	arg2, TF_R24-TRAPFRAME_SIZEOF(sr1, t3)
364	stw	arg1, TF_R25-TRAPFRAME_SIZEOF(sr1, t3)
365	stw	arg0, TF_R26-TRAPFRAME_SIZEOF(sr1, t3)
366	stw	r27, TF_R27-TRAPFRAME_SIZEOF(sr1, t3)	/* dp */
367	stw	sp, TF_R30 -TRAPFRAME_SIZEOF(sr1, t3)	/* user stack */
368	copy	t3, sp
369	stw,ma	r0, HPPA_FRAME_SIZE+HPPA_FRAME_MAXARGS(sr1, sp)
370	stw	r0, HPPA_FRAME_CRP(sr1, sp)
371	mfctl	r29, t1
372	ldw	CI_PSW(sr1, t1), t1
373	stw	r1, TF_CR15-TRAPFRAME_SIZEOF(sr1, t3)	/* eiem ,bc */
374	stw	t1, TF_CR22-TRAPFRAME_SIZEOF(sr1, t3)	/* ipsw */
375	mfsp	sr3, t1
376	stw	t1, TF_SR3-TRAPFRAME_SIZEOF(sr1, t3)
377	stw	ret0, TF_CR8-TRAPFRAME_SIZEOF(sr1, t3)	/* pidr1 */
378	/* now we can allow interrupts to happen */
379	mtctl	r1, eiem
380
381	/*
382	 * we believe that any callee-save registers
383	 * will be saved accordingly in either syscall()
384	 * or deeper called functions and caller-save
385	 * are saved in userland.
386	 */
387	stw	r2 , TF_R2 -TRAPFRAME_SIZEOF(sr1, t3)
388	stw	r3 , TF_R3 -TRAPFRAME_SIZEOF(sr1, t3)
389	copy	t3, r3
390	/* save callee-save registers */
391	stw	r4 , TF_R4 -TRAPFRAME_SIZEOF(sr1, t3)
392	stw	r5 , TF_R5 -TRAPFRAME_SIZEOF(sr1, t3)
393	stw	r6 , TF_R6 -TRAPFRAME_SIZEOF(sr1, t3)
394	stw	r7 , TF_R7 -TRAPFRAME_SIZEOF(sr1, t3)
395	stw	r8 , TF_R8 -TRAPFRAME_SIZEOF(sr1, t3)
396	stw	r9 , TF_R9 -TRAPFRAME_SIZEOF(sr1, t3)
397	stw	r10, TF_R10-TRAPFRAME_SIZEOF(sr1, t3)
398	stw	r11, TF_R11-TRAPFRAME_SIZEOF(sr1, t3)
399	stw	r12, TF_R12-TRAPFRAME_SIZEOF(sr1, t3)
400	stw	r13, TF_R13-TRAPFRAME_SIZEOF(sr1, t3)
401	stw	r14, TF_R14-TRAPFRAME_SIZEOF(sr1, t3)
402	stw	r15, TF_R15-TRAPFRAME_SIZEOF(sr1, t3)
403	stw	r16, TF_R16-TRAPFRAME_SIZEOF(sr1, t3)
404	stw	r17, TF_R17-TRAPFRAME_SIZEOF(sr1, t3)
405	stw	r18, TF_R18-TRAPFRAME_SIZEOF(sr1, t3)
406	/*
407	 * Save the rest of the CPU context
408	 */
409	mfsp	sr0, arg0				/* use ,bc */
410	stw	arg0, TF_IISQH-TRAPFRAME_SIZEOF(sr1, t3)
411	stw	arg0, TF_IISQT-TRAPFRAME_SIZEOF(sr1, t3)
412
413	ldo	4(r31), arg1
414	stw	r31, TF_IIOQH-TRAPFRAME_SIZEOF(sr1, t3)
415	stw	arg1, TF_IIOQT-TRAPFRAME_SIZEOF(sr1, t3)
416
417	stw	arg0, TF_CR20-TRAPFRAME_SIZEOF(sr1, t3)	/* use ,bc */
418	stw	r31, TF_CR21-TRAPFRAME_SIZEOF(sr1, t3)
419
420	ldil	L%TFF_LAST|TFF_SYS, arg1
421	stw	r0, TF_CR19-TRAPFRAME_SIZEOF(sr1, t3)	/* iir */
422	stw	arg1, TF_FLAGS-TRAPFRAME_SIZEOF(sr1, t3)
423
424	mfsp	sr2, arg2
425	mfsp	sr4, arg3
426	stw	arg0, TF_SR0-TRAPFRAME_SIZEOF(sr1, t3)
427	stw	arg0, TF_SR1-TRAPFRAME_SIZEOF(sr1, t3)
428	stw	arg2, TF_SR2-TRAPFRAME_SIZEOF(sr1, t3)
429	stw	arg3, TF_SR4-TRAPFRAME_SIZEOF(sr1, t3)
430
431	mfsp	sr5, arg0
432	mfsp	sr6, arg1
433	mfsp	sr7, arg2
434	mfctl	pidr2, arg3
435	stw	arg0, TF_SR5-TRAPFRAME_SIZEOF(sr1, t3)
436	stw	arg1, TF_SR6-TRAPFRAME_SIZEOF(sr1, t3)
437	stw	arg2, TF_SR7-TRAPFRAME_SIZEOF(sr1, t3)
438	stw	arg3, TF_CR9-TRAPFRAME_SIZEOF(sr1, t3)
439
440#if pbably_not_worth_it
441	mfctl	pidr3, arg2
442	mfctl	pidr4, arg3
443	stw	arg2, TF_CR12-TRAPFRAME_SIZEOF(sr1, t3)
444	stw	arg3, TF_CR13-TRAPFRAME_SIZEOF(sr1, t3)
445#endif
446
447#ifdef DDB
448	/*
449	 * Save hpt mask and v2p translation table pointer
450	 */
451	mfctl	eirr, arg0
452	mfctl	vtop, arg1
453	stw	arg0, TF_CR23-TRAPFRAME_SIZEOF(sr1, t3)
454	stw	arg1, TF_CR25-TRAPFRAME_SIZEOF(sr1, t3)
455
456	mfctl	cr28, arg1
457	stw	arg1, TF_CR28-TRAPFRAME_SIZEOF(sr1, t3)
458#endif
459
460	/* setup kernel context */
461	mtsp	r0, sr0
462	mtsp	r0, sr1
463	mtsp	r0, sr2
464	mtsp	r0, sr3
465	mtsp	r0, sr4
466	mtsp	r0, sr5
467	mtsp	r0, sr6
468	mtsp	r0, sr7
469
470	ldo	-TRAPFRAME_SIZEOF(t3), arg0
471	ldo	4(t3), arg1
472
473	ldil	L%$global$,dp
474	ldo	R%$global$(dp),dp
475
476	/* do a syscall */
477	.import	syscall,code
478	ldil	L%syscall, r1
479	ldo	R%syscall(r1), r1
480	.call
481	blr	r0, rp
482	bv,n	0(r1)
483	nop
484
485	mfctl	cr29, r1
486	ldw	CI_CURPROC(r1), r1
487	ldw	P_MD_REGS(r1), t3
488
489	.exit
490	.procend
491	/* FALLTHROUGH */
492
493	.export	$syscall_return, entry
494	.proc
495	.callinfo no_calls
496	.entry
497$syscall_return
498	/* t3 == VA trapframe */
499
500	/* disable interrupts, just in case */
501#ifdef MULTIPROCESSOR
502	mfctl	eiem, t1
503	stw	t1, TF_CR15(t3)
504#endif
505	mtctl	r0, eiem
506
507	/*
508	 * 1a. Copy a `phys' part of the frame into temp store
509	 *	(see a note for trapall)
510	 *	hopefully no page fault would happen on or after the copy,
511	 *	and interrupts are disabled.
512	 */
513	mfctl	cr29, t2
514	ldo	CI_TRAP_SAVE(t2), t2
515	/* use ,bc each cache line */
516	ldw  0(t3), r1 ! ldw  4(t3), t1 ! stw r1,  0(t2) ! stw t1,  4(t2)
517	ldw  8(t3), r1 ! ldw 12(t3), t1 ! stw r1,  8(t2) ! stw t1, 12(t2)
518	ldw 16(t3), r1 ! ldw 20(t3), t1 ! stw r1, 16(t2) ! stw t1, 20(t2)
519	ldw 24(t3), r1 ! ldw 28(t3), t1 ! stw r1, 24(t2) ! stw t1, 28(t2)
520	ldw 32(t3), r1 ! ldw 36(t3), t1 ! stw r1, 32(t2) ! stw t1, 36(t2)
521	ldw 40(t3), r1 ! ldw 44(t3), t1 ! stw r1, 40(t2) ! stw t1, 44(t2)
522	ldw 48(t3), r1 ! ldw 52(t3), t1 ! stw r1, 48(t2) ! stw t1, 52(t2)
523	ldw 56(t3), r1 ! ldw 60(t3), t1 ! stw r1, 56(t2) ! stw t1, 60(t2)
524
525	/* 1b. restore most of the general registers */
526	ldw	TF_CR11(t3), t1
527	mtctl	t1, sar
528	ldw	TF_R1(t3), r1
529	ldw	TF_R2(t3), r2
530	ldw	TF_R3(t3), r3
531	ldw	TF_R4(t3), r4
532	ldw	TF_R5(t3), r5
533	ldw	TF_R6(t3), r6
534	ldw	TF_R7(t3), r7
535	ldw	TF_R8(t3), r8
536	ldw	TF_R9(t3), r9
537	ldw	TF_R10(t3), r10
538	ldw	TF_R11(t3), r11
539	ldw	TF_R12(t3), r12
540	ldw	TF_R13(t3), r13
541	ldw	TF_R14(t3), r14
542	ldw	TF_R15(t3), r15
543	ldw	TF_R16(t3), r16
544	ldw	TF_R17(t3), r17
545	ldw	TF_R18(t3), r18
546	ldw	TF_R19(t3), t4
547	/*	r20(t3) is used as a temporary and will be restored later */
548	/*	r21(t2) is used as a temporary and will be restored later */
549	/*	r22(t1) is used as a temporary and will be restored later */
550	ldw	TF_R23(t3), r23
551	ldw	TF_R24(t3), r24
552	ldw	TF_R25(t3), r25
553	ldw	TF_R26(t3), r26
554	ldw	TF_R27(t3), r27
555	ldw	TF_R28(t3), r28
556	ldw	TF_R29(t3), r29
557	/*	r30 (sp) will be restored later */
558	ldw	TF_R31(t3), r31
559
560	/* 2. restore all the space regs and pid regs, except sr3, pidr1 */
561	ldw	TF_SR0(t3), t1
562	ldw	TF_SR1(t3), t2
563	mtsp	t1, sr0
564	mtsp	t2, sr1
565
566	ldw	TF_SR2(sr3, t3), t1
567	ldw	TF_SR4(sr3, t3), t2
568	mtsp	t1, sr2
569	mtsp	t2, sr4
570
571	ldw	TF_SR5(sr3, t3), t1
572	ldw	TF_SR6(sr3, t3), t2
573	mtsp	t1, sr5
574	mtsp	t2, sr6
575
576	ldw	TF_SR7(sr3, t3), t1
577	ldw	TF_CR9(sr3, t3), t2
578	mtsp	t1, sr7
579	mtctl	t2, pidr2
580
581#if pbably_not_worth_it
582	ldw	TF_CR12(sr3, t3), t1
583	ldw	TF_CR13(sr3, t3), t2
584	mtctl	t1, pidr3
585	mtctl	t2, pidr4
586#endif
587	ldw	TF_CR0(sr3, t3), t1
588	mtctl	t1, rctr
589	ldw	TF_CR27(sr3, t3), t1
590	ldw	TF_CR30(sr3, t3), t2
591	mtctl	t1, cr27
592	mtctl	t2, cr30
593
594	/*
595	 * clear the system mask, this puts us back into physical mode.
596	 * reload trapframe pointer w/ correspondent PA value.
597	 * sp will be left in virtual until restored from trapframe,
598	 * since we don't use it anyway.
599	 */
600	ssm	0, r0
601	mfctl	cr29, t3
602	ldo	CI_TRAP_SAVE(t3), t3
603	nop ! nop ! nop ! nop ! nop
604	rsm	RESET_PSL, r0
605$syscall_return_phys
606
607	/* clear cr26 to avoid information leak */
608	mtctl	r0, cr26
609
610	/* finally we can restore the space and offset queues and the ipsw */
611	ldw	TF_IISQH(t3), t1
612	ldw	TF_IISQT(t3), t2
613	mtctl	t1, pcsq
614	mtctl	t2, pcsq
615
616	ldw	TF_IIOQH(t3), t1
617	ldw	TF_IIOQT(t3), t2
618	mtctl	t1, pcoq
619	mtctl	t2, pcoq
620
621	ldw	TF_CR15(t3), t1
622	ldw	TF_CR22(t3), t2
623	mtctl	t1, eiem
624	mtctl	t2, ipsw
625
626	ldw	TF_SR3(t3), t1
627	ldw	TF_CR8(t3), t2
628	mtsp	t1, sr3
629	mtctl	t2, pidr1
630
631	ldw	TF_R22(t3), t1
632	ldw	TF_R21(t3), t2
633	ldw	TF_R30(t3), sp
634	ldw	TF_R20(t3), t3
635
636	rfi
637	nop
638	.exit
639	.procend
640	.size	$syscall, .-$syscall
641$syscall_end
642
643/*
644 * interrupt vector table
645 */
646#define	TLABEL(name)	$trap$name
647#define TRAP(name,num) \
648	mtctl	r1, tr7			! \
649	.call				! \
650	.import TLABEL(name), code	! \
651	b	TLABEL(name)		! \
652	ldi	num, r1			! \
653	.align	32
654
655#define	ATRAP(name,num) \
656	.export	TLABEL(name)$num, entry	! \
657	.label	TLABEL(name)$num	! \
658	TRAP(all,num)			! \
659	.size	TLABEL(name)$num, .-TLABEL(name)$num
660
661#define	CTRAP(name,num,pre) \
662	.export	TLABEL(name)$num, entry	! \
663	.label	TLABEL(name)$num	! \
664	pre				! \
665	TRAP(name,num)			! \
666	.size	TLABEL(name)$num, .-TLABEL(name)$num
667
668#define	STRAP(name,num,pre) \
669	.export	TLABEL(name)$num, entry	! \
670	.label	TLABEL(name)$num	! \
671	pre				! \
672	mtctl	r1, tr7			! \
673	.export	trap_ep_##num, entry	! \
674	.label	trap_ep_##num		! \
675	.call				! \
676	b	__CONCAT($name,_l)	! \
677	ldi	num, r1			! \
678	b	__CONCAT($name,_t)+8	! \
679	b	__CONCAT($name,_s)+12	! \
680	b	__CONCAT($name,_u)+16	! \
681	.size	TLABEL(name)$num, .-TLABEL(name)$num
682
683#define	ITLBPRE \
684	mfctl	pcoq,r9 ! \
685	mfctl	pcsq,r8
686#define	DTLBPRE \
687	mfctl	ior, r9 ! \
688	mfctl	isr, r8
689	/* CR28XXX according to a popular belief cr28 should be read here */
690
691#define	HPMCPRE	nop
692#define	INTRPRE	\
693	mfctl	eirr, r8	! \
694	mtctl	r8, eirr
695
696	.align NBPG
697	.export $ivaaddr, entry
698	.export hpmc_v, entry
699$ivaaddr
700	ATRAP(null,T_NONEXIST)		/*  0. invalid interrupt vector */
701hpmc_v
702	CTRAP(hpmc,T_HPMC,HPMCPRE)	/*  1. high priority machine check */
703	ATRAP(power,T_POWERFAIL)	/*  2. power failure */
704	ATRAP(recnt,T_RECOVERY)		/*  3. recovery counter trap */
705	CTRAP(intr,T_INTERRUPT,INTRPRE)	/*  4. external interrupt */
706	ATRAP(lpmc,T_LPMC)		/*  5. low-priority machine check */
707	STRAP(itlb,T_ITLBMISS,ITLBPRE)	/*  6. instruction TLB miss fault */
708	ATRAP(iprot,T_IPROT)		/*  7. instruction protection trap */
709	ATRAP(ill,T_ILLEGAL)		/*  8. Illegal instruction trap */
710	CTRAP(ibrk,T_IBREAK,)		/*  9. break instruction trap */
711	ATRAP(privop,T_PRIV_OP)		/* 10. privileged operation trap */
712	ATRAP(privr,T_PRIV_REG)		/* 11. privileged register trap */
713	ATRAP(ovrfl,T_OVERFLOW)		/* 12. overflow trap */
714	ATRAP(cond,T_CONDITION)		/* 13. conditional trap */
715	CTRAP(excpt,T_EXCEPTION,)	/* 14. assist exception trap */
716	STRAP(dtlb,T_DTLBMISS,DTLBPRE)	/* 15. data TLB miss fault */
717	STRAP(itlbna,T_ITLBMISSNA,DTLBPRE)/* 16. ITLB non-access miss fault */
718	STRAP(dtlbna,T_DTLBMISSNA,DTLBPRE)/* 17. DTLB non-access miss fault */
719	ATRAP(dprot,T_DPROT)		/* 18. data protection trap
720					      unaligned data reference trap */
721	ATRAP(dbrk,T_DBREAK)		/* 19. data break trap */
722	STRAP(tlbd,T_TLB_DIRTY,DTLBPRE)	/* 20. TLB dirty bit trap */
723	ATRAP(pgref,T_PAGEREF)		/* 21. page reference trap */
724	CTRAP(emu,T_EMULATION,)		/* 22. assist emulation trap */
725	ATRAP(hpl,T_HIGHERPL)		/* 23. higher-privelege transfer trap*/
726	ATRAP(lpl,T_LOWERPL)		/* 24. lower-privilege transfer trap */
727	ATRAP(tknbr,T_TAKENBR)		/* 25. taken branch trap */
728	ATRAP(dacc,T_DATACC)		/* 26. data access rights trap */
729	ATRAP(dpid,T_DATAPID)		/* 27. data protection ID trap */
730	ATRAP(dalgn,T_DATALIGN)		/* 28. unaligned data ref trap */
731	ATRAP(unk29,29)
732	ATRAP(unk30,30)
733	ATRAP(unk31,31)
734	ATRAP(unk32,32)
735	ATRAP(unk33,33)
736	ATRAP(unk34,34)
737	ATRAP(unk35,35)
738	ATRAP(unk36,36)
739	ATRAP(unk37,37)
740	ATRAP(unk38,38)
741	ATRAP(unk39,39)
742	ATRAP(unk40,40)
743	ATRAP(unk41,41)
744	ATRAP(unk42,42)
745	ATRAP(unk43,43)
746	ATRAP(unk44,44)
747	ATRAP(unk45,45)
748	ATRAP(unk46,46)
749	ATRAP(unk47,47)
750	ATRAP(unk48,48)
751	ATRAP(unk49,49)
752	ATRAP(unk50,50)
753	ATRAP(unk51,51)
754	ATRAP(unk52,52)
755	ATRAP(unk53,53)
756	ATRAP(unk54,54)
757	ATRAP(unk55,55)
758	ATRAP(unk56,56)
759	ATRAP(unk57,57)
760	ATRAP(unk58,58)
761	ATRAP(unk59,59)
762	ATRAP(unk60,60)
763	ATRAP(unk61,61)
764	ATRAP(unk62,62)
765	ATRAP(unk63,63)
766					/* 64 */
767	.size	$ivaaddr, .-$ivaaddr
768
769	.export TLABEL(excpt), entry
770ENTRY(TLABEL(excpt),0)
771	/* assume we never get this one w/o fpu [enabled] */
772	copy	rp, r1
773	copy	arg0, r8
774	mfctl	cr30, r9
775#if HFP_REGS != 0
776	ldo	HFP_REGS(r9), r9
777#endif
778	.import	fpu_save, code
779	.call
780	bl	fpu_save, rp
781	copy	r9, arg0
782	copy	r1, rp
783	copy	r8, arg0
784	mfctl	cr29, r1
785	mtctl	r0, ccr		/* cause a reload after exception */
786	ldw	CI_FPU_STATE(r1), r16
787	stw	r0, CI_FPU_STATE(r1)
788	stw	r0, HFP_CPU(r16)
789	sync
790
791	/* now, check for trap */
792	ldw	0(r9), r1
793	bb,>=,n	r1, HPPA_FPU_T_POS, excpt_notrap
794	ldw	1*4(r9), r1
795	comb,<>,n r0, r1, excpt_emulate
796	ldw	2*4(r9), r1
797	comb,<>,n r0, r1, excpt_emulate
798	ldw	3*4(r9), r1
799	comb,<>,n r0, r1, excpt_emulate
800	ldw	4*4(r9), r1
801	comb,<>,n r0, r1, excpt_emulate
802	ldw	5*4(r9), r1
803	comb,<>,n r0, r1, excpt_emulate
804	ldw	6*4(r9), r1
805	comb,<>,n r0, r1, excpt_emulate
806	ldw	7*4(r9), r1
807
808excpt_emulate
809	bb,>=,n r1, 5, excpt_notrap	/* HPPA_FPU_UNMPL not set */
810
811	ldw	0(r9), r16
812	depi	0, HPPA_FPU_T_POS, 1, r16
813	.import	$fpu_emulate, code
814	b	$fpu_emulate
815	stw	r16, 0(r9)
816
817excpt_notrap
818	sync
819	b	TLABEL(all)
820	ldi	T_EXCEPTION, r1
821EXIT(TLABEL(excpt))
822
823	.export TLABEL(emu), entry
824ENTRY(TLABEL(emu),0)
825
826	/*
827	 * Switch FPU/SFU context
828	 *
829	 * isr:ior - data address
830	 * iir - instruction to emulate
831	 * iisq:iioq - address of instruction to emulate
832	 *
833	 * note: ISR and IOR contain valid data only if the
834	 *	 instruction is a coprocessor load or store.
835	 *
836	 */
837
838	mfctl	iir, r8
839	extru	r8, 5, 6, r9	/* no sfu implementation right now */
840	comib,=	4, r9, TLABEL(all)
841	ldi	T_ILLEGAL, r1
842
843	/*
844	 * pass through for all coprocessors now and
845	 * do not check the uid here.
846	 * in case that piece does not exist emulate
847	 * or the trap will be generated later.
848	 */
849
850	ldil	L%cpu_fpuena, r1
851	ldw	R%cpu_fpuena(r1), r9
852	comib,=	0, r9, $fpusw_emu
853
854	/* if we are already enabled and hit again, emulate */
855	mfctl	ccr, r1
856	extru,<> r1, 25, 2, r0
857	b,n	$fpusw_set
858	nop
859
860$fpusw_emu
861	mfctl	cr29, r1
862	mtctl	r0, ccr		/* cause a reload after exception */
863	ldw	CI_FPU_STATE(r1), r16
864	stw	r0, CI_FPU_STATE(r1)
865	stw	r0, HFP_CPU(r16)
866	sync
867#if 0
868	/* here we emulate the fld/fst */
869	mfctl	iir, r1
870	extru	r1, 5, 6, r1
871	comib,=	0xb, r9, TLABEL(all)
872	ldi	T_ILLEGAL, r1
873
874	mfctl	iir, r1
875	extru	r1, 5, 6, r1
876	comib,=	0x9, r9, TLABEL(all)
877	ldi	T_ILLEGAL, r1
878#endif
879	mfctl	iir, r1
880	.import	$fpu_emulate, code
881	b	$fpu_emulate
882	nop
883
884$fpusw_set
885	/* enable coprocessor XXX */
886	depi	3, 25, 2, r1
887	mtctl	r1, ccr
888
889	mfctl	cr29, r16
890	mfctl	cr30, r9
891	ldw	CI_FPU_STATE(r16), r16
892
893	comb,=,n r16, r0, $fpusw_nosave
894	comb,=,n r16, r9, $fpusw_done
895
896	copy	arg0, r17
897	copy	rp, r1
898#if HFP_REGS != 0
899	ldo	HFP_REGS(r16), r16
900#endif
901	.import	fpu_save, code
902	.call
903	bl	fpu_save, rp
904	copy	r16, arg0
905	copy	r1, rp
906	copy	r17, arg0
907
908	mfctl	cr29, r1
909	ldw	CI_FPU_STATE(r1), r16
910	stw	r0, CI_FPU_STATE(r1)
911	stw	r0, HFP_CPU(r16)
912	sync
913
914$fpusw_nosave
915
916#ifdef MULTIPROCESSOR
917	/* See if this process has FPU context on another CPU. */
918	ldw	HFP_CPU(r9), r1
919	comb,=,n r1, r0, $fpusw_noshoot
920
921	/* Perform FPU shootdown. */
922	ldi	(1 << HPPA_IPI_FPU_SAVE), r1
923	ldw	HFP_CPU(r9), r16
924	stw	r1, CI_IPI(r16)
925	ldi	1, r1
926	ldw	CI_HPA(r16), r16
927	stw	r1, 0(r16)
928
929$fpusw_spin
930	/* Wait for shootdown to complete. */
931	sync
932	ldw	HFP_CPU(r9), r1
933	comb,<>,n r1, r0, $fpusw_spin
934
935$fpusw_noshoot
936#endif
937
938	/* count switches */
939	.import	uvmexp, data
940	ldil	L%(uvmexp+FPSWTCH), r1
941	ldw	R%(uvmexp+FPSWTCH)(r1), r16
942	ldo	31*8+HFP_REGS(r9), r17
943	ldo	1(r16), r16
944	stw	r16, R%(uvmexp+FPSWTCH)(r1)
945
946	fldds,ma -8(r17), fr31
947	fldds,ma -8(r17), fr30
948	fldds,ma -8(r17), fr29
949	fldds,ma -8(r17), fr28
950	fldds,ma -8(r17), fr27
951	fldds,ma -8(r17), fr26
952	fldds,ma -8(r17), fr25
953	fldds,ma -8(r17), fr24
954	fldds,ma -8(r17), fr23
955	fldds,ma -8(r17), fr22
956	fldds,ma -8(r17), fr21
957	fldds,ma -8(r17), fr20
958	fldds,ma -8(r17), fr19
959	fldds,ma -8(r17), fr18
960	fldds,ma -8(r17), fr17
961	fldds,ma -8(r17), fr16
962	fldds,ma -8(r17), fr15
963	fldds,ma -8(r17), fr14
964	fldds,ma -8(r17), fr13
965	fldds,ma -8(r17), fr12
966	fldds,ma -8(r17), fr11
967	fldds,ma -8(r17), fr10
968	fldds,ma -8(r17), fr9
969	fldds,ma -8(r17), fr8
970	fldds,ma -8(r17), fr7
971	fldds,ma -8(r17), fr6
972	fldds,ma -8(r17), fr5
973	fldds,ma -8(r17), fr4
974	fldds,ma -8(r17), fr3
975	fldds,ma -8(r17), fr2
976	fldds,ma -8(r17), fr1
977	fldds     0(r17), fr0	/* fr0 must be restored last */
978
979	mfctl	cr29, r1
980	stw	r9, CI_FPU_STATE(r1)
981	stw	r1, HFP_CPU(r9)
982	sync
983
984$fpusw_done
985	rfir
986	nop
987EXIT(TLABEL(emu))
988
989	/* Construct the virtual address tag. */
990#define	VTAG ! \
991	shd	r0, r9, 1, r16		/* r16[1..15] = off[0..14] */	! \
992	dep	r8, 31, 16, r16		/* put in the space id */	! \
993	depi	1, 0, 1, r16		/* and set the valid bit */
994
995#if 0
996	.export	dtlb_c, data
997	BSS(dtlb_c, 8)
998	.export	tlbd_c, data
999	BSS(tlbd_c, 8)
1000	.export	itlb_c, data
1001	BSS(itlb_c, 8)
1002
1003	.text
1004	/* XXX this touches tr5, which it should not, perhaps */
1005
1006#define	TLB_STATS_PRE(t) \
1007	mfctl	itmr, r17	! \
1008	mtctl	r17, tr5
1009#define	TLB_STATS_AFT(t) \
1010	mfctl	itmr, r16			! \
1011	mfctl	tr5, r17			! \
1012	ldil	L%__CONCAT(t,_c), r25		! \
1013	ldo	R%__CONCAT(t,_c)(r25), r25	! \
1014	sub	r16, r17, r16			! \
1015	ldw	0(r25), r24			! \
1016	ldw	4(r25), r17			! \
1017	ldo	1(r24), r24			! \
1018	ldo	-2(r16), r16 /* for mtctl */	! \
1019	add	r16, r17, r17			! \
1020	stw	r24, 0(r25)			! \
1021	stw	r17, 4(r25)
1022
1023#else
1024#define	TLB_STATS_PRE(t)	/**/
1025#define	TLB_STATS_AFT(t)	/**/
1026#endif
1027
1028#if defined(HP7000_CPU) || defined(HP7100_CPU) || defined(HP7200_CPU)
1029#define	TLB_PULL(bits,lbl)							! \
1030	/* space:pgaddr -- r8:r9 */					! \
1031	mfctl	vtop, r16						! \
1032	ldwax,s	r8(r16), r17		/* space -> page directory */	! \
1033	extru	r9, 9, 10, r25						! \
1034	combt,=,n r0, r17, lbl						! \
1035	ldwax,s	r25(r17), r24		/* page -> page table */	! \
1036	extru	r9, 19, 10, r16						! \
1037	combt,=,n r0, r24, lbl						! \
1038	ldwax,s	r16(r24), r17		/* va -> pa:prot */		! \
1039	sh2addl	r16, r24, r25						! \
1040	combt,=,n r0, r17, lbl						! \
1041	copy	r17, r16						! \
1042	depi	(bits), 21+bits, 1+bits, r17				! \
1043	sub,=	r16, r17, r0		/* do not store if unchanged */	! \
1044	stwas	r17, 0(r25)		/* store back w/ the bits */	! \
1045	shd	r17, r0, 13, r25					! \
1046	dep	r8, 30, 15, r25		/* mix0r the pid from the sid */! \
1047	dep	r0, 31, 12, r17		/* needed ? */			! \
1048	addi	2, r25, r25						! \
1049	extru	r17, 24, 25, r17
1050
1051	.align	32
1052LEAF_ENTRY($tlbd_s)
1053ALTENTRY($tlbd_t)
1054	TLB_STATS_PRE(tlbd)
1055	TLB_PULL(1, TLABEL(all))
1056	mfsp	sr1, r16
1057	mtsp	r8, sr1
1058	idtlba	r17,(sr1, r9)
1059	idtlbp	r25,(sr1, r9)
1060	mtsp	r16, sr1
1061	TLB_STATS_AFT(tlbd)
1062	rfir
1063	nop
1064EXIT($tlbd_s)
1065
1066LEAF_ENTRY($itlb_s)
1067ALTENTRY($itlb_t)
1068	TLB_STATS_PRE(itlb)
1069	TLB_PULL(0, TLABEL(all))
1070	extru,=	r25, 5, 1, r0	/* gateway page needs to be public */
1071	depi	0, 30, 15, r25
1072	mfsp	sr1, r16
1073	mtsp	r8, sr1
1074	iitlba	r17,(sr1, r9)
1075	iitlbp	r25,(sr1, r9)
1076	mtsp	r16, sr1
1077	TLB_STATS_AFT(itlb)
1078	rfir
1079	nop
1080EXIT($itlb_s)
1081
1082LEAF_ENTRY($dtlb_s)
1083ALTENTRY($dtlb_t)
1084	TLB_STATS_PRE(dtlb)
1085	TLB_PULL(0, TLABEL(all))
1086	mfsp	sr1, r16
1087	mtsp	r8, sr1
1088	idtlba	r17,(sr1, r9)
1089	idtlbp	r25,(sr1, r9)
1090	mtsp	r16, sr1
1091	TLB_STATS_AFT(dtlb)
1092	rfir
1093	nop
1094EXIT($dtlb_s)
1095
1096LEAF_ENTRY($dtlbna_s)
1097ALTENTRY($itlbna_s)
1098ALTENTRY($dtlbna_t)
1099ALTENTRY($itlbna_t)
1100	TLB_STATS_PRE(dtlb)
1101	TLB_PULL(0, $dtlbna_t_fake)
1102	mfsp	sr1, r16
1103	mtsp	r8, sr1
1104	idtlba	r17,(sr1, r9)
1105	idtlbp	r25,(sr1, r9)
1106	mtsp	r16, sr1
1107	TLB_STATS_AFT(dtlb)
1108	rfir
1109	nop
1110$dtlbna_s_fake
1111$dtlbna_t_fake
1112	/* parse prober/w insns, have to decent to trap() to set regs proper */
1113	mfctl	iir, r16
1114	extru	r16, 6, 6, r24
1115	comib,=,n 1, r24, TLABEL(all)
1116	extru	r16, 24, 6, r24
1117	subi,<>	0x23, r24, r0
1118	b	TLABEL(all)
1119	/* otherwise generate a flush-only tlb entry */
1120	copy	r0, r17
1121	zdep	r8, 30, 15, r25
1122	depi	-13, 11, 7, r25
1123	ldo	2(r25), r25   /* 3? */
1124	mfsp	sr1, r16
1125	mtsp	r8, sr1
1126	idtlba	r17,(sr1, r9)
1127	idtlbp	r25,(sr1, r9)
1128	mtsp	r16, sr1
1129	TLB_STATS_AFT(dtlb)
1130	rfir
1131	nop
1132EXIT($dtlbna_s)
1133
1134#endif /*  defined(HP7000_CPU) || defined(HP7100_CPU) || defined(HP7200_CPU) */
1135
1136#if defined(HP7100LC_CPU) || defined(HP7300LC_CPU)
1137
1138#define	IITLBAF(r)	.word	0x04000440 | ((r) << 16)
1139#define	IITLBPF(r)	.word	0x04000400 | ((r) << 16)
1140#define	IDTLBAF(r)	.word	0x04001440 | ((r) << 16)
1141#define	IDTLBPF(r)	.word	0x04001400 | ((r) << 16)
1142
1143/*
1144 * possible optimizations:
1145 *	change pte to reduce number of shifts
1146 *	reorder to reduce stalls
1147 */
1148#define	TLB_PULL_L(bits,lbl)						! \
1149	/* space:pgaddr -- r8:r9 */					! \
1150	mfctl	vtop, r16						! \
1151	ldwx,s	r8(r16), r17		/* space -> page directory */	! \
1152	extru	r9, 9, 10, r25						! \
1153	combt,=,n r0, r17, lbl						! \
1154	ldwx,s	r25(r17), r24		/* page -> page table */	! \
1155	extru	r9, 19, 10, r16						! \
1156	combt,=,n r0, r24, lbl						! \
1157	ldwx,s	r16(r24), r17		/* va -> pa:prot */		! \
1158	sh2addl	r16, r24, r25						! \
1159	combt,=,n r0, r17, lbl						! \
1160	copy	r17, r16						! \
1161	depi	(bits), 21+bits, 1+bits, r17				! \
1162	sub,=	r16, r17, r0		/* do not store if unchanged */	! \
1163	stws	r17, 0(r25)		/* store back w/ the bits */	! \
1164	shd	r17, r0, 13, r25					! \
1165	dep	r8, 30, 15, r25		/* mix0r the pid from the sid */! \
1166	dep	r0, 31, 12, r17		/* needed ? */			! \
1167	addi	2, r25, r25						! \
1168	extru	r17, 24, 25, r17	/* tlbbtop(r17) */		! \
1169	sync
1170
1171	.align	32
1172LEAF_ENTRY($tlbd_l)
1173	TLB_STATS_PRE(tlbd)
1174	TLB_PULL_L(1, TLABEL(all))
1175	IDTLBAF(17)
1176	IDTLBPF(25)
1177#ifdef USE_HPT
1178	/* invalidate instead of update */
1179	mfctl	cr28, r17
1180	ldw	0(r17), r24
1181	VTAG
1182	sub,<>	r16, r24, r0
1183	stw	r0, 0(r17)
1184#endif
1185	TLB_STATS_AFT(tlbd)
1186	rfir
1187	nop
1188EXIT($tlbd_l)
1189
1190	/*
1191	 * from 7100lc ers, pg.6:
1192	 * we found a post-silicon bug that makes cr28
1193	 * unreliable for the itlb miss handler
1194	 */
1195LEAF_ENTRY($itlb_l)
1196	TLB_STATS_PRE(itlb)
1197	TLB_PULL_L(0, TLABEL(all))
1198	extru,=	r25, 5, 1, r0	/* gateway page needs to be public */
1199	depi	0, 30, 15, r25
1200	IITLBAF(17)
1201	IITLBPF(25)
1202	TLB_STATS_AFT(itlb)
1203	rfir
1204	nop
1205EXIT($itlb_l)
1206
1207LEAF_ENTRY($dtlbna_l)
1208ALTENTRY($itlbna_l)
1209	TLB_STATS_PRE(dtlb)
1210	TLB_PULL_L(0, $dtlbna_l_fake)
1211	IDTLBAF(17)
1212	IDTLBPF(25)
1213	TLB_STATS_AFT(dtlb)
1214	rfir
1215	nop
1216$dtlbna_l_fake
1217	/* parse prober/w insns, have to decent to trap() to set regs proper */
1218	mfctl	iir, r16
1219	extru	r16, 6, 6, r24
1220	comib,=,n 1, r24, TLABEL(all)
1221	extru	r16, 24, 6, r24
1222	subi,<>	0x23, r24, r0
1223	b	TLABEL(all)
1224	/* otherwise generate a flush-only tlb entry */
1225	copy	r0, r17
1226	zdep	r8, 30, 15, r25
1227	depi	-13, 11, 7, r25
1228	ldo	2(r25), r25   /* 3? */
1229	IDTLBAF(17)
1230	IDTLBPF(25)
1231	TLB_STATS_AFT(dtlb)
1232	rfir
1233	nop
1234EXIT($dtlbna_l)
1235
1236LEAF_ENTRY($dtlb_l)
1237	TLB_STATS_PRE(dtlb)
1238	TLB_PULL_L(0, TLABEL(all))
1239	IDTLBAF(17)
1240	IDTLBPF(25)
1241#ifdef USE_HPT
1242	/*
1243	 * cache the next page mapping in the hpt.
1244	 *
1245	 * mapping for a page at the end of each 128k is uncachable
1246	 * in the hvt since it'd be in the tlb itself and thus there
1247	 * is no reason to cache it!
1248	 * as a side effect this avoids recomputing hpt entry and
1249	 * retraversing the whole page table each time.
1250	 */
1251
1252	ldo	PAGE_SIZE(r9), r9
1253	extru,<> r9, 20, 5, r0
1254	b,n	$dtlb_done_l	/* skip if no simple advance */
1255	/* do not check the PT overlap since the above
1256	 * check already guaranties that */
1257
1258	/* ripped from TLB_PULL_L(0) */
1259	extru	r9, 19, 10, r16		/* r24 was loaded in the TLB_PULL_L */
1260	ldwx,s	r16(r24), r17		/* va -> pa:prot */
1261	sh2addl	r16, r24, r25
1262	combt,=,n r0, r17, $dtlb_done_l
1263	copy	r17, r16
1264	depi	0, 21, 1, r17
1265	sub,=	r16, r17, r0		/* do not store if unchanged */
1266	stws	r17, 0(r25)		/* store back w/ the bits */
1267	shd	r17, r0, 13, r25
1268	dep	r8, 30, 15, r25		/* mix0r the pid from the sid */
1269	dep	r0, 31, 12, r17		/* needed ? */
1270	addi	2, r25, r25
1271	extru	r17, 24, 25, r17
1272	sync
1273
1274	mfctl	cr28, r24
1275	VTAG
1276	ldo	16(r24), r24
1277	stw	r16, 0(r24)
1278	stw	r25, 4(r24)
1279	stw	r17, 8(r24)
1280$dtlb_done_l
1281#endif
1282	TLB_STATS_AFT(dtlb)
1283	rfir
1284	nop
1285EXIT($dtlb_l)
1286#endif /* HP7100LC_CPU */
1287
1288#if defined(HP8000_CPU) || defined(HP8200_CPU) || defined(HP8500_CPU)
1289	.level	2.0w
1290
1291	/* xlate 32bit->64bit pte */
1292#define	TLB_PCX2PCXU \
1293	extrw,u	r25, 14, 13, r16		! \
1294	depdi	0, 31, 32, r17			! \
1295		/* fix io mappings */		! \
1296	extrd,s	r17, 42, 4, r1			! \
1297	addi,<>	1, r1, r0			! \
1298	depdi	-1, 38, 32, r17			! \
1299		/* fix prom mappings */		! \
1300	extrd,s	r17, 46, 8, r1			! \
1301	addi,<>	0x10, r1, r0			! \
1302	depdi	0, 38, 4, r17			! \
1303		/* weak ordering, dyn bp */	! \
1304	depwi	1, 31, 2, r16			! \
1305	depdi	0, 44, 30, r25			! \
1306	depd	r16, 14, 15, r25
1307
1308LEAF_ENTRY($tlbd_u)
1309	TLB_STATS_PRE(tlbd)
1310	TLB_PULL_L(1, TLABEL(all))
1311	TLB_PCX2PCXU
1312	idtlbt	r17, r25
1313	TLB_STATS_AFT(tlbd)
1314	rfir
1315	nop
1316EXIT($tlbd_u)
1317
1318LEAF_ENTRY($itlb_u)
1319	TLB_STATS_PRE(itlb)
1320	TLB_PULL_L(0, TLABEL(all))
1321	extru,=	r25, 5, 1, r0	/* gateway page needs to be public */
1322	depi	0, 30, 15, r25
1323	TLB_PCX2PCXU
1324	iitlbt	r17, r25
1325	TLB_STATS_AFT(itlb)
1326	rfir
1327	nop
1328EXIT($itlb_u)
1329
1330LEAF_ENTRY($dtlbna_u)
1331ALTENTRY($itlbna_u)
1332	TLB_STATS_PRE(dtlb)
1333	TLB_PULL_L(0, $dtlbna_u_fake)
1334	TLB_PCX2PCXU
1335	idtlbt	r17, r25
1336	TLB_STATS_AFT(dtlb)
1337	rfir
1338	nop
1339$dtlbna_u_fake
1340	/* parse prober/w insns, have to decent to trap() to set regs proper */
1341	mfctl	iir, r16
1342	extru	r16, 6, 6, r24
1343	comib,=,n 1, r24, TLABEL(all)
1344	extru	r16, 24, 6, r24
1345	subi,<>	0x23, r24, r0
1346	b	TLABEL(all)
1347	/* otherwise generate a flush-only tlb entry */
1348	copy	r0, r17
1349	zdep	r8, 30, 15, r25
1350	depi	-13, 11, 7, r25
1351	ldo	2(r25), r25   /* 3? */
1352	idtlbt	r17, r25
1353	TLB_STATS_AFT(dtlb)
1354	rfir
1355	nop
1356EXIT($dtlbna_u)
1357
1358LEAF_ENTRY($dtlb_u)
1359	TLB_STATS_PRE(dtlb)
1360	TLB_PULL_L(0, TLABEL(all))
1361	TLB_PCX2PCXU
1362	idtlbt	r17, r25
1363	TLB_STATS_AFT(dtlb)
1364	rfir
1365	nop
1366EXIT($dtlb_u)
1367
1368	.level	1.1
1369#endif /* HP8000_CPU */
1370
1371	.align	64
1372	.export	TLABEL(all), entry
1373ENTRY(TLABEL(all),0)
1374	/* r1 still has trap type */
1375
1376	/*
1377	 * at this point we have:
1378	 *	psw copied into ipsw
1379	 *	psw = E(default), M(1 if HPMC, else 0)
1380	 *	PL = 0
1381	 *	r1, r8, r9, r16, r17, r24, r25 shadowed (maybe)
1382	 *	trap number in r1 (old r1 is saved in tr7)
1383	 */
1384
1385	/* do not overwrite cr28 */
1386	mtctl	t3, cr26
1387
1388	mfctl	cr29, t3
1389	ldo	CI_TRAP_SAVE(t3), t3
1390	stw	t1, TF_R22(t3)		/* use ,bc */
1391	stw	t2, TF_R21(t3)
1392
1393	mfctl	cr26, t1
1394	stw	sp, TF_R30(t3)	/* sp */
1395	stw	t1, TF_R20(t3)	/* t3 */
1396
1397	/*
1398	 * Now, save away other volatile state that prevents us from turning
1399	 * the PC queue back on, namely, the pc queue and ipsw, and the
1400	 * interrupt information.
1401	 */
1402
1403	mfctl	eiem, t1
1404	mfctl	ipsw, t2
1405	stw	t1, TF_CR15(t3)		/* use ,bc */
1406	stw	t2, TF_CR22(t3)
1407
1408	mfsp	sr3, t1
1409	mfctl	pidr1, t2
1410	stw	t1, TF_SR3(t3)
1411	stw	t2, TF_CR8(t3)
1412
1413	/*
1414	 * Setup kernel context
1415	 */
1416
1417	ldi	HPPA_PID_KERNEL,t1
1418	mtctl	t1, pidr1
1419	mtsp	r0, sr3
1420
1421	/* this will enable interrupts after `cold' */
1422	mfctl	cr29, t1
1423	ldw	CI_PSW(t1), t2
1424	mtctl	r0, eiem
1425	mtctl	t2, ipsw
1426
1427	mfctl	pcsq, t1
1428	mtctl	r0, pcsq
1429	mfctl	pcsq, t2
1430	stw	t1, TF_IISQH(t3)	/* use ,bc */
1431	stw	t2, TF_IISQT(t3)
1432	mtctl	r0, pcsq
1433
1434	/*
1435	 * Set up the kernel stack pointer.  If the trap happened
1436	 * while we were in unprivileged code, or in privileged
1437	 * code in the SYSCALLGATE page, move to the kernel stack
1438	 * in curproc's PCB; otherwise, start a new stack frame
1439	 * on whatever kernel stack we're already on.
1440	 *
1441	 * This used to check only for a trap while we were in
1442	 * unprivileged code, but this ignored the possibility
1443	 * that a trap could come in during the period between
1444	 * a gateway instruction to raise privilege and the
1445	 * disabling of interrupts.  During this period we're
1446	 * still on the user's stack, and we must move to the
1447	 * kernel stack.
1448	 *
1449	 * - fredette@
1450	 */
1451	mfctl	pcoq, t1
1452	ldil	L%SYSCALLGATE, t2
1453	ldo	TF_PHYS-1(sp), sp
1454	dep	t1, 31, PGSHIFT, t2
1455	dep,<>	t1, 31, 2, r0
1456	comb,<>	t1, t2, $trap_from_kernel
1457	dep	r0, 31, 6, sp
1458
1459	mfctl	cr29, t2
1460	ldw	CI_CURPROC(t2), t2
1461	depi	1, T_USER_POS, 1, r1
1462	depi	1, TFF_LAST_POS, 1, r1
1463	ldw	P_ADDR(t2), sp
1464	ldo	NBPG(sp), sp
1465
1466$trap_from_kernel
1467	ldil	L%$trapnowvirt, t2
1468	ldo	R%$trapnowvirt(t2), t2
1469	mtctl	t2, pcoq
1470	stw	t1, TF_IIOQH(t3)
1471	ldo	4(t2), t2
1472	mfctl	pcoq, t1
1473	stw	t1, TF_IIOQT(t3)
1474	mtctl	t2, pcoq
1475
1476	mfctl	isr, t1
1477	mfctl	ior, t2
1478	stw	t1, TF_CR20(t3)		/* use ,bc */
1479	stw	t2, TF_CR21(t3)
1480
1481	mfctl	iir, t2
1482	stw	t2, TF_CR19(t3)
1483	stw	r1, TF_FLAGS(t3)
1484
1485	mfctl	rctr, t1		/* gotta get it before R is up */
1486
1487	copy	sp, t3
1488	ldo	HPPA_FRAME_SIZE+TRAPFRAME_SIZEOF(sp), sp
1489	rfir
1490	nop ! nop ! nop ! nop ! nop ! nop ! nop ! nop
1491$trapnowvirt
1492	/*
1493	 * t3 contains the virtual address of the trapframe
1494	 * sp is loaded w/ the right VA (we did not need it being physical)
1495	 */
1496
1497	mfctl	ccr, t2
1498	stw	t1, TF_CR0(sr3, t3)
1499	stw	t2, TF_CR10(sr3, t3)
1500
1501	mfsp	sr0, t1
1502	mfsp	sr1, t2
1503	stw	t1, TF_SR0(sr3, t3)
1504	stw	t2, TF_SR1(sr3, t3)
1505
1506	mfsp	sr2, t1
1507	mfsp	sr4, t2
1508	stw	t1, TF_SR2(sr3, t3)
1509	stw	t2, TF_SR4(sr3, t3)
1510
1511	mfsp	sr5, t2
1512	mfsp	sr6, t1
1513	stw	t2, TF_SR5(sr3, t3)
1514	stw	t1, TF_SR6(sr3, t3)
1515
1516	mfsp	sr7, t1
1517	mfctl	pidr2, t2
1518	stw	t1, TF_SR7(sr3, t3)
1519	stw	t2, TF_CR9(sr3, t3)
1520
1521	mtsp	r0, sr0
1522	mtsp	r0, sr1
1523	mtsp	r0, sr2
1524	mtsp	r0, sr4
1525	mtsp	r0, sr5
1526	mtsp	r0, sr6
1527	mtsp	r0, sr7
1528
1529#if pbably_not_worth_it
1530	mfctl	pidr3, t1
1531	mfctl	pidr4, t2
1532	stw	t1, TF_CR12(t3)
1533	stw	t2, TF_CR13(t3)
1534#endif
1535
1536	/*
1537	 * Save all general registers that we haven't saved already
1538	 */
1539
1540	mfctl	sar, t1			/* use ,bc each cache line */
1541	stw	t1, TF_CR11(t3)
1542	stw	r1, TF_R1(t3)
1543	stw	r2, TF_R2(t3)
1544	stw	r3, TF_R3(t3)
1545
1546	copy	sp, r3
1547	stw,mb	r0, -HPPA_FRAME_SIZE(r3)
1548
1549	/*
1550	 * Copy partially saved state from the store into the frame
1551	 */
1552	mfctl	cr29, t2
1553	ldo	CI_TRAP_SAVE(t2), t2
1554	/* use ,bc each cache line */
1555	ldw  0(t2), r1 ! ldw  4(t2), t1 ! stw r1,  0(t3) ! stw t1,  4(t3)
1556	ldw  8(t2), r1 ! ldw 12(t2), t1 ! stw r1,  8(t3) ! stw t1, 12(t3)
1557	ldw 16(t2), r1 ! ldw 20(t2), t1 ! stw r1, 16(t3) ! stw t1, 20(t3)
1558	ldw 24(t2), r1 ! ldw 28(t2), t1 ! stw r1, 24(t3) ! stw t1, 28(t3)
1559	ldw 32(t2), r1 ! ldw 36(t2), t1 ! stw r1, 32(t3) ! stw t1, 36(t3)
1560	ldw 40(t2), r1 ! ldw 44(t2), t1 ! stw r1, 40(t3) ! stw t1, 44(t3)
1561	ldw 48(t2), r1 ! ldw 52(t2), t1 ! stw r1, 48(t3) ! stw t1, 52(t3)
1562	ldw 56(t2), r1 ! ldw 60(t2), t1 ! stw r1, 56(t3) ! stw t1, 60(t3)
1563
1564	stw	r4, TF_R4(t3)
1565	stw	r5, TF_R5(t3)
1566	stw	r6, TF_R6(t3)
1567	stw	r7, TF_R7(t3)
1568	stw	r8, TF_R8(t3)
1569	stw	r9, TF_R9(t3)
1570	stw	r10, TF_R10(t3)
1571	stw	r11, TF_R11(t3)
1572	stw	r12, TF_R12(t3)
1573	stw	r13, TF_R13(t3)
1574	stw	r14, TF_R14(t3)
1575	stw	r15, TF_R15(t3)
1576	stw	r16, TF_R16(t3)
1577	stw	r17, TF_R17(t3)
1578	stw	r18, TF_R18(t3)
1579	stw	r19, TF_R19(t3)	/* t4 */
1580	stw	r23, TF_R23(t3)
1581	stw	r24, TF_R24(t3)
1582	stw	r25, TF_R25(t3)
1583	stw	r26, TF_R26(t3)
1584	stw	r27, TF_R27(t3)
1585	stw	r28, TF_R28(t3)
1586	stw	r29, TF_R29(t3)
1587	stw	r31, TF_R31(t3)
1588
1589	/*
1590	 * Save the necessary control registers that have not already saved.
1591	 */
1592
1593#ifdef DDB
1594	/*
1595	 * Save hpt mask and v2p translation table pointer
1596	 */
1597	mfctl	eirr, t1
1598	mfctl	vtop, t2
1599	stw	t1, TF_CR23(t3)
1600	stw	t2, TF_CR25(t3)
1601
1602	mfctl	cr28, t2
1603	stw	t2, TF_CR28(t3)
1604#endif
1605	mfctl	cr27, t1
1606	mfctl	cr30, t2
1607	stw	t1, TF_CR27(t3)
1608	stw	t2, TF_CR30(t3)
1609
1610	/*
1611	 * load the global pointer for the kernel
1612	 */
1613
1614	ldil	L%$global$, dp
1615	ldo	R%$global$(dp), dp
1616
1617	/*
1618	 * call the C routine trap().
1619	 * form trap type in the first argument to trap()
1620	 */
1621	ldw	TF_FLAGS(t3), arg0
1622	dep	r0, 24, 25, arg0
1623	copy	t3, arg1
1624
1625	copy	arg0, r4
1626	copy	arg1, r5
1627
1628	.import	trap, code
1629	ldil	L%trap,t1
1630	ldo	R%trap(t1),t1
1631	.call
1632	blr	r0,rp
1633	bv,n	r0(t1)
1634	nop
1635
1636	copy	r5, t3
1637
1638	/* see if curproc have changed */
1639	extru,<> r4, TFF_LAST_POS, 1, r0
1640	b	$syscall_return
1641
1642	/* see if curproc have really changed */
1643	mfctl	cr29, t1
1644	ldw	CI_CURPROC(t1), t2
1645	sub,<>	r0, t2, r0
1646	ldw	P_MD_REGS(t2), t3
1647
1648	/* means curproc has actually changed */
1649	b	$syscall_return
1650	nop
1651EXIT(TLABEL(all))
1652
1653#if defined(HP7000_CPU)
1654/*
1655 * void desidhash_s(void)
1656 */
1657LEAF_ENTRY(desidhash_s)
1658	sync
1659	MFCPU_C_PCXST(DR_CPUCFG,22)	/* t1 */
1660	MFCPU_C_PCXST(DR_CPUCFG,22)
1661	nop
1662	nop
1663	depi	0, DR0_PCXS_DHE, 3, t1	/* 3: DR0_PCXS_DOMAIN|DR0_PCXS_IHE */
1664	depi	1, DR0_PCXS_EQWSTO, 1, t1
1665	/* clear `write to clear' bits so they don't get reset */
1666	depi	0, DR0_PCXS_DHPMC, 1, t1
1667	depi	0, DR0_PCXS_ILPMC, 1, t1
1668	sync
1669	MTCPU_PCXST(22,DR_CPUCFG)
1670	MTCPU_PCXST(22,DR_CPUCFG)
1671	nop
1672	nop
1673	bv	0(rp)
1674	extru	t1, 4, 5, ret0	/* return chip revision */
1675EXIT(desidhash_s)
1676#endif /* HP7000_CPU */
1677
1678#if defined(HP7100_CPU) || defined(HP7200_CPU)
1679/*
1680 * void desidhash_t(void)
1681 */
1682LEAF_ENTRY(desidhash_t)
1683	sync
1684	MFCPU_C_PCXST(DR_CPUCFG,22)	/* t1 */
1685	MFCPU_C_PCXST(DR_CPUCFG,22)
1686	nop
1687	nop
1688	depi	0, DR0_PCXT_IHE, 1, t1
1689	depi	0, DR0_PCXT_DHE, 1, t1
1690	/* clear `write to clear' bits so they don't get reset */
1691	depi	0, DR0_PCXT_DHPMC, 1, t1
1692	depi	0, DR0_PCXT_ILPMC, 1, t1
1693	sync
1694	MTCPU_PCXST(22,DR_CPUCFG)
1695	MTCPU_PCXST(22,DR_CPUCFG)
1696	nop
1697	nop
1698	bv	0(rp)
1699	extru	t1, 4, 5, ret0	/* return chip revision */
1700EXIT(desidhash_t)
1701#endif /* HP7100_CPU || HP7200_CPU */
1702
1703#ifdef HP7300LC_CPU
1704	.data
1705	BSS(eaio_l2_mask, 4)
1706LEAF_ENTRY(eaio_l2)
1707	ldil	L%eaio_l2_mask, t2
1708	ldw	R%eaio_l2_mask(t2), t1
1709	or	t1, arg0, t1
1710	MTCPU_PCXL(22, DR0_PCXL2_ACCEL_IO)
1711	nop
1712	nop
1713	bv	0(rp)
1714	stw	t1, R%eaio_l2_mask(t2)
1715EXIT(eaio_l2)
1716#endif /* HP7300LC_CPU */
1717
1718#if defined(HP7100LC_CPU) || defined(HP7300LC_CPU)
1719
1720/*
1721 * int
1722 * ibtlb_l(int i, pa_space_t sp, vaddr_t va, paddr_t pa, vsize_t sz, u_int prot)
1723 */
1724LEAF_ENTRY(ibtlb_l)
1725	rsm	(PSL_R|PSL_I), t4
1726	nop ! nop ! nop ! nop ! nop ! nop ! nop
1727
1728	bv	0(rp)
1729	mtsm	t4
1730EXIT(ibtlb_l)
1731
1732/*
1733 * int desidhash_l(void)
1734 */
1735LEAF_ENTRY(desidhash_l)
1736	MFCPU_C_PCXL(DR_CPUCFG,22)	/* t1 */
1737	nop
1738	nop
1739	depi	0, DR0_PCXL_L2IHASH_EN, 2, t1	/* 2: DR0_PCXL_L2DHASH_EN */
1740#if 0 /* better trust the PROM if it left some bits set here */
1741	depi	0, DR0_PCXL_DUAL_DIS, 2, t1
1742#endif
1743	/* clear `write to clear' bits so they don't get reset */
1744	depi	0, DR0_PCXL_L2IHPMC, 1, t1
1745	depi	0, DR0_PCXL_L2DHPMC, 1, t1
1746	depi	0, DR0_PCXL_L1IHPMC, 1, t1
1747	depi	0, DR0_PCXL_L2PARERR, 4, t1
1748	sync
1749	MTCPU_PCXL(22,DR_CPUCFG)
1750	nop
1751	nop
1752	bv	0(rp)
1753	extru	t1, 4, 5, ret0	/* return chip revision */
1754EXIT(desidhash_l)
1755
1756#endif /* HP7100LC_CPU */
1757
1758#if defined(HP8000_CPU) || defined(HP8200_CPU) || defined(HP8500_CPU)
1759	.level	2.0w
1760LEAF_ENTRY(desidhash_u)
1761	MFCPU_PCXU(2,28)
1762	depdi	0, 54, 1, r28
1763	MTCPU_PCXU(28,2)
1764	bv	r0(rp)
1765	copy	r0, ret0	/* XXX dunno how to get chip rev */
1766EXIT(desidhash_u)
1767
1768LEAF_ENTRY(ibtlb_u)
1769	/* TODO insert a locked large tlb entry */
1770	bv	0(rp)
1771	nop
1772EXIT(ibtlb_u)
1773
1774LEAF_ENTRY(pbtlb_u)
1775	/* TODO purge a locked tlb entry */
1776	bv	0(rp)
1777	nop
1778EXIT(pbtlb_u)
1779	.level	1.1
1780#endif /* HP8000_CPU */
1781
1782/*
1783 * High Priority Machine Check Interrupt
1784 */
1785	.export	TLABEL(hpmc), entry
1786ENTRY(TLABEL(hpmc),0)
1787ALTENTRY(hpmc_tramp)
1788
1789	mtsp	r0, sr0
1790	ldil	L%hppa_vtop, t1
1791	ldw	R%hppa_vtop(t1), t1
1792	mtctl	t1, CR_VTOP
1793
1794	.import	hpmc_dump, code
1795	ldil	L%hpmc_dump, rp
1796	ldo	R%hpmc_dump(rp), rp
1797	mfctl	cr29, %arg2
1798	ldw	CI_PSW(%arg2), %arg2
1799	depi	0, PSL_I_POS, 1, %arg2
1800	stw	%arg2, CI_PSW(t1)
1801	ldil	L%emrg_stack, arg1
1802	b	$kernel_setup
1803	ldw	R%emrg_stack(arg1), arg1
1804
1805	/* never returns, but still */
1806	ldil	L%HPPA_GBCAST, t1
1807	ldi	CMD_RESET, t2
1808	stw	t2, R%HPPA_GBCAST(t1)
1809hpmc_never_dies
1810	b	hpmc_never_dies
1811	nop
1812ALTENTRY(hpmc_tramp_end)
1813EXIT(TLABEL(hpmc))
1814
1815/*
1816 * transfer of control handler
1817 */
1818ENTRY(hppa_toc,0)
1819
1820	mtsp	r0, sr0
1821	ldil	L%hppa_vtop, t1
1822	ldw	R%hppa_vtop(t1), t1
1823	mtctl	t1, CR_VTOP
1824
1825	/* TODO reload btlb */
1826
1827	.import	boot, code
1828	ldil	L%boot, rp
1829	ldo	R%boot(rp), rp
1830	mfctl	cr29, %arg2
1831	ldw	CI_PSW(%arg2), %arg2
1832	depi	0, PSL_I_POS, 1, %arg2
1833	stw	%arg2, CI_PSW(t1)
1834	ldi	0, arg0
1835	ldil	L%emrg_stack, arg1
1836	b	$kernel_setup
1837	ldw	R%emrg_stack(arg1), arg1
1838
1839ALTENTRY(hppa_toc_end)
1840	.word	0
1841EXIT(hppa_toc)
1842
1843/*
1844 * power fail recovery handler
1845 */
1846ENTRY(hppa_pfr,0)
1847
1848	mtsp	r0, sr0
1849	ldil	L%hppa_vtop, t1
1850	ldw	R%hppa_vtop(t1), t1
1851	mtctl	t1, CR_VTOP
1852
1853	/* TODO reload btlb */
1854
1855	.import	boot, code
1856	ldil	L%boot, rp
1857	ldo	R%boot(rp), rp
1858	mfctl	cr29, %arg2
1859	ldw	CI_PSW(%arg2), %arg2
1860	depi	0, PSL_I_POS, 1, %arg2
1861	stw	%arg2, CI_PSW(t1)
1862	ldi	RB_HALT|RB_POWERDOWN, arg0
1863	ldil	L%emrg_stack, arg1
1864	b	$kernel_setup
1865	ldw	R%emrg_stack(arg1), arg1
1866
1867ALTENTRY(hppa_pfr_end)
1868	.word	0
1869EXIT(hppa_pfr)
1870
1871#if 0
1872	.align	8
1873intr_ticks
1874	.word	0, 0
1875
1876#define	INTR_PROF_PRE \
1877	mfctl	itmr, r9		! \
1878	mtctl	r9, tr5
1879#define	INTR_PROF_AFT \
1880	mfctl	itmr, r8		! \
1881	mfctl	tr5, r9			! \
1882	ldil	L%intr_ticks, r1	! \
1883	ldo	R%intr_ticks(r1), r1	! \
1884	sub	r8, r9, r8		! \
1885	ldw	0(r1), r16		! \
1886	ldw	4(r1), r17		! \
1887	add	r8, r16, r16		! \
1888	addi	1, r17, r17		! \
1889	stw	r16, 0(r1)		! \
1890	stw	r17, 4(r1)
1891#else
1892#define	INTR_PROF_PRE	/* */
1893#define	INTR_PROF_AFT	/* */
1894#endif
1895
1896	.import	imask, data
1897	.import	intr_table, data
1898	.align	32
1899ENTRY(TLABEL(intr),0)
1900	/*
1901	 * r8 is set to eirr in the INTRPRE
1902	 */
1903
1904	INTR_PROF_PRE
1905
1906	ldil	L%intr_table + 32*32, r1
1907	ldo	R%intr_table + 32*32(r1), r1
1908	mfctl	cr29, r17
1909	b	$intr_cont
1910	ldw	CI_IPENDING(r17), r24
1911
1912$intr_ffs
1913	addi	-32, r1, r1
1914	bb,>=	r8, 0, $intr_ffs
1915	zdep	r8, 30, 31, r8
1916
1917	ldw	0(r1), r17
1918	bb,>=,n	r17, 23, $intr_nocall
1919
1920	ldw	2*4(r1), r16	/* func */
1921	ldw	3*4(r1), r9	/* arg: ioreg */
1922	mtctl	r1, tr7
1923	bv	r0(r16)
1924	ldw	6*4(r1), r1	/* next: sub-intr_table */
1925
1926$intr_nocall
1927	ldw	4*4(r1), r17	/* bit */
1928	or	r17, r24, r24	/* ipending */
1929
1930	/* also return from nested handlers */
1931$intr_cont
1932	comb,<>,n r0, r8, $intr_ffs
1933	ldw	-32(r1), r0	/* preload cache */
1934
1935	mfctl	cr29, r17
1936	stw	r24, CI_IPENDING(r17)
1937	ldw	CI_CPL(r17), r17
1938	ldil	L%imask, r16
1939	ldo	R%imask(r16), r16
1940	ldwx,s	r17(r16), r25
1941
1942	INTR_PROF_AFT
1943
1944	ldi	T_INTERRUPT, r1
1945	andcm,=	r24, r25, r0
1946	b	TLABEL(all)
1947	nop
1948
1949	rfir
1950	nop
1951EXIT(TLABEL(intr))
1952
1953/*
1954 * called with:
1955 *	r1	sub intr_table
1956 *	r9	ioregs
1957 *	r24	ipending (in/out)
1958 *	tr7	saved r1 (restore on return)
1959 * free:
1960 *	r9, r16, r17, r25
1961 */
1962	.align	32
1963LEAF_ENTRY(gsc_intr)
1964	ldw	0(r9), r16	/* irr */
1965
1966	/* we know that first 5 bits are never used ... should skip */
1967$gsc_intr_loop
1968	comb,=,n r0, r16, $intr_cont
1969	mfctl	tr7, r1
1970$gsc_ffs
1971	addi	32, r1, r1
1972	bb,>=	r16, 31, $gsc_ffs
1973	shd	r0, r16, 1, r16
1974
1975	ldo	-32(r1), r9
1976$gsc_share
1977	ldw	4*4(r9), r17	/* bit */
1978	ldw	5*4(r9), r9	/* share */
1979
1980	comb,<>	r0, r9, $gsc_share
1981	or	r17, r24, r24	/* ipending */
1982
1983	b,n	$gsc_intr_loop
1984EXIT(gsc_intr)
1985
1986	/* see above for calling conventions */
1987	.align	32
1988LEAF_ENTRY(dino_intr)
1989	ldw	3*4(r9), r16	/* irr0 */
1990
1991$dino_intr_loop
1992	comb,=,n r0, r16, $intr_cont
1993	mfctl	tr7, r1
1994$dino_ffs
1995	addi	32, r1, r1
1996	bb,>=	r16, 31, $dino_ffs
1997	shd	r0, r16, 1, r16
1998
1999	ldo	-32(r1), r9
2000$dino_share
2001	ldw	4*4(r9), r17	/* bit */
2002	ldw	5*4(r9), r9	/* share */
2003
2004	comb,<>	r0, r9, $dino_share
2005	or	r17, r24, r24	/* ipending */
2006
2007	b,n	$dino_intr_loop
2008EXIT(dino_intr)
2009
2010	.export	TLABEL(ibrk), entry
2011ENTRY(TLABEL(ibrk),0)
2012	/* If called by a user process then always pass it to trap() */
2013	mfctl	pcoq, r8
2014	extru,=	r8, 31, 2, r0
2015	b,n	$ibrk_bad
2016
2017	/* don't accept breaks from data segments */
2018	.import etext
2019	ldil	L%etext, r9
2020	ldo	R%etext(r9), r9
2021	comb,>>=,n r8, r9, $ibrk_bad
2022
2023	mfctl	iir, r8
2024	extru	r8, 31, 5, r9
2025	comib,<>,n HPPA_BREAK_KERNEL, r9, $ibrk_bad
2026
2027	/* now process all those `break' calls we make */
2028	extru	r8, 18, 13, r9
2029	comib,=,n HPPA_BREAK_GET_PSW, r9, $ibrk_getpsw
2030	comib,=,n HPPA_BREAK_SET_PSW, r9, $ibrk_setpsw
2031	comib,=,n HPPA_BREAK_SPLLOWER, r9, $ibrk_spllower
2032
2033$ibrk_bad
2034	/* illegal (unimplemented) break entry point */
2035	b	TLABEL(all)
2036	nop
2037
2038$ibrk_getpsw
2039	b	$ibrk_exit
2040	mfctl	ipsw, ret0
2041
2042$ibrk_setpsw
2043	mfctl	ipsw, ret0
2044	b	$ibrk_exit
2045	mtctl	arg0, ipsw
2046
2047$ibrk_spllower
2048	/* skip the break */
2049	mtctl	r0, pcoq
2050	mfctl	pcoq, r9
2051	mtctl	r9, pcoq
2052	ldo	4(r9), r9
2053	mtctl	r9, pcoq
2054
2055	mfctl	cr29, r17
2056	ldw	CI_IPENDING(r17), r8
2057	ldil	L%imask, r9
2058	ldo	R%imask(r9), r9
2059	ldw	CI_CPL(r17), ret0
2060	ldwx,s	arg0(r9), r16
2061	stw	arg0, CI_CPL(r17)
2062	ldi	T_INTERRUPT, r1
2063	andcm,=	r8, r16, r0
2064	b	TLABEL(all)
2065	nop
2066	rfir
2067	nop
2068
2069	/* insert other fast breaks here */
2070	nop ! nop
2071
2072$ibrk_exit
2073	/* skip the break */
2074	mtctl	r0, pcoq
2075	mfctl	pcoq, r9
2076	mtctl	r9, pcoq
2077	ldo	4(r9), r9
2078	mtctl	r9, pcoq
2079
2080	rfir
2081	nop
2082EXIT(TLABEL(ibrk))
2083
2084LEAF_ENTRY(fpu_exit)
2085	/* enable coprocessor XXX */
2086	depi	3, 25, 2, r1
2087	mtctl	r1, ccr
2088
2089	ldil	L%fpu_scratch, %r25
2090	ldo	R%fpu_scratch(%r25), %r25
2091	fstds	%fr0, 0(%r25)
2092	sync
2093	bv	%r0(%rp)
2094	mtctl	r0, ccr
2095EXIT(fpu_exit)
2096
2097LEAF_ENTRY(fpu_save)
2098	fstds,ma %fr0 , 8(arg0)
2099	fstds,ma %fr1 , 8(arg0)
2100	fstds,ma %fr2 , 8(arg0)
2101	fstds,ma %fr3 , 8(arg0)
2102	fstds,ma %fr4 , 8(arg0)
2103	fstds,ma %fr5 , 8(arg0)
2104	fstds,ma %fr6 , 8(arg0)
2105	fstds,ma %fr7 , 8(arg0)
2106	fstds,ma %fr8 , 8(arg0)
2107	fstds,ma %fr9 , 8(arg0)
2108	fstds,ma %fr10, 8(arg0)
2109	fstds,ma %fr11, 8(arg0)
2110	fstds,ma %fr12, 8(arg0)
2111	fstds,ma %fr13, 8(arg0)
2112	fstds,ma %fr14, 8(arg0)
2113	fstds,ma %fr15, 8(arg0)
2114	fstds,ma %fr16, 8(arg0)
2115	fstds,ma %fr17, 8(arg0)
2116	fstds,ma %fr18, 8(arg0)
2117	fstds,ma %fr19, 8(arg0)
2118	fstds,ma %fr20, 8(arg0)
2119	fstds,ma %fr21, 8(arg0)
2120	fstds,ma %fr22, 8(arg0)
2121	fstds,ma %fr23, 8(arg0)
2122	fstds,ma %fr24, 8(arg0)
2123	fstds,ma %fr25, 8(arg0)
2124	fstds,ma %fr26, 8(arg0)
2125	fstds,ma %fr27, 8(arg0)
2126	fstds,ma %fr28, 8(arg0)
2127	fstds,ma %fr29, 8(arg0)
2128	fstds,ma %fr30, 8(arg0)
2129	fstds    %fr31, 0(arg0)
2130	bv	r0(rp)
2131	sync
2132EXIT(fpu_save)
2133
2134#ifdef FPEMUL
2135	/*
2136	 * Emulate FPU
2137	 *
2138	 * iisq:iioq - exception triggered instruction
2139	 */
2140ENTRY($fpu_emulate,320)
2141	copy	r31, r9
2142
2143	mfctl	cr29, r31
2144	ldw	CI_STACK(r31), r31
2145
2146	/* stw	r1 , TF_R1 (r31) shadowed */
2147	stw	r2 , TF_R2 (r31)
2148	stw	r3 , TF_R3 (r31)
2149	stw	r4 , TF_R4 (r31)
2150	stw	r5 , TF_R5 (r31)
2151	stw	r6 , TF_R6 (r31)
2152	stw	r7 , TF_R7 (r31)
2153	/* stw	r8 , TF_R8 (r31) shadowed */
2154	/* stw	r9 , TF_R9 (r31) shadowed */
2155	stw	r10, TF_R10(r31)
2156	stw	r11, TF_R11(r31)
2157	stw	r12, TF_R12(r31)
2158	stw	r13, TF_R13(r31)
2159	stw	r14, TF_R14(r31)
2160	stw	r15, TF_R15(r31)
2161	/* stw	r16, TF_R16(r31) shadowed */
2162	/* stw	r17, TF_R17(r31) shadowed */
2163	stw	r18, TF_R18(r31)
2164	stw	r19, TF_R19(r31)
2165	stw	r20, TF_R20(r31)
2166	stw	r21, TF_R21(r31)
2167	stw	r22, TF_R22(r31)
2168	stw	r23, TF_R23(r31)
2169	/* stw	r24, TF_R24(r31) shadowed */
2170	/* stw	r25, TF_R25(r31) shadowed */
2171	stw	r26, TF_R26(r31)
2172	stw	r27, TF_R27(r31)
2173	stw	r28, TF_R28(r31)
2174	stw	r29, TF_R29(r31)
2175	stw	sp, TF_R30(r31)
2176	stw	r9, TF_R31(r31)
2177	copy	r1, arg0
2178	mfctl	sar, r1
2179	stw	r1, TF_CR11(r31)
2180	stw	arg0, TF_CR19(r31)
2181
2182	ldo	TRAPFRAME_SIZEOF(r31), r3
2183	ldo	TRAPFRAME_SIZEOF+HPPA_FRAME_SIZE(r31), sp
2184
2185	ldil	L%$global$, dp
2186	ldo	R%$global$(dp), dp
2187
2188	.import	fpu_emulate, code
2189	ldil	L%fpu_emulate,t1
2190	ldo	R%fpu_emulate(t1),t1
2191	mfctl	cr30, arg2
2192	.call
2193	blr	r0,rp
2194	bv,n	0(t1)
2195	nop
2196
2197	mfctl	cr30, r25
2198	ldi	32, r1
2199
2200	ldw	4(r25), r17	/* fpu exception reg 0 */
2201	zdep	ret0, 5, 6, r17	/* intentionally zero the insn */
2202	stw	r17, 4(r25)
2203
2204	mfctl	cr29, r31
2205	ldw	CI_STACK(r31), r31
2206
2207	ldw	TF_CR11(r31), r1
2208	ldw	TF_R2 (r31), r2
2209	ldw	TF_R3 (r31), r3
2210	mtsar	r1
2211	copy	ret0, r1
2212	ldw	TF_R4 (r31), r4
2213	ldw	TF_R5 (r31), r5
2214	ldw	TF_R6 (r31), r6
2215	ldw	TF_R7 (r31), r7
2216	/* ldw	TF_R8 (r31), r8 shadowed */
2217	/* ldw	TF_R9 (r31), r9 shadowed */
2218	ldw	TF_R10(r31), r10
2219	ldw	TF_R11(r31), r11
2220	ldw	TF_R12(r31), r12
2221	ldw	TF_R13(r31), r13
2222	ldw	TF_R14(r31), r14
2223	ldw	TF_R15(r31), r15
2224	/* ldw	TF_R16(r31), r16 shadowed */
2225	/* ldw	TF_R17(r31), r17 shadowed */
2226	ldw	TF_R18(r31), r18
2227	ldw	TF_R19(r31), r19
2228	ldw	TF_R20(r31), r20
2229	ldw	TF_R21(r31), r21
2230	ldw	TF_R22(r31), r22
2231	ldw	TF_R23(r31), r23
2232	/* ldw	TF_R24(r31), r24 shadowed */
2233	/* ldw	TF_R25(r31), r25 shadowed */
2234	ldw	TF_R26(r31), r26
2235	ldw	TF_R27(r31), r27
2236	ldw	TF_R28(r31), r28
2237	ldw	TF_R29(r31), r29
2238	ldw	TF_R30(r31), r30
2239	ldw	TF_R31(r31), r31
2240
2241	bb,>=,n	r1, 24, $fpu_emulate_done
2242
2243	b	TLABEL(all)
2244	ldi	T_EMULATION, r1
2245
2246$fpu_emulate_done
2247	comb,<>	r0, r1, TLABEL(all)
2248	ldi	T_EXCEPTION, r1
2249
2250	rfir
2251	nop
2252EXIT($fpu_emulate)
2253
2254#endif /* FPEMUL */
2255
2256	.import	dcache_stride, data
2257LEAF_ENTRY(fdcache)
2258	ldil	L%dcache_stride,t1
2259	ldw	R%dcache_stride(t1), arg3
2260
2261	mtsp	arg0, sr1		/* move the space register to sr1 */
2262	add	arg1, arg2, arg0	/* get the last byte to flush in arg0 */
2263
2264	zdep	arg3, 27, 28, t1	/* get size of a 16X loop in t1 */
2265	comb,<	arg2, t1, fdc_short	/* check for count < 16 * stride */
2266	addi	-1, t1, t1		/* compute size of large loop - 1 */
2267
2268	andcm	arg2, t1, t1		/* L = count - (count mod lenbigloop) */
2269	add	arg1, t1, t1		/* ub for big loop is lb + L */
2270
2271	fdc,m	arg3(sr1, arg1)		/* Start flushing first cache line. */
2272fdc_long
2273	fdc,m	arg3(sr1, arg1)
2274	fdc,m	arg3(sr1, arg1)
2275	fdc,m	arg3(sr1, arg1)
2276	fdc,m	arg3(sr1, arg1)
2277	fdc,m	arg3(sr1, arg1)
2278	fdc,m	arg3(sr1, arg1)
2279	fdc,m	arg3(sr1, arg1)
2280	fdc,m	arg3(sr1, arg1)
2281	fdc,m	arg3(sr1, arg1)
2282	fdc,m	arg3(sr1, arg1)
2283	fdc,m	arg3(sr1, arg1)
2284	fdc,m	arg3(sr1, arg1)
2285	fdc,m	arg3(sr1, arg1)
2286	fdc,m	arg3(sr1, arg1)
2287	fdc,m	arg3(sr1, arg1)
2288	comb,<<,n arg1, t1, fdc_long
2289	fdc,m	arg3(sr1, arg1)
2290fdc_short				/* flush one line at a time */
2291	comb,<<,n arg1, arg0, fdc_short
2292	fdc,m	arg3(sr1, arg1)
2293
2294	addi	-1, arg0, arg1
2295	fdc	r0(sr1, arg1)
2296
2297	sync
2298	syncdma
2299	bv	r0(r2)
2300	nop
2301EXIT(fdcache)
2302
2303	.import	dcache_stride, data
2304LEAF_ENTRY(pdcache)
2305	ldil	L%dcache_stride,t1
2306	ldw	R%dcache_stride(t1), arg3
2307
2308	mtsp	arg0, sr1		/* move the space register to sr1 */
2309	add	arg1, arg2, arg0	/* get the last byte to purge in arg0 */
2310
2311	zdep	arg3, 27, 28, t1	/* get size of a 16X loop in t1 */
2312	comb,<	arg2, t1, pdc_short	/* check for count < 16 * stride */
2313	addi	-1, t1, t1		/* compute size of large loop - 1 */
2314
2315	andcm	arg2, t1, t1		/* L = count - (count mod lenbigloop) */
2316	add	arg1, t1, t1		/* ub for big loop is lb + L */
2317
2318	pdc,m	arg3(sr1, arg1)		/* Start purging first cache line. */
2319pdc_long
2320	pdc,m	arg3(sr1, arg1)
2321	pdc,m	arg3(sr1, arg1)
2322	pdc,m	arg3(sr1, arg1)
2323	pdc,m	arg3(sr1, arg1)
2324	pdc,m	arg3(sr1, arg1)
2325	pdc,m	arg3(sr1, arg1)
2326	pdc,m	arg3(sr1, arg1)
2327	pdc,m	arg3(sr1, arg1)
2328	pdc,m	arg3(sr1, arg1)
2329	pdc,m	arg3(sr1, arg1)
2330	pdc,m	arg3(sr1, arg1)
2331	pdc,m	arg3(sr1, arg1)
2332	pdc,m	arg3(sr1, arg1)
2333	pdc,m	arg3(sr1, arg1)
2334	pdc,m	arg3(sr1, arg1)
2335	comb,<<,n arg1, t1, pdc_long
2336	pdc,m	arg3(sr1, arg1)
2337pdc_short				/* purge one line at a time */
2338	comb,<<,n arg1, arg0, pdc_short
2339	pdc,m	arg3(sr1, arg1)
2340
2341	addi	-1, arg0, arg1
2342	pdc	r0(sr1, arg1)
2343
2344	sync
2345	syncdma
2346	bv	r0(r2)
2347	nop
2348EXIT(pdcache)
2349
2350	.import	icache_stride, data
2351LEAF_ENTRY(ficache)
2352	ldil	L%icache_stride,t1
2353	ldw	R%icache_stride(t1), arg3
2354
2355	mtsp	arg0, sr1		/* move the space register to sr1 */
2356	add	arg1, arg2, arg0	/* get the last byte to flush in arg0 */
2357
2358	zdep	arg3, 27, 28, t1	/* get size of a 16X loop in t1 */
2359	comb,<	arg2, t1, fic_short	/* check for count < 16 * stride */
2360	addi	-1, t1, t1		/* compute size of large loop - 1 */
2361
2362	andcm	arg2, t1, t1		/* L = count - (count mod lenbigloop) */
2363	add	arg1, t1, t1		/* ub for big loop is lb + L */
2364
2365	fic,m	arg3(sr1, arg1)		/* Start flushing first cache line. */
2366fic_long
2367	fic,m	arg3(sr1, arg1)
2368	fic,m	arg3(sr1, arg1)
2369	fic,m	arg3(sr1, arg1)
2370	fic,m	arg3(sr1, arg1)
2371	fic,m	arg3(sr1, arg1)
2372	fic,m	arg3(sr1, arg1)
2373	fic,m	arg3(sr1, arg1)
2374	fic,m	arg3(sr1, arg1)
2375	fic,m	arg3(sr1, arg1)
2376	fic,m	arg3(sr1, arg1)
2377	fic,m	arg3(sr1, arg1)
2378	fic,m	arg3(sr1, arg1)
2379	fic,m	arg3(sr1, arg1)
2380	fic,m	arg3(sr1, arg1)
2381	fic,m	arg3(sr1, arg1)
2382	comb,<<,n arg1, t1, fic_long
2383	fic,m	arg3(sr1, arg1)
2384fic_short				/* flush one line at a time */
2385	comb,<<,n arg1, arg0, fic_short
2386	fic,m	arg3(sr1, arg1)
2387
2388	addi	-1, arg0, arg1
2389	fic	r0(sr1, arg1)
2390
2391	sync
2392	syncdma
2393	bv	r0(r2)
2394	nop
2395EXIT(ficache)
2396
2397#ifdef DDB
2398LEAF_ENTRY(setjmp)
2399/*
2400 * Save the other general registers whose contents are expected to remain
2401 * across function calls.  According to the "HP 9000 Series 800 Assembly
2402 * Language Reference Manual", procedures can use general registers 19-26,
2403 * 28, 29, 1, and 31 without restoring them.  Hence, we do not save these.
2404 */
2405	stwm	r3,4(arg0)
2406	stwm	r4,4(arg0)
2407	stwm	r5,4(arg0)
2408	stwm	r6,4(arg0)
2409	stwm	r7,4(arg0)
2410	stwm	r8,4(arg0)
2411	stwm	r9,4(arg0)
2412	stwm	r10,4(arg0)
2413	stwm	r11,4(arg0)
2414	stwm	r12,4(arg0)
2415	stwm	r13,4(arg0)
2416	stwm	r14,4(arg0)
2417	stwm	r15,4(arg0)
2418	stwm	r16,4(arg0)
2419	stwm	r17,4(arg0)
2420	stwm	r18,4(arg0)
2421	stwm	r27,4(arg0)	/* Good idea to save the data pointer (dp) */
2422	stwm	rp,4(arg0)	/* Save the return pointer */
2423	stwm	sp,4(arg0)	/* Save the original stack pointer */
2424
2425	bv	0(rp)
2426	copy	r0, ret0
2427EXIT(setjmp)
2428
2429LEAF_ENTRY(longjmp)
2430/*
2431 * Restore general registers.
2432 */
2433	ldwm	4(arg0),r3
2434	ldwm	4(arg0),r4
2435	ldwm	4(arg0),r5
2436	ldwm	4(arg0),r6
2437	ldwm	4(arg0),r7
2438	ldwm	4(arg0),r8
2439	ldwm	4(arg0),r9
2440	ldwm	4(arg0),r10
2441	ldwm	4(arg0),r11
2442	ldwm	4(arg0),r12
2443	ldwm	4(arg0),r13
2444	ldwm	4(arg0),r14
2445	ldwm	4(arg0),r15
2446	ldwm	4(arg0),r16
2447	ldwm	4(arg0),r17
2448	ldwm	4(arg0),r18
2449	ldwm	4(arg0),r27
2450	ldwm	4(arg0),rp	/* Restore return address pointer, */
2451	ldwm	4(arg0),sp	/* stack pointer, */
2452
2453	bv	0(rp)
2454	ldi	1, ret0
2455EXIT(longjmp)
2456#endif /* DDB */
2457
2458	.align	32
2459
2460LEAF_ENTRY(copy_on_fault)
2461	mtsp	r0, sr1
2462	mtsp	r0, sr2
2463	stw	r1, PCB_ONFAULT+U_PCB(r2)
2464	ldw	HPPA_FRAME_CRP(sp), rp
2465	ldo	-64(sp), sp
2466	bv	0(rp)
2467	ldi	EFAULT, %ret0
2468EXIT(copy_on_fault)
2469
2470/*
2471 * int spstrcpy (pa_space_t ssp, const void *src, pa_space_t dsp, void *dst,
2472 *		 size_t size, size_t *rsize)
2473 * do a space to space strncpy, return actual copy size in the rsize;
2474 */
2475LEAF_ENTRY(spstrcpy)
2476	ldw	HPPA_FRAME_ARG(4)(sp), t2
2477	ldo	64(sp), sp
2478	add	t2, arg1, t2
2479	stw	rp, HPPA_FRAME_CRP(sp)
2480	/* setup fault handler */
2481	mfctl	cr29, t1
2482	ldw	CI_CURPROC(t1), t3
2483	ldil	L%copy_on_fault, t4
2484	ldw	P_ADDR(t3), r2
2485	ldo	R%copy_on_fault(t4), t4
2486	ldw	PCB_ONFAULT+U_PCB(r2), r1
2487	stw	t4, PCB_ONFAULT+U_PCB(r2)
2488
2489	mtsp	arg0, sr1
2490	mtsp	arg2, sr2
2491	copy	arg1, arg0
2492	copy	r0, ret0
2493
2494$spstrcpy_loop
2495	ldbs,ma	1(sr1, arg1), t1
2496	comb,=	r0, t1, $spstrcpy_exit
2497	stbs,ma	t1, 1(sr2, arg3)
2498	comb,<>,n t2, arg1, $spstrcpy_loop
2499	nop
2500	ldi	ENAMETOOLONG, ret0
2501
2502$spstrcpy_exit
2503	mtsp	r0, sr1
2504	mtsp	r0, sr2
2505	stw	r1, PCB_ONFAULT+U_PCB(r2)
2506	ldw	HPPA_FRAME_CRP(sp), rp
2507	sub	arg1, arg0, arg1
2508	ldo	-64(sp), sp
2509	ldw	HPPA_FRAME_ARG(5)(sp), arg0
2510	sub,=	r0, arg0, r0
2511	stw	arg1, 0(arg0)
2512	bv	0(rp)
2513	nop
2514EXIT(spstrcpy)
2515
2516/*
2517 * int spcopy32 (pa_space_t ssp, const uint32_t *src, pa_space_t dsp,
2518 *		uint32_t *dst)
2519 * do an atomic space to space copy of a futex
2520 */
2521LEAF_ENTRY(spcopy32)
2522	extru	arg1, 31, 2, t3
2523	extru	arg3, 31, 2, t4
2524	comb,<>,n 0, t3, $spcopy32_misaligned
2525	comb,<>,n 0, t4, $spcopy32_misaligned
2526
2527	ldo	64(sp), sp
2528	stw	rp, HPPA_FRAME_CRP(sp)
2529	/* setup fault handler */
2530	mfctl	cr29, t1
2531	ldw	CI_CURPROC(t1), t3
2532	ldil	L%copy_on_fault, t2
2533	ldw	P_ADDR(t3), r2
2534	ldo	R%copy_on_fault(t2), t2
2535	ldw	PCB_ONFAULT+U_PCB(r2), r1
2536	stw	t2, PCB_ONFAULT+U_PCB(r2)
2537
2538	mtsp	arg0, sr1
2539	mtsp	arg2, sr2
2540
2541	ldw	0(sr1, arg1), t1
2542	stw	t1, 0(sr2, arg3)
2543
2544	mtsp	r0, sr1
2545	mtsp	r0, sr2
2546	/* reset fault handler */
2547	stw	r1, PCB_ONFAULT+U_PCB(r2)
2548	ldw	HPPA_FRAME_CRP(sp), rp
2549	ldo	-64(sp), sp
2550	bv	0(rp)
2551	copy	r0, ret0
2552
2553$spcopy32_misaligned
2554	bv	0(rp)
2555	ldi	EFAULT, ret0
2556EXIT(spcopy32)
2557
2558/*
2559 * int cpu_switchto(struct proc *old, struct proc *new)
2560 * Switch from "old" proc to "new".
2561 */
2562	.align	32
2563ENTRY(cpu_switchto,128)
2564	copy	r3, r1
2565	stw	rp, HPPA_FRAME_CRP(sp)
2566	copy	sp, r3
2567	stwm	r1, HPPA_FRAME_SIZE+16*4(sp)
2568
2569#ifdef DIAGNOSTIC
2570	b	kstack_check
2571	nop
2572switch_error
2573	copy	arg1, arg2
2574	copy	arg0, arg1
2575	ldil	L%panic, r1
2576	ldil	L%Lcspstr, arg0
2577	ldo	R%panic(r1), r1
2578	ldo	R%Lcspstr(arg0), arg0
2579	.call
2580	blr	%r0, rp
2581	bv,n	%r0(r1)
2582	nop
2583Lcspstr
2584	.asciz	"cpu_switch:old=%p, new=%p"
2585	.align	8
2586kstack_check
2587	/*
2588	 * The new process' kernel stack must be reasonable.
2589	 */
2590	ldw     P_ADDR(arg1), arg2
2591	ldw	U_PCB+PCB_KSP(arg2), t1
2592	ldo     NBPG(arg2), arg2
2593	comb,>>,n arg2, t1, switch_error
2594	nop
2595	sub     t1, arg2, t1
2596	ldil    L%USPACE, arg2
2597	ldo     R%USPACE(arg2), arg2
2598	comb,<<=,n arg2, t1, switch_error
2599	nop
2600kstack_ok
2601#endif
2602
2603	/* Record new proc. */
2604	ldi	SONPROC, t1
2605	stb	t1, P_STAT(arg1)
2606	mfctl	cr29, t1
2607	stw	arg1, CI_CURPROC(t1)
2608
2609	/* If old process exited, don't bother. */
2610	comb,=,n r0, arg0, switch_exited
2611
2612	/*
2613	 * 2. save old proc context
2614	 *
2615	 * arg0: old proc
2616	 */
2617	ldw	P_ADDR(arg0), t1
2618	/* save callee-save registers */
2619	stw	r4,   1*4(r3)
2620	stw	sp, U_PCB+PCB_KSP(t1)
2621	stw	r5,   2*4(r3)
2622	stw	r6,   3*4(r3)
2623	stw	r7,   4*4(r3)
2624	stw	r8,   5*4(r3)
2625	stw	r9,   6*4(r3)
2626	stw	r10,  7*4(r3)
2627	stw	r11,  8*4(r3)
2628	stw	r12,  9*4(r3)
2629	stw	r13, 10*4(r3)
2630	stw	r14, 11*4(r3)
2631	stw	r15, 12*4(r3)
2632	stw	r16, 13*4(r3)
2633	stw	r17, 14*4(r3)
2634	stw	r18, 15*4(r3)
2635	fdc	r0(t1)
2636	stw	r0, HPPA_FRAME_ARG(1)(sp)	/* say no trampoline */
2637	sync
2638
2639	/* don't need old curproc (arg0) starting from here */
2640switch_exited
2641	/*
2642	 * 3. restore new proc context
2643	 *
2644	 * arg1: new proc
2645	 */
2646	/* XXX disable interrupts? */
2647	ldw	P_ADDR(arg1), t2
2648	ldw	P_MD_REGS(arg1), t1
2649	ldw	U_PCB+PCB_KSP(t2), sp
2650	mtctl	r0, ccr			/* disable FPU */
2651	ldw	TF_CR30(t1), t2
2652	ldw	TF_CR9(t1), t3
2653	mtctl	t2, cr30
2654	mtctl	t3, pidr2
2655	/* XXX enable interrupts? */
2656	ldo	-(HPPA_FRAME_SIZE+16*4)(sp), r3
2657	ldw	HPPA_FRAME_ARG(0)(sp), arg0
2658	ldw	HPPA_FRAME_ARG(1)(sp), t4 /* in case we're on trampoline */
2659	sub,=	r0, t4, r0
2660	b	switch_return
2661	ldw	 1*4(r3), r4
2662	ldw	 2*4(r3), r5
2663	ldw	 3*4(r3), r6
2664	ldw	 4*4(r3), r7
2665	ldw	 5*4(r3), r8
2666	ldw	 6*4(r3), r9
2667	ldw	 7*4(r3), r10
2668	ldw	 8*4(r3), r11
2669	ldw	 9*4(r3), r12
2670	ldw	10*4(r3), r13
2671	ldw	11*4(r3), r14
2672	ldw	12*4(r3), r15
2673	ldw	13*4(r3), r16
2674	ldw	14*4(r3), r17
2675	ldw	15*4(r3), r18
2676
2677switch_return
2678	ldw	HPPA_FRAME_CRP(r3), rp
2679	bv	0(rp)
2680	ldwm	-(HPPA_FRAME_SIZE+16*4)(sp), r3
2681EXIT(cpu_switchto)
2682
2683LEAF_ENTRY(cpu_idle_enter)
2684	bv	0(rp)
2685	nop
2686EXIT(cpu_idle_enter)
2687
2688LEAF_ENTRY(cpu_idle_cycle)
2689	bv	0(rp)
2690	nop
2691EXIT(cpu_idle_cycle)
2692
2693LEAF_ENTRY(cpu_idle_leave)
2694	bv	0(rp)
2695	nop
2696EXIT(cpu_idle_leave)
2697
2698ENTRY(proc_trampoline,0)
2699	copy	r0, r3
2700	copy	t4, r5
2701	copy	arg0, r4
2702	bl	proc_trampoline_mi, rp
2703	nop
2704	copy	r4, arg0
2705	copy	r5, t4
2706	.call
2707	blr	r0, rp
2708	bv,n	r0(t4)
2709	nop
2710	mfctl	cr29, t1
2711	ldw	CI_CURPROC(t1), t2
2712	.call
2713	b	$syscall_return
2714	ldw	P_MD_REGS(t2), t3
2715EXIT(proc_trampoline)
2716
2717#ifdef MULTIPROCESSOR
2718/*
2719 * Trampoline to spin up secondary processors.
2720 */
2721ENTRY(hw_cpu_spinup_trampoline, 0)
2722
2723	/*
2724	 * disable interrupts and turn off all bits in the psw so that
2725	 * we start in a known state.
2726	 */
2727	rsm	RESET_PSL, r0
2728	nop ! nop ! nop ! nop ! nop ! nop
2729
2730	/* get things ready for the kernel to run in virtual mode */
2731	ldi	HPPA_PID_KERNEL, r1
2732	mtctl	r1, pidr1
2733	mtctl	r1, pidr2
2734#if pbably_not_worth_it
2735	mtctl	r0, pidr3
2736	mtctl	r0, pidr4
2737#endif
2738	mtsp	r0, sr0
2739	mtsp	r0, sr1
2740	mtsp	r0, sr2
2741	mtsp	r0, sr3
2742	mtsp	r0, sr4
2743	mtsp	r0, sr5
2744	mtsp	r0, sr6
2745	mtsp	r0, sr7
2746
2747	/*
2748	 * disable all coprocessors
2749	 */
2750	mtctl   r0, ccr
2751
2752	/*
2753	 * to keep the spl() routines consistent we need to put the correct
2754	 * spl level into eiem, and reset any pending interrupts
2755	 */
2756	ldi	-1, r1
2757	mtctl	r0, eiem
2758	mtctl	r1, eirr
2759
2760	/*
2761	 * load address of interrupt vector table
2762	 */
2763	ldil	L%$ivaaddr, t2
2764	ldo	R%$ivaaddr(t2), t2
2765	mtctl	t2, iva
2766
2767	/*
2768	 * set up the dp pointer so that we can do quick references off of it
2769	 */
2770	ldil	L%$global$,dp
2771	ldo	R%$global$(dp),dp
2772
2773	/*
2774	 * Store address of cpu_info in CR29.
2775	 */
2776	ldil	L%cpu_hatch_info, r3
2777	ldw	R%cpu_hatch_info(r3), r3
2778	mtctl	r3, cr29
2779
2780	/*
2781	 * Setup the stack frame for us to call C with and mark this as the
2782	 * first frame on the stack.
2783	 */
2784	ldw	CI_STACK(r3), sp
2785	stw,ma	r0, HPPA_FRAME_SIZE(sp)
2786	stw	r0, HPPA_FRAME_CRP(sp)
2787	stw	r0, HPPA_FRAME_PSP(sp)
2788
2789	ldil	L%TFF_LAST, t1
2790	stw	t1, TF_FLAGS-TRAPFRAME_SIZEOF(sp)
2791
2792	/* Provide CPU with page tables. */
2793	ldil	L%hppa_vtop, t1
2794	ldw	R%hppa_vtop(t1), t1
2795	mtctl	t1, CR_VTOP
2796
2797	/* Turn on the Q bit so that we can handle TLB traps. */
2798	ldil	L%$q_enabled, t1
2799	ldo	R%$q_enabled(t1), t1
2800	mtctl	r0, pcsq
2801	mtctl	r0, pcsq
2802	mtctl	t1, pcoq
2803	ldo	4(t1), t1
2804	mtctl	t1, pcoq
2805	ldi	PSL_Q|PSL_I, t2
2806	mtctl	t2, ipsw
2807	rfi
2808	nop
2809
2810$q_enabled
2811
2812	/* Call C routine to setup CPU. */
2813	ldil	L%cpu_hw_init, r1
2814	ldo	R%cpu_hw_init(r1), r1
2815	.import cpu_hw_init, code
2816	.call
2817	blr	r0, rp
2818	bv,n	(r1)
2819	nop
2820
2821	/* Switch CPU mode. */
2822	ldil	L%$cpu_spinup_vm, t1
2823	ldo	R%$cpu_spinup_vm(t1), t1
2824	mtctl	r0, pcsq
2825	mtctl	r0, pcsq
2826	mtctl	t1, pcoq
2827	ldo	4(t1), t1
2828	mtctl	t1, pcoq
2829	mfctl	cr29, t2
2830	ldw	CI_PSW(t2), t2
2831	mtctl	t2, ipsw
2832	rfi
2833	nop
2834
2835$cpu_spinup_vm
2836
2837	/*
2838	 * Okay, time to return to the land of C.
2839	 */
2840	b	cpu_hatch
2841	nop
2842
2843EXIT(hw_cpu_spinup_trampoline)
2844#endif
2845
2846/*
2847 * Signal "trampoline" code. Invoked from RTE setup by sendsig().
2848 */
2849	.section .rodata
2850	.align 4
2851	.export	sigcode, entry
2852	.label sigcode
2853	.proc
2854	.callinfo frame=0,calls, save_rp, save_sp
2855	.entry
2856sigcode:
2857	bb,>=,n	arg3, 30, sigcode_call
2858	dep	r0, 31, 2, arg3
2859	ldw	4(arg3), r19
2860	ldw	0(arg3), arg3
2861sigcode_call
2862	.call
2863	ble	0(sr0, arg3)
2864	copy	r31, rp
2865
2866	ldil	L%SYSCALLGATE, r1
2867	copy	r4, arg0
2868	.call
2869	.globl	sigcodecall
2870sigcodecall:
2871	ble	4(sr7, r1)
2872	 ldi	SYS_sigreturn, t1
2873	.globl  sigcoderet
2874sigcoderet:
2875	break	0,0
2876ALTENTRY(esigcode)
2877
2878EXIT(sigcode)
2879	.globl	sigfill
2880sigfill:
2881	break	0,0
2882esigfill:
2883	.align	4
2884	.globl	sigfillsiz
2885sigfillsiz:
2886	.word	esigfill - sigfill
2887
2888	.text
2889
2890	.end
2891