Commit | Line | Data |
---|---|---|
344ce65a SL |
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 | } |