1 /* Areadable.c 1.2 90/12/04 */ 2 3 #include "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