.TITLE SYSCLL system call facility .IDENT /02.03/ .LIST ME .NLIST CND ; ; This file implements a symbolic system call mechanism. ; Only one real system call is provided, REGSYS, which is used to register ; symbolic system calls. A system call is identified by its name, which is ; expected to be on the stack (RAD50 encoded). ; Registering a system call that already exists does not result in error, ; the old system call will just not be reachable anymore. ; A call to an inexistant systemm call will result in a .WAIT for that system ; call, so registering a system call will do a .DONE on that system call. ; ; The system call mechanism sets up the stack in a way such that system calls ; can use .ENTRY and .RETRN just like any other subroutines. This implies that ; system calls can use R0, R1 and the carry flag to return information to the ; caller. ; ; 05-AUG-2005 H. Rosenfeld the syscall name is now put directly in R0 and ; R1 instead of transferring it through the ; stack, the syscall mechanism will now never ; lower the CPU priority ; 04-JUL-2005 H. Rosenfeld adjust to R50HSH calling changes, changed ; TBLSIZ ; 12-JUN-2005 H. Rosenfeld reworked system call facility to use a hash ; table instead of a binary tree ; 22-MAY-2005 H. Rosenfeld use .DONE on $REGSYS and .WAIT on unknown call ; 19-MAY-2005 H. Rosenfeld make SYSLST global ; 04-MAY-2005 H. Rosenfeld do a stack trace on unknown system call ; 03-MAY-2005 H. Rosenfeld added system call priority ; 22-APR-2005 H. Rosenfeld adapt to change of POOL system ; 13-APR-2005 H. Rosenfeld add global SYSRET for system call detection in ; stack trace (HNDLER.MAC) ; 09-APR-2005 H. Rosenfeld adapt to change of POOL system ; 25-JAN-2005 H. Rosenfeld changed the system call mechanism to use the ; new calling convention ; 24-JAN-2005 H. Rosenfeld added calling convention library & .MCALLs ; 06-DEC-2004 H. Rosenfeld changed register corruption bug and calling ; convention, arguments are now expected to be ; on the stack ; 04-NOV-2004 H. Rosenfeld ; .ENABL REG .LIBRARY /CALL.SML/ .LIBRARY /MEMORY.SML/ .LIBRARY /JOBCTL.SML/ .LIBRARY /UTIL.SML/ .MCALL .R50HSH .MCALL .CALL,.ENTRY,.RETRN .MCALL .P$ALLO,.P$ERR .MCALL .JOBCTL,.DONE,.WAIT .GLOBL CURJOB TBLSIZ=17 ; hash table size, 17(8) entries S$NEXT=0 ; pointer to next entry S$NAME=2 ; name of system call S$ADDR=6 ; address of system call routine S$PRIO=10 ; cpu priority of system call routine SIZE$S=12 .MACRO $SYS NAM1,NAM2,P1,P2,P3,P4,P5,P6,P7,P8,P9 .MCALL .ARGS CMP -(SP),-(SP) MOV R5,-(SP) .ARGS P1 P2 P3 P4 P5 P6 P7 P8 P9 MOV SP,R5 MOV NAM2,R1 MOV NAM1,R0 IOT .ENDM .MACRO $REGSYS NAM1,NAM2,ENTRY,PRIO $SYS #^RREG,#^RSYS,NAM1,NAM2,ENTRY,PRIO .ENDM .MACRO .S$INIT .GLOBL S$INIT .CALL S$INIT .ENDM .JOBCTL .CSECT ; S$INIT, initialize system call facility S$INIT::.ENTRY .P$ALLO #TBLSIZ*2 ; allocate hash table BCC 1$ ; no error .P$ERR ; print message HALT ; abort system initialization 1$: MOV R0,SYSTBL ; save pointer to hash table MOV #TBLSIZ,R4 ; get hash table size 2$: CLR (R0)+ ; clear hash table SOB R4,2$ .CALL REGSYS,#^RREG,#^RSYS,#REGSYS,#340 ; register REGSYS system call .RETRN ; REGSYS, register system call ; input: system call name (two RAD50 words), entry point, system call priority ; output: system call structure created and linked into syscall tree ; return: carry set on error, clear otherwise REGSYS::.ENTRY MOV CURJOB,-(SP) ; switch to system job for allocating buffer MOV #SYSJOB,CURJOB .P$ALLO #SIZE$S ; allocate system call buffer MOV (SP)+,CURJOB ; restore current job BCC 1$ ; continue if no error .P$ERR ; print message SEC ; indicate error .RETRN 1$: MOV R0,R4 ; save buffer address MOV 6(R5),S$NAME(R4); store name MOV 10(R5),S$NAME+2(R4) MOV 12(R5),S$ADDR(R4) MOV 14(R5),S$PRIO(R4) .R50HSH 6(R5),10(R5),#TBLSIZ ; calculate name hash ASL R0 ADD SYSTBL,R0 ; get table entry MOV (R0),S$NEXT(R4) ; prepend to list MOV R4,(R0) .DONE 6(R5),10(R5) ; wake up anyone waiting for this syscall CLC ; no error .RETRN ; The syscall dispatcher will not use .ENTRY to save registers, as this is ; supposed to be done by the syscall routine. Therefore, it must not change ; registers other than R0 or R1, which contain the syscall name. IOTHND::MOV (R5),-(SP) ; get MARK instruction SUB #MARK-2,(SP) ; leave raw argument count ASL (SP) ; convert to byte offset ADD (SP)+,R5 ; rewind frame over arguments MOV (SP)+,(R5)+ ; store return PC and PSW in the buffer MOV (SP),(R5)+ ; that has been allocated by $SYS 1$: MOV R1,-(SP) ; save first part of name MOV R0,-(SP) ; save second part of name .R50HSH R0,R1,#TBLSIZ ; calculate name hash ASL R0 ADD SYSTBL,R0 ; get table entry MOV R0,R5 MOV (SP)+,R0 ; restore first part of name MOV (SP)+,R1 ; restore second part of name 2$: MOV @R5,R5 ; get syscall entry BEQ 5$ ; no such syscall CMP R0,S$NAME(R5) ; first part matching? BNE 2$ ; no, get next CMP R1,S$NAME+2(R5) ; second part matching? BNE 2$ ; no, get next BR 6$ 5$: MOV R0,-(SP) ; save first part of syscall name MOV R1,-(SP) ; save second part of syscall name .WAIT R0,R1 ; wait for this syscall to appear MOV (SP)+,R1 ; restore second part of syscall name MOV (SP)+,R0 ; restore first part of syscall name BR 1$ ; try again 6$: MOV (SP)+,R0 ; get callers PSW MOV S$ADDR(R5),-(SP); store address of syscall routine MOV S$PRIO(R5),-(SP); store PSW for syscall routine MOV (SP),R1 ; get PSW for syscall routine BIC #177437,R0 ; mask priority in callers PSW BIC #177437,R1 ; mask priority in syscall PSW CMP R0,R1 ; call priority lower/same as syscall priority? BLOS 4$ ; yea, skip adjusting BIC #000340,(SP) ; reset syscall priority BIS R0,(SP) ; use call priority instead 4$: MOV SP,R5 ; set frame pointer CMP (R5)+,(R5)+ ; adjust frame pointer MTPS (SP)+ ; set syscall PSW JSR PC,@(SP)+ ; dispatch to syscall routine SYSRET::BCC 8$ ; flag the error condition in the saved PSW BIS #1,2(SP) RTI 8$: BIC #1,2(SP) RTI .PSECT DATA SYSTBL::.BLKW 1 .END