[comp.arch] resuming after fault

chris@mimsy.umd.edu (Chris Torek) (08/06/90)

In article <3729@auspex.auspex.com> guy@auspex.auspex.com (Guy Harris) writes:
(in re resuming a faulted instruction on the 680[123]0)
>Part of the problem is that Motorola:
>1) wouldn't commit to the the "stack puke" stored by the 680[1andup]0
>   being "safe" to hand to user-mode code; i.e., they wouldn't say
>   "nothing you can do to the 'stack puke' is risky";
>2) wouldn't describe the format of the "stack puke" to the extent
>   necessary to have the kernel validate it.

(the Sun-2 versus the VAX:)
>The former has more context than the latter; the former has the 68010
>"stack puke", the latter has, as I remember, just the First Part Done
>bit (and some of the general-purpose registers, for some of the
>long-running instructions like MOVCn).
>
>The latter is safe and, I think, appears in the "signal context"
>saved by a BSD signal, so that the instruction can be continued from
>user mode without the kernel having to tuck away one or more sets of
>context.

Right (except that the registers do not appear in the sigcontext;
the FPD bit is simply one in the PSL, and the VAX PSL is easy for
the kernel to verify).  (The registers are saved as part of the
trap handling sequence, and ultimately restored in the `sigreturn'
syscall called from the signal trampoline code in the u. area.)

Basically, the problem here is that on an exception, the 680[123]0
simply pushes the entire microengine state; a return from exception
reloads the microengine state so that the instruction can be continued
(rather than restarted, as on the VAX; the VAX `first part done' bit
allows restarting without resetting important context, e.g., the
registers for the character string instructions).

If there is no documented way to verify the state (as there is on the
VAX), it becomes difficult for an O/S to allow user code to handle an
exception: if the user code modifies the state, this could crash the
machine, or allow improper privileges.  The kernel can stash a copy of
the exception state (the `stack puke') and compare this on return to
ensure that it has not been changed, but this then limits the actions
user code can take.  If the user code elects not to return from the
signal (e.g., to longjmp instead), the kernel may wind up carrying
around useless copies of this state.

In terms of computer architecture, the lesson here is that there must
be a documented method to verify any state left behind.  *Someone* will
want it.  The simplest solution is not to leave state behind.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@cs.umd.edu	Path:	uunet!mimsy!chris
	(New campus phone system, active sometime soon: +1 301 405 2750)

melvin@rigel (Steve Melvin) (08/08/90)

In article <25899@mimsy.umd.edu> chris@mimsy.umd.edu (Chris Torek) writes:
>...
>Basically, the problem here is that on an exception, the 680[123]0
>simply pushes the entire microengine state; a return from exception
>reloads the microengine state so that the instruction can be continued
>...
>If there is no documented way to verify the state (as there is on the
>VAX), it becomes difficult for an O/S to allow user code to handle an
>exception: if the user code modifies the state, this could crash the
>machine, or allow improper privileges.
>...
>In terms of computer architecture, the lesson here is that there must
>be a documented method to verify any state left behind.

It seems that what you really must be saying is that the hardware should
provide protections, becuase in this particular example, the OS has no way
of verifying the register contents.  If the user mangles the registers and
then returns with FPD set, an access violation may result, but the hardware
guarantees that the machine won't crash and no improper privileges will
result.

The VAX architecture specifies what the lower 2, 4 or 6 registers contain
after a string instruction is finished, but not what they contain in the
middle of a string instruction when an exception is taken with FPD set.
(Officially, an instruction is "unpredictable" if registers are modified
with FPD set or if FPD is set by software.)  Most implementations have done
things in similar ways, but these are not architecturally guaranteed (see
below).

The larger point about allowing user level access to exception handling
is well taken, but that's a separate issue from forcing the exact
specification of all the temporary state which an implementation may want
to keep around.

----
Steve Melvin						  ...!ucbvax!melvin
University of California, Berkeley		melvin@polaris.Berkeley.EDU
----

P.S.  Here's a little program I wrote several years ago which relies on
differences in FPD state packing to prove that user level programs could
discern different implementations.  There is an 8-bit field "delta pc"
packed into R0 which encodes the length of the instruction so that upon
restarting, the instruction doesn't have to be decoded again.
----
/* testimpl.c */

/* Use hardware dependencies in how FPD information is packed away to
 * test the type of VAX implementation being run on.  Depends on whether
 * or not the delta PC value stored in R0 should be added to the PC of
 * the opcode or the incremented PC.  Uses the fact that the REI
 * instruction can be executed from unprivileged code.
 */

main()
{
	if (tstimpl()) {
		printf("implementation is 11/780, microvax\n");
	} else {
		printf("implementation is 8600\n");
	}
}

/* link with the following assembly language file:
	.data
	.comm	_buf1,8
	.comm	_buf2,8

	.text
	.align	1
	.globl	_tstimpl
_tstimpl:
	.word	0xFFC
	movl	$0x010c,r0
	movl	$_buf1+4,r1
	movl	$0,r2
	movl	$_buf2+4,r3
	movl	$0,r4
	movl	$0,r5
	movpsl	r11
	bisl2	$0x08000000, r11
	pushl	r11
	pushl	$_tst1
	rei
_tst1:
	movc3	$2,_buf1,_buf2
	ret
	incl	r0
	ret
*/