need time.h if no user.h
[unix-history] / usr / src / sys / tahoe / align / Areadable.c
CommitLineData
344ce65a
SL
1/* Areadable.c 1.1 86/07/20 */
2
3#include "../tahoealign/align.h"
4
5long readable(infop, address, length)
6process_info *infop;
7long 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}