xref: /csrg-svn/sys/tahoe/align/Awriteable.c (revision 45699)
1*45699Sbostic /*	Awriteable.c	1.2	90/12/04	*/
229644Ssam 
3*45699Sbostic #include "align.h"
429644Ssam 
529644Ssam long writeable(infop, address, length)
629644Ssam process_info 	*infop;
729644Ssam long		address, length;
829644Ssam /*
929644Ssam  *   Return TRUE (= -1) if the specified bytes can be written without an access
1029644Ssam  * control violation (limit and/or protection). Page faults are OK.
1129644Ssam  *   If problems, return the code that would be pushed by HW on the
1229644Ssam  * stack (see the architecture manual).
1329644Ssam  *   Assumption is that in most cases, access is OK, so a quick 'probew'
1429644Ssam  * will be enough. If not, we have to work harder to determine the exact
1529644Ssam  * cause and return the right code, without getting the fault here in
1629644Ssam  * the kernel !!.
1729644Ssam  *
1829644Ssam  * The address is assumed to be write for the user.!
1929644Ssam  */
2029644Ssam {
2129644Ssam 	register	long	Register_12;	/* Has to be first reg ! */
2229644Ssam 	register	long	Register_11;
2329644Ssam 	register	long	Register_10;
2429644Ssam 	register	long	Register_9;
2529644Ssam 	register	long	Register_8;
2629644Ssam 	register	long	subspace;
2729644Ssam 	register	long	last_page;
2829644Ssam 
2929644Ssam 	Register_12 = address;
3029644Ssam 	Register_11 = length-1;
3129644Ssam 	asm ("		probew	$1,(r12),$1	");	/* Yeach ... */
3229644Ssam 	asm ("		beql	no_access	");
3329644Ssam 	asm ("		addl2	r11,r12		");	/* last byte */
3429644Ssam 	asm ("		probew	$1,(r12),$1	");
3529644Ssam 	asm ("		beql	no_access	");
3629644Ssam 	asm ("		movl	$-1,r0		");	/* TRUE */
3729644Ssam 	asm ("		ret#1			");
3829644Ssam 	asm ("no_access:			");
3929644Ssam /*
4029644Ssam  * Now the hard work. Have to check length violation first.
4129644Ssam  * If any byte (first or last) causes a length violation, report it as such.
4229644Ssam  */
4329644Ssam 	asm ("	mfpr	$3,r8	");	/* Get length registers. P0LR */
4429644Ssam 	asm ("	mfpr	$5,r9	");	/* P1LR */
4529644Ssam 	asm ("	mfpr	$7,r10	");	/* P2LR */
4629644Ssam 	asm ("	mfpr	$1,r11	");	/* SLR */
4729644Ssam 
4829644Ssam 	subspace = (address >> 30) & 3;
4929644Ssam 	Register_12 = (address >> 10) & 0xfffff;	/* 1'st byte page # */
5029644Ssam 	last_page = ( (address+length-1) >> 10) & 0xfffff;
5129644Ssam 	switch ( subspace ) {
5229644Ssam 	case 0:
5329644Ssam 		if ( (Register_12 >= Register_8) ||
5429644Ssam 		     (last_page   >= Register_8) ) return (1);
5529644Ssam 		break;
5629644Ssam 	case 1:
5729644Ssam 		if ( (Register_12 >= Register_9) ||
5829644Ssam 		     (last_page   >= Register_9) ) return (1);
5929644Ssam 		break;
6029644Ssam 	case 2:
6129644Ssam 		if ( (Register_12 < Register_10) ||
6229644Ssam 		     (last_page   < Register_10) ) return (1);
6329644Ssam 		break;
6429644Ssam 	case 3:
6529644Ssam 		if ( (Register_12 >= Register_11) ||
6629644Ssam 		     (last_page   >= Register_11) ) return (1);
6729644Ssam 		break;
6829644Ssam 	}
6929644Ssam /*
7029644Ssam  * OK, it's not a length violation. Must have been an access problem
7129644Ssam  * (no write by user).
7229644Ssam  *
7329644Ssam  * NOTE : I definitely ignore the case of 'no PTE access' since I
7429644Ssam  *	assume that's not the case for user mode. Besides, the poor
7529644Ssam  *	guy will just get an access violation that will most probably
7629644Ssam  *	send him into hyperspace anyway, so no need to be too acurate here.
7729644Ssam  */
7829644Ssam 	return (4);
7929644Ssam }
80