1/*	$NetBSD: intvec.S,v 1.20 2011/04/12 18:07:57 matt Exp $   */
2
3/*
4 * Copyright (c) 1994, 1997 Ludd, University of Lule}, Sweden.
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 * 3. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *     This product includes software developed at Ludd, University of Lule}.
18 * 4. The name of the author may not be used to endorse or promote products
19 *    derived from this software without specific prior written permission
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33
34#include "assym.h"
35#include <sys/cdefs.h>
36#include <net/netisr.h>
37
38#include "opt_ddb.h"
39#include "opt_cputype.h"
40#include "opt_emulate.h"
41#include "opt_multiprocessor.h"
42#include "opt_lockdebug.h"
43#include "leds.h"
44
45#define SCBENTRY(name) \
46	.text			; \
47	.align 2		; \
48	.globl __CONCAT(X,name)	; \
49__CONCAT(X,name):
50
51#define TRAPCALL(namn, typ) \
52SCBENTRY(namn)			; \
53	pushl $0		; \
54	pushl $typ		; \
55	jbr Xtrap
56
57#define TRAPARGC(namn, typ) \
58SCBENTRY(namn)			; \
59	pushl $typ		; \
60	jbr Xtrap
61
62#define FASTINTR(namn, rutin) \
63SCBENTRY(namn)			; \
64	pushr $0x3f		; \
65	calls $0,_C_LABEL(rutin)	; \
66	popr $0x3f		; \
67	rei
68
69#define	PUSHR	pushr	$0x3f
70#define	POPR	popr	$0x3f
71
72#define KSTACK 0
73#define ISTACK 1
74#define	NOVEC	.long 0
75#define INTVEC(label,stack)	\
76	.long	__CONCAT(X,label)+stack;
77
78	.text
79
80	.globl	_C_LABEL(kernbase), _C_LABEL(rpb), _C_LABEL(kernel_text)
81	.set	_C_LABEL(kernel_text),KERNBASE
82_C_LABEL(kernbase):
83_C_LABEL(rpb):
84/*
85 * First page in memory we have rpb; so that we know where
86 * (must be on a 64k page boundary, easiest here). We use it
87 * to store SCB vectors generated when compiling the kernel,
88 * and move the SCB later to somewhere else.
89 */
90
91	NOVEC;				# Unused, 0
92	INTVEC(mcheck, ISTACK)		# Machine Check., 4
93	INTVEC(invkstk, ISTACK) 	# Kernel Stack Invalid., 8
94	NOVEC;			 	# Power Failed., C
95	INTVEC(privinflt, KSTACK)	# Privileged/Reserved Instruction.
96	INTVEC(xfcflt, KSTACK)		# Customer Reserved Instruction, 14
97	INTVEC(resopflt, KSTACK)	# Reserved Operand/Boot Vector(?), 18
98	INTVEC(resadflt, KSTACK)	# Reserved Address Mode., 1C
99	INTVEC(access_v, KSTACK)	# Access Control Violation, 20
100	INTVEC(transl_v, KSTACK)	# Translation Invalid, 24
101	INTVEC(tracep, KSTACK)		# Trace Pending, 28
102	INTVEC(breakp, KSTACK)		# Breakpoint Instruction, 2C
103	NOVEC;			 	# Compatibility Exception, 30
104	INTVEC(arithflt, KSTACK)	# Arithmetic Fault, 34
105	NOVEC;			 	# Unused, 38
106	NOVEC;			 	# Unused, 3C
107	INTVEC(syscall, KSTACK)		# main syscall trap, chmk, 40
108	INTVEC(chmx, KSTACK)		# chme, 44
109	INTVEC(chmx, KSTACK)		# chms, 48
110	INTVEC(chmx, KSTACK)		# chmu, 4C
111	NOVEC;				# System Backplane Exception/BIerror, 50
112	INTVEC(cmrerr, ISTACK)		# Corrected Memory Read, 54
113	NOVEC;				# System Backplane Alert/RXCD, 58
114	INTVEC(sbiflt, ISTACK)		# System Backplane Fault, 5C
115	NOVEC;				# Memory Write Timeout, 60
116	NOVEC;				# Unused, 64
117	NOVEC;				# Unused, 68
118	NOVEC;				# Unused, 6C
119	NOVEC;				# Unused, 70
120	NOVEC;				# Unused, 74
121	NOVEC;				# Unused, 78
122	NOVEC;				# Unused, 7C
123	NOVEC;				# Unused, 80
124	NOVEC;				# Unused, 84
125	INTVEC(astintr,	KSTACK)		# Asynchronous Sustem Trap, AST (IPL 02)
126	NOVEC;				# Unused, 8C
127	NOVEC;				# Unused, 90
128	NOVEC;				# Unused, 94
129	NOVEC;				# Unused, 98
130	NOVEC;				# Unused, 9C
131	INTVEC(softclock, KSTACK);	# Software clock interrupt, A0 (IPL 08)
132	NOVEC;				# Unused, A4 (IPL 09)
133	NOVEC;				# Unused, A8 (IPL 10)
134	INTVEC(softbio, KSTACK);	# Software bio interrupt, AC (IPL 11)
135	INTVEC(softnet, KSTACK);	# Software net interrupt, B0 (IPL 12)
136	INTVEC(softserial, KSTACK);	# Software serial interrupt, B4 (IPL 13)
137	NOVEC;				# Unused, B8 (IPL 14)
138	INTVEC(ddbtrap, ISTACK) 	# Kernel debugger trap, BC (IPL 15)
139	INTVEC(hardclock,ISTACK)	# Interval Timer
140	NOVEC;				# Unused, C4
141	INTVEC(emulate, KSTACK)		# Subset instruction emulation, C8
142	NOVEC;				# Unused, CC
143	NOVEC;				# Unused, D0
144	NOVEC;				# Unused, D4
145	NOVEC;				# Unused, D8
146	NOVEC;				# Unused, DC
147	NOVEC;				# Unused, E0
148	NOVEC;				# Unused, E4
149	NOVEC;				# Unused, E8
150	NOVEC;				# Unused, EC
151	NOVEC;
152	NOVEC;
153	NOVEC;
154	NOVEC;
155
156	/* space for adapter vectors */
157	.space 0x100
158
159		.align 2
160#
161# mcheck is the badaddress trap, also called when referencing
162# a invalid address (busserror)
163# _memtest (memtest in C) holds the address to continue execution
164# at when returning from a intentional test.
165#
166SCBENTRY(mcheck)
167	tstl	_C_LABEL(cold)		# Ar we still in coldstart?
168	bneq	L4		# Yes.
169
170	pushr	$0x7f
171	pushab	24(%sp)
172	movl	_C_LABEL(dep_call),%r6	# CPU dependent mchk handling
173	calls	$1,*MCHK(%r6)
174	tstl	%r0		# If not machine check, try memory error
175	beql	1f
176	calls	$0,*MEMERR(%r6)
177	pushab	2f
178	calls	$1,_C_LABEL(panic)
1792:	.asciz	"mchk"
1801:	popr	$0x7f
181	addl2	(%sp)+,%sp
182
183	rei
184
185L4:	addl2	(%sp)+,%sp	# remove info pushed on stack
186	pushr	$0x3f		# save regs for clobbering
187	movl	_C_LABEL(dep_call),%r0	# get CPU-specific mchk handler
188	tstl	BADADDR(%r0)	# any handler available?
189	bneq	4f		# yep, call it
190	popr	$0x3f		# nope, restore regs
191	brb	0f		# continue
1924:	calls	$0,*BADADDR(%r0)	# call machine-specific handler
193	popr	$0x3f		# restore regs
194	brb	2f
195
1960:	cmpl	_C_LABEL(vax_cputype),$1 # Is it a 11/780?
197	bneq	1f		# No...
198
199	mtpr	$0, $PR_SBIFS	# Clear SBI fault register
200	brb	2f
201
2021:	cmpl	_C_LABEL(vax_cputype),$4 # Is it a 8600?
203	bneq	3f
204
205	mtpr	$0, $PR_EHSR	# Clear Error status register
206	brb	2f
207
2083:	mtpr	$0xF,$PR_MCESR	# clear the bus error bit
2092:	movl	_C_LABEL(memtest),(%sp)	# REI to new address
210	rei
211
212	TRAPCALL(invkstk, T_KSPNOTVAL)
213
214SCBENTRY(privinflt)	# Privileged/unimplemented instruction
215#ifndef NO_INSN_EMULATE
216	jsb	_C_LABEL(unimemu)	# do not return if insn emulated
217#endif
218	pushl	$0
219	pushl	$T_PRIVINFLT
220	jbr	Xtrap
221
222	TRAPCALL(xfcflt, T_XFCFLT);
223	TRAPCALL(resopflt, T_RESOPFLT)
224	TRAPCALL(resadflt, T_RESADFLT)
225
226/*
227 * default handler for CHME and CHMS
228 */
229SCBENTRY(chmx)
230	clrl	(%sp)			# CHM code already on stack
231	pushl	$T_RESOPFLT
232	jbr	Xtrap
233
234/*
235 * Translation fault, used only when simulating page reference bit.
236 * Therefore it is done a fast revalidation of the page if it is
237 * referenced. Trouble here is the hardware bug on KA650 CPUs that
238 * put in a need for an extra check when the fault is gotten during
239 * PTE reference. Handled in pmap.c.
240 */
241SCBENTRY(transl_v)		# 20: Translation violation
242	pushr	$0x3f
243	pushl	28(%sp)
244	pushl	28(%sp)
245	calls	$2,_C_LABEL(pmap_simulref)
246	tstl	%r0
247	bneq	1f
248	popr	$0x3f
249	addl2	$8,%sp
250	rei
2511:	popr	$0x3f
252	brw	Xaccess_v
253
254SCBENTRY(access_v)			# 24: Access cntrl viol fault
255	blbs	(%sp), ptelen
256	pushl	$T_ACCFLT
257	bbc	$1,4(%sp),1f
258	bisl2	$T_PTEFETCH,(%sp)
2591:	bbc	$2,4(%sp),2f
260	bisl2	$T_WRITE,(%sp)
2612:	movl	(%sp), 4(%sp)
262	addl2	$4, %sp
263	jbr	Xtrap
264
265ptelen: movl	$T_PTELEN, (%sp)		# PTE must expand (or send segv)
266	jbr	Xtrap;
267
268TRAPCALL(tracep, T_TRCTRAP)
269TRAPCALL(breakp, T_BPTFLT)
270
271TRAPARGC(arithflt, T_ARITHFLT)
272
273SCBENTRY(syscall)			# Main system call
274#if 1
275	cmpl	(%sp), $SYS__lwp_getprivate
276	bneq	1f
277	mfpr	$PR_SSP, %r0		# get curlwp
278	movl	L_PRIVATE(%r0), %r0	# get l_private
279	addl2	$4, %sp			# eat the code
280	rei
2811:
282#endif
283	pushl	$T_SYSCALL
284	pushr	$0xfff
285	mfpr	$PR_USP, -(%sp)
286	mfpr    $PR_SSP, %r0		/* SSP contains curlwp */
287	movl	L_PROC(%r0), %r0
288	pushl	%ap
289	pushl	%fp
290	pushl	%sp		# pointer to syscall frame; defined in trap.h
291	calls	$1, *P_MD_SYSCALL(%r0)
292	movl	(%sp)+, %fp
293	movl	(%sp)+, %ap
294	mtpr	(%sp)+, $PR_USP
295	popr	$0xfff
296	addl2	$8, %sp
297	mtpr	$IPL_HIGH, $PR_IPL	# Be sure we can REI
298	rei
299
300
301SCBENTRY(cmrerr)
302	PUSHR
303	movl	_C_LABEL(dep_call),%r0
304	calls	$0,*MEMERR(%r0)
305	POPR
306	rei
307
308SCBENTRY(sbiflt);
309	pushab	sbifltmsg
310	calls	$1, _C_LABEL(panic)
311
312TRAPCALL(astintr, T_ASTFLT)
313
314TRAPCALL(ddbtrap, T_KDBTRAP)
315
316SCBENTRY(hardclock)
317#ifdef DDB
318	tstl	0x80000100		# rpb wait element
319	beql	1f			# set, jmp to debugger
320	pushl	$0
321	pushl	$T_KDBTRAP
322	jbr	Xtrap
323#endif
3241:	pushr	$0x3f
325	mfpr    $PR_ICCS,%r0
326	tstl    %r0
327	bgeq    2f
328	incl    _C_LABEL(clock_misscnt)+EV_COUNT
329	adwc    $0,_C_LABEL(clock_misscnt)+EV_COUNT+4
3302:      mtpr	$0x800000c1,$PR_ICCS		# Reset interrupt flag
331	incl	_C_LABEL(clock_intrcnt)+EV_COUNT	# count the number of clock interrupts
332	adwc	$0,_C_LABEL(clock_intrcnt)+EV_COUNT+4
333
334	mfpr    $PR_SSP, %r0		/* SSP contains curlwp */
335	movl	L_CPU(%r0), %r0		/* get current CPU */
336	incl    CI_NINTR(%r0)
337	adwc    $0,(CI_NINTR+4)(%r0)
338
339#if VAX46 || VAXANY
340	cmpl	_C_LABEL(vax_boardtype),$VAX_BTYP_46
341	bneq	1f
342	movl	_C_LABEL(ka46_cpu),%r0
343	clrl	VC_DIAGTIMM(%r0)
344#endif
3451:	pushl	%sp
346	addl2	$24,(%sp)
347	calls	$1,_C_LABEL(hardclock)
348#if NLEDS
349	calls	$0,_C_LABEL(leds_intr)
350#endif
351	popr	$0x3f
352	rei
353
354/*
355 * Main routine for traps; all go through this.
356 * Note that we put USP on the frame here, which sometimes should
357 * be KSP to be correct, but because we only alters it when we are
358 * called from user space it doesn't care.
359 * _sret is used in cpu_set_kpc to jump out to user space first time.
360 */
361	.globl	_C_LABEL(sret)
362Xtrap:	pushr	$0xfff
363	mfpr	$PR_USP, -(%sp)
364	pushl	%ap
365	pushl	%fp
366	pushl	%sp
367	calls	$1, _C_LABEL(trap)
368_C_LABEL(sret):
369	movl	(%sp)+, %fp
370	movl	(%sp)+, %ap
371	mtpr	(%sp)+, $PR_USP
372	popr	$0xfff
373	addl2	$8, %sp
374	mtpr	$IPL_HIGH, $PR_IPL	# Be sure we can REI
375	rei
376
377sbifltmsg:
378	.asciz	"SBI fault"
379
380#ifndef NO_INSN_EMULATE
381/*
382 * Table of emulated Microvax instructions supported by emulate.s.
383 * Use noemulate to convert unimplemented ones to reserved instruction faults.
384 */
385	.globl	_C_LABEL(emtable)
386_C_LABEL(emtable):
387/* f8 */ .long _C_LABEL(EMashp);	.long _C_LABEL(EMcvtlp)
388/* fa */ .long noemulate;		.long noemulate
389/* fc */ .long noemulate;		.long noemulate
390/* fe */ .long noemulate;		.long noemulate
391/* 00 */ .long noemulate;		.long noemulate
392/* 02 */ .long noemulate;		.long noemulate
393/* 04 */ .long noemulate;		.long noemulate
394/* 05 */ .long noemulate;		.long noemulate
395/* 08 */ .long _C_LABEL(EMcvtps);	.long _C_LABEL(EMcvtsp)
396/* 0a */ .long noemulate;		.long _C_LABEL(EMcrc)
397/* 0c */ .long noemulate;		.long noemulate
398/* 0e */ .long noemulate;		.long noemulate
399/* 10 */ .long noemulate;		.long noemulate
400/* 12 */ .long noemulate;		.long noemulate
401/* 14 */ .long noemulate;		.long noemulate
402/* 16 */ .long noemulate;		.long noemulate
403/* 18 */ .long noemulate;		.long noemulate
404/* 1a */ .long noemulate;		.long noemulate
405/* 1c */ .long noemulate;		.long noemulate
406/* 1e */ .long noemulate;		.long noemulate
407/* 20 */ .long _C_LABEL(EMaddp4);	.long _C_LABEL(EMaddp6)
408/* 22 */ .long _C_LABEL(EMsubp4);	.long _C_LABEL(EMsubp6)
409/* 24 */ .long _C_LABEL(EMcvtpt);	.long _C_LABEL(EMmulp)
410/* 26 */ .long _C_LABEL(EMcvttp);	.long _C_LABEL(EMdivp)
411/* 28 */ .long noemulate;		.long _C_LABEL(EMcmpc3)
412/* 2a */ .long _C_LABEL(EMscanc);	.long _C_LABEL(EMspanc)
413/* 2c */ .long noemulate;		.long _C_LABEL(EMcmpc5)
414/* 2e */ .long _C_LABEL(EMmovtc);	.long _C_LABEL(EMmovtuc)
415/* 30 */ .long noemulate;		.long noemulate
416/* 32 */ .long noemulate;		.long noemulate
417/* 34 */ .long _C_LABEL(EMmovp);	.long _C_LABEL(EMcmpp3)
418/* 36 */ .long _C_LABEL(EMcvtpl);	.long _C_LABEL(EMcmpp4)
419/* 38 */ .long _C_LABEL(EMeditpc);	.long _C_LABEL(EMmatchc)
420/* 3a */ .long _C_LABEL(EMlocc);	.long _C_LABEL(EMskpc)
421#endif
422/*
423 * The following is called with the stack set up as follows:
424 *
425 *	  (%sp): Opcode
426 *	 4(%sp): Instruction PC
427 *	 8(%sp): Operand 1
428 *	12(%sp): Operand 2
429 *	16(%sp): Operand 3
430 *	20(%sp): Operand 4
431 *	24(%sp): Operand 5
432 *	28(%sp): Operand 6
433 *	32(%sp): Operand 7 (unused)
434 *	36(%sp): Operand 8 (unused)
435 *	40(%sp): Return PC
436 *	44(%sp): Return PSL
437 *	48(%sp): TOS before instruction
438 *
439 * Each individual routine is called with the stack set up as follows:
440 *
441 *	  (%sp): Return address of trap handler
442 *	 4(%sp): Opcode (will get return PSL)
443 *	 8(%sp): Instruction PC
444 *	12(%sp): Operand 1
445 *	16(%sp): Operand 2
446 *	20(%sp): Operand 3
447 *	24(%sp): Operand 4
448 *	28(%sp): Operand 5
449 *	32(%sp): Operand 6
450 *	36(%sp): saved register 11
451 *	40(%sp): saved register 10
452 *	44(%sp): Return PC
453 *	48(%sp): Return PSL
454 *	52(%sp): TOS before instruction
455 *	See the VAX Architecture Reference Manual, Section B-5 for more
456 *	information.
457 */
458
459SCBENTRY(emulate)
460#ifndef NO_INSN_EMULATE
461	movl	%r11,32(%sp)		# save register %r11 in unused operand
462	movl	%r10,36(%sp)		# save register %r10 in unused operand
463	cvtbl	(%sp),%r10		# get opcode
464	addl2	$8,%r10			# shift negative opcodes
465	subl3	%r10,$0x43,%r11		# forget it if opcode is out of range
466	bcs	noemulate
467	movl	_C_LABEL(emtable)[%r10],%r10
468				# call appropriate emulation routine
469	jsb	(%r10)		# routines put return values into regs 0-5
470	movl	32(%sp),%r11		# restore register %r11
471	movl	36(%sp),%r10		# restore register %r10
472	insv	(%sp),$0,$4,44(%sp)	# and condition codes in Opcode spot
473	addl2	$40,%sp			# adjust stack for return
474	rei
475noemulate:
476	addl2	$48,%sp			# adjust stack for
477#endif
478	.word	0xffff			# "reserved instruction fault"
479