xref: /original-bsd/sys/vax/vax/locore.s (revision 4da674f5)
1/*
2 * Copyright (c) 1980, 1986 Regents of the University of California.
3 * All rights reserved.  The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
6 *	@(#)locore.s	7.30 (Berkeley) 03/26/91
7 */
8
9#include "vax/include/psl.h"
10#include "vax/include/pte.h"
11
12#include "sys/errno.h"
13#include "sys/syscall.h"
14#include "sys/cmap.h"
15
16#include "vax/include/mtpr.h"
17#include "vax/include/trap.h"
18#include "vax/include/cpu.h"
19#include "vax/vax/nexus.h"
20#include "vax/vax/cons.h"
21#include "vax/include/clock.h"
22#include "vax/vax/ioa.h"
23#include "vax/vax/ka630.h"
24#include "vax/vax/ka650.h"
25#include "vax/vax/ka820.h"
26#include "vax/uba/ubareg.h"
27
28#include "dz.h"
29#include "dp.h"
30#include "uu.h"
31#include "ps.h"
32#include "mba.h"
33#include "uba.h"
34#include "imp.h"
35
36	.set	HIGH,0x1f	# mask for total disable
37	.set	MCKVEC,4	# offset into scb of machine check vector
38	.set	NBPG,512
39	.set	PGSHIFT,9
40	.set	SYSTEM,0x80000000	# virtual address of system start
41
42	.set	NISP,3		# number of interrupt stack pages
43
44/*
45 * User structure is UPAGES at top of user space.
46 */
47	.globl	_u
48	.set	_u,0x80000000 - UPAGES*NBPG
49
50	.globl	_intstack
51_intstack:
52	.space	NISP*NBPG
53eintstack:
54
55/*
56 * Do a dump.
57 * Called by auto-restart.
58 * May be called manually.
59 */
60	.align	2
61	.globl	_doadump
62	.globl	_msgbufmapped
63_doadump:
64	nop; nop				# .word 0x0101
65#define	_rpbmap	_Sysmap				# rpb, scb, UNIvec[], istack*4
66	bicl2	$PG_PROT,_rpbmap
67	bisl2	$PG_KW,_rpbmap
68	mtpr	$0,$TBIA
69	tstl	_rpb+RP_FLAG			# dump only once!
70	bneq	1f
71	incl	_rpb+RP_FLAG
72	movl	sp,erpb
73	movab	erpb,sp
74	mfpr	$PCBB,-(sp)
75	mfpr	$MAPEN,-(sp)
76	mfpr	$IPL,-(sp)
77	clrl	_msgbufmapped
78	mtpr	$0,$MAPEN
79	mtpr	$HIGH,$IPL
80	pushr	$0x3fff
81	calls	$0,_dumpsys
821:
83	clrl	r11				# boot flags
84	calls	$0,_vaxboot
85	halt
86
87/*
88 * Interrupt vector routines
89 */
90	.globl	_waittime
91
92#define	SCBVEC(name)	.align 2; .globl _X/**/name; _X/**/name
93#define	PANIC(msg)	clrl _waittime; pushab 1f; \
94			calls $1,_panic; 1: .asciz msg
95#define	PRINTF(n,msg)	pushab 1f; calls $n+1,_printf; MSG(msg)
96#define	MSG(msg)	.data; 1: .asciz msg; .text
97#define	PUSHR		pushr $0x3f
98#define	POPR		popr $0x3f
99
100	.data
101nofault: .long	0	# where to go on predicted machcheck
102	.text
103SCBVEC(machcheck):
104	tstl	nofault
105	bneq	1f
106	PUSHR; pushab 6*4(sp); calls $1,_machinecheck; POPR;
107	addl2 (sp)+,sp; rei
108	.align	2
1091:
110	casel	_cpu,$1,$VAX_MAX
1110:
112	.word	8f-0b		# 1 is 780
113	.word	5f-0b		# 2 is 750
114	.word	5f-0b		# 3 is 730
115	.word	7f-0b		# 4 is 8600
116	.word	5f-0b		# 5 is 8200
117	.word	1f-0b		# 6 is 8800 (unsupported)
118	.word	1f-0b		# 7 is 610  (unsupported)
119	.word	1f-0b		# 8 is 630
120	.word	1f-0b		# 9 is ???
121	.word	9f-0b		# 10 is 650
1225:
123#if defined(VAX8200) || defined(VAX750) || defined(VAX730)
124	mtpr	$0xf,$MCESR
125#endif
126	brb	1f
1277:
128#if VAX8600
129	mtpr	$0,$EHSR
130#endif
131	brb	1f
1328:
133#if VAX780
134	mtpr	$0,$SBIFS
135#endif
136	brb	1f
1379:
138#if VAX650
139	bitl	$PG_V,_KA650MERRmap
140	beql	1f	# don't bother clearing err reg if not mapped in
141	movl	$DSER_CLEAR,_ka650merr+4
142#endif
1431:
144	addl2	(sp)+,sp		# discard mchchk trash
145	movl	nofault,(sp)
146	rei
147
148SCBVEC(kspnotval):
149	PANIC("KSP not valid");
150SCBVEC(powfail):
151	halt
152SCBVEC(chme): SCBVEC(chms): SCBVEC(chmu):
153	PANIC("CHM? in kernel");
154
155SCBVEC(nex0zvec):
156	PUSHR
157	clrl	r0
158	brb	1f
159SCBVEC(nex1zvec):
160	PUSHR
161	movl	$1,r0
1621:
163	cmpl	_cpu,$VAX_8600		# this is a frill
164	beql	2f
165	mfpr	$IPL,-(sp)
166	PRINTF(1, "nexus stray intr ipl%x\n")
167	POPR
168	rei
1692:
170	pushl	r0
171	mfpr	$IPL,-(sp)
172	PRINTF(2, "nexus stray intr ipl%x sbia%d\n")
173	POPR
174	rei
175
176SCBVEC(cmrd):
177	PUSHR; calls $0,_memerr; POPR; rei
178
179SCBVEC(wtime):			/* sbi0err on 8600 */
180#if VAX8600
181	cmpl	_cpu,$VAX_8600
182	bneq	wtimo
183	PANIC("sbia0 error")
184wtimo:
185#endif
186	PUSHR; pushl 6*4(sp); PRINTF(1, "write timeout %x\n"); POPR
187	PANIC("wtimo")
188
189SCBVEC(sbi0fail):
190	PANIC("sbia0 fail")
191SCBVEC(sbi0alert):
192#if VAX8200
193	cmpl	_cpu,$VAX_8200
194	bneq	alert
195	PUSHR; calls $0,_rxcdintr; POPR; rei
196alert:
197#endif
198	PANIC("sbia0 alert")
199SCBVEC(sbi0fault):
200	PANIC("sbia0 fault")
201
202#ifdef notyet
203#if VAX8600
204SCBVEC(sbi1fail):
205	PANIC("sbia1 fail")
206SCBVEC(sbi1alert):
207	PANIC("sbia1 alert")
208SCBVEC(sbi1fault):
209	PANIC("sbia1 fault")
210SCBVEC(sbi1err):
211	PANIC("sbia1 error")
212#endif
213#endif
214
215/*
216 * BI 0 bus error (8200), or SBI silo compare error (others)
217 * VMS boot leaves us 1 BI error to ignore.
218 */
219#if VAX8200 && 0
220	.data
221	.align	2
222_ignorebi: .globl _ignorebi
223	.long	1
224	.text
225#endif VAX8200
226
227SCBVEC(sbisilo):
228#if VAX8200
229	cmpl	_cpu,$VAX_8200
230	bneq	sbisilo
231#if 0
232	blbs	_ignorebi,1f
233#else
234	blbs	_cold,1f
235#endif
236	PUSHR; pushl $0; calls $1,_bi_buserr; POPR
2371:
238	rei
239#endif
240sbisilo:
241	PANIC("sbi silo compare error")
242
243/*
244 * SCB stray interrupt catcher.  Compute and print the actual
245 * SCB vector (for fault diagnosis).
246 */
247	.align	2
248_scbstray: .globl _scbstray
249#define	PJ	PUSHR;jsb 1f
250	/* 128 of 'em */
251	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
252	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
253	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
254	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
255	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
256	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
257	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
258	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
259#if VAX8600
260	/* and another 128, for the second SBIA's scb */
261	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
262	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
263	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
264	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
265	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
266	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
267	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
268	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
269#endif
270#undef PJ
2711:
272	subl3	$_scbstray+8,(sp)+,r0
273	mfpr	$IPL,-(sp)
274	ashl	$-1,r0,-(sp)
275/* call a C handler instead? perhaps later */
276	PRINTF(2, "stray scb intr vec 0x%x ipl%x\n")
277	POPR
278	rei
279
280#if NMBA > 0
281SCBVEC(mba3int):
282	PUSHR; incl _intrcnt+I_MBA3; pushl $3; brb 1f
283SCBVEC(mba2int):
284	PUSHR; incl _intrcnt+I_MBA2; pushl $2; brb 1f
285SCBVEC(mba1int):
286	PUSHR; incl _intrcnt+I_MBA1; pushl $1; brb 1f
287SCBVEC(mba0int):
288	PUSHR; incl _intrcnt+I_MBA0; pushl $0
2891:	calls $1,_mbintr
290	POPR
291	incl	_cnt+V_INTR
292	rei
293#endif
294
295#ifdef DW780
296/*
297 * Registers for the uba handling code
298 */
299#define	rUBANUM	r0
300#define	rUBAHD	r1
301#define	rUVEC	r3
302#define	rUBA	r4
303/* r2,r5 are scratch */
304
305#define	I_UBA	I_UBA0		/* base of UBA interrupt counters */
306
307#if NUBA > 4
308SCBVEC(ua7int):
309	PUSHR; movl $7,rUBANUM; moval _uba_hd+(7*UH_SIZE),rUBAHD; brb 1f
310SCBVEC(ua6int):
311	PUSHR; movl $6,rUBANUM; moval _uba_hd+(6*UH_SIZE),rUBAHD; brb 1f
312SCBVEC(ua5int):
313	PUSHR; movl $5,rUBANUM; moval _uba_hd+(5*UH_SIZE),rUBAHD; brb 1f
314SCBVEC(ua4int):
315	PUSHR; movl $4,rUBANUM; moval _uba_hd+(4*UH_SIZE),rUBAHD; brb 1f
316#endif
317SCBVEC(ua3int):
318	PUSHR; movl $3,rUBANUM; moval _uba_hd+(3*UH_SIZE),rUBAHD; brb 1f
319SCBVEC(ua2int):
320	PUSHR; movl $2,rUBANUM; moval _uba_hd+(2*UH_SIZE),rUBAHD; brb 1f
321SCBVEC(ua1int):
322	PUSHR; movl $1,rUBANUM; moval _uba_hd+(1*UH_SIZE),rUBAHD; brb 1f
323SCBVEC(ua0int):
324	PUSHR; movl $0,rUBANUM; moval _uba_hd+(0*UH_SIZE),rUBAHD;
3251:
326	mfpr	$IPL,r2				/* r2 = mfpr(IPL); */
327	movl	UH_UBA(rUBAHD),rUBA		/* uba = uhp->uh_uba; */
328	movl	UBA_BRRVR-0x14*4(rUBA)[r2],rUVEC
329					/* uvec = uba->uba_brrvr[r2-0x14] */
330ubanorm:
331	bleq	ubaerror
332	addl2	UH_VEC(rUBAHD),rUVEC		/* uvec += uh->uh_vec */
333	bicl3	$3,(rUVEC),r1
334	jmp	2(r1)				/* 2 skips ``pushr $0x3f'' */
335ubaerror:
336	PUSHR; calls $0,_ubaerror; POPR		/* ubaerror r/w's r0-r5 */
337	tstl rUVEC; jneq ubanorm		/* rUVEC contains result */
338	incl _intrcnt+I_UBA[rUBANUM]
339	incl	_cnt+V_INTR
340	POPR
341	rei
342#endif
343SCBVEC(cnrint):
344	PUSHR; calls $0,_cnrint; POPR
345	incl _cnt+V_INTR
346	incl _intrcnt+I_CNR
347	rei
348SCBVEC(cnxint):
349	PUSHR; calls $0,_cnxint; POPR
350	incl _cnt+V_INTR
351	incl _intrcnt+I_CNX
352	rei
353SCBVEC(hardclock):
354	PUSHR
355	mtpr $ICCS_RUN|ICCS_IE|ICCS_INT|ICCS_ERR,$ICCS
356#if NPS > 0
357	pushl	4+6*4(sp); pushl 4+6*4(sp);
358	calls	$2,_psextsync
359#endif
360	pushl 4+6*4(sp); pushl 4+6*4(sp);
361	calls $2,_hardclock			# hardclock(pc,psl)
362	POPR;
363	incl	_cnt+V_INTR
364	incl	_intrcnt+I_CLOCK
365	rei
366SCBVEC(softclock):
367	PUSHR
368	pushl	4+6*4(sp); pushl 4+6*4(sp);
369	calls	$2,_softclock			# softclock(pc,psl)
370	POPR;
371	incl	_cnt+V_SOFT
372	rei
373
374#include "net/netisr.h"
375	.globl	_netisr
376SCBVEC(netintr):
377	PUSHR
378#if NIMP > 0
379	bbcc	$NETISR_IMP,_netisr,1f; calls $0,_impintr; 1:
380#endif
381#ifdef INET
382	bbcc	$NETISR_IP,_netisr,1f; calls $0,_ipintr; 1:
383#endif
384#ifdef NS
385	bbcc	$NETISR_NS,_netisr,1f; calls $0,_nsintr; 1:
386#endif
387#ifdef ISO
388	bbcc	$NETISR_ISO,_netisr,1f; calls $0,_clnlintr; 1:
389#endif
390#ifdef CCITT
391	bbcc	$NETISR_CCITT,_netisr,1f; calls $0,_hdintr; 1:
392#endif
393	POPR
394	incl	_cnt+V_SOFT
395	rei
396
397SCBVEC(consdin):
398	PUSHR;
399	incl	_intrcnt+I_TUR
400	casel	_cpu,$VAX_750,$VAX_8200
4010:
402	.word	5f-0b		# 2 is VAX_750
403	.word	3f-0b		# 3 is VAX_730
404	.word	6f-0b		# 4 is VAX_8600
405	.word	7f-0b		# 5 is VAX_8200
406	halt
4075:
408#if defined(VAX750) && !defined(MRSP)
409	jsb	tudma
410#endif
4113:
412#if defined(VAX750) || defined(VAX730)
413	calls	$0,_turintr
414	brb	2f
415#else
416	halt
417#endif
4187:
419#if VAX8200
420	calls	$0,_rx50intr
421	brb	2f
422#else
423	halt
424#endif
4256:
426#if VAX8600
427	calls	$0,_crlintr
428#else
429	halt
430#endif
4312:
432	POPR
433	incl	_cnt+V_INTR
434	rei
435
436#if defined(VAX750) || defined(VAX730)
437SCBVEC(consdout):
438	PUSHR; calls $0,_tuxintr; POPR
439	incl _cnt+V_INTR
440	incl _intrcnt+I_TUX
441	rei
442#else
443SCBVEC(consdout):
444	halt
445#endif
446
447#if NDZ > 0
448/*
449 * DZ pseudo dma routine:
450 *	r0 - controller number
451 */
452	.align	1
453	.globl	dzdma
454dzdma:
455	mull2	$8*20,r0
456	movab	_dzpdma(r0),r3		# pdma structure base
457					# for this controller
458dzploop:
459	movl	r3,r0
460	movl	(r0)+,r1		# device register address
461	movzbl	1(r1),r2		# get line number
462	bitb	$0x80,r2		# TRDY on?
463	beql	dzprei			# no
464	bicb2	$0xf8,r2		# clear garbage bits
465	mull2	$20,r2
466	addl2	r2,r0			# point at line's pdma structure
467	movl	(r0)+,r2		# p_mem
468	cmpl	r2,(r0)+		# p_mem < p_end ?
469	bgequ	dzpcall			# no, go call dzxint
470	movb	(r2)+,6(r1)		# dztbuf = *p_mem++
471	movl	r2,-8(r0)
472	brb 	dzploop			# check for another line
473dzprei:
474	POPR
475	incl	_cnt+V_PDMA
476	rei
477
478dzpcall:
479	pushl	r3
480	pushl	(r0)+			# push tty address
481	calls	$1,*(r0)		# call interrupt rtn
482	movl	(sp)+,r3
483	brb 	dzploop			# check for another line
484#endif
485
486#if NDP > 0
487/*
488 * DPV-11 pseudo dma routine:
489 *	r0 - controller number
490 */
491	.align	1
492	.globl	dprdma
493	.globl	dpxdma
494dprdma:
495	mull3	$2*20,r0,r3
496	movab	_dppdma+20(r3),r3	# pdma structure base
497	movl	(r3),r1			# device register address
498	movw	(r1),r2			# get dprcsr
499	bitw	$0x400,r2		# Attention on?
500	bneq	dprcall			# yes
501	bitw	$0x80,r2		# Data Ready?
502	beql	dprcall			# no
503	movl	4(r3),r4
504	cmpl	r4,8(r3)		# p_mem < p_end ?
505	bgequ	dprcall			# no, go call dprint
506	movb	2(r1),(r4)+		# *p_mem++ = dptbuf
507	movl	r4,4(r3)		# put back adjusted count
508					# Since we've been interrupted
509	#bitw	$0x4,4(r1)		# check if we can send
510	#beql	dpprei			# no, return
511	#subl2	$20,r3			# point to send pdma
512	#movl	4(r3),r4		# check if
513	#cmpl	r4,8(r3)		# p_mem < p_end ?
514	#bgequ	dpxcall			# no, go call dpxint
515	#tstw	6(r1)			# get dptdsr, sender starved ?
516	#blss	dpxcall			# yes, go call dpxint
517	#movb	(r4)+,6(r1)		# dptbuf = *p_mem++
518	#movl	r4,4(r3)		# put back adjusted count
519dpprei:
520	POPR
521	incl	_cnt+V_PDMA
522	rei
523dprcall:
524	movw	r2,12(r3)
525dpxcall:
526	pushl	r1			# push csr address
527	pushl	r3			# push pdma address
528	pushl	r0			# push unit number
529	calls	$3,*16(r3)		# call interrupt rtn
530	brb	dpprei
531	.globl	dpxdma
532dpxdma:
533	mull3	$2*20,r0,r3
534	movab	_dppdma(r3),r3		# pdma structure base
535	movl	(r3),r1			# device register address
536dpxcheck:
537	movl	4(r3),r4
538	cmpl	r4,8(r3)		# p_mem < p_end ?
539	bgequ	dpxcall			# no, go call dpxint
540	bitw	$0x4,4(r1)		# ok to send
541	beql	dpxcall			# no, go call dpxint
542	tstw	6(r1)			# get dptdsr, sender starved ?
543	blss	dpxcall			# yes, go call dpxint
544	movzbw	(r4)+,6(r1)		# dptbuf = *p_mem++, turn off XSM.
545	movl	r4,4(r3)		# put back adjusted count
546	incl	12(r3)		# positive indication we did everything
547	#addl2	$20,r3			# check if input ready
548	#movw	(r1),r2			# get dprcsr
549	#bitw	$0x400,r2		# Attention on?
550	#bneq	dprcall			# yes
551	#bitw	$0x80,r2		# Data Ready?
552	#beql	dpprei			# no, just return
553	#movl	4(r3),r4
554	#cmpl	r4,8(r3)		# p_mem < p_end ?
555	#bgequ	dprcall			# no, go call dprint
556	#movb	2(r1),(r4)+		# dptbuf = *p_mem++
557	#movl	r4,4(r3)		# put back adjusted count
558	brb	dpprei
559#endif
560
561#if NUU > 0 && defined(UUDMA)
562/*
563 * Pseudo DMA routine for tu58 (on DL11)
564 *	r0 - controller number
565 */
566	.align	1
567	.globl	uudma
568uudma:
569	movl	_uudinfo[r0],r2
570	movl	16(r2),r2		# r2 = uuaddr
571	mull3	$48,r0,r3
572	movab	_uu_softc(r3),r5	# r5 = uuc
573
574	cvtwl	2(r2),r1		# c = uuaddr->rdb
575	bbc	$15,r1,1f		# if (c & UUDB_ERROR)
576	movl	$13,16(r5)		#	uuc->tu_state = TUC_RCVERR;
577	rsb				#	let uurintr handle it
5781:
579	tstl	4(r5)			# if (uuc->tu_rcnt) {
580	beql	1f
581	movb	r1,*0(r5)		#	*uuc->tu_rbptr++ = r1
582	incl	(r5)
583	decl	4(r5)			#	if (--uuc->tu_rcnt)
584	beql	2f			#		done
585	tstl	(sp)+
586	POPR				# 	registers saved in ubglue.s
587	rei				# }
5882:
589	cmpl	16(r5),$8		# if (uuc->tu_state != TUS_GETH)
590	beql	2f			# 	let uurintr handle it
5911:
592	rsb
5932:
594	mull2	$14,r0			# sizeof(uudata[ctlr]) = 14
595	movab	_uudata(r0),r4		# data = &uudata[ctlr];
596	cmpb	$1,(r4)			# if (data->pk_flag != TUF_DATA)
597	bneq	1b
598#ifdef notdef
599	/* this is for command packets */
600	beql	1f			# 	r0 = uuc->tu_rbptr
601	movl	(r5),r0
602	brb	2f
6031:					# else
604#endif
605	movl	24(r5),r0		# 	r0 = uuc->tu_addr
6062:
607	movzbl	1(r4),r3		# counter to r3 (data->pk_count)
608	movzwl	(r4),r1			# first word of checksum (=header)
609	mfpr	$IPL,-(sp)		# s = spl5();
610	mtpr	$0x15,$IPL		# to keep disk interrupts out
611	clrw	(r2)			# disable receiver interrupts
6123:	bbc	$7,(r2),3b		# while ((uuaddr->rcs & UUCS_READY)==0);
613	cvtwb	2(r2),(r0)+		# *buffer = uuaddr->rdb & 0xff
614	sobgtr	r3,1f			# continue with next byte ...
615	addw2	2(r2),r1		# unless this was the last (odd count)
616	brb	2f
617
6181:	bbc	$7,(r2),1b		# while ((uuaddr->rcs & UUCS_READY)==0);
619	cvtwb	2(r2),(r0)+		# *buffer = uuaddr->rdb & 0xff
620	addw2	-2(r0),r1		# add to checksum..
6212:
622	adwc	$0,r1			# get the carry
623	sobgtr	r3,3b			# loop while r3 > 0
624/*
625 * We're ready to get the checksum
626 */
6271:	bbc	$7,(r2),1b		# while ((uuaddr->rcs & UUCS_READY)==0);
628	cvtwb	2(r2),12(r4)		# get first (lower) byte
6291:	bbc	$7,(r2),1b
630	cvtwb	2(r2),13(r4)		# ..and second
631	cmpw	12(r4),r1		# is checksum ok?
632	beql	1f
633	movl	$14,16(r5)		# uuc->tu_state = TUS_CHKERR
634	brb	2f			# exit
6351:
636	movl	$11,16(r5)		# uuc->tu_state = TUS_GET (ok)
6372:
638	movw	$0x40,(r2)		# enable receiver interrupts
639	mtpr	(sp)+,$IPL		# splx(s);
640	rsb				# continue processing in uurintr
641#endif
642
643#if defined(VAX750) && !defined(MRSP)
644/*
645 * Pseudo DMA routine for VAX-11/750 console tu58
646 *   	    (without MRSP)
647 */
648	.align	1
649	.globl	tudma
650tudma:
651	movab	_tu,r5			# r5 = tu
652	tstl	4(r5)			# if (tu.tu_rcnt) {
653	beql	3f
654	mfpr	$CSRD,r1		# get data from tu58
655	movb	r1,*0(r5)		#	*tu.tu_rbptr++ = r1
656	incl	(r5)
657	decl	4(r5)			#	if (--tu.tu_rcnt)
658	beql	1f			#		done
659	tstl	(sp)+
660	POPR				# 	registers saved in ubglue.s
661	rei				# 	data handled, done
6621:					# }
663	cmpl	16(r5),$8		# if (tu.tu_state != TUS_GETH)
664	beql	2f			# 	let turintr handle it
6653:
666	rsb
6672:
668	movab	_tudata,r4		# r4 = tudata
669	cmpb	$1,(r4)			# if (tudata.pk_flag != TUF_DATA)
670	bneq	3b			# 	let turintr handle it
6711:					# else
672	movl	24(r5),r1		# get buffer pointer to r1
673	movzbl	1(r4),r3		# counter to r3
674	movzwl	(r4),r0			# first word of checksum (=header)
675	mtpr	$0,$CSRS		# disable receiver interrupts
6763:
677	bsbw	5f			# wait for next byte
678	mfpr	$CSRD,r5
679	movb	r5,(r1)+		# *buffer = rdb
680	sobgtr	r3,1f			# continue with next byte ...
681	mfpr	$CSRD,r2		# unless this was the last (odd count)
682	brb	2f
683
6841:	bsbw	5f			# wait for next byte
685	mfpr	$CSRD,r5
686	movb	r5,(r1)+		# *buffer = rdb
687	movzwl	-2(r1),r2		# get the last word back from memory
6882:
689	addw2	r2,r0			# add to checksum..
690	adwc	$0,r0			# get the carry
691	sobgtr	r3,3b			# loop while r3 > 0
692/*
693 * We're ready to get the checksum.
694 */
695	bsbw	5f
696	movab	_tudata,r4
697	mfpr	$CSRD,r5
698	movb	r5,12(r4)		# get first (lower) byte
699	bsbw	5f
700	mfpr	$CSRD,r5
701	movb	r5,13(r4)		# ..and second
702	movab	_tu,r5
703	cmpw	12(r4),r0		# is checksum ok?
704	beql	1f
705	movl	$14,16(r5)		# tu.tu_state = TUS_CHKERR
706	brb	2f			# exit
7071:
708	movl	$11,16(r5)		# tu.tu_state = TUS_GET
7092:
710	mtpr	$0x40,$CSRS		# enable receiver interrupts
711	rsb				# continue processing in turintr
712/*
713 * Loop until a new byte is ready from
714 * the tu58, make sure we don't loop forever
715 */
7165:
717	movl	$5000,r5		# loop max 5000 times
7181:
719	mfpr	$CSRS,r2
720	bbs	$7,r2,1f
721	sobgtr	r5,1b
722	movab	_tu,r5
723	movl	$13,16(r5)		# return TUS_RCVERR
724	tstl	(sp)+			# and let turintr handle it
7251:
726	rsb
727#endif
728
729/*
730 * BI passive release things.
731 */
732SCBVEC(passiverel):
733	rei				# well that was useless
734
735/*
736 * Stray UNIBUS interrupt catch routines
737 */
738	.data
739	.align	2
740#define	PJ	PUSHR;jsb _Xustray
741	.globl	_catcher
742_catcher:
743	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
744	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
745	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
746	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
747	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
748	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
749	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
750	PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
751
752	.globl	_cold
753	.globl	_br
754	.globl	_cvec
755_cold:	.long	1
756_br:	.long	0
757_cvec:	.long	0
758
759	.text
760SCBVEC(ustray):
761	blbc	_cold,1f
762	mfpr	$IPL,r11
763	movl	r11,_br
764	subl3	$_catcher+8,(sp)+,r10
765	ashl	$-1,r10,r10
766	movl	r10,_cvec
767	POPR
768	rei
7691:
770	subl3	$_catcher+8,(sp)+,r0
771	ashl	$-1,r0,-(sp)
772	mfpr	$IPL,-(sp)
773	PRINTF(2, "uba?: stray intr ipl %x vec %o\n")
774	POPR
775	rei
776
777#if VAX630 || VAX650
778/*
779 * Emulation OpCode jump table:
780 *	ONLY GOES FROM 0xf8 (-8) TO 0x3B (59)
781 */
782#define EMUTABLE	0x43
783#define NOEMULATE	.long noemulate
784#define	EMULATE(a)	.long _EM/**/a
785	.globl	_emJUMPtable
786_emJUMPtable:
787/* f8 */	EMULATE(ashp);	EMULATE(cvtlp);	NOEMULATE;	NOEMULATE
788/* fc */	NOEMULATE;	NOEMULATE;	NOEMULATE;	NOEMULATE
789/* 00 */	NOEMULATE;	NOEMULATE;	NOEMULATE;	NOEMULATE
790/* 04 */	NOEMULATE;	NOEMULATE;	NOEMULATE;	NOEMULATE
791/* 08 */	EMULATE(cvtps);	EMULATE(cvtsp);	NOEMULATE;	EMULATE(crc)
792/* 0c */	NOEMULATE;	NOEMULATE;	NOEMULATE;	NOEMULATE
793/* 10 */	NOEMULATE;	NOEMULATE;	NOEMULATE;	NOEMULATE
794/* 14 */	NOEMULATE;	NOEMULATE;	NOEMULATE;	NOEMULATE
795/* 18 */	NOEMULATE;	NOEMULATE;	NOEMULATE;	NOEMULATE
796/* 1c */	NOEMULATE;	NOEMULATE;	NOEMULATE;	NOEMULATE
797/* 20 */	EMULATE(addp4);	EMULATE(addp6);	EMULATE(subp4);	EMULATE(subp6)
798/* 24 */	EMULATE(cvtpt);	EMULATE(mulp);	EMULATE(cvttp);	EMULATE(divp)
799/* 28 */	NOEMULATE;	EMULATE(cmpc3);	EMULATE(scanc);	EMULATE(spanc)
800/* 2c */	NOEMULATE;	EMULATE(cmpc5);	EMULATE(movtc);	EMULATE(movtuc)
801/* 30 */	NOEMULATE;	NOEMULATE;	NOEMULATE;	NOEMULATE
802/* 34 */	EMULATE(movp);	EMULATE(cmpp3);	EMULATE(cvtpl);	EMULATE(cmpp4)
803/* 38 */	EMULATE(editpc); EMULATE(matchc); EMULATE(locc); EMULATE(skpc)
804#endif
805
806/*
807 * Trap and fault vector routines
808 */
809#define	TRAP(a)	pushl $T_/**/a; jbr alltraps
810
811/*
812 * Ast delivery (profiling and/or reschedule)
813 */
814SCBVEC(astflt):
815	pushl $0; TRAP(ASTFLT)
816SCBVEC(privinflt):
817	pushl $0; TRAP(PRIVINFLT)
818SCBVEC(xfcflt):
819	pushl $0; TRAP(XFCFLT)
820SCBVEC(resopflt):
821	pushl $0; TRAP(RESOPFLT)
822SCBVEC(resadflt):
823	pushl $0; TRAP(RESADFLT)
824SCBVEC(bptflt):
825	pushl $0; TRAP(BPTFLT)
826SCBVEC(compatflt):
827	TRAP(COMPATFLT);
828SCBVEC(kdbintr):
829	pushl $0; TRAP(KDBTRAP)
830SCBVEC(tracep):
831	pushl $0; TRAP(TRCTRAP)
832SCBVEC(arithtrap):
833	TRAP(ARITHTRAP)
834SCBVEC(protflt):
835	blbs	(sp)+,segflt
836	TRAP(PROTFLT)
837segflt:
838	TRAP(SEGFLT)
839
840/*
841 * The following is called with the stack set up as follows:
842 *
843 *	  (sp):	Opcode
844 *	 4(sp):	Instruction PC
845 *	 8(sp):	Operand 1
846 *	12(sp):	Operand 2
847 *	16(sp):	Operand 3
848 *	20(sp):	Operand 4
849 *	24(sp):	Operand 5
850 *	28(sp):	Operand 6
851 *	32(sp):	Operand 7 (unused)
852 *	36(sp):	Operand 8 (unused)
853 *	40(sp):	Return PC
854 *	44(sp):	Return PSL
855 *	48(sp): TOS before instruction
856 *
857 * Each individual routine is called with the stack set up as follows:
858 *
859 *	  (sp):	Return address of trap handler
860 *	 4(sp):	Opcode (will get return PSL)
861 *	 8(sp):	Instruction PC
862 *	12(sp):	Operand 1
863 *	16(sp):	Operand 2
864 *	20(sp):	Operand 3
865 *	24(sp):	Operand 4
866 *	28(sp):	Operand 5
867 *	32(sp):	Operand 6
868 *	36(sp):	saved register 11
869 *	40(sp):	saved register 10
870 *	44(sp):	Return PC
871 *	48(sp):	Return PSL
872 *	52(sp): TOS before instruction
873 */
874
875SCBVEC(emulate):
876#if VAX630 || VAX650
877	movl	r11,32(sp)		# save register r11 in unused operand
878	movl	r10,36(sp)		# save register r10 in unused operand
879	cvtbl	(sp),r10		# get opcode
880	addl2	$8,r10			# shift negative opcodes
881	subl3	r10,$EMUTABLE,r11	# forget it if opcode is out of range
882	bcs	noemulate
883	movl	_emJUMPtable[r10],r10	# call appropriate emulation routine
884	jsb	(r10)		# routines put return values into regs 0-5
885	movl	32(sp),r11		# restore register r11
886	movl	36(sp),r10		# restore register r10
887	insv	(sp),$0,$4,44(sp)	# and condition codes in Opcode spot
888	addl2	$40,sp			# adjust stack for return
889	rei
890noemulate:
891	addl2	$48,sp			# adjust stack for
892#endif
893	.word	0xffff			# "reserved instruction fault"
894SCBVEC(emulateFPD):
895	.word	0xffff			# "reserved instruction fault"
896SCBVEC(transflt):
897	bitl	$2,(sp)+
898	bnequ	tableflt
899 	jsb	Fastreclaim		# try and avoid pagein
900	TRAP(PAGEFLT)
901tableflt:
902	TRAP(TABLEFLT)
903
904alltraps:
905	mfpr	$USP,-(sp); calls $0,_trap; mtpr (sp)+,$USP
906	incl	_cnt+V_TRAP
907	addl2	$8,sp			# pop type, code
908	mtpr	$HIGH,$IPL		## dont go to a higher IPL (GROT)
909	rei
910
911SCBVEC(syscall):
912	pushl	$T_SYSCALL
913	mfpr	$USP,-(sp); calls $0,_syscall; mtpr (sp)+,$USP
914	incl	_cnt+V_SYSCALL
915	addl2	$8,sp			# pop type, code
916	mtpr	$HIGH,$IPL		## dont go to a higher IPL (GROT)
917	rei
918
919/*
920 * System page table
921 * Mbmap and Usrptmap are enlarged by CLSIZE entries
922 * as they are managed by resource maps starting with index 1 or CLSIZE.
923 */
924#define	vaddr(x)	((((x)-_Sysmap)/4)*NBPG+0x80000000)
925#define	SYSMAP(mname, vname, npte)			\
926_/**/mname:	.globl	_/**/mname;		\
927	.space	(npte)*4;				\
928	.globl	_/**/vname;			\
929	.set	_/**/vname,vaddr(_/**/mname)
930#define	ADDMAP(npte)	.space	(npte)*4
931
932	.data
933	.align	2
934	SYSMAP(Sysmap	,Sysbase	,SYSPTSIZE	)
935	SYSMAP(Forkmap	,forkutl	,UPAGES		)
936	SYSMAP(Xswapmap	,xswaputl	,UPAGES		)
937	SYSMAP(Xswap2map,xswap2utl	,UPAGES		)
938	SYSMAP(Swapmap	,swaputl	,UPAGES		)
939	SYSMAP(Pushmap	,pushutl	,UPAGES		)
940	SYSMAP(Vfmap	,vfutl		,UPAGES		)
941	SYSMAP(CMAP1	,CADDR1		,1		)
942	SYSMAP(CMAP2	,CADDR2		,1		)
943	SYSMAP(mmap	,vmmap		,1		)
944	SYSMAP(alignmap	,alignutl	,1		)	/* XXX */
945	SYSMAP(msgbufmap,msgbuf		,MSGBUFPTECNT	)
946	SYSMAP(Mbmap	,mbutl		,NMBCLUSTERS*MCLBYTES/NBPG+CLSIZE )
947#ifdef MFS
948#include "ufs/mfsiom.h"
949	/*
950	 * Used by the mfs_doio() routine for physical I/O
951	 */
952	SYSMAP(Mfsiomap	,mfsiobuf	,MFS_MAPREG )
953#endif /* MFS */
954#ifdef NFS
955#include "nfs/nfsiom.h"
956	/*
957	 * Used by the nfs_doio() routine for physical I/O
958	 */
959	SYSMAP(Nfsiomap	,nfsiobuf	,NFS_MAPREG )
960#endif /* NFS */
961	/*
962	 * This is the map used by the kernel memory allocator.
963	 * It is expanded as necessary by the special features
964	 * that use it.
965	 *
966	 * XXX: NEED way to compute kmem size from maxusers,
967	 * device complement
968	 */
969	SYSMAP(kmempt	,kmembase	,NKMEMCLUSTERS*CLSIZE )
970#ifdef	SYSVSHM
971				ADDMAP(	SHMMAXPGS	)
972#endif
973#ifdef	GPROF
974				ADDMAP( 600*CLSIZE	)
975#endif
976	SYSMAP(ekmempt	,kmemlimit	,0		)
977
978	SYSMAP(UMBAbeg	,umbabeg	,0		)
979	SYSMAP(Nexmap	,nexus		,16*MAXNNEXUS	)
980#ifdef QBA
981#if (QBAPAGES+UBAIOPAGES) > (UBAPAGES+UBAIOPAGES)*NUBA
982	SYSMAP(UMEMmap	,umem		,(QBAPAGES+UBAIOPAGES) )
983#else
984	SYSMAP(UMEMmap	,umem		,(UBAPAGES+UBAIOPAGES)*NUBA )
985#endif
986#else /* QBA */
987	SYSMAP(UMEMmap	,umem		,(UBAPAGES+UBAIOPAGES)*NUBA )
988#endif /* QBA */
989#if VAX8600
990	SYSMAP(Ioamap	,ioa		,MAXNIOA*IOAMAPSIZ/NBPG	)
991#endif
992#if VAX8200 || VAX630
993	SYSMAP(Clockmap	,ka630clock	,1		)
994#endif
995#if VAX8200
996	/* alas, the clocks on the 8200 and 630 are not quite identical */
997	/* they could be shared for now, but this seemed cleaner */
998	.globl _ka820clock; .set _ka820clock,_ka630clock
999	SYSMAP(Ka820map	,ka820port	,1		)
1000	SYSMAP(RX50map	,rx50device	,1		)
1001#ifdef notyet
1002	SYSMAP(BRAMmap	,ka820bootram	,KA820_BRPAGES	)
1003	SYSMAP(EEPROMmap,ka820eeprom	,KA820_EEPAGES	)
1004#endif
1005#endif
1006#if VAX630
1007	SYSMAP(Ka630map	,ka630cpu	,1		)
1008#endif
1009#if VAX650
1010 	SYSMAP(KA650MERRmap	,ka650merr	,1		)
1011 	SYSMAP(KA650CBDmap	,ka650cbd	,1		)
1012 	SYSMAP(KA650SSCmap	,ka650ssc	,3		)
1013 	SYSMAP(KA650IPCRmap	,ka650ipcr	,1		)
1014 	SYSMAP(KA650CACHEmap	,ka650cache	,KA650_CACHESIZE/NBPG )
1015#endif
1016#ifdef QBA
1017	/*
1018	 * qvss and qdss don't coexist - one map will suffice
1019	 * for either. qvss is 256K each and qdss is 64K each.
1020	 */
1021#include "qv.h"
1022#include "qd.h"
1023#if NQV > 0 || NQD > 0
1024	SYSMAP(QVmap	,qvmem		,((512*NQV)+(128*NQD)))
1025#endif
1026#endif
1027	SYSMAP(UMBAend	,umbaend	,0		)
1028
1029	SYSMAP(Usrptmap	,usrpt		,USRPTSIZE+CLSIZE )
1030
1031eSysmap:
1032	.globl	_Syssize
1033	.set	_Syssize,(eSysmap-_Sysmap)/4
1034	.text
1035
1036/*
1037 * Initialization
1038 *
1039 * ipl 0x1f; mapen 0; scbb, pcbb, sbr, slr, isp, ksp not set
1040 */
1041	.data
1042	.globl	_cpu
1043_cpu:	.long	0
1044	.text
1045	.globl	start
1046start:
1047	.word	0
1048	mtpr	$0,$ICCS
1049/* set system control block base and system page table params */
1050	mtpr	$_scb-0x80000000,$SCBB
1051	mtpr	$_Sysmap-0x80000000,$SBR
1052	mtpr	$_Syssize,$SLR
1053/* double map the kernel into the virtual user addresses of phys mem */
1054	mtpr	$_Sysmap,$P0BR
1055	mtpr	$_Syssize,$P0LR
1056/* set ISP and get cpu type */
1057	movl	$_intstack+NISP*NBPG,sp
1058	mfpr	$SID,r0
1059	movab	_cpu,r1
1060	extzv	$24,$8,r0,(r1)
1061/* init RPB */
1062	movab	_rpb,r0
1063	movl	r0,(r0)+			# rp_selfref
1064	movab	_doadump,r1
1065	movl	r1,(r0)+			# rp_dumprout
1066	movl	$0x1f,r2
1067	clrl	r3
10681:	addl2	(r1)+,r3; sobgtr r2,1b
1069	movl	r3,(r0)+			# rp_chksum
1070/* count up memory; _physmem contains limit */
1071	clrl	r7
1072	ashl	$PGSHIFT,_physmem,r8
1073	decl	r8
10741:	pushl	$4; pushl r7; calls $2,_badaddr; tstl r0; bneq 9f
1075	acbl	r8,$64*1024,r7,1b
10769:
1077#if  VAX630 || VAX650
1078/* reserve area at top of memory for processor specific use */
1079	cmpb	_cpu,$VAX_630
1080	beql	1f
1081	cmpb	_cpu,$VAX_650
1082	bneq	2f
1083	subl2	$32768,r7	# space for Qbus map registers
1084	brb	2f
10851:
1086	subl2   $4096,r7	# space for console scratchpad
10872:
1088#endif
1089/* clear memory from kernel bss and pages for proc 0 u. and page table */
1090	movab	_edata,r6; bicl2 $SYSTEM,r6
1091	movab	_end,r5; bicl2 $SYSTEM,r5
1092#ifdef KADB
1093	subl2	$4,r5
10941:	clrl	(r6); acbl r5,$4,r6,1b		# clear just bss
1095	addl2	$4,r5
1096	bbc	$6,r11,0f			# check RB_KDB
1097	bicl3	$SYSTEM,r9,r5			# skip symbol & string tables
1098	bicl3	$SYSTEM,r9,r6			# r9 obtained from boot
1099#endif
11000:	bisl3	$SYSTEM,r5,r9			# convert to virtual address
1101	addl2	$NBPG-1,r9			# roundup to next page
1102	addl2	$(UPAGES*NBPG)+NBPG+NBPG,r5
11031:	clrq	(r6); acbl r5,$8,r6,1b
1104/* trap() and syscall() save r0-r11 in the entry mask (per ../h/reg.h) */
1105/* panic() is convenient place to save all for debugging */
1106	bisw2	$0x0fff,_trap
1107	bisw2	$0x0fff,_syscall
1108	bisw2	$0x0fff,_panic
1109	calls	$0,_fixctlrmask
1110/* initialize system page table: uba vectors and int stack writeable */
1111	clrl	r2
1112	movab	eintstack,r1; bbcc $31,r1,0f; 0: ashl $-PGSHIFT,r1,r1
11131:	bisl3	$PG_V|PG_KW,r2,_Sysmap[r2]; aoblss r1,r2,1b
1114/*
1115 * make rpb read-only as red zone for interrupt stack
1116 * (scb(s) and UNIvec are write-protected later)
1117 */
1118	bicl2	$PG_PROT,_rpbmap
1119	bisl2	$PG_KR,_rpbmap
1120/* make kernel text space read-only */
1121	movab	_etext+NBPG-1,r1; bbcc $31,r1,0f; 0: ashl $-PGSHIFT,r1,r1
11221:	bisl3	$PG_V|PG_URKR,r2,_Sysmap[r2]; aoblss r1,r2,1b
1123/* make kernel data, bss, read-write */
1124	bicl3	$SYSTEM,r9,r1; ashl $-PGSHIFT,r1,r1
11251:	bisl3	$PG_V|PG_KW,r2,_Sysmap[r2]; aoblss r1,r2,1b
1126/* now go to mapped mode */
1127	mtpr	$0,$TBIA; mtpr $1,$MAPEN; jmp *$0f; 0:
1128/* init mem sizes */
1129	ashl	$-PGSHIFT,r7,_physmem
1130/* setup context for proc[0] == Scheduler */
1131	bicl3	$SYSTEM|(NBPG-1),r9,r6	# make phys, page boundary
1132/* setup page table for proc[0] */
1133	ashl	$-PGSHIFT,r6,r3			# r3 = btoc(r6)
1134	bisl3	$PG_V|PG_KW,r3,_Usrptmap	# init first upt entry
1135	incl	r3
1136	movab	_usrpt,r0
1137	mtpr	r0,$TBIS
1138/* init p0br, p0lr */
1139	mtpr	r0,$P0BR
1140	mtpr	$0,$P0LR
1141/* init p1br, p1lr */
1142	movab	NBPG(r0),r0
1143	movl	$0x200000-UPAGES,r1
1144	mtpr	r1,$P1LR
1145	mnegl	r1,r1
1146	moval	-4*UPAGES(r0)[r1],r2
1147	mtpr	r2,$P1BR
1148/* setup mapping for UPAGES of _u */
1149	movl	$UPAGES,r2; movab _u+NBPG*UPAGES,r1; addl2 $UPAGES,r3; jbr 2f
11501:	decl	r3
1151	moval	-NBPG(r1),r1;
1152	bisl3	$PG_V|PG_URKW,r3,-(r0)
1153	mtpr	r1,$TBIS
11542:	sobgeq	r2,1b
1155/* initialize (slightly) the pcb */
1156	movab	UPAGES*NBPG(r1),PCB_KSP(r1)
1157	mnegl	$1,PCB_ESP(r1)
1158	mnegl	$1,PCB_SSP(r1)
1159	movl	r1,PCB_USP(r1)
1160	mfpr	$P0BR,PCB_P0BR(r1)
1161	mfpr	$P0LR,PCB_P0LR(r1)
1162	movb	$4,PCB_P0LR+3(r1)		# disable ast
1163	mfpr	$P1BR,PCB_P1BR(r1)
1164	mfpr	$P1LR,PCB_P1LR(r1)
1165	movl	$CLSIZE,PCB_SZPT(r1)		# init u.u_pcb.pcb_szpt
1166	movl	r9,PCB_R9(r1)
1167	movl	r10,PCB_R10(r1)
1168	movl	r11,PCB_R11(r1)
1169	movab	1f,PCB_PC(r1)			# initial pc
1170	clrl	PCB_PSL(r1)			# mode(k,k), ipl=0
1171	ashl	$PGSHIFT,r3,r3
1172	mtpr	r3,$PCBB			# first pcbb
1173/* set regs, p0br, p0lr, p1br, p1lr, astlvl, ksp and change to kernel mode */
1174	ldpctx
1175	rei
1176/* put signal trampoline code in u. area */
11771:	movab	_u,r0
1178	movc3	$19,sigcode,PCB_SIGC(r0)
1179/* save boot device in global _bootdev */
1180	movl	r10,_bootdev
1181/* save reboot flags in global _boothowto */
1182	movl	r11,_boothowto
1183#ifdef KADB
1184/* save end of symbol & string table in global _bootesym */
1185	subl3	$NBPG-1,r9,_bootesym
1186#endif
1187/* calculate firstaddr, and call main() */
1188	bicl3	$SYSTEM,r9,r0; ashl $-PGSHIFT,r0,-(sp)
1189	addl2	$UPAGES+1,(sp); calls $1,_main
1190/* proc[1] == /etc/init now running here; run icode */
1191	pushl	$PSL_CURMOD|PSL_PRVMOD; pushl $0; rei
1192
1193/* signal trampoline code: it is known that this code takes exactly 19 bytes */
1194/* in ../vax/pcb.h and in the movc3 above */
1195sigcode:
1196	calls	$4,8(pc)	# params pushed by sendsig
1197	movl	sp,ap		# calls frame built by sendsig
1198	chmk	$SYS_sigreturn	# cleanup mask and onsigstack
1199	halt			# sigreturn() does not return!
1200	.word	0x3f		# registers 0-5
1201	callg	(ap),*16(ap)	# call the signal handler
1202	ret			# return to code above
1203
1204	.globl	_icode
1205	.globl	_initflags
1206	.globl	_szicode
1207	.data
1208/*
1209 * Icode is copied out to process 1 to exec /etc/init.
1210 * If the exec fails, process 1 exits.
1211 */
1212_icode:
1213	pushl	$0
1214	pushab	b`argv-l0(pc)
1215l0:	pushab	b`init-l1(pc)
1216l1:	pushl	$2
1217	movl	sp,ap
1218	chmk	$SYS_execve
1219	pushl	r0
1220	chmk	$SYS_exit
1221
1222init:	.asciz	"/sbin/init"
1223	.align	2
1224_initflags:
1225	.long	0
1226argv:	.long	init+6-_icode
1227	.long	_initflags-_icode
1228	.long	0
1229_szicode:
1230	.long	_szicode-_icode
1231	.text
1232
1233/*
1234 * Primitives
1235 */
1236
1237#ifdef GPROF
1238#define	ENTRY(name, regs) \
1239	.globl _/**/name; .align 1; _/**/name: .word regs; jsb mcount
1240#define	JSBENTRY(name, regs) \
1241	.globl _/**/name; _/**/name: \
1242	movl fp,-(sp); movab -12(sp),fp; pushr $(regs); jsb mcount; \
1243	popr $(regs); movl (sp)+,fp
1244#else
1245#define	ENTRY(name, regs) \
1246	.globl _/**/name; .align 1; _/**/name: .word regs
1247#define	JSBENTRY(name, regs) \
1248	.globl _/**/name; _/**/name:
1249#endif GPROF
1250#define R0 0x01
1251#define R1 0x02
1252#define R2 0x04
1253#define R3 0x08
1254#define R4 0x10
1255#define R5 0x20
1256#define R6 0x40
1257
1258/*
1259 * badaddr(addr, len)
1260 *	see if access addr with a len type instruction causes a machine check
1261 *	len is length of access (1=byte, 2=short, 4=long)
1262 */
1263	.globl	_badaddr
1264_badaddr:
1265	.word	0
1266	movl	$1,r0
1267	mfpr	$IPL,r1
1268	mtpr	$HIGH,$IPL
1269	movl	4(ap),r3
1270	movl	8(ap),r4
1271	movab	2f,nofault		# jump to 2f on machcheck
1272	bbc	$0,r4,1f; tstb	(r3)
12731:	bbc	$1,r4,1f; tstw	(r3)
12741:	bbc	$2,r4,1f; tstl	(r3)
12751:	clrl	r0			# made it w/o machine checks
12762:	clrl	nofault
1277	mtpr	r1,$IPL
1278	ret
1279
1280/*
1281 * update profiling information for the user
1282 * addupc(pc, &u.u_prof, ticks)
1283 */
1284ENTRY(addupc, 0)
1285	movl	8(ap),r2		# &u.u_prof
1286	subl3	8(r2),4(ap),r0		# corrected pc
1287	blss	9f
1288	extzv	$1,$31,r0,r0		# logical right shift
1289	extzv	$1,$31,12(r2),r1	# ditto for scale
1290	emul	r1,r0,$0,r0
1291	ashq	$-14,r0,r0
1292	tstl	r1
1293	bneq	9f
1294	bicl2	$1,r0
1295	cmpl	r0,4(r2)		# length
1296	bgequ	9f
1297	addl2	(r2),r0			# base
1298	probew	$3,$2,(r0)
1299	beql	8f
1300	addw2	12(ap),(r0)
13019:
1302	ret
13038:
1304	clrl	12(r2)
1305	ret
1306
1307/*
1308 * Copy a null terminated string from the user address space into
1309 * the kernel address space.
1310 *
1311 * copyinstr(fromaddr, toaddr, maxlength, &lencopied)
1312 */
1313ENTRY(copyinstr, R6)
1314	movl	12(ap),r6		# r6 = max length
1315	jlss	8f
1316	movl	4(ap),r1		# r1 = user address
1317	bicl3	$~(NBPG*CLSIZE-1),r1,r2	# r2 = bytes on first page
1318	subl3	r2,$NBPG*CLSIZE,r2
1319	movl	8(ap),r3		# r3 = kernel address
13201:
1321	cmpl	r6,r2			# r2 = min(bytes on page, length left);
1322	jgeq	2f
1323	movl	r6,r2
13242:
1325	prober	$3,r2,(r1)		# bytes accessible?
1326	jeql	8f
1327	subl2	r2,r6			# update bytes left count
1328#ifdef NOSUBSINST
1329	# fake the locc instr. for processors that don't have it
1330	movl	r2,r0
13316:
1332	tstb	(r1)+
1333	jeql	5f
1334	sobgtr	r0,6b
1335	jbr	7f
13365:
1337	decl	r1
1338	jbr	3f
13397:
1340#else
1341	locc	$0,r2,(r1)		# null byte found?
1342	jneq	3f
1343#endif
1344	subl2	r2,r1			# back up pointer updated by `locc'
1345	movc3	r2,(r1),(r3)		# copy in next piece
1346	movl	$(NBPG*CLSIZE),r2	# check next page
1347	tstl	r6			# run out of space?
1348	jneq	1b
1349	movl	$ENAMETOOLONG,r0	# set error code and return
1350	jbr	9f
13513:
1352	tstl	16(ap)			# return length?
1353	beql	4f
1354	subl3	r6,12(ap),r6		# actual len = maxlen - unused pages
1355	subl2	r0,r6			#	- unused on this page
1356	addl3	$1,r6,*16(ap)		#	+ the null byte
13574:
1358	subl2	r0,r2			# r2 = number of bytes to move
1359	subl2	r2,r1			# back up pointer updated by `locc'
1360	incl	r2			# copy null byte as well
1361	movc3	r2,(r1),(r3)		# copy in last piece
1362	clrl	r0			# redundant
1363	ret
13648:
1365	movl	$EFAULT,r0
13669:
1367	tstl	16(ap)
1368	beql	1f
1369	subl3	r6,12(ap),*16(ap)
13701:
1371	ret
1372
1373/*
1374 * Copy a null terminated string from the kernel
1375 * address space to the user address space.
1376 *
1377 * copyoutstr(fromaddr, toaddr, maxlength, &lencopied)
1378 */
1379ENTRY(copyoutstr, R6)
1380	movl	12(ap),r6		# r6 = max length
1381	jlss	8b
1382	movl	4(ap),r1		# r1 = kernel address
1383	movl	8(ap),r3		# r3 = user address
1384	bicl3	$~(NBPG*CLSIZE-1),r3,r2	# r2 = bytes on first page
1385	subl3	r2,$NBPG*CLSIZE,r2
13861:
1387	cmpl	r6,r2			# r2 = min(bytes on page, length left);
1388	jgeq	2f
1389	movl	r6,r2
13902:
1391	probew	$3,r2,(r3)		# bytes accessible?
1392	jeql	8b
1393	subl2	r2,r6			# update bytes left count
1394#ifdef NOSUBSINST
1395	# fake the locc instr. for processors that don't have it
1396	movl	r2,r0
13976:
1398	tstb	(r1)+
1399	jeql	5f
1400	sobgtr	r0,6b
1401	jbr	7f
14025:
1403	decl	r1
1404	jbr	3b
14057:
1406#else
1407	locc	$0,r2,(r1)		# null byte found?
1408	jneq	3b
1409#endif
1410	subl2	r2,r1			# back up pointer updated by `locc'
1411	movc3	r2,(r1),(r3)		# copy in next piece
1412	movl	$(NBPG*CLSIZE),r2	# check next page
1413	tstl	r6			# run out of space?
1414	jneq	1b
1415	movl	$ENAMETOOLONG,r0	# set error code and return
1416	jbr	9b
1417
1418/*
1419 * Copy a null terminated string from one point to another in
1420 * the kernel address space.
1421 *
1422 * copystr(fromaddr, toaddr, maxlength, &lencopied)
1423 */
1424ENTRY(copystr, R6)
1425	movl	12(ap),r6		# r6 = max length
1426	jlss	8b
1427	movl	4(ap),r1		# r1 = src address
1428	movl	8(ap),r3		# r3 = dest address
14291:
1430	movzwl	$65535,r2		# r2 = bytes in first chunk
1431	cmpl	r6,r2			# r2 = min(bytes in chunk, length left);
1432	jgeq	2f
1433	movl	r6,r2
14342:
1435	subl2	r2,r6			# update bytes left count
1436#ifdef NOSUBSINST
1437	# fake the locc instr. for processors that don't have it
1438	movl	r2,r0
14396:
1440	tstb	(r1)+
1441	jeql	5f
1442	sobgtr	r0,6b
1443	jbr	7f
14445:
1445	decl	r1
1446	jbr	3b
14477:
1448#else
1449	locc	$0,r2,(r1)		# null byte found?
1450	jneq	3b
1451#endif
1452	subl2	r2,r1			# back up pointer updated by `locc'
1453	movc3	r2,(r1),(r3)		# copy in next piece
1454	tstl	r6			# run out of space?
1455	jneq	1b
1456	movl	$ENAMETOOLONG,r0	# set error code and return
1457	jbr	9b
1458
1459/*
1460 * Copy specified amount of data from user space into the kernel
1461 * Copyin(from, to, len)
1462 *	r1 == from (user source address)
1463 *	r3 == to (kernel destination address)
1464 *	r5 == length
1465 */
1466	.align	1
1467JSBENTRY(Copyin, R1|R3|R5)
1468	cmpl	r5,$(NBPG*CLSIZE)	# probing one page or less ?
1469	bgtru	1f			# no
1470	prober	$3,r5,(r1)		# bytes accessible ?
1471	bneq	4f			# yes
1472	tstl	r5			# if zero bytes, lie.
1473	bneq	ersb
1474	clrl	r0
1475	rsb
14764:
1477	movc3	r5,(r1),(r3)
1478/*	clrl	r0			# redundant */
1479	rsb
14801:
1481	blss	ersb			# negative length?
1482	pushl	r6			# r6 = length
1483	movl	r5,r6
1484	bicl3	$~(NBPG*CLSIZE-1),r1,r0	# r0 = bytes on first page
1485	subl3	r0,$(NBPG*CLSIZE),r0
1486	addl2	$(NBPG*CLSIZE),r0	# plus one additional full page
1487	jbr	2f
1488
1489ciloop:
1490	movc3	r0,(r1),(r3)
1491	movl	$(2*NBPG*CLSIZE),r0	# next amount to move
14922:
1493	cmpl	r0,r6
1494	bleq	3f
1495	movl	r6,r0
14963:
1497	prober	$3,r0,(r1)		# bytes accessible ?
1498	beql	ersb1			# no
1499	subl2	r0,r6			# last move?
1500	bneq	ciloop			# no
1501
1502	movc3	r0,(r1),(r3)
1503/*	clrl	r0			# redundant */
1504	movl	(sp)+,r6		# restore r6
1505	rsb
1506
1507ersb1:
1508	movl	(sp)+,r6		# restore r6
1509ersb:
1510	movl	$EFAULT,r0
1511	rsb
1512
1513/*
1514 * Copy specified amount of data from kernel to the user space
1515 * Copyout(from, to, len)
1516 *	r1 == from (kernel source address)
1517 *	r3 == to (user destination address)
1518 *	r5 == length
1519 */
1520	.align	1
1521JSBENTRY(Copyout, R1|R3|R5)
1522	cmpl	r5,$(NBPG*CLSIZE)	# moving one page or less ?
1523	bgtru	1f			# no
1524	probew	$3,r5,(r3)		# bytes writeable?
1525	bneq	4f			# yes
1526	tstl	r5			# if zero bytes, it's ok anyway.
1527	bneq	ersb			# otherwise indicate error
1528	clrl	r0
1529	rsb
15304:
1531	movc3	r5,(r1),(r3)
1532/*	clrl	r0			# redundant */
1533	rsb
15341:
1535	blss	ersb			# negative length?
1536	pushl	r6			# r6 = length
1537	movl	r5,r6
1538	bicl3	$~(NBPG*CLSIZE-1),r3,r0	# r0 = bytes on first page
1539	subl3	r0,$(NBPG*CLSIZE),r0
1540	addl2	$(NBPG*CLSIZE),r0	# plus one additional full page
1541	jbr	2f
1542
1543coloop:
1544	movc3	r0,(r1),(r3)
1545	movl	$(2*NBPG*CLSIZE),r0	# next amount to move
15462:
1547	cmpl	r0,r6
1548	bleq	3f
1549	movl	r6,r0
15503:
1551	probew	$3,r0,(r3)		# bytes writeable?
1552	beql	ersb1			# no
1553	subl2	r0,r6			# last move?
1554	bneq	coloop			# no
1555
1556	movc3	r0,(r1),(r3)
1557/*	clrl	r0			# redundant */
1558	movl	(sp)+,r6		# restore r6
1559	rsb
1560
1561/*
1562 * savectx is like setjmp but saves all registers.
1563 * Called before swapping out the u. area, restored by resume()
1564 * below.
1565 */
1566#define PCLOC 16	/* location of pc in calls frame */
1567#define APLOC 8		/* location of ap,fp in calls frame */
1568
1569ENTRY(savectx, 0)
1570	movl	4(ap),r0
1571	movq	r6,(r0)+
1572	movq	r8,(r0)+
1573	movq	r10,(r0)+
1574	movq	APLOC(fp),(r0)+	# save ap, fp
1575	addl3	$8,ap,(r0)+	# save sp
1576	movl	PCLOC(fp),(r0)	# save pc
1577	clrl	r0
1578	ret
1579
1580#ifdef KADB
1581/*
1582 * C library -- reset, setexit
1583 *
1584 *	reset(x)
1585 * will generate a "return" from
1586 * the last call to
1587 *	setexit()
1588 * by restoring r6 - r12, ap, fp
1589 * and doing a return.
1590 * The returned value is x; on the original
1591 * call the returned value is 0.
1592 */
1593ENTRY(setexit, 0)
1594	movab	setsav,r0
1595	movq	r6,(r0)+
1596	movq	r8,(r0)+
1597	movq	r10,(r0)+
1598	movq	8(fp),(r0)+		# ap, fp
1599	movab	4(ap),(r0)+		# sp
1600	movl	16(fp),(r0)		# pc
1601	clrl	r0
1602	ret
1603
1604ENTRY(reset, 0)
1605	movl	4(ap),r0	# returned value
1606	movab	setsav,r1
1607	movq	(r1)+,r6
1608	movq	(r1)+,r8
1609	movq	(r1)+,r10
1610	movq	(r1)+,r12
1611	movl	(r1)+,sp
1612	jmp 	*(r1)
1613
1614	.data
1615	.align  2
1616setsav:	.space	10*4
1617	.text
1618#endif
1619
1620	.globl	_whichqs
1621	.globl	_qs
1622	.globl	_cnt
1623
1624	.globl	_noproc
1625	.comm	_noproc,4
1626	.globl	_runrun
1627	.comm	_runrun,4
1628
1629/*
1630 * The following primitives use the fancy VAX instructions
1631 * much like VMS does.  _whichqs tells which of the 32 queues _qs
1632 * have processes in them.  Setrq puts processes into queues, Remrq
1633 * removes them from queues.  The running process is on no queue,
1634 * other processes are on a queue related to p->p_pri, divided by 4
1635 * actually to shrink the 0-127 range of priorities into the 32 available
1636 * queues.
1637 */
1638
1639/*
1640 * Setrq(p), using fancy VAX instructions.
1641 *
1642 * Call should be made at splclock(), and p->p_stat should be SRUN
1643 */
1644	.align	1
1645JSBENTRY(Setrq, R0)
1646	tstl	P_RLINK(r0)		## firewall: p->p_rlink must be 0
1647	beql	set1			##
1648	pushab	set3			##
1649	calls	$1,_panic		##
1650set1:
1651	movzbl	P_PRI(r0),r1		# put on queue which is p->p_pri / 4
1652	ashl	$-2,r1,r1
1653	movaq	_qs[r1],r2
1654	insque	(r0),*4(r2)		# at end of queue
1655	bbss	r1,_whichqs,set2	# mark queue non-empty
1656set2:
1657	rsb
1658
1659set3:	.asciz	"setrq"
1660
1661/*
1662 * Remrq(p), using fancy VAX instructions
1663 *
1664 * Call should be made at splclock().
1665 */
1666	.align	1
1667JSBENTRY(Remrq, R0)
1668	movzbl	P_PRI(r0),r1
1669	ashl	$-2,r1,r1
1670	bbsc	r1,_whichqs,rem1
1671	pushab	rem3			# it wasn't recorded to be on its q
1672	calls	$1,_panic
1673rem1:
1674	remque	(r0),r2
1675	beql	rem2
1676	bbss	r1,_whichqs,rem2
1677rem2:
1678	clrl	P_RLINK(r0)		## for firewall checking
1679	rsb
1680
1681rem3:	.asciz	"remrq"
1682
1683/*
1684 * Masterpaddr is the p->p_addr of the running process on the master
1685 * processor.  When a multiprocessor system, the slave processors will have
1686 * an array of slavepaddr's.
1687 */
1688	.globl	_masterpaddr
1689	.data
1690_masterpaddr:
1691	.long	0
1692
1693	.text
1694sw0:	.asciz	"swtch"
1695
1696/*
1697 * When no processes are on the runq, Swtch branches to idle
1698 * to wait for something to come ready.
1699 */
1700	.globl	Idle
1701Idle: idle:
1702	movl	$1,_noproc
1703	mtpr	$0,$IPL			# must allow interrupts here
17041:
1705	tstl	_whichqs		# look for non-empty queue
1706	bneq	sw1
1707	brb	1b
1708
1709badsw:	pushab	sw0
1710	calls	$1,_panic
1711	/*NOTREACHED*/
1712
1713/*
1714 * Swtch(), using fancy VAX instructions
1715 */
1716	.align	1
1717JSBENTRY(Swtch, 0)
1718	incl	_cnt+V_SWTCH
1719sw1:	ffs	$0,$32,_whichqs,r0	# look for non-empty queue
1720	beql	idle			# if none, idle
1721	mtpr	$0x18,$IPL		# lock out all so _whichqs==_qs
1722	bbcc	r0,_whichqs,sw1		# proc moved via interrupt
1723	movaq	_qs[r0],r1
1724	remque	*(r1),r2		# r2 = p = highest pri process
1725	bvs	badsw			# make sure something was there
1726	beql	sw2
1727	insv	$1,r0,$1,_whichqs	# still more procs in this queue
1728sw2:
1729	clrl	_noproc
1730	clrl	_runrun
1731#ifdef notdef
1732	tstl	P_WCHAN(r2)		## firewalls
1733	bneq	badsw			##
1734	cmpb	P_STAT(r2),$SRUN	##
1735	bneq	badsw			##
1736#endif
1737	clrl	P_RLINK(r2)		##
1738	movl	*P_ADDR(r2),r0
1739#ifdef notdef
1740	cmpl	r0,_masterpaddr		# resume of current proc is easy
1741	beql	res0
1742#endif
1743	movl	r0,_masterpaddr
1744	ashl	$PGSHIFT,r0,r0		# r0 = pcbb(p)
1745/* fall into... */
1746
1747/*
1748 * Resume(pf)
1749 */
1750JSBENTRY(Resume, R0)
1751	mtpr	$HIGH,$IPL			# no interrupts, please
1752	movl	_CMAP2,_u+PCB_CMAP2	# yech
1753	svpctx
1754	mtpr	r0,$PCBB
1755	ldpctx
1756	movl	_u+PCB_CMAP2,_CMAP2	# yech
1757	mtpr	$_CADDR2,$TBIS
1758res0:
1759	tstl	_u+PCB_SSWAP
1760	bneq	res1
1761	rei
1762res1:
1763	movl	_u+PCB_SSWAP,r0		# restore alternate saved context
1764	clrl	_u+PCB_SSWAP
1765	movq	(r0)+,r6			# restore r6, r7
1766	movq	(r0)+,r8			# restore r8, r9
1767	movq	(r0)+,r10			# restore r10, r11
1768	movq	(r0)+,r12			# restore ap, fp
1769	movl	(r0)+,r1			# saved sp
1770	cmpl	r1,sp				# must be a pop
1771	bgequ	1f
1772	pushab	2f
1773	calls	$1,_panic
1774	/* NOTREACHED */
17751:
1776	movl	r1,sp				# restore sp
1777	pushl	$PSL_PRVMOD			# return psl
1778	pushl	(r0)				# address to return to
1779	rei
1780
17812:	.asciz	"ldctx"
1782
1783/*
1784 * {fu,su},{byte,word}, all massaged by asm.sed to jsb's
1785 */
1786	.align	1
1787JSBENTRY(Fuword, R0)
1788	prober	$3,$4,(r0)
1789	beql	fserr
1790	movl	(r0),r0
1791	rsb
1792fserr:
1793	mnegl	$1,r0
1794	rsb
1795
1796	.align	1
1797JSBENTRY(Fubyte, R0)
1798	prober	$3,$1,(r0)
1799	beql	fserr
1800	movzbl	(r0),r0
1801	rsb
1802
1803	.align	1
1804JSBENTRY(Suword, R0|R1)
1805	probew	$3,$4,(r0)
1806	beql	fserr
1807	movl	r1,(r0)
1808	clrl	r0
1809	rsb
1810
1811	.align	1
1812JSBENTRY(Subyte, R0|R1)
1813	probew	$3,$1,(r0)
1814	beql	fserr
1815	movb	r1,(r0)
1816	clrl	r0
1817	rsb
1818
1819/*
1820 * Copy 1 relocation unit (NBPG bytes)
1821 * from user virtual address to physical address
1822 */
1823ENTRY(copyseg, 0)
1824	bisl3	$PG_V|PG_KW,8(ap),_CMAP2
1825	mtpr	$_CADDR2,$TBIS	# invalidate entry for copy
1826	movc3	$NBPG,*4(ap),_CADDR2
1827	ret
1828
1829/*
1830 * zero out physical memory
1831 * specified in relocation units (NBPG bytes)
1832 */
1833ENTRY(clearseg, 0)
1834	bisl3	$PG_V|PG_KW,4(ap),_CMAP1
1835	mtpr	$_CADDR1,$TBIS
1836	movc5	$0,(sp),$0,$NBPG,_CADDR1
1837	ret
1838
1839/*
1840 * Check address.
1841 * Given virtual address, byte count, and rw flag
1842 * returns 0 on no access.
1843 */
1844ENTRY(useracc, 0)
1845	movl	4(ap),r0		# get va
1846	movl	8(ap),r1		# count
1847	tstl	12(ap)			# test for read access ?
1848	bneq	userar			# yes
1849	cmpl	$NBPG,r1			# can we do it in one probe ?
1850	bgeq	uaw2			# yes
1851uaw1:
1852	probew	$3,$NBPG,(r0)
1853	beql	uaerr			# no access
1854	addl2	$NBPG,r0
1855	acbl	$NBPG+1,$-NBPG,r1,uaw1
1856uaw2:
1857	probew	$3,r1,(r0)
1858	beql	uaerr
1859	movl	$1,r0
1860	ret
1861
1862userar:
1863	cmpl	$NBPG,r1
1864	bgeq	uar2
1865uar1:
1866	prober	$3,$NBPG,(r0)
1867	beql	uaerr
1868	addl2	$NBPG,r0
1869	acbl	$NBPG+1,$-NBPG,r1,uar1
1870uar2:
1871	prober	$3,r1,(r0)
1872	beql	uaerr
1873	movl	$1,r0
1874	ret
1875uaerr:
1876	clrl	r0
1877	ret
1878
1879/*
1880 * kernacc - check for kernel access privileges
1881 *
1882 * We can't use the probe instruction directly because
1883 * it ors together current and previous mode.
1884 */
1885 ENTRY(kernacc, 0)
1886	movl	4(ap),r0	# virtual address
1887	bbcc	$31,r0,kacc1
1888	bbs	$30,r0,kacerr
1889	mfpr	$SBR,r2		# address and length of page table (system)
1890	bbss	$31,r2,0f; 0:
1891	mfpr	$SLR,r3
1892	brb	kacc2
1893kacc1:
1894	bbsc	$30,r0,kacc3
1895	mfpr	$P0BR,r2	# user P0
1896	mfpr	$P0LR,r3
1897	brb	kacc2
1898kacc3:
1899	mfpr	$P1BR,r2	# user P1 (stack)
1900	mfpr	$P1LR,r3
1901kacc2:
1902	addl3	8(ap),r0,r1	# ending virtual address
1903	addl2	$NBPG-1,r1
1904	ashl	$-PGSHIFT,r0,r0
1905	ashl	$-PGSHIFT,r1,r1
1906	bbs	$31,4(ap),kacc6
1907	bbc	$30,4(ap),kacc6
1908	cmpl	r0,r3		# user stack
1909	blss	kacerr		# address too low
1910	brb	kacc4
1911kacc6:
1912	cmpl	r1,r3		# compare last page to P0LR or SLR
1913	bgtr	kacerr		# address too high
1914kacc4:
1915	movl	(r2)[r0],r3
1916	bbc	$31,4(ap),kacc4a
1917	bbc	$31,r3,kacerr	# valid bit is off
1918kacc4a:
1919	cmpzv	$27,$4,r3,$1	# check protection code
1920	bleq	kacerr		# no access allowed
1921	tstb	12(ap)
1922	bneq	kacc5		# only check read access
1923	cmpzv	$27,$2,r3,$3	# check low 2 bits of prot code
1924	beql	kacerr		# no write access
1925kacc5:
1926	aoblss	r1,r0,kacc4	# next page
1927	movl	$1,r0		# no errors
1928	ret
1929kacerr:
1930	clrl	r0		# error
1931	ret
1932/*
1933 * Extracted and unrolled most common case of pagein (hopefully):
1934 *	resident and not on free list (reclaim of page is purely
1935 *	for the purpose of simulating a reference bit)
1936 *
1937 * Built in constants:
1938 *	CLSIZE of 2, any bit fields in pte's
1939 */
1940	.text
1941	.globl	Fastreclaim
1942Fastreclaim:
1943	PUSHR
1944#ifdef GPROF
1945	movl	fp,-(sp)
1946	movab	12(sp),fp
1947	jsb	mcount
1948	movl	(sp)+,fp
1949#endif GPROF
1950	extzv	$9,$23,28(sp),r3	# virtual address
1951	bicl2	$1,r3			# v = clbase(btop(virtaddr));
1952	movl	_u+U_PROCP,r5		# p = u.u_procp
1953					# from vtopte(p, v) ...
1954	movl	$1,r2			# type = CTEXT;
1955	cmpl	r3,P_TSIZE(r5)
1956	jlssu	1f			# if (isatsv(p, v)) {
1957	addl3	P_TSIZE(r5),P_DSIZE(r5),r0
1958	cmpl	r3,r0
1959	jgequ	2f
1960	clrl	r2			#	type = !CTEXT;
19611:
1962	ashl	$2,r3,r4
1963	addl2	P_P0BR(r5),r4		#	tptopte(p, vtotp(p, v));
1964	jbr	3f
19652:
1966	cvtwl	P_SZPT(r5),r4		# } else (isassv(p, v)) {
1967	ashl	$7,r4,r4
1968	subl2	$0x400000,r4
1969	addl2	r3,r4
1970	ashl	$2,r4,r4
1971	addl2	P_P0BR(r5),r4		#	sptopte(p, vtosp(p, v));
1972	clrl	r2			# 	type = !CTEXT;
19733:					# }
1974	bitb	$0x82,3(r4)
1975	beql	2f			# if (pte->pg_v || pte->pg_fod)
1976	POPR; rsb			#	let pagein handle it
19772:
1978	bicl3	$0xffe00000,(r4),r0
1979	jneq	2f			# if (pte->pg_pfnum == 0)
1980	POPR; rsb			# 	let pagein handle it
19812:
1982	subl2	_firstfree,r0
1983	ashl	$-1,r0,r0
1984	incl	r0			# pgtocm(pte->pg_pfnum)
1985	mull2	$SZ_CMAP,r0
1986	addl2	_cmap,r0		# &cmap[pgtocm(pte->pg_pfnum)]
1987	tstl	r2
1988	jeql	2f			# if (type == CTEXT &&
1989	jbc	$C_INTRANS,(r0),2f	#     c_intrans)
1990	POPR; rsb			# 	let pagein handle it
19912:
1992	jbc	$C_FREE,(r0),2f		# if (c_free)
1993	POPR; rsb			# 	let pagein handle it
19942:
1995	bisb2	$0x80,3(r4)		# pte->pg_v = 1;
1996	jbc	$26,4(r4),2f		# if (anycl(pte, pg_m)
1997	bisb2	$0x04,3(r4)		#	pte->pg_m = 1;
19982:
1999	bicw3	$0x7f,2(r4),r0
2000	bicw3	$0xff80,6(r4),r1
2001	bisw3	r0,r1,6(r4)		# distcl(pte);
2002	ashl	$PGSHIFT,r3,r0
2003	mtpr	r0,$TBIS
2004	addl2	$NBPG,r0
2005	mtpr	r0,$TBIS		# tbiscl(v);
2006	tstl	r2
2007	jeql	2f			# if (type == CTEXT)
2008	movl	P_TEXTP(r5),r0
2009	movl	X_CADDR(r0),r5		# for (p = p->p_textp->x_caddr; p; ) {
2010	jeql	2f
2011	ashl	$2,r3,r3
20123:
2013	addl3	P_P0BR(r5),r3,r0	#	tpte = tptopte(p, tp);
2014	bisb2	$1,P_FLAG+3(r5)		#	p->p_flag |= SPTECHG;
2015	movl	(r4),(r0)+		#	for (i = 0; i < CLSIZE; i++)
2016	movl	4(r4),(r0)		#		tpte[i] = pte[i];
2017	movl	P_XLINK(r5),r5		#	p = p->p_xlink;
2018	jneq	3b			# }
20192:					# collect a few statistics...
2020	incl	_u+U_RU+RU_MINFLT	# u.u_ru.ru_minflt++;
2021	moval	_cnt,r0
2022	incl	V_FAULTS(r0)		# cnt.v_faults++;
2023	incl	V_PGREC(r0)		# cnt.v_pgrec++;
2024	incl	V_FASTPGREC(r0)		# cnt.v_fastpgrec++;
2025	incl	V_TRAP(r0)		# cnt.v_trap++;
2026	POPR
2027	addl2	$8,sp			# pop pc, code
2028	mtpr	$HIGH,$IPL		## dont go to a higher IPL (GROT)
2029	rei
2030