Annotation of sys/arch/vax/vax/subr.s, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: subr.s,v 1.26 2007/05/16 05:19:15 miod Exp $ */
2: /* $NetBSD: subr.s,v 1.32 1999/03/25 00:41:48 mrg Exp $ */
3:
4: /*
5: * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed at Ludd, University of Lule}.
19: * 4. The name of the author may not be used to endorse or promote products
20: * derived from this software without specific prior written permission
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32: */
33:
34: #include <machine/asm.h>
35:
36: #include "assym.h"
37: #ifdef COMPAT_ULTRIX
38: #include <compat/ultrix/ultrix_syscall.h>
39: #endif
40:
41: #define JSBENTRY(x) .globl x ; .align 2 ; x :
42:
43: .text
44:
45: /*
46: * First entry routine from boot. This should be in a file called locore.
47: */
48: ASENTRY(start, 0)
49: bisl3 $0x80000000,r9,_esym # End of loaded code
50: pushl $0x1f0000 # Push a nice PSL
51: pushl $to # Address to jump to
52: rei # change to kernel stack
53: to: movw $0xfff,_panic # Save all regs in panic
54: moval _end, r0 # Get kernel end address
55: addl2 $0x3ff, r0 # Round it up
56: cmpl _esym, r0 # Compare with symbol table end
57: bleq eskip # Symbol table not present
58: addl3 _esym, $0x3ff, r0 # Use symbol end and round
59: eskip:
60: bicl3 $0x3ff,r0,_proc0paddr # save proc0 uarea pointer
61: bicl3 $0x80000000,_proc0paddr,r0 # get phys proc0 uarea addr
62: mtpr r0,$PR_PCBB # Save in IPR PCBB
63: addl3 $USPACE,_proc0paddr,r0 # Get kernel stack top
64: mtpr r0,$PR_KSP # put in IPR KSP
65: movl r0,_Sysmap # SPT start addr after KSP
66:
67: # Set some registers in known state
68: movl _proc0paddr,r0
69: clrl P0LR(r0)
70: clrl P1LR(r0)
71: mtpr $0,$PR_P0LR
72: mtpr $0,$PR_P1LR
73: movl $0x80000000,r1
74: movl r1,P0BR(r0)
75: movl r1,P1BR(r0)
76: mtpr r1,$PR_P0BR
77: mtpr r1,$PR_P1BR
78: clrl IFTRAP(r0)
79: mtpr $0,$PR_SCBB
80:
81: # Copy the RPB to its new position
82: #if 1 /* compat with old bootblocks */
83: tstl (ap) # Any arguments?
84: bneq 1f # Yes, called from new boot
85: movl r11,_boothowto # Howto boot (single etc...)
86: # movl r10,_bootdev # uninteresting, will complain
87: movl r8,_avail_end # Usable memory (from VMB)
88: clrl -(sp) # Have no RPB
89: brb 2f
90: #endif
91:
92: 1: pushl 4(ap) # Address of old rpb
93: 2: calls $1,_start # Jump away.
94: /* NOTREACHED */
95:
96:
97: /*
98: * Signal handler code.
99: */
100:
101: .globl _sigcode,_esigcode
102: _sigcode: pushr $0x3f
103: subl2 $0xc,sp
104: movl 0x24(sp),r0
105: calls $3,(r0)
106: popr $0x3f
107: chmk $SYS_sigreturn
108: chmk $SYS_exit
109: halt
110: .align 2
111: _esigcode:
112:
113: #ifdef COMPAT_ULTRIX
114: .globl _ultrix_sigcode,_ultrix_esigcode
115: _ultrix_sigcode: pushr $0x3f
116: subl2 $0xc,sp
117: movl 0x24(sp),r0
118: calls $3,(r0)
119: popr $0x3f
120: chmk $ULTRIX_SYS_sigreturn
121: chmk $SYS_exit
122: halt
123: .align 2
124: _ultrix_esigcode:
125: #endif
126:
127: .globl _idsptch, _eidsptch
128: _idsptch: pushr $0x3f
129: .word 0x9f16 # jsb to absolute address
130: .long _cmn_idsptch # the absolute address
131: .long 0 # the callback interrupt routine
132: .long 0 # its argument
133: .long 0 # ptr to correspond evcount struct
134: _eidsptch:
135:
136: _cmn_idsptch:
137: movl (sp)+,r0 # get pointer to idspvec
138: movl 8(r0),r1 # get evcount pointer
139: beql 1f # no ptr, skip increment
140: incl EC_COUNT(r1) # increment low longword
141: adwc $0,EC_COUNT+4(r1) # add any carry to hi longword
142: 1: pushl 4(r0) # push argument
143: calls $1,*(r0) # call interrupt routine
144: popr $0x3f # pop registers
145: rei # return from interrut
146:
147: ENTRY(badaddr,R2|R3) # Called with addr,b/w/l
148: mfpr $0x12,r0 # splhigh()
149: mtpr $0x1f,$0x12
150: movl 4(ap),r2 # First argument, the address
151: movl 8(ap),r1 # Sec arg, b,w,l
152: pushl r0 # Save old IPL
153: clrl r3
154: movab 4f,_memtest # Set the return address
155:
156: caseb r1,$1,$4 # What is the size
157: 1: .word 1f-1b
158: .word 2f-1b
159: .word 3f-1b # This is unused
160: .word 3f-1b
161:
162: 1: movb (r2),r1 # Test a byte
163: brb 5f
164:
165: 2: movw (r2),r1 # Test a word
166: brb 5f
167:
168: 3: movl (r2),r1 # Test a long
169: brb 5f
170:
171: 4: incl r3 # Got machine chk => addr bad
172: 5: mtpr (sp)+,$0x12
173: movl r3,r0
174: ret
175:
176: # Have bcopy and bzero here to be sure that system files that not gets
177: # macros.h included will not complain.
178: ENTRY(bcopy,R2|R3|R4|R5|R6)
179: movl 4(ap), r0
180: movl 8(ap), r1
181: movzwl 12(ap), r2
182: movzwl 14(ap), r6
183:
184: movc3 r2, (r0), (r1)
185:
186: tstl r6
187: bleq 1f
188: 0: movb (r1)+, (r3)+
189: movc3 $0xffff, (r1), (r3)
190: sobgtr r6, 0b
191:
192: 1: ret
193:
194: ENTRY(bzero,R2|R3|R4|R5|R6)
195: movl 4(ap), r0
196: movzwl 8(ap), r1
197: movzwl 10(ap), r6
198:
199: movc5 $0, (r0), $0, r1, (r0)
200:
201: tstl r6
202: bleq 1f
203: 0: clrb (r3)+
204: movc5 $0, (r3), $0, $0xffff, (r3)
205: sobgtr r6, 0b
206:
207: 1: ret
208:
209: # cmpc3 is sometimes emulated; we cannot use it
210: ENTRY(bcmp, R2);
211: movl 4(ap), r2
212: movl 8(ap), r1
213: movl 12(ap), r0
214: 2: cmpb (r2)+, (r1)+
215: bneq 1f
216: decl r0
217: bneq 2b
218: 1: ret
219:
220: #ifdef DDB
221: /*
222: * DDB is the only routine that uses setjmp/longjmp.
223: */
224: ENTRY(setjmp, 0)
225: movl 4(ap), r0
226: movl 8(fp), (r0)
227: movl 12(fp), 4(r0)
228: movl 16(fp), 8(r0)
229: addl3 fp,$28,12(r0)
230: clrl r0
231: ret
232:
233: ENTRY(longjmp, 0)
234: movl 4(ap), r1
235: movl 8(ap), r0
236: movl (r1), ap
237: movl 4(r1), fp
238: movl 12(r1), sp
239: jmp *8(r1)
240: #endif
241:
242: #
243: # setrunqueue/remrunqueue fast variants.
244: #
245:
246: JSBENTRY(Setrq)
247: #ifdef DIAGNOSTIC
248: tstl 4(r0) # Check that process actually are off the queue
249: beql 1f
250: pushab setrq
251: calls $1,_panic
252: setrq: .asciz "setrunqueue"
253: #endif
254: 1: extzv $2,$6,P_PRIORITY(r0),r1 # get priority
255: movaq _qs[r1],r2 # get address of queue
256: insque (r0),*4(r2) # put proc last in queue
257: bbss r1,_whichqs,1f # set queue bit.
258: 1: rsb
259:
260: JSBENTRY(Remrq)
261: extzv $2,$6,P_PRIORITY(r0),r1
262: #ifdef DIAGNOSTIC
263: bbs r1,_whichqs,1f
264: pushab remrq
265: calls $1,_panic
266: remrq: .asciz "remrunqueue"
267: #endif
268: 1: remque (r0),r2
269: bneq 1f # Not last process on queue
270: bbsc r1,_whichqs,1f
271: 1: clrl 4(r0) # saftey belt
272: rsb
273:
274: #
275: # Idle loop. Here we could do something fun, maybe, like calculating
276: # pi or something.
277: #
278: idle: mtpr $0,$PR_IPL # Enable all types of interrupts
279: 1: tstl _whichqs # Anything ready to run?
280: beql 1b # no, continue to loop
281: brb Swtch # Yes, goto switch again.
282:
283: #
284: # cpu_switch, cpu_exit and the idle loop implemented in assembler
285: # for efficiency. r0 contains pointer to last process.
286: #
287:
288: #define CURPROC _cpu_info_store + CI_CURPROC
289:
290: JSBENTRY(Swtch)
291: clrl CURPROC # Stop process accounting
292: #bpt
293: mtpr $0x1f,$PR_IPL # block all interrupts
294: ffs $0,$32,_whichqs,r3 # Search for bit set
295: beql idle # no bit set, go to idle loop
296:
297: movaq _qs[r3],r1 # get address of queue head
298: remque *(r1),r2 # remove proc pointed to by queue head
299: #ifdef DIAGNOSTIC
300: bvc 1f # check if something on queue
301: pushab noque
302: calls $1,_panic
303: noque: .asciz "swtch"
304: #endif
305: 1: bneq 2f # more processes on queue?
306: bbsc r3,_whichqs,2f # no, clear bit in whichqs
307: 2: clrl 4(r2) # clear proc backpointer
308: clrl _want_resched # we are now changing process
309: movb $SONPROC,P_STAT(r2) # p->p_stat = SONPROC
310: movl r2,CURPROC # set new process running
311: cmpl r0,r2 # Same process?
312: bneq 1f # No, continue
313: rsb
314: xxd:
315: 1: movl P_ADDR(r2),r0 # Get pointer to new pcb.
316: addl3 r0,$IFTRAP,pcbtrap # Save for copy* functions.
317:
318: #
319: # Nice routine to get physical from virtual addresses.
320: #
321: extzv $9,$21,r0,r1 # extract offset
322: movl *_Sysmap[r1],r2 # get pte
323: ashl $9,r2,r3 # shift to get phys address.
324:
325: #
326: # Do the actual process switch. pc + psl are already on stack, from
327: # the calling routine.
328: #
329: svpctx
330: mtpr r3,$PR_PCBB
331: ldpctx
332: rei
333:
334: #
335: # the last routine called by a process.
336: #
337:
338: ENTRY(cpu_exit,0)
339: movl 4(ap),r6 # Process pointer in r6
340: mtpr $0x18,$PR_IPL # Block almost everything
341: addl3 $512,_scratch,sp # Change stack, and schedule it to be freed
342:
343: pushl r6
344: calls $1,_exit2
345:
346: clrl r0 # No process to switch from
347: bicl3 $0xc0000000,_scratch,r1
348: mtpr r1,$PR_PCBB
349: brw Swtch
350:
351:
352: #
353: # copy/fetch/store routines.
354: #
355: .align 2,1
356: ENTRY(copyin, R2|R3|R4|R5|R6)
357: movl 4(ap), r0
358: blss 3f # kernel space
359: movl 8(ap), r1
360: brb 2f
361:
362: ENTRY(copyout, R2|R3|R4|R5|R6)
363: movl 8(ap), r1
364: blss 3f # kernel space
365: movl 4(ap), r0
366: 2: movab 1f,*pcbtrap
367: movzwl 12(ap), r2
368: movzwl 14(ap), r6
369:
370: movc3 r2, (r0), (r1)
371:
372: tstl r6
373: bleq 1f
374: 0: movb (r1)+, (r3)+
375: movc3 $0xffff, (r1), (r3)
376: sobgtr r6,0b
377:
378: 1: clrl *pcbtrap
379: ret
380:
381: 3: movl $EFAULT, r0
382: ret
383:
384: /* kcopy: just like bcopy, except return -1 upon failure */
385: ENTRY(kcopy,R2|R3|R4|R5|R6)
386: movl *pcbtrap,-(sp)
387: movab 2f,*pcbtrap
388: movl 4(ap), r0
389: movl 8(ap), r1
390: movzwl 12(ap), r2
391: movzwl 14(ap), r6
392:
393: movc3 r2, (r0), (r1)
394:
395: tstl r6
396: bleq 1f
397: 0: movb (r1)+, (r3)+
398: movc3 $0xffff, (r1), (r3)
399: sobgtr r6, 0b
400:
401: /*
402: * If there is a failure, trap.c will set r1 to -1, and jump
403: * to the following 2. If not, we return 0. We duplicate a
404: * minuscule amount of code in the interest of speed; movc3
405: * sets r0 to 0 anyway.
406: */
407: 1:
408: movl (sp)+,*pcbtrap
409: ret
410:
411: 2: movl (sp)+,*pcbtrap
412: movl r1,r0
413: ret
414:
415: ENTRY(copyinstr,0)
416: tstl 4(ap) # is from a kernel address?
417: bgeq 8f # no, continue
418:
419: 6: movl $EFAULT,r0
420: ret
421:
422: ENTRY(copyoutstr,0)
423: tstl 8(ap) # is to a kernel address?
424: bgeq 8f # no, continue
425: brb 6b
426:
427: ENTRY(copystr,0)
428: 8: movl 4(ap),r4 # from
429: movl 8(ap),r5 # to
430: movl 16(ap),r3 # copied
431: movl 12(ap),r2 # len
432:
433: bneq 1f # nothing to copy?
434: movl $ENAMETOOLONG,r0
435: tstl r3
436: beql 0f
437: movl $0,(r3)
438: 0: ret
439:
440: 1: movab 2f,*pcbtrap
441:
442: /*
443: * This routine consists of two parts: One is for MV2 that doesn't have
444: * locc in hardware, the other is a fast version with locc. But because
445: * locc only handles <64k strings, we default to the slow version if the
446: * string is longer.
447: */
448: cmpl _vax_cputype,$VAX_TYP_UV2
449: bneq 4f # Check if locc emulated
450:
451: 9: movl r2,r0
452: 7: movb (r4)+,(r5)+
453: beql 6f # end of string
454: sobgtr r0,7b # no null byte in the len first bytes?
455: brb 1f
456:
457: 6: tstl r3
458: beql 5f
459: incl r2
460: subl3 r0,r2,(r3)
461: 5: clrl r0
462: clrl *pcbtrap
463: ret
464:
465: 4: cmpl r2,$65535 # maxlen < 64k?
466: blss 8f # then use fast code.
467:
468: locc $0,$65535,(r4) # is strlen < 64k?
469: beql 9b # No, use slow code
470: subl3 r0,$65535,r1 # Get string len
471: brb 0f # do the copy
472:
473: 8: locc $0,r2,(r4) # check for null byte
474: beql 1f
475:
476: subl3 r0,r2,r1 # Calculate len to copy
477: 0: incl r1 # Copy null byte also
478: tstl r3
479: beql 3f
480: movl r1,(r3) # save len copied
481: 3: movc3 r1,(r4),(r5)
482: brb 4f
483:
484: 1: movl $ENAMETOOLONG,r0
485: 2: movab 4f,*pcbtrap # if we fault again, don't resume there
486: subl3 8(ap),r5,r1 # did we write to the string?
487: beql 3f
488: decl r5
489: 3: movb $0,(r5) # null terminate the output string
490: tstl r3
491: beql 4f
492: incl r1 # null byte accounts for outlen...
493: movl r1,(r3) # save len copied
494: 4: clrl *pcbtrap
495: ret
496:
497: #
498: # data department
499: #
500: .data
501:
502: _memtest: .long 0 ; .globl _memtest # Memory test in progress.
503: pcbtrap: .long 0x800001fc; .globl pcbtrap # Safe place
504: _bootdev: .long 0; .globl _bootdev
505:
506: /*
507: * Fill more than 64k of memory (used by bzero and memset).
508: */
509: ENTRY(blkfill,R2|R3|R4|R5|R6|R7)
510: movl 4(ap), r3
511: movl 8(ap), r7
512: movl 12(ap), r6
513: jbr 2f
514: 1: subl2 r0, r6
515: movc5 $0,(r3),r7,r0,(r3)
516: 2: movzwl $65535,r0
517: cmpl r6, r0
518: jgtr 1b
519: movc5 $0,(r3),r7,r6,(r3)
520: ret
CVSweb