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