xref: /csrg-svn/sys/tahoe/align/Areadable.c (revision 29630)
1 /*	Areadable.c	1.1	86/07/20	*/
2 
3 #include "../tahoealign/align.h"
4 
5 long readable(infop, address, length)
6 process_info 	*infop;
7 long		address, length;
8 /*
9  *   Return TRUE (= -1) if the specified bytes can be read without an access
10  * control violation (limit and/or protection). Page faults are OK.
11  *   If problems, return the code that would be pushed by HW on the
12  * stack (see the architecture manual).
13  *   Assumption is that in most cases, access is OK, so a quick 'prober'
14  * will be enough. If not, we have to work harder to determine the exact
15  * cause and return the right code, without getting the fault here in
16  * the kernel !!.
17  *
18  * The address is assumed to be read for the user.!
19  */
20 {
21 	register	long	Register_12;	/* Has to be first reg ! */
22 	register	long	Register_11;
23 	register	long	Register_10;
24 	register	long	Register_9;
25 	register	long	Register_8;
26 	register	long	subspace;
27 	register	long	last_page;
28 
29 	Register_12 = address;
30 	Register_11 = length-1;
31 	asm ("		prober	$1,(r12),$1	");	/* Yeach ... */
32 	asm ("		beql	no_access	");
33 	asm ("		addl2	r11,r12		");	/* last byte */
34 	asm ("		prober	$1,(r12),$1	");
35 	asm ("		beql	no_access	");
36 	asm ("		movl	$-1,r0		");	/* TRUE */
37 	asm ("		ret#1			");
38 	asm ("no_access:			");
39 /*
40  * Now the hard work. Have to check length violation first.
41  * If any byte (first or last) causes a length violation, report it as such.
42  */
43 	asm ("	mfpr	$3,r8	");	/* Get length registers. P0LR */
44 	asm ("	mfpr	$5,r9	");	/* P1LR */
45 	asm ("	mfpr	$7,r10	");	/* P2LR */
46 	asm ("	mfpr	$1,r11	");	/* SLR  */
47 
48 	subspace = (address >> 30) & 3;
49 	Register_12 = (address >> 10) & 0xfffff;	/* 1'st byte page # */
50 	last_page = ( (address+length-1) >> 10) & 0xfffff;
51 	switch ( subspace ) {
52 	case 0:
53 		if ( (Register_12 >= Register_8) ||
54 		     (last_page   >= Register_8) ) return (1);
55 		break;
56 	case 1:
57 		if ( (Register_12 >= Register_9) ||
58 		     (last_page   >= Register_9) ) return (1);
59 		break;
60 	case 2:
61 		if ( (Register_12 < Register_10) ||
62 		     (last_page   < Register_10) ) return (1);
63 		break;
64 	case 3:
65 		if ( (Register_12 >= Register_11) ||
66 		     (last_page   >= Register_11) ) return (1);
67 		break;
68 	}
69 /*
70  * OK, it's not a length violation. Must have been an access problem
71  * (no read by user).
72  *
73  * NOTE : I definitely ignore the case of 'no PTE access' since I
74  *	assume that's not the case for user mode. Besides, the poor
75  *	guy will just get an access violation that will most probably
76  *	send him into hyperspace anyway, so no need to be too acurate here.
77  */
78 	return (0);
79 }
80