xref: /csrg-svn/sys/tahoe/align/Areadable.c (revision 45760)
1*45760Sbostic /*-
2*45760Sbostic  * Copyright (c) 1986 The Regents of the University of California.
3*45760Sbostic  * All rights reserved.
4*45760Sbostic  *
5*45760Sbostic  * This code is derived from software contributed to Berkeley by
6*45760Sbostic  * Computer Consoles Inc.
7*45760Sbostic  *
8*45760Sbostic  * %sccs.include.redist.c%
9*45760Sbostic  *
10*45760Sbostic  *	@(#)Areadable.c	7.1 (Berkeley) 12/06/90
11*45760Sbostic  */
1229630Ssam 
1345699Sbostic #include "align.h"
1429630Ssam 
readable(infop,address,length)1529630Ssam long readable(infop, address, length)
1629630Ssam process_info 	*infop;
1729630Ssam long		address, length;
1829630Ssam /*
1929630Ssam  *   Return TRUE (= -1) if the specified bytes can be read without an access
2029630Ssam  * control violation (limit and/or protection). Page faults are OK.
2129630Ssam  *   If problems, return the code that would be pushed by HW on the
2229630Ssam  * stack (see the architecture manual).
2329630Ssam  *   Assumption is that in most cases, access is OK, so a quick 'prober'
2429630Ssam  * will be enough. If not, we have to work harder to determine the exact
2529630Ssam  * cause and return the right code, without getting the fault here in
2629630Ssam  * the kernel !!.
2729630Ssam  *
2829630Ssam  * The address is assumed to be read for the user.!
2929630Ssam  */
3029630Ssam {
3129630Ssam 	register	long	Register_12;	/* Has to be first reg ! */
3229630Ssam 	register	long	Register_11;
3329630Ssam 	register	long	Register_10;
3429630Ssam 	register	long	Register_9;
3529630Ssam 	register	long	Register_8;
3629630Ssam 	register	long	subspace;
3729630Ssam 	register	long	last_page;
3829630Ssam 
3929630Ssam 	Register_12 = address;
4029630Ssam 	Register_11 = length-1;
4129630Ssam 	asm ("		prober	$1,(r12),$1	");	/* Yeach ... */
4229630Ssam 	asm ("		beql	no_access	");
4329630Ssam 	asm ("		addl2	r11,r12		");	/* last byte */
4429630Ssam 	asm ("		prober	$1,(r12),$1	");
4529630Ssam 	asm ("		beql	no_access	");
4629630Ssam 	asm ("		movl	$-1,r0		");	/* TRUE */
4729630Ssam 	asm ("		ret#1			");
4829630Ssam 	asm ("no_access:			");
4929630Ssam /*
5029630Ssam  * Now the hard work. Have to check length violation first.
5129630Ssam  * If any byte (first or last) causes a length violation, report it as such.
5229630Ssam  */
5329630Ssam 	asm ("	mfpr	$3,r8	");	/* Get length registers. P0LR */
5429630Ssam 	asm ("	mfpr	$5,r9	");	/* P1LR */
5529630Ssam 	asm ("	mfpr	$7,r10	");	/* P2LR */
5629630Ssam 	asm ("	mfpr	$1,r11	");	/* SLR  */
5729630Ssam 
5829630Ssam 	subspace = (address >> 30) & 3;
5929630Ssam 	Register_12 = (address >> 10) & 0xfffff;	/* 1'st byte page # */
6029630Ssam 	last_page = ( (address+length-1) >> 10) & 0xfffff;
6129630Ssam 	switch ( subspace ) {
6229630Ssam 	case 0:
6329630Ssam 		if ( (Register_12 >= Register_8) ||
6429630Ssam 		     (last_page   >= Register_8) ) return (1);
6529630Ssam 		break;
6629630Ssam 	case 1:
6729630Ssam 		if ( (Register_12 >= Register_9) ||
6829630Ssam 		     (last_page   >= Register_9) ) return (1);
6929630Ssam 		break;
7029630Ssam 	case 2:
7129630Ssam 		if ( (Register_12 < Register_10) ||
7229630Ssam 		     (last_page   < Register_10) ) return (1);
7329630Ssam 		break;
7429630Ssam 	case 3:
7529630Ssam 		if ( (Register_12 >= Register_11) ||
7629630Ssam 		     (last_page   >= Register_11) ) return (1);
7729630Ssam 		break;
7829630Ssam 	}
7929630Ssam /*
8029630Ssam  * OK, it's not a length violation. Must have been an access problem
8129630Ssam  * (no read by user).
8229630Ssam  *
8329630Ssam  * NOTE : I definitely ignore the case of 'no PTE access' since I
8429630Ssam  *	assume that's not the case for user mode. Besides, the poor
8529630Ssam  *	guy will just get an access violation that will most probably
8629630Ssam  *	send him into hyperspace anyway, so no need to be too acurate here.
8729630Ssam  */
8829630Ssam 	return (0);
8929630Ssam }
90