xref: /original-bsd/sys/vax/vax/locore.s (revision ba72ef4c)
1#
2# Machine Language Assist for UC Berkeley Virtual Vax/Unix
3#
4#	locore.s		3.16	10/02/80
5#
6
7	.set	HIGH,31		# mask for total disable
8	.set	MCKVEC,4	# offset into Scbbase of machine check vector
9	.set	NBPG,512
10	.set	PGSHIFT,9
11
12	.set	CLSIZE,2
13	.set	BSIZE,NBPG*CLSIZE
14	.set	NBUF,62
15	.set	UPAGES,6	# size of user area, in pages
16
17# ====================================
18# Trap vectors and C interface for Vax
19# ====================================
20
21#
22# System control block
23#
24
25	.set	INTSTK,1	# handle this interrupt on the interrupt stack
26	.set	HALT,3		# halt if this interrupt occurs
27#	.align	PGSHIFT
28	.globl	Scbbase
29Scbbase:
30	.long	Xstray + INTSTK		# unused
31	.long	Xmachcheck + INTSTK	# machine check interrupt
32	.long	Xkspnotval + INTSTK	# kernel stack not valid
33	.long	Xpowfail + HALT		# power fail
34	.long	Xprivinflt		# privileged instruction
35	.long	Xxfcflt			# xfc instruction
36	.long	Xresopflt		# reserved operand
37	.long	Xresadflt		# reserved addressing
38	.long	Xprotflt		# protection and pt length violation
39	.long	Xtransflt		# address translation not valid fault
40	.long	Xtracep			# trace pending
41	.long	Xbptflt			# bpt instruction
42	.long	Xcompatflt		# compatibility mode fault
43	.long	Xarithtrap		# arithmetic trap
44	.long	Xstray + INTSTK		# unused
45	.long	Xstray + INTSTK		# unused
46	.long	Xsyscall		# chmk
47	.long	Xchme+INTSTK		# chme
48	.long	Xchms+INTSTK		# chms
49	.long	Xchmu+INTSTK		# chmu
50	.long	Xstray + INTSTK		# unused
51	.long	Xstray + INTSTK		# unused
52	.long	Xstray + INTSTK		# unused
53	.long	Xstray + INTSTK		# unused
54	.long	Xstray + INTSTK		# unused
55	.long	Xstray + INTSTK		# unused
56	.long	Xstray + INTSTK		# unused
57	.long	Xstray + INTSTK		# unused
58	.long	Xstray + INTSTK		# unused
59	.long	Xstray + INTSTK		# unused
60	.long	Xstray + INTSTK		# unused
61	.long	Xstray + INTSTK		# unused
62	.long	Xstray + INTSTK		# unused
63	.long	Xstray + INTSTK		# software level 1
64	.long	Xstray + INTSTK		# software level 2 (asts)
65	.long	Xresched		# reschedule nudge
66	.long	Xstray + INTSTK		# unused
67	.long	Xstray + INTSTK		# unused
68	.long	Xstray + INTSTK		# unused
69	.long	Xstray + INTSTK		# unused
70	.long	Xstray + INTSTK		# unused
71	.long	Xstray + INTSTK		# unused
72	.long	Xstray + INTSTK		# unused
73	.long	Xstray + INTSTK		# unused
74	.long	Xstray + INTSTK		# unused
75	.long	Xstray + INTSTK		# unused
76	.long	Xstray + INTSTK		# unused
77	.long	Xstray + INTSTK		# unused
78ubabase:
79	.long	Xclockint		# clock
80	.long	Xstray + INTSTK		# unused
81	.long	Xstray + INTSTK		# unused
82	.long	Xstray + INTSTK		# unused
83	.long	Xstray + INTSTK		# unused
84	.long	Xstray + INTSTK		# unused
85	.long	Xstray + INTSTK		# unused
86	.long	Xstray + INTSTK		# unused
87	.long	Xstray + INTSTK		# unused
88	.long	Xstray + INTSTK		# unused
89	.long	Xstray + INTSTK		# unused
90	.long	Xstray + INTSTK		# unused
91	.long	Xstray + INTSTK		# unused
92	.long	Xstray + INTSTK		# unused
93	.long	Xcnrint + INTSTK	# console receiver
94	.long	Xcnxint + INTSTK	# console transmitter
95
96#
97# I/O vectors
98#
99
100# IPL 14
101	.long	Xstray + INTSTK		# unused
102	.long	Xstray + INTSTK		# unused
103	.long	Xstray + INTSTK		# unused
104	.long	Xua0int + INTSTK	# UBA 0 br4
105	.long	Xstray + INTSTK		# unused
106	.long	Xstray + INTSTK		# unused
107	.long	Xstray + INTSTK		# unused
108	.long	Xstray + INTSTK		# unused
109	.long	Xstray + INTSTK		# unused
110	.long	Xstray + INTSTK		# unused
111	.long	Xstray + INTSTK		# unused
112	.long	Xstray + INTSTK		# unused
113	.long	Xstray + INTSTK		# unused
114	.long	Xstray + INTSTK		# unused
115	.long	Xstray + INTSTK		# unused
116	.long	Xstray + INTSTK		# unused
117
118# IPL 15
119	.long	Xstray + INTSTK		# unused
120	.long	Xstray + INTSTK		# unused
121	.long	Xstray + INTSTK		# unused
122	.long	Xua0int + INTSTK	# UBA 0 br5
123	.long	Xstray + INTSTK		# unused
124	.long	Xstray + INTSTK		# unused
125	.long	Xstray + INTSTK		# unused
126	.long	Xstray + INTSTK		# unused
127	.long	Xmba0int + INTSTK	# mass bus adapter 0
128	.long	Xmba1int + INTSTK	# mass bus adapter 1
129	.long	Xstray + INTSTK		# unused
130	.long	Xstray + INTSTK		# unused
131	.long	Xstray + INTSTK		# unused
132	.long	Xstray + INTSTK		# unused
133	.long	Xstray + INTSTK		# unused
134	.long	Xstray + INTSTK		# unused
135
136# IPL 16
137	.long	Xstray + INTSTK		# unused
138	.long	Xstray + INTSTK		# unused
139	.long	Xstray + INTSTK		# unused
140	.long	Xua0int + INTSTK	# UBA 0 br6
141	.long	Xstray + INTSTK		# unused
142	.long	Xstray + INTSTK		# unused
143	.long	Xstray + INTSTK		# unused
144	.long	Xstray + INTSTK		# unused
145	.long	Xstray + INTSTK		# unused
146	.long	Xstray + INTSTK		# unused
147	.long	Xstray + INTSTK		# unused
148	.long	Xstray + INTSTK		# unused
149	.long	Xstray + INTSTK		# unused
150	.long	Xstray + INTSTK		# unused
151	.long	Xstray + INTSTK		# unused
152	.long	Xstray + INTSTK		# unused
153
154# IPL 17
155	.long	Xstray + INTSTK		# unused
156	.long	Xstray + INTSTK		# unused
157	.long	Xstray + INTSTK		# unused
158	.long	Xstray + INTSTK		# unused
159	.long	Xstray + INTSTK		# unused
160	.long	Xstray + INTSTK		# unused
161	.long	Xstray + INTSTK		# unused
162	.long	Xstray + INTSTK		# unused
163	.long	Xstray + INTSTK		# unused
164	.long	Xstray + INTSTK		# unused
165	.long	Xstray + INTSTK		# unused
166	.long	Xstray + INTSTK		# unused
167	.long	Xstray + INTSTK		# unused
168	.long	Xstray + INTSTK		# unused
169	.long	Xstray + INTSTK		# unused
170	.long	Xstray + INTSTK		# unused
171
172# 0x200
173
174# =====================================
175# Produce a core image dump on mag tape
176# =====================================
177	.globl	doadump
178doadump:
179	movl	sp,dumpstack		# save stack pointer
180	movab	dumpstack,sp		# reinit stack
181	mfpr	$PCBB,-(sp)		# save u-area pointer
182	mfpr	$MAPEN,-(sp)		# save value
183	mfpr	$IPL,-(sp)		# ...
184	mtpr	$0,$MAPEN		# turn off memory mapping
185	mtpr	$HIGH,$IPL		# disable interrupts
186	pushr	$0x3fff			# save regs 0 - 13
187	calls	$0,_dumptrc		# print out trace information, if any
188	calls	$0,_dump		# produce dump
189
190	.data
191	.align	2
192	.globl	dumpstack
193	.space	58*4			# separate stack for tape dumps
194dumpstack:
195	.space	4
196	.text
197
198#
199# Debugging print switches given here so they won't move around
200#
201	.data
202	.align	2
203	.globl	_printsw
204_printsw:
205	.space	4
206	.globl	_coresw
207_coresw:
208	.space	4
209	.text
210
211# =============================
212# I/O interrupt vector routines
213# =============================
214
215#
216# Physical i/o addresses
217#
218	.set	PHYSMCR,0x20002000	# memory controller register
219	.set	PHYSUBA,0x20006000	# uba 0
220	.set	PHYSUMEM,0x2013e000	# unibus memory
221
222#
223# Catch random or unexpected interrupts
224#
225	.align	2
226Xmachcheck:
227	pushab	Emachk
228	calls	$1,_panic
229
230	.align	2
231Xkspnotval:
232	pushab	Eksp
233	calls	$1,_panic
234
235	.align	2
236Xpowfail:
237	halt
238
239	.align	2
240Xchme:
241Xchms:
242Xchmu:
243	pushab	Echm
244	calls	$1,_panic
245
246Emachk:	.asciz	"Machine check"
247Eksp:	.asciz	"KSP not valid"
248Echm:	.asciz	"CHM? in kernel"
249
250	.align	2
251Xstray:
252	pushr	$0x3f
253	pushab	straym
254	calls	$1,_printf
255	popr	$0x3f
256	rei
257
258#
259# Massbus 0 adapter interrupts
260#
261	.align	2
262Xmba0int:
263	pushr	$0x3f			# save r0 - r5
264	movab	MBA0_CSR,r0		# point at mba regs
265	movl	MBA_AS(r0),r1		# get attn summary bits
266	cvtwl	r1,-(sp)		# push attn summary as arg
267	pushl	MBA_SR(r0)		# pass sr as argument
268	mnegl	$1,MBA_SR(r0)		# clear attention bit
269	calls	$2,_hpintr		# call rp06 interrupt dispatcher
270	brw 	int_ret			# merge with common interrupt code
271
272#
273# Massbus 1 adapter interrupts
274#
275	.align	2
276Xmba1int:
277	pushr	$0x3f
278	movab	MBA1_CSR,r0
279	pushl	MBA_AS(r0)
280	mnegl	$1,MBA_AS(r0)
281	pushl	MBA_SR(r0)		# pass sr as argument
282	mnegl	$1,MBA_SR(r0)		# clear attention bit
283	calls	$2,_htintr		# call te16 interrupt dispatcher
284	brw 	int_ret			# return from interrupt
285
286#
287# Unibus adapter interrupts
288#
289	.align	2
290Xua0int:
291	pushr	$0x3f  			# save regs 0-5
292	mfpr	$IPL,r2			# get br level
293	movl	UBA0+UBR_OFF-20*4[r2],r3# get unibus device vector
294	bleq	ubasrv  		# branch if zero vector
295					# ... or UBA service required
296
297#
298# Normal UBA interrupt point - device on a UBA has generated an
299# interrupt - r3 holds interrupt vector.  Get the service routine
300# address and controller code from the UNIBUS vector area
301# and service the interrupt.
302#
303ubanorm:
304	movl	_UNIvec(r3),r1
305	extzv	$27,$4,r1,r0  		# controller code is in 4 most
306					# significant bits-1 of ISR addr
307	bicl2	$0x78000000,r1		# clear code
308	jlbc	r1,ubanpdma		# no pseudo dma here
309	jmp 	-1(r1)			# branch to pseudo dma rtn
310ubanpdma:
311	pushl	r0			# controller code
312	calls	$1,(r1)  		# call ISR
313	brw	int_ret			# go to common interrupt return
314
315#
316# Come here for zero or negative UBA interrupt vector.
317# Negative vector -> UBA requires service.
318#
319ubasrv:
320	beql	ubapass
321#
322# UBA service required.
323# The following 'printf' calls should probably be replaced
324# with calls to an error logger and/or some corrective action.
325#
326	bitl	$CFGFLT,UBA0+UCN_OFF  	# any SBI faults ?
327	beql	UBAflt
328	pushr	$0xf  			# save regs 0-3
329	pushab	SBImsg
330	calls	$1,_panic
331#	popr	$0xf
332
333#
334# No SBI fault bits set in UBA config reg - must be
335# some error bits set in UBA status reg.
336#
337UBAflt:
338	movl	UBA0+UST_OFF,r2  	# UBA status reg
339	pushr	$0xf  			# save regs 0-3
340	mfpr	$IPL,-(sp)
341	mtpr	$HIGH,$IPL
342	pushl	UBA0+UFUBAR_OFF
343	pushl	UBA0+UFMER_OFF
344	pushl	r2
345	pushab	UBAmsg
346	calls	$4,_printf
347	mtpr	(sp)+,$IPL
348	popr	$0xf
349	movl	r2,UBA0+UST_OFF		# clear error bits
350	bicl2	$0x80000000,r3  	# clear neg bit in vector
351	jneq	ubanorm  		# branch if normal UBA interrupt
352					# to process
353	brw 	int_ret			# restore regs and return
354#
355# Zero interrupt vector - count 'em
356#
357ubapass:
358	incl	_zvcnt
359	cmpl	_zvcnt,$250000
360	jlss	int_ret
361	pushab	ZERmsg
362	calls	$1,_printf
363	clrl	_zvcnt
364	calls	$0,_ubareset
365	brw 	int_ret
366	.data
367	.globl	_zvcnt
368_zvcnt:	.space	4
369	.globl	_dzdcnt
370_dzdcnt:.space	4
371	.text
372
373#
374# DZ pseudo dma routine:
375#	r0 - controller number
376#
377	.align	1
378	.globl	_dzdma
379_dzdma:
380#	bisw2	$4,*_draddr	# leading edge for dr11-c
381	mull2	$8*20,r0
382	movab	_dzpdma(r0),r3		# pdma structure base
383					# for this controller
384dzploop:
385	movl	r3,r0
386	movl	(r0)+,r1		# device register address
387	movzbl	1(r1),r2		# get line number
388	bitb	$0x80,r2		# TRDY on?
389	beql	dzprei			# no
390	incl	_dzdcnt		## loop trips
391	bicb2	$0xf8,r2		# clear garbage bits
392	mull2	$20,r2
393	addl2	r2,r0			# point at line's pdma structure
394	movl	(r0)+,r2		# p_mem
395	cmpl	r2,(r0)+		# p_mem < p_end ?
396	bgequ	dzpcall			# no, go call dzxint
397	movb	(r2)+,6(r1)		# dztbuf = *p_mem++
398	movl	r2,-8(r0)
399	brb 	dzploop			# check for another line
400dzprei:
401#	bicw2	$4,*_draddr	# trailing edge for dr11-c
402	popr	$0x3f
403	incl	_cnt+V_PDMA
404	rei
405
406dzpcall:
407	pushl	(r0)			# push tty address
408	calls	$1,_dzxint		# call interrupt rtn
409	brb 	dzploop			# check for another line
410
411#
412# Console receiver interrupt
413#
414	.align	2
415Xcnrint:
416	pushr	$0x3f			# save registers 0 - 5
417	calls	$0,_cnrint
418	brb 	int_ret			# merge
419
420#
421# Console transmit interrupt
422#
423	.align	2
424Xcnxint:
425	pushr	$0x3f			# save registers 0 - 5
426	calls	$0,_cnxint
427	brb 	int_ret
428
429#
430# Clock interrupt
431#
432	.align	2
433Xclockint:
434	pushr	$0x3f			# save regs 0 - 5
435	pushl	4+6*4(sp)		# push psl
436	pushl	4+6*4(sp)		# push pc
437	calls	$2,_clock
438	brb 	int_ret
439
440#
441# Common code for interrupts.
442# At this point, the interrupt stack looks like:
443#
444#	r0	<- isp
445#	...
446#	r5
447#	pc
448#	psl
449#
450
451int_ret:
452	incl	_cnt+V_INTR
453#	bbssi	$0,idleflag,int_r0	# escape from idle() if old switch code
454#int_r0:
455	popr	$0x3f			# restore regs 0 - 5
456	bitl	$PSL_CURMOD,4(sp)	# interrupt from user mode?
457	beql	int_r1			# no, from kernel, just rei
458	tstb	_runrun			# should we reschedule?
459	beql	int_r1			# no, just rei
460#
461# If here, interrupt from user mode, and time to reschedule.
462# To do this, we set a software level 3 interrupt to
463# change to kernel mode, switch stacks, and format
464# kernel stack for a `qswitch' trap to force a reschedule.
465#
466	mtpr	$0x18,$IPL
467	mtpr	$3,$SIRR		# request level 1 software interrupt
468int_r1:
469	rei 				# return to interrupted process
470
471# ==================================
472# User area virtual addresses
473# ==================================
474
475	.globl	_u
476	.set	_u,0x80000000 - UPAGES*NBPG
477
478	.data
479	.align	2
480	.globl	_Sysmap
481_Sysmap:
482	.space	6*NBPG
483UBA0map:
484	.space	16*4
485	.globl	_umbabeg
486	.set	_umbabeg,((UBA0map-_Sysmap)/4)*512+0x80000000
487UMEMmap:
488	.space	16*4
489	.globl	_MBA0map
490_MBA0map:
491	.space	16*4
492	.globl	_MBA1map
493_MBA1map:
494	.space	16*4
495umend:
496	.globl	_umbaend
497	.set	_umbaend,((umend-_Sysmap)/4)*512+0x80000000
498
499	.globl	_Usrptmap
500_Usrptmap:
501	.space	8*NBPG
502	.globl	_usrpt
503	.set	_usrpt,((_Usrptmap-_Sysmap)/4)*NBPG+0x80000000
504
505	.globl	_Forkmap
506_Forkmap:
507	.space	4*UPAGES
508	.globl	_forkutl
509	.set	_forkutl,((_Forkmap-_Sysmap)/4)*NBPG+0x80000000
510
511	.globl	_Xswapmap
512_Xswapmap:
513	.space	4*UPAGES
514	.globl	_xswaputl
515	.set	_xswaputl,((_Xswapmap-_Sysmap)/4)*NBPG+0x80000000
516
517	.globl	_Xswap2map
518_Xswap2map:
519	.space	4*UPAGES
520	.globl	_xswap2utl
521	.set	_xswap2utl,((_Xswap2map-_Sysmap)/4)*NBPG+0x80000000
522
523	.globl	_Swapmap
524_Swapmap:
525	.space	4*UPAGES
526	.globl	_swaputl
527	.set	_swaputl,((_Swapmap-_Sysmap)/4)*NBPG+0x80000000
528
529	.globl	_Pushmap
530_Pushmap:
531	.space	4*UPAGES
532	.globl	_pushutl
533	.set	_pushutl,((_Pushmap-_Sysmap)/4)*NBPG+0x80000000
534
535	.globl	_Vfmap
536_Vfmap:
537	.space	4*UPAGES
538	.globl	_vfutl
539	.set	_vfutl,((_Vfmap-_Sysmap)/4)*NBPG+0x80000000
540
541CMAP1:
542	.space	4
543	.set	CADDR1,((CMAP1-_Sysmap)/4)*NBPG+0x80000000
544CMAP2:
545	.space	4
546	.set	CADDR2,((CMAP2-_Sysmap)/4)*NBPG+0x80000000
547
548	.globl	_mcrmap
549_mcrmap:
550	.space	4
551	.globl	_mcr
552	.set	_mcr,((_mcrmap-_Sysmap)/4)*NBPG+0x80000000
553
554	.globl	_mmap
555_mmap:
556	.space	4
557	.globl	_vmmap
558	.set	_vmmap,((_mmap-_Sysmap)/4)*NBPG+0x80000000
559
560	.globl	_bufmap
561_bufmap:
562	.space	4*NBUF*CLSIZE
563	.globl	_buffers
564	.set	_buffers,((_bufmap-_Sysmap)/4)*NBPG+0x80000000
565	.globl	eSysmap
566eSysmap:
567	.set	Syssize,(eSysmap-_Sysmap)/4
568	.text
569
570# ==============================
571# Trap and fault vector routines
572# ==============================
573
574#
575# Reschedule trap (Software level 3 interrupt)
576#
577	.align	2
578Xresched:
579	mtpr	$0,$IPL			# lower ipl
580	pushl	$0			# dummy code
581	pushl	$RESCHED		# type
582	bitl	$PSL_CURMOD,12(sp)
583	bneq	alltraps
584	addl2	$8,sp
585	mtpr	$HIGH,$IPL
586	rei
587
588#
589# Privileged instruction fault
590#
591	.align	2
592Xprivinflt:
593	pushl	$0			# push dummy code
594	pushl	$PRIVINFLT		# push type
595	brw 	alltraps		# merge
596
597#
598# Xfc instruction fault
599#
600	.align	2
601Xxfcflt:
602	pushl	$0			# push dummy code value
603	pushl	$XFCFLT			# push type value
604	brw 	alltraps		# merge
605
606#
607# Reserved operand fault
608#
609	.align	2
610Xresopflt:
611	pushl	$0			# push dummy code value
612	pushl	$RESOPFLT		# push type value
613	brw 	alltraps		# merge
614
615#
616# Reserved addressing mode fault
617#
618	.align	2
619Xresadflt:
620	pushl	$0			# push dummy code value
621	pushl	$RESADFLT		# push type value
622	brw 	alltraps		# merge with common code
623
624#
625# Bpt instruction fault
626#
627	.align	2
628Xbptflt:
629	pushl	$0			# push dummy code value
630	pushl	$BPTFLT			# push type value
631	brw 	alltraps		# merge with common code
632
633#
634# Compatibility mode fault
635#
636	.align	2
637Xcompatflt:
638	pushl	$COMPATFLT		# push type value
639	brw 	alltraps		# merge with common code
640
641#
642# Trace trap
643#
644	.align	2
645Xtracep:
646	pushl	$0			# push dummy code value
647	pushl	$TRCTRAP		# push type value
648	brw 	alltraps		# go do it
649
650#
651# Arithmetic trap
652#
653	.align	2
654Xarithtrap:
655	pushl	$ARITHTRAP		# push type value
656	brw 	alltraps		# merge with common code
657
658#
659# Protection and segmentation fault
660#
661	.align	2
662Xprotflt:
663	blbs	(sp),segflt		# check for pt length violation
664	addl2	$4,sp			# pop fault param word
665	pushl	$PROTFLT
666	brw 	alltraps
667
668#
669# Segmentation fault
670#
671segflt:
672	addl2	$4,sp
673	pushl	$SEGFLT
674	brb 	alltraps
675
676#
677# Translation Not Valid Fault
678#
679	.align  2
680Xtransflt:
681	bbs	$1,(sp),tableflt	# check for page table fault
682	addl2	$4,sp			# pop fault parameter word
683	pushl	$PAGEFLT		# push type value
684	brb	alltraps
685
686#
687# Page table fault
688#
689tableflt:
690	addl2	$4,sp			# pop fault parameter word
691	pushl	$TABLEFLT		# push type value
692	brb	alltraps
693
694#
695# all traps but syscalls...
696#
697alltraps:
698	mfpr	$USP,-(sp)		# get usp
699	calls	$0,_trap		# $0 so ret wont pop args
700	incl	_cnt+V_TRAP
701	mtpr	(sp)+,$USP		# restore usp
702	addl2	$8,sp			# pop type, code
703	mtpr	$HIGH,$IPL		# make sure we are not going to
704					# a higher IPL
705	rei
706
707#
708# CHMK trap (syscall trap)
709#
710# Kernel stack on entry:
711#
712#	code	<- ksp
713#	pc
714#	psl
715#
716#
717# Stack (parameters) at calls to _trap or _syscall
718#
719#	usp	<- ksp
720#	type
721#	code
722#	pc
723#	psl
724#
725
726	.align	2
727Xsyscall:
728	pushl	$SYSCALL		# push type value
729	mfpr	$USP,-(sp)		# get usp
730	calls	$0,_syscall		# $0 so ret wont pop args
731	incl	_cnt+V_SYSCALL
732	mtpr	(sp)+,$USP		# restore usp
733	addl2	$8,sp			# pop type, code
734	mtpr	$HIGH,$IPL		# make sure we are not going to
735					# a higher IPL
736	rei
737
738# ==============
739# Initialization
740# ==============
741#
742#	IPL == 1F
743#	MAPEN == off
744#	SCBB, PCBB not set
745#	SBR, SLR not set
746#	ISP, KSP not set
747#
748	.globl	start
749start:
750	.word	0x0000
751	mtpr	$HIGH,$IPL		# no interrupts yet
752	mtpr	$Scbbase,$SCBB		# set SCBB
753	mtpr	$_Sysmap,$SBR		# set SBR
754	mtpr	$Syssize,$SLR		# set SLR
755	mtpr	$_Sysmap,$P0BR		# set temp P0BR
756	mtpr	$Syssize,$P0LR		# set temp P0LR
757	movl	$_intstack+2048,sp	# set ISP
758#
759# Initialize I/O adapters.
760#
761	movl	$1,PHYSUBA+4		# init & interrupt enable
762	movl	$0x78,PHYSUBA+4		# init & interrupt enable
763
764	movl	Scbbase+MCKVEC,r5	# save machine check entry
765	movab	2f+INTSTK,Scbbase+MCKVEC	# set new vector address
766#
767# Will now see how much memory there really is
768# in 64kb chunks.  Save number of bytes in r7.
769#
770	mtpr	$HIGH-1,$IPL		# allow machine check interrupts
771	clrl	r7
7721:
773	tstl	(r7)			# this chunk really there?
774	acbl	$8096*1024-1,$64*1024,r7,1b	# loop till mach check
775	brb 	2f			# full load of memory
776
777	.align	2
7782:
779	mtpr	$0,$SBIFS		# clear sbi fault status
780	movl	r5,Scbbase+MCKVEC	# restore machine check vector
781	movl	$_intstack+2048,sp	# reset interrupt stack pointer
782#
783# calculate size of cmap[] based on available memory, and allocate space for it
784#
785	movab	_end,r5
786	movl	r5,_cmap
787	bbss	$31,_cmap,0f; 0:
788	subl3	r5,r7,r1
789	divl2	$(NBPG*CLSIZE)+CMSIZE,r1
790	mull2	$CMSIZE,r1
791	addl3	_cmap,r1,_ecmap
792#
793# Clear memory starting with kernel bss, and extra pages for
794# proc 0 u. and proc 0 paget.
795#
796	movab	_edata,r6
797	movl	_ecmap,r5		# clear to end of cmap[]
798	bbcc	$31,r5,0f; 0:
799	addl2	$(UPAGES*NBPG)+NBPG+NBPG,r5
8001:
801	clrq	(r6)
802	acbl	r5,$8,r6,1b
803
804#
805# Finagle _trap and _syscall to save r0-r11 so
806# that it won't be necessary to pushr/popr what
807# the (already time consuming) calls is prepared to do.
808# The fact that this is done is well known (e.g. in the definition
809# of the stack offsets of the registers in ../h/reg.h)
810#
811	bisw2	$0x0fff,_trap		# so _trap saves r0-r11
812	bisw2	$0x0fff,_syscall	# so _syscall saves r0-r11
813
814#
815# Initialize system page table
816#
817	movab	_etext+NBPG-1,r1	# end of kernel text segment
818	bbcc	$31,r1,0f; 0:		# turn off high order bit
819	ashl	$-9,r1,r1		# last page of kernel text
820	clrl	r2			# point at first kernel text page
8211:
822	bisl3	$PG_V|PG_KR,r2,_Sysmap[r2]	# initialize page table entry
823	aoblss	r1,r2,1b		# fill text entries
824	addl3	_ecmap,$NBPG-1,r1	# end of cmap[]
825	bbcc	$31,r1,0f; 0:		# turn off high order bit
826	ashl	$-9,r1,r1		# last page of kernel data
8271:
828	bisl3	$PG_V|PG_KW,r2,_Sysmap[r2]	# fill data entries
829	aoblss	r1,r2,1b
830#
831# initialize memory controller mapping
832#
833	movl	$PHYSMCR/NBPG,r1
834	movab	_mcrmap,r2
835	bisl3	$PG_V|PG_KW,r1,(r2)
836#
837# Initialize UNIBUS page table entries
838#
839	movl	$PHYSUBA/NBPG,r1	# page frame number for uba
840	movab	UBA0map,r2		# page table address
841	movab	15(r1),r3		# last pt entry
8421:
843	bisl3	$PG_V|PG_KW,r1,(r2)+	# init pt entry
844	aobleq	r3,r1,1b
845	movl	$PHYSUMEM/NBPG,r1
846	movab	UMEMmap,r2		# page table address
847	movab	15(r1),r3		# limit
8481:
849	bisl3	$PG_V|PG_KW,r1,(r2)+
850	aobleq	r3,r1,1b
851	mtpr	$1,$TBIA		# invalidate all trans buffer entries
852	mtpr	$1,$MAPEN		# turn on memory mapping
853	jmp 	*$0f			# put system virtual address in pc
854#
855# Now we move forward, virtually.
856#
8570:
858	ashl	$-9,r7,_maxmem		# set maxmem = btoc(r7)
859	movl	_maxmem,_physmem
860	movl	_maxmem,_freemem
861
862#
863# Setup context for proc[0] == Scheduler
864#
865# First page: paget for proc[0]
866# Next UPAGES: _u for proc[0]
867# Initialize (slightly) the pcb.
868#
869	addl3	_ecmap,$NBPG-1,r6
870	bicl2	$NBPG-1,r6		# make page boundary
871#
872# set up u area page table
873#
874	bbcc	$31,r6,0f; 0:
875	ashl	$-9,r6,r3			# r3 = btoc(r6)
876	bisl3	$PG_V|PG_KW,r3,_Usrptmap	# init first upt entry
877	movab	_usrpt,r0
878	mtpr	r0,$TBIS
879	mtpr	r0,$P0BR
880	mtpr	$0,$P0LR
881	movab	NBPG(r0),r0
882	movl	$0x200000-UPAGES,r1
883	mtpr	r1,$P1LR
884	mnegl	r1,r1
885	moval	-4*UPAGES(r0)[r1],r2
886	mtpr	r2,$P1BR
887	movl	$UPAGES,r2
888	movab	_u+NBPG*UPAGES,r1
889	jbr	2f
8901:
891	incl	r3
892	moval	-NBPG(r1),r1
893	bisl3	$PG_V|PG_URKW,r3,-(r0)
894	mtpr	r1,$TBIS
8952:
896	sobgeq	r2,1b
897
898	movab	UPAGES*NBPG(r1),PCB_KSP(r1)	# init ksp
899	mnegl	$1,PCB_ESP(r1)			# invalidate esp
900	mnegl	$1,PCB_SSP(r1)			# invalidate ssp
901	movl	r1,PCB_USP(r1)			# set user sp
902	mfpr	$P0BR,PCB_P0BR(r1)
903	mfpr	$P0LR,PCB_P0LR(r1)
904	movb	$4,PCB_P0LR+3(r1)		# disable ast
905	mfpr	$P1BR,PCB_P1BR(r1)
906	mfpr	$P1LR,PCB_P1LR(r1)
907	movl	$CLSIZE,PCB_SZPT(r1)		# init u.u_pcb.pcb_szpt
908	movl	r11,PCB_R11(r1)
909
910	movab	1f,PCB_PC(r1)			# initial pc
911	clrl	PCB_PSL(r1)			# mode(k,k), ipl=0
912	ashl	$9,r3,r3
913	mtpr	r3,$PCBB			# first pcbb
914#
915# set regs, p0br, p0lr, p1br, p1lr
916# astlvl, ksp and change to kernel mode
917#
918	ldpctx
919	rei
920
921#
922# put signal trampoline code in u. area
923#
9241:
925	movab	_u,r0
926	movc3	$12,sigcode,PCB_SIGC(r0)
927
928	addl3	_ecmap,$NBPG-1,r0		# calculate firstaddr
929	bbcc	$31,r0,0f; 0:
930	ashl	$-9,r0,-(sp)			# convert to clicks and stack
931	calls	$1,_main			# startup, fork off /etc/init.vm
932#
933# proc[1] == /etc/init now running here.
934# execute code at location 0, in user mode.
935#
936	pushl	$PSL_CURMOD|PSL_PRVMOD		# psl, user mode, ipl = 0
937	pushl	$0				# pc, $location 0
938	rei 					# do /etc/init.vm
939
940#
941# signal trampoline code
942# it is known that this code takes exactly 12 bytes
943# in ../h/pcb.h and in the movc3 above
944#
945sigcode:
946	calls	$3,1(pc)
947	rei
948	.word	0x7f
949	callg	(ap),*12(ap)			# registers 0-6 (6==sp/compat)
950	ret
951
952# ==========
953# Primitives
954# ==========
955
956_addupc:	.globl	_addupc
957	.word	0x0000
958	movl	8(ap),r2		# &u.u_prof
959	subl3	8(r2),4(ap),r0		# corrected pc
960	blss	9f
961	extzv	$1,$31,r0,r0		# logical right shift
962	extzv	$1,$31,12(r2),r1	# ditto for scale
963	emul	r1,r0,$0,r0
964	ashq	$-14,r0,r0
965	tstl	r1
966	bneq	9f
967	incl	r0
968	bicb2	$1,r0
969	blss	9f
970	cmpl	r0,4(r2)		# length
971	bgequ	9f
972	addl2	(r2),r0			# base
973	probew	$3,$2,(r0)
974	beql	8f
975	addw2	12(ap),(r0)
9769:
977	ret
9788:
979	clrl	12(r2)
980	ret
981
982_Copyin:	.globl	_Copyin		# <<<massaged for jsb by asm.sed>>>
983	movl	12(sp),r0		# copy length
984	blss	ersb
985	movl	4(sp),r1		# copy user address
986	cmpl	$NBPG,r0		# probing one page or less ?
987	bgeq	cishort			# yes
988ciloop:
989	prober	$3,$NBPG,(r1)		# bytes accessible ?
990	beql	ersb			# no
991	addl2	$NBPG,r1		# incr user address ptr
992	acbl	$NBPG+1,$-NBPG,r0,ciloop	# reduce count and loop
993cishort:
994	prober	$3,r0,(r1)		# bytes accessible ?
995	beql	ersb			# no
996	movc3	12(sp),*4(sp),*8(sp)
997	clrl	r0
998	rsb
999
1000ersb:
1001	mnegl	$1,r0
1002	rsb
1003
1004_Copyout: 	.globl	_Copyout	# <<<massaged for jsb by asm.sed >>>
1005	movl	12(sp),r0		# get count
1006	blss	ersb
1007	movl	8(sp),r1		# get user address
1008	cmpl	$NBPG,r0		# can do in one probew?
1009	bgeq	coshort			# yes
1010coloop:
1011	probew	$3,$NBPG,(r1)		# bytes accessible?
1012	beql	ersb			# no
1013	addl2	$NBPG,r1		# increment user address
1014	acbl	$NBPG+1,$-NBPG,r0,coloop	# reduce count and loop
1015coshort:
1016	probew	$3,r0,(r1)		# bytes accessible?
1017	beql	ersb			# no
1018	movc3	12(sp),*4(sp),*8(sp)
1019	clrl	r0
1020	rsb
1021
1022#
1023# non-local goto's
1024#
1025	.globl	_Setjmp
1026_Setjmp:
1027	movq	r6,(r0)+
1028	movq	r8,(r0)+
1029	movq	r10,(r0)+
1030	movq	r12,(r0)+
1031	addl3	$4,sp,(r0)+
1032	movl	(sp),(r0)
1033	clrl	r0
1034	rsb
1035
1036	.globl	_Longjmp
1037_Longjmp:
1038	movq	(r0)+,r6
1039	movq	(r0)+,r8
1040	movq	(r0)+,r10
1041	movq	(r0)+,r12
1042	movl	(r0)+,r1
1043	cmpl	r1,sp				# must be a pop
1044	bgequ	lj2
1045	pushab	lj1
1046	calls	$1,_panic
1047lj2:
1048	movl	r1,sp
1049	jmp	*(r0)				# ``rsb''
1050
1051lj1:	.asciz	"longjmp"
1052
1053	.globl	_whichqs
1054	.globl	_qs
1055	.globl	_cnt
1056
1057	.globl	_noproc
1058	.comm	_noproc,4
1059	.globl	_runrun
1060	.comm	_runrun,4
1061
1062#
1063# The following primitives use the fancy VAX instructions
1064# much like VMS does.  _whichqs tells which of the 32 queues _qs
1065# have processes in them.  Setrq puts processes into queues, Remrq
1066# removes them from queues.  The running process is on no queue,
1067# other processes are on a queue related to p->p_pri, divided by 4
1068# actually to shrink the 0-127 range of priorities into the 32 available
1069# queues.
1070#
1071
1072#
1073# Setrq(p), using fancy VAX instructions.
1074#
1075# Call should be made at spl6(), and p->p_stat should be SRUN
1076#
1077	.globl	_Setrq		# <<<massaged to jsb by "asm.sed">>>
1078_Setrq:
1079	tstl	P_RLINK(r0)		## firewall: p->p_rlink must be 0
1080	beql	set1			##
1081	pushab	set3			##
1082	calls	$1,_panic		##
1083set1:
1084	movzbl	P_PRI(r0),r1		# put on queue which is p->p_pri / 4
1085	ashl	$-2,r1,r1
1086	movaq	_qs[r1],r2
1087	insque	(r0),*4(r2)		# at end of queue
1088	bbss	r1,_whichqs,set2	# mark queue non-empty
1089set2:
1090	rsb
1091
1092set3:	.asciz	"setrq"
1093
1094#
1095# Remrq(p), using fancy VAX instructions
1096#
1097# Call should be made at spl6().
1098#
1099	.globl	_Remrq		# <<<massaged to jsb by "asm.sed">>>
1100_Remrq:
1101	movzbl	P_PRI(r0),r1
1102	ashl	$-2,r1,r1
1103	bbsc	r1,_whichqs,rem1
1104	pushab	rem3			# it wasn't recorded to be on its q
1105	calls	$1,_panic
1106rem1:
1107	remque	(r0),r2
1108	beql	rem2
1109	bbss	r1,_whichqs,rem2
1110rem2:
1111	clrl	P_RLINK(r0)		## for firewall checking
1112	rsb
1113
1114rem3:	.asciz	"remrq"
1115
1116sw0:	.asciz	"swtch"
1117#
1118# Swtch(), using fancy VAX instructions
1119#
1120	.globl	_Swtch
1121_Swtch:				# <<<massaged to jsb by "asm.sed">>>
1122	movl	$1,_noproc
1123	clrl	_runrun
1124sw1:	ffs	$0,$32,_whichqs,r0	# look for non-empty queue
1125	bneq	sw1a
1126	mtpr	$0,$IPL			# must allow interrupts here
1127	brw	sw1			# this is an idle loop!
1128sw1a:	mtpr	$0x18,$IPL		# lock out all so _whichqs==_qs
1129	bbcc	r0,_whichqs,sw1		# proc moved via lbolt interrupt
1130	movaq	_qs[r0],r1
1131	remque	*(r1),r2		# r2 = p = highest pri process
1132	bvc	sw2			# make sure something was there
1133sw1b:	pushab	sw0
1134	calls	$1,_panic
1135sw2:	beql	sw3
1136	insv	$1,r0,$1,_whichqs	# still more procs in this queue
1137sw3:
1138	clrl	_noproc
1139	tstl	P_WCHAN(r2)		## firewalls
1140	bneq	sw1b			##
1141	movzbl	P_STAT(r2),r3		##
1142	cmpl	$SRUN,r3		##
1143	bneq	sw1b			##
1144	clrl	P_RLINK(r2)		##
1145	ashl	$PGSHIFT,*P_ADDR(r2),r0	# r0 = pcbb(p)
1146#	mfpr	$PCBB,r1		# resume of current proc is easy
1147#	cmpl	r0,r1
1148#	beql	res0
1149	incl	_cnt+V_SWTCH
1150# fall into...
1151
1152#
1153# Resume(pf)
1154#
1155	.globl	_Resume		# <<<massaged to jsb by "asm.sed">>>
1156_Resume:
1157	mtpr	$0x18,$IPL			# no interrupts, please
1158	movl	CMAP2,_u+PCB_CMAP2	# yech
1159	svpctx
1160	mtpr	r0,$PCBB
1161	ldpctx
1162	movl	_u+PCB_CMAP2,CMAP2	# yech
1163res0:
1164	tstl	_u+PCB_SSWAP
1165	beql	res1
1166	movl	_u+PCB_SSWAP,r0
1167	clrl	_u+PCB_SSWAP
1168	movab	_Longjmp,(sp)
1169	movl	$PSL_PRVMOD,4(sp)		# ``cheating'' (jfr)
1170res1:
1171	rei
1172
1173#
1174# {fu,su},{byte,word}, all massaged by asm.sed to jsb's
1175#
1176	.globl	_Fuword
1177_Fuword:
1178	prober	$3,$4,(r0)
1179	beql	fserr
1180	movl	(r0),r0
1181	rsb
1182fserr:
1183	mnegl	$1,r0
1184	rsb
1185
1186	.globl	_Fubyte
1187_Fubyte:
1188	prober	$3,$1,(r0)
1189	beql	fserr
1190	movzbl	(r0),r0
1191	rsb
1192
1193	.globl	_Suword
1194_Suword:
1195	probew	$3,$4,(r0)
1196	beql	fserr
1197	movl	r1,(r0)
1198	clrl	r0
1199	rsb
1200
1201	.globl	_Subyte
1202_Subyte:
1203	probew	$3,$1,(r0)
1204	beql	fserr
1205	movb	r1,(r0)
1206	clrl	r0
1207	rsb
1208
1209#
1210# Copy 1 relocation unit (NBPG bytes)
1211# from user virtual address to physical address
1212#
1213_copyseg: 	.globl	_copyseg
1214	.word	0x0000
1215	mfpr	$IPL,r0		# get current pri level
1216	mtpr	$HIGH,$IPL	# turn off interrupts
1217	bisl3	$PG_V|PG_KW,8(ap),CMAP2
1218	mtpr	$CADDR2,$TBIS	# invalidate entry for copy
1219	movc3	$NBPG,*4(ap),CADDR2
1220	mtpr	r0,$IPL		# restore pri level
1221	ret
1222
1223#
1224# zero out physical memory
1225# specified in relocation units (NBPG bytes)
1226#
1227_clearseg: 	.globl	_clearseg
1228	.word	0x0000
1229	mfpr	$IPL,r0		# get current pri level
1230	mtpr	$HIGH,$IPL	# extreme pri level
1231	bisl3	$PG_V|PG_KW,4(ap),CMAP1
1232	mtpr	$CADDR1,$TBIS
1233	movc5	$0,(sp),$0,$NBPG,CADDR1
1234	mtpr	r0,$IPL		# restore pri level
1235	ret
1236
1237#
1238# Check address.
1239# Given virtual address, byte count, and rw flag
1240# returns 0 on no access.
1241#
1242_useracc:	.globl	_useracc
1243	.word	0x0000
1244	movl	4(ap),r0		# get va
1245	movl	8(ap),r1		# count
1246	tstl	12(ap)			# test for read access ?
1247	bneq	userar			# yes
1248	cmpl	$NBPG,r1			# can we do it in one probe ?
1249	bgeq	uaw2			# yes
1250uaw1:
1251	probew	$3,$NBPG,(r0)
1252	beql	uaerr			# no access
1253	addl2	$NBPG,r0
1254	acbl	$NBPG+1,$-NBPG,r1,uaw1
1255uaw2:
1256	probew	$3,r1,(r0)
1257	beql	uaerr
1258	movl	$1,r0
1259	ret
1260
1261userar:
1262	cmpl	$NBPG,r1
1263	bgeq	uar2
1264uar1:
1265	prober	$3,$NBPG,(r0)
1266	beql	uaerr
1267	addl2	$NBPG,r0
1268	acbl	$NBPG+1,$-NBPG,r1,uar1
1269uar2:
1270	prober	$3,r1,(r0)
1271	beql	uaerr
1272	movl	$1,r0
1273	ret
1274uaerr:
1275	clrl	r0
1276	ret
1277
1278#
1279# kernacc - check for kernel access privileges
1280#
1281# We can't use the probe instruction directly because
1282# it ors together current and previous mode.
1283#
1284	.globl	_kernacc
1285_kernacc:
1286	.word	0x0000
1287	movl	4(ap),r0	# virtual address
1288	bbcc	$31,r0,kacc1
1289	mfpr	$SBR,r2		# address and length of page table (system)
1290	mfpr	$SLR,r3
1291	brb	kacc2
1292kacc1:
1293	bbsc	$30,r0,kacc3
1294	mfpr	$P0BR,r2	# user P0
1295	mfpr	$P0LR,r3
1296	brb	kacc2
1297kacc3:
1298	mfpr	$P1BR,r2	# user P1 (stack)
1299	mfpr	$P1LR,r3
1300kacc2:
1301	addl3	8(ap),r0,r1	# ending virtual address
1302	ashl	$-9,r0,r0	# page number
1303	ashl	$-9,r1,r1
1304	bbs	$31,4(ap),kacc6
1305	bbc	$30,4(ap),kacc6
1306	cmpl	r0,r3		# user stack
1307	blss	kacerr		# address too low
1308	brb	kacc4
1309kacc6:
1310	cmpl	r1,r3		# compare last page to P0LR or SLR
1311	bgeq	kacerr		# address too high
1312kacc4:
1313	movl	(r2)[r0],r3
1314	bbc	$31,4(ap),kacc4a
1315	bbc	$31,r3,kacerr	# valid bit is off
1316kacc4a:
1317	cmpzv	$27,$4,r3,$1	# check protection code
1318	bleq	kacerr		# no access allowed
1319	tstb	12(ap)
1320	bneq	kacc5		# only check read access
1321	cmpzv	$27,$2,r3,$3	# check low 2 bits of prot code
1322	beql	kacerr		# no write access
1323kacc5:
1324	aobleq	r1,r0,kacc4	# next page
1325	movl	$1,r0		# no errors
1326	ret
1327kacerr:
1328	clrl	r0		# error
1329	ret
1330
1331#
1332# unsigned int divide:
1333#	(int) i = udiv( (int)dvdnd , (int) divis)
1334#
1335#  unsigned int remainder:
1336#	(int) j = urem( (int)dvdnd , (int) divis)
1337#
1338	.text
1339	.align	1
1340	.globl	_udiv
1341_udiv :
1342	.word	0  			# no reg save
1343	movl	4(ap),r0  		# dividend
1344	clrl	r1
1345	ediv	8(ap),r0,r0,r1  	# quotient in r0
1346	ret
1347
1348#	.globl	_urem
1349#	.align 	1
1350#_urem:
1351#	.word	0
1352#	movl	4(ap),r0
1353#	clrl	r1
1354#	ediv	8(ap),r0,r1,r0  	#  remainder in r0
1355#	ret
1356
1357# ==============
1358# Error messages
1359# ==============
1360
1361	.data
1362SBImsg: .asciz	"SBI fault\n"
1363UBAmsg: .asciz	"UBA error UBASR %X, FMER %X, FUBAR %X\n"
1364straym: .asciz	"Stray Interrupt\n"
1365ZERmsg:	.asciz	"ZERO VECTOR "
1366
1367#
1368# Junk.
1369#
1370
1371#
1372# This is needed when running old-style switch code.
1373# Be sure to enable setting of idleflag in interrupt code above also.
1374#
1375#_idle:	.globl	_idle
1376#	.word	0x0000
1377#	mtpr	$0,$IPL			# enable interrupts
1378#waitloc:
1379#	blbc	idleflag,waitloc	# loop until interrupt
1380#ewaitloc:
1381#	bbcci	$0,idleflag,idle1	# clear idle escape flag
1382#idle1:
1383#	ret
1384#	.data
1385#	.globl	_waitloc
1386#	.globl	_ewaitloc
1387#l	.align	2
1388#_waitloc:	.long	waitloc
1389#_ewaitloc:	.long	ewaitloc
1390#idleflag:	.long	0
1391#	.text
1392
1393