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