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