1: /*
   2:  * Copyright (c) 1987 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  */
   6: 
   7: #if defined(LIBC_SCCS) && !defined(KERNEL) && !defined(SUPERVISOR)
   8:         <@(#)csv.s	2.4 (2.11BSD GTE) 12/24/92\0>
   9:         .even
  10: #endif
  11: 
  12: /*
  13:  * C register save and restore routines.  When a C routine is called its stack
  14:  * frame (after csv or ovhandlr have set things up) looks like this:
  15:  *
  16:  *	_________________________________
  17:  *	| return address to caller 	|
  18:  *	|-------------------------------|
  19:  * r5->	| old r5 ("frame pointer")	|
  20:  *	|-------------------------------|
  21:  *	| previous __ovno		|
  22:  *	|-------------------------------|
  23:  *	| old r4			|
  24:  *	|-------------------------------|
  25:  *	| old r3			|
  26:  *	|-------------------------------|
  27:  *	| old r2			|
  28:  *	|-------------------------------|
  29:  * sp->	| empty parameter slot		|
  30:  *	|_______________________________|
  31:  *
  32:  * The "empty parameter slot" is a simple optimization the compiler uses to
  33:  * avoid overhead in its generated parameter cleanup code after a function
  34:  * has been called.  Rather than (for example) generating:
  35:  *
  36:  *	mov	foo,-(sp)	/ push parameter
  37:  *	jsr	pc,bar		/ call function
  38:  *	tst	(sp)+		/ throw away parameter
  39:  *
  40:  * The compiler always keeps one empty slot on the stack and generates:
  41:  *
  42:  *	mov	foo,(sp)	/ pass parameter
  43:  *	jsr	pc,bar		/ call function
  44:  *
  45:  * The savings are not quite so dramatic when more than one parameter is
  46:  * passed, but still worth the effort.  If the function has any local stack
  47:  * variables, space for them will have be be allocated by the function thereby
  48:  * "moving" the empty parameter slot down.
  49:  */
  50: 
  51: /*
  52:  * KERNEP and SUPERVISOR (network code) notes:
  53:  *
  54:  * Stack checking can be enabled for the KERNEL (and SUPERVISOR network)
  55:  * by defining CHECKSTACK in the config file.  Looks to see if the
  56:  * kernel and supervisor (network) stacks have collided, etc.
  57:  *
  58:  * Networking kernel doesn't currently need overlays (and probably never
  59:  * will).  If it's ever necessary to overlay the networking code, it would
  60:  * be done in exactly the same manner as that used by the kernel.  This would
  61:  * actually end up simplifying things ...
  62:  *
  63:  * It's debatable whether or not the standard library, KERNEL, and
  64:  * SUPERVISOR copies of csv/cret should be integrated this way, because
  65:  * the ifdef's sometimes make it hard to keep track of things.  But the
  66:  * code and comments here are complicated enough that it's worth the effort
  67:  * to keep all three versions in general sync.
  68:  */
  69: #include "DEFS.h"
  70: 
  71: #ifndef SUPERVISOR              /* networking kernel doesn't use overlays */
  72: #ifdef KERNEL
  73: #include "../machine/mch_iopage.h"
  74: #include "../machine/koverlay.h"
  75: #endif
  76: 
  77: .data
  78: #ifdef KERNEL
  79: .globl  ova, ovd                / overlay descriptor tables
  80: #endif
  81: .globl  __ovno                  / currently mapped overlay
  82: __ovno: 0
  83: .text
  84: 
  85: .globl  _etext                  / used by cret to determine returns to overlay
  86:                                 / area (any return address higher than _etext)
  87:                                 / the loader defines only if referenced
  88: 
  89: /*
  90:  * The loader (/bin/ld) generates `thunks' for functions loaded in overlays.
  91:  * A thunk resides in the base segment and takes the name _foo which is the
  92:  * function's interface to the outside world (this allows pointers to functions
  93:  * to work even if functions are located in overlays).  The function itself is
  94:  * renamed to ~foo.
  95:  *
  96:  * ovhndlr(1-9,a-f) are called from the thunks via a jsr r5 after r1 is set to
  97:  * the location of the first instruction in the subroutine after the call to
  98:  * csv (~foo+4).
  99:  *
 100:  *	_foo:	mov	$~foo+4,r1
 101:  *		jsr	r5,ovhndlr`n'
 102:  *
 103:  * The ovhndlr`n' in turn move the requested overlay number into r0 and
 104:  * branch to ovhndlr which sets the overlay, simulates a csv and transfers to
 105:  * (r1) (~foo+4).  Thus, the function's call to csv is bypassed.
 106:  */
 107: #define ovh(x, n)       .globl  ovhndlr/**/x; \
 108:                 ovhndlr/**/x: \
 109:                         mov     $n,r0; \
 110:                         br      ovhndlr;
 111: 
 112: ovh(1,001);     ovh(2,002);     ovh(3,003);     ovh(4,004)
 113: ovh(5,005);     ovh(6,006);     ovh(7,007);     ovh(8,010)
 114: ovh(9,011);     ovh(a,012);     ovh(b,013);     ovh(c,014)
 115: ovh(d,015);     ovh(e,016);     ovh(f,017)
 116: 
 117: #ifndef KERNEL
 118: emt     = 0104000               / overlays switched by emulator trap
 119:                                 / overlay number is placed in r0
 120: #endif KERNEL
 121: 
 122: /*
 123:  * ovhndlr(ov::r0, ~foo+4::r1, _foo+8::r5)
 124:  *
 125:  * Ovhandler builds the new stack frame as fast as possible to avoid problems
 126:  * with getting interrupted halfway through.  if we get interrupted between the
 127:  * "jsr r5,ovhndlr`x'" and the "mov sp,r5" below and a longjmp is attempted,
 128:  * rollback will fail utterly.  If we get interrupted before we finish saving
 129:  * registers reserved for register variables and an attempt is made to longjmp
 130:  * to the caller of our service routine rollback will incorrectly pull `saved'
 131:  * register values from the incomplete stack frame leading to
 132:  * non-deterministic behavior.
 133:  *
 134:  * There's very little that can be done about this asside from changing the
 135:  * entire stack frame sequence which involves changes to the compiler, loader,
 136:  * this file and any other routine (like rollback) which `knows' how the C
 137:  * stack frame is put together ...
 138:  */
 139: ovhndlr:
 140: #if defined(KERNEL) && defined(CHECKSTACK)
 141:         cmp     sp, $_u         / before the u. area?
 142:         blo     9f              /   yes, assume it's remapped, so OK
 143:         cmp     sp, $KERN_SBASE / falling off the bottom?
 144:         bhi     9f              /   no, also OK
 145:         spl     7               / lock out interrupts
 146:         halt                    / can't 'panic', that uses the stack!
 147:         br      .               / in case continue is done
 148: 9:
 149: #endif
 150:         mov     sp,r5           / simulate a csv ...
 151:         mov     __ovno,-(sp)
 152:         cmp     r0,(sp)         / is the requested overlay already mapped?
 153:         beq     1f
 154: #ifdef KERNEL
 155:         mov     PS,-(sp)        / save PS
 156:         SPL7
 157:         mov     r0,__ovno       / set new overlay number
 158:         asl     r0              / compute descriptor index and map
 159:         mov     ova(r0), OVLY_PAR / the new overlay in
 160:         mov     ovd(r0), OVLY_PDR
 161:         mov     (sp)+,PS        / restore PS, unmask interrupts
 162: #else
 163:         emt                     /   no, ask the kernel for it ...
 164:         mov     r0,__ovno       /     and indicate the new overlay
 165:         /*
 166: 	 * SPECIAL NOTE: the pair of instructions "emt" and "mov r0,__ovno"
 167: 	 * form a race condition.  A signal can interrupt the sequence
 168: 	 * causing all sorts of nastiness if the signal routine calls a
 169: 	 * routine in the old overlay or is itself in the old overlay ...
 170: 	 * There is no solution that doesn't involve changing the way
 171: 	 * an overlay switch from the kernal.  Most [potential] solutions
 172: 	 * significantly increase the overhead of an overlay switch.
 173: 	 * A tenable solution has yet to be found ...
 174: 	 */
 175: #endif
 176: 1:
 177:         mov     r4,-(sp)
 178:         mov     r3,-(sp)
 179:         mov     r2,-(sp)
 180:         jsr     pc,(r1)         / jsr leaves empty parameter slot on stack
 181: #endif /* !SUPERVISOR */
 182: 
 183: 
 184: /*
 185:  * Csv for routines called directly (in base or intra-overlay calls).
 186:  * no overlays have been changed, so we just save the previous overlay
 187:  * number on the stack.  Note that r0 isn't set to the current overlay
 188:  * because we weren't called through a thunk.
 189:  */
 190: .globl  csv
 191: csv:
 192: #if (defined(KERNEL) || defined(SUPERVISOR)) && defined(CHECKSTACK)
 193: #ifdef SUPERVISOR
 194:         cmp     sp,$NET_STOP    / out of the top of the stack?
 195:         bhi     8f              /   yes, die
 196:         cmp     sp,$NET_SBASE   / falling off the bottom?
 197:         bhi     9f              /   no, so OK
 198: 8:
 199:         spl     7               / lock out interrupts
 200:         halt                    / can't 'panic', that uses the stack!
 201:         br      .               / in case continue is done
 202: 9:
 203: #else
 204:         cmp     sp,$_u          / before the u. area?
 205:         blo     9f              / assume it was remapped, so OK
 206:         cmp     sp,$KERN_SBASE  / falling off the bottom?
 207:         bhi     9f              / no, so OK
 208:         spl     7               / lock out interrupts
 209:         halt                    / can't 'panic', that uses the stack!
 210:         br      .               / in case continue is done
 211: 9:
 212: #endif
 213: #endif
 214:         mov     r5,r1           / save transfer address,
 215:         mov     sp,r5
 216: #ifdef SUPERVISOR
 217:         clr     -(sp)
 218: #else
 219:         mov     __ovno,-(sp)
 220: #endif
 221:         mov     r4,-(sp)
 222:         mov     r3,-(sp)
 223:         mov     r2,-(sp)
 224:         jsr     pc,(r1)
 225: 
 226: /*
 227:  * Cret is used by everyone so it has to check if we're returning to an
 228:  * overlay different from the one that may be currently mapped.
 229:  */
 230: .globl  cret
 231: cret:
 232: #if (defined(KERNEL) || defined(SUPERVISOR)) && defined(CHECKSTACK)
 233: #ifdef SUPERVISOR
 234:         cmp     sp,$NET_STOP    / out of the top of the stack?
 235:         bhi     8f              /   yes, die
 236:         cmp     sp,$NET_SBASE   / falling off the bottom?
 237:         bhi     9f              /   no, so OK
 238: 8:
 239:         spl     7               / lock out interrupts
 240:         halt                    / can't 'panic', that uses the stack!
 241:         br      .               / in case continue is done
 242: 9:
 243: #else
 244:         cmp     sp,$_u          / before the u. area?
 245:         blo     9f              / assume it was remapped, so OK
 246:         cmp     sp,$KERN_SBASE  / falling off the bottom?
 247:         bhi     9f              / no, so OK
 248:         spl     7               / lock out interrupts
 249:         halt                    / can't 'panic', that uses the stack!
 250:         br      .               / in case continue is done
 251: 9:
 252: #endif
 253: #endif
 254:         mov     r5,r2
 255: #ifdef SUPERVISOR
 256:         tst     -(r2)           / skip over overlay slot
 257: #else
 258:         mov     -(r2),r4        / r4 = old __ovno - if non-zero we've started
 259:         bne     2f              /   using overlays so we'll have to make
 260:                                 /   sure the old overlay is mapped if we're
 261:                                 /   returning to the overlay area
 262: 1:
 263: #endif
 264:         mov     -(r2),r4        / restore registers, reset stack, pop frame
 265:         mov     -(r2),r3        /   pointer and return
 266:         mov     -(r2),r2
 267:         mov     r5,sp           / (more interrupt problems here *sigh* ...)
 268:         mov     (sp)+,r5
 269:         rts     pc
 270: #ifndef SUPERVISOR
 271: 2:
 272:         /*
 273: 	 * Not returning to base segment, so check that the right
 274: 	 * overlay is mapped in, and if not change the mapping.
 275: 	 */
 276:         cmp     r4,__ovno       / current overlay same as old overlay?
 277:         beq     1b              /   lucked out!
 278: #if     defined(KERNEL) && defined(INET)
 279:         cmp     2(r5),$Kretu    / must always restore overlays if returning
 280:         beq     3f              /   from SKcall
 281: #endif
 282:         cmp     2(r5),$_etext   / returning to base segment?
 283:         blos    1b              /   sometimes things *do* work out ...
 284: #ifdef KERNEL
 285: 3:
 286:         mov     PS,-(sp)        / (sigh) returning to a different overlay
 287:         SPL7
 288:         mov     r4,__ovno       / set new overlay number
 289:         asl     r4              / and map the new overlay in
 290:         mov     ova(r4), OVLY_PAR
 291:         mov     ovd(r4), OVLY_PDR
 292:         mov     (sp)+,PS        / restore PS, unmask interrupts
 293:         br      1b
 294: #else
 295:         mov     r0,r3           / (sigh) returning to a different overlay -
 296:         mov     r4,r0           /   have to save r0 because we can't trash
 297:         emt                     /   a function result and ask UNIX to switch
 298:         mov     r4,__ovno       /   the old overlay in
 299:         mov     r3,r0           / note that as with ovhndlr the pair "emt"
 300:         br      1b              /   "mov r4,__ovno" can be interrupted
 301: #endif
 302: #endif /* !SUPERVISOR */

Defined functions

emt defined in line 118; used 2 times
ovhndlr defined in line 139; never used

Defined variables

__ovno declared in line 81; defined in line 82; used 20 times

Defined macros

ovh defined in line 107; used 15 times
Last modified: 1992-12-25
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3855
Valid CSS Valid XHTML 1.0 Strict