/* * Copyright (c) 1988 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)mch_KScall.s 1.1 (2.10BSD Berkeley) 4/3/88 */ #include "DEFS.h" #include "../machine/mch_iopage.h" /* * Inter-address-space procedure call subroutines. * KScall -- kernel to supervisor */ /* * KScall(func, nbytes, a1, ..., aN) * * C-call from kernel to supervisor. * Calls func(a1, ..., aN) in supervisor mode. */ ENTRY(KScall) mov r5,-(sp) mov PS,-(sp) / Save current PS mov 010(sp),r0 / r0: # bytes of arguments to copy /* * Allocate enough space on the supervisor stack to hold * the call frame. We must allocate space to hold all the * arguments, plus: * a null R5 entry as a marker * a return address (Sretu) * * We assume here that the supervisor stack pointer is always * in seg6 and further that both supervisor and kernel addresses * in this region are mapped to the same physical memory. * * This means that it is NOT ok for the network code to move the * supervisor SP outside of seg6, or for it to remap SDSA6 to * point to something other than the stack, unless it can guarantee * that KScall will not be called for the duration of the stack * fiddling. */ mov $010340,PS / Current KERN, prev SUPV, spl7 (paranoia) mfpd sp / Supervisor stack pointer mov (sp),r1 / Pointer to base of call frame #ifdef CHECKSTACK /* * The following is just to make sure that the supervisor stack * pointer looks reasonable and a check that *SDSA6 == *KDSA6 */ cmp r1,$_u blos 8f cmp r1,$USIZE\<6.+_u bhis 8f cmp SDSA6,KDSA6 beq 9f 8: spl 7 / lock out interrupts halt / drop dead so people can see where we are br . / go no further 9: #endif /* CHECKSTACK */ sub r0,(sp) sub $4.,(sp) / New SP. mtpd sp / Set up alternate stack ptr mov (sp),PS / Restore current PS mov r5,-(r1) / Old frame ptr mov r1,r5 / New frame ptr for other mode /* * Copy arguments. * Note that the stack offsets here are one word deeper than * after we saved the PS. */ mov r2,-(sp) / Save mov r0,r2 / r2: number of bytes of arguments to copy beq 2f / None to copy? if so, skip loop asr r2 / r2: number of words of arguments to copy add sp,r0 add $12.,r0 / r0: ptr to argN+1 1: mov -(r0),-(r1) sob r2,1b 2: mov (sp)+,r2 / Restore /* * Build the remainder of the frame on the * supervisor stack. */ mov $Sretu,-(r1) / Return address in supervisor space /* * Push the iothndlr pair, and the * pair for calling the supervisor function * on the kernel stack. */ mov PS,r0 / To get current priority bic $170000,r0 / Clear out current/previous modes bis $050000,r0 / Current SUPV, previous SUPV mov $ret,-(sp) / Stack kernel PC to go with saved kernel PS mov r0,-(sp) / Stack the new PS mov 10.(sp),-(sp) / Stack the address of function being called /* * At this point, the stacks look like the following: * * KERNEL SUPERVISOR * ------ ---------- *KSP-> <-SSP * * ... * * <0> * * * <# bytes of args> * * ... * * * "" is the address in supervisor address * space of the function being called. */ rtt / Call the function /* * Return to caller of KScall. * We arrive here with the same PS as that with which we were * called, via the rtt in iothndlr. */ ret: mov (sp)+,r5 rts pc /* * Kretu is the exit point in kernel code that cleans up * the kernel stack for return to supervisor mode from a * net-to-kernel procedure call. */ ASENTRY(Kretu) mov r5,sp / Throw away arguments from stack tst (sp)+ / Discard old frame pointer /* * At this point, the stacks look like the following: * * SUPERVISOR KERNEL * ---------- ------ *SSP-> * <_Kretu> * * <# bytes of args> ... * * ... <0> * <-KSP * */ rtt / Back to previous address space