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
readable(infop,address,length)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