Subject: Re: 2nd review of fixes to sig_return() and LDT's
To: None <brezak@apollo.hp.com, port-i386@sun-lamp.cs.berkeley.edu>
From: Bruce Evans <bde@kralizec.zeta.org.au>
List: port-i386
Date: 01/09/1994 03:39:24
	/* make sure they aren't trying to do anything funny */
! 	if ((scp->sc_ps & PSL_MBZ) != 0 || (scp->sc_ps & PSL_MBO) != PSL_MBO) {
! 		force_signal(p, SIGBUS);
		return(EINVAL);
+ 	}
  
	/* compare IOPL; we can't insist that it's always 3 or the X server
	   will fail */
! 	if ((tf->tf_eflags & PSL_IOPL) < (scp->sc_efl & PSL_IOPL)) {
! 		force_signal(p, SIGBUS);
		return(EINVAL);
+ 	}

The PSL_MBZ and PSL_MBO masks aren't appropriate for deciding which bits
can be changed.  The value of PSL_MBZ == 0xfffc7fb7 in the FreeBSD-1.0.2
sources is wrong too.  I think it should be 0xfff88028.  The (1 << 18)
bit has become the variable PSL_AC bit on 486's and most of the low bits
were always variable.

Instead, you should use something like the PSL_USERSET and PSL_USERCLR
masks.  These are wrong too in FreeBSD-1.0.2.  PSL_USERSET == PSL_IOPL
but the IOPL is variable.  PSL_I should be in PSL_USERSET.  PSL_USRCLR
== (PSL_I|PSL_NT) but PSL_I is in the wrong place and PSL_RF and PSL_VM
are not considered.

I think it would be clearer to use a PSL_UCC (user can change) mask.
Then the above two tests could be combined.  I think the correct value
for PSL_UCC is

	((PSL_AC = (1L << 18))
	 | PSL_V | PSL_D | PSL_T
	 | PSL_N | PSL_Z | PSL_AF
	 | PSL_PF | PSL_C) == 0x40dd5

This satisfies 0xffffffff = PSL_MBZ | PSL_MBO | PSL_UCC
			    | PSL_IOPL | PSL_I | PSL_NT | PSL_RF | PSL_VM

(disjoint union).

Bruce

------------------------------------------------------------------------------