break; case PT_AR_RSC: ptr = pt_reg_addr(pt, ar_rsc); 
access_uarea (struct task_struct *child, unsigned long addr,	      unsigned long *data, int write_access){	unsigned long *ptr, regnum, urbs_end, rnat_addr, cfm;	struct switch_stack *sw;	struct pt_regs *pt;#	define pt_reg_addr(pt, reg)	((void *)			    \					 ((unsigned long) (pt)		    \					  + offsetof(struct pt_regs, reg)))	pt = ia64_task_regs(child);	sw = (struct switch_stack *) (child->thread.ksp + 16);	if ((addr & 0x7) != 0) {		dprintk("ptrace: unaligned register address 0x%lx\n", addr);		return -1;	}	if (addr < PT_F127 + 16) {		/* accessing fph */		if (write_access)			ia64_sync_fph(child);		else			ia64_flush_fph(child);		ptr = (unsigned long *)			((unsigned long) &child->thread.fph + addr);	} else if ((addr >= PT_F10) && (addr < PT_F11 + 16)) {		/* scratch registers untouched by kernel (saved in pt_regs) */		ptr = pt_reg_addr(pt, f10) + (addr - PT_F10);	} else if (addr >= PT_F12 && addr < PT_F15 + 16) {		/*		 * Scratch registers untouched by kernel (saved in		 * switch_stack).		 */		ptr = (unsigned long *) ((long) sw					 + (addr - PT_NAT_BITS - 32));	} else if (addr < PT_AR_LC + 8) {		/* preserved state: */		struct unw_frame_info info;		char nat = 0;		int ret;		unw_init_from_blocked_task(&info, child);		if (unw_unwind_to_user(&info) < 0)			return -1;		switch (addr) {		      case PT_NAT_BITS:			return access_nat_bits(child, pt, &info,					       data, write_access);		      case PT_R4: case PT_R5: case PT_R6: case PT_R7:			if (write_access) {				/* read NaT bit first: */				unsigned long dummy;				ret = unw_get_gr(&info, (addr - PT_R4)/8 + 4,						 &dummy, &nat);				if (ret < 0)					return ret;			}			return unw_access_gr(&info, (addr - PT_R4)/8 + 4, data,					     &nat, write_access);		      case PT_B1: case PT_B2: case PT_B3:		      case PT_B4: case PT_B5:			return unw_access_br(&info, (addr - PT_B1)/8 + 1, data,					     write_access);		      case PT_AR_EC:			return unw_access_ar(&info, UNW_AR_EC, data,					     write_access);		      case PT_AR_LC:			return unw_access_ar(&info, UNW_AR_LC, data,					     write_access);		      default:			if (addr >= PT_F2 && addr < PT_F5 + 16)				return access_fr(&info, (addr - PT_F2)/16 + 2,						 (addr & 8) != 0, data,						 write_access);			else if (addr >= PT_F16 && addr < PT_F31 + 16)				return access_fr(&info,						 (addr - PT_F16)/16 + 16,						 (addr & 8) != 0,						 data, write_access);			else {				dprintk("ptrace: rejecting access to register "					"address 0x%lx\n", addr);				return -1;			}		}	} else if (addr < PT_F9+16) {		/* scratch state */		switch (addr) {		      case PT_AR_BSP:			/*			 * By convention, we use PT_AR_BSP to refer to			 * the end of the user-level backing store.			 * Use ia64_rse_skip_regs(PT_AR_BSP, -CFM.sof)			 * to get the real value of ar.bsp at the time			 * the kernel was entered.			 *			 * Furthermore, when changing the contents of			 * PT_AR_BSP (or PT_CFM) we MUST copy any			 * users-level stacked registers that are			 * stored on the kernel stack back to			 * user-space because otherwise, we might end			 * up clobbering kernel stacked registers.			 * Also, if this happens while the task is			 * blocked in a system call, which convert the			 * state such that the non-system-call exit			 * path is used.  This ensures that the proper			 * state will be picked up when resuming			 * execution.  However, it *also* means that			 * once we write PT_AR_BSP/PT_CFM, it won't be			 * possible to modify the syscall arguments of			 * the pending system call any longer.  This			 * shouldn't be an issue because modifying			 * PT_AR_BSP/PT_CFM generally implies that			 * we're either abandoning the pending system			 * call or that we defer it's re-execution			 * (e.g., due to GDB doing an inferior			 * function call).			 */			urbs_end = ia64_get_user_rbs_end(child, pt, &cfm);			if (write_access) {				if (*data != urbs_end) {					if (ia64_sync_user_rbs(child, sw,							       pt->ar_bspstore,							       urbs_end) < 0)						return -1;					if (in_syscall(pt))						convert_to_non_syscall(child,								       pt,								       cfm);					/*					 * Simulate user-level write					 * of ar.bsp:					 */					pt->loadrs = 0;					pt->ar_bspstore = *data;				}			} else				*data = urbs_end;			return 0;		      case PT_CFM:			urbs_end = ia64_get_user_rbs_end(child, pt, &cfm);			if (write_access) {				if (((cfm ^ *data) & PFM_MASK) != 0) {					if (ia64_sync_user_rbs(child, sw,							       pt->ar_bspstore,							       urbs_end) < 0)						return -1;					if (in_syscall(pt))						convert_to_non_syscall(child,								       pt,								       cfm);					pt->cr_ifs = ((pt->cr_ifs & ~PFM_MASK)						      | (*data & PFM_MASK));				}			} else				*data = cfm;			return 0;		      case PT_CR_IPSR:			if (write_access)				pt->cr_ipsr = ((*data & IPSR_MASK)					       | (pt->cr_ipsr & ~IPSR_MASK));			else				*data = (pt->cr_ipsr & IPSR_MASK);			return 0;		      case PT_AR_RNAT:			urbs_end = ia64_get_user_rbs_end(child, pt, NULL);			rnat_addr = (long) ia64_rse_rnat_addr((long *)							      urbs_end);			if (write_access)				return ia64_poke(child, sw, urbs_end,						 rnat_addr, *data);			else				return ia64_peek(child, sw, urbs_end,						 rnat_addr, data);		      case PT_R1:			ptr = pt_reg_addr(pt, r1);			break;		      case PT_R2:  case PT_R3:			ptr = pt_reg_addr(pt, r2) + (addr - PT_R2);			break;		      case PT_R8:  case PT_R9:  case PT_R10: case PT_R11:			ptr = pt_reg_addr(pt, r8) + (addr - PT_R8);			break;		      case PT_R12: case PT_R13:			ptr = pt_reg_addr(pt, r12) + (addr - PT_R12);			break;		      case PT_R14:			ptr = pt_reg_addr(pt, r14);			break;		      case PT_R15:			ptr = pt_reg_addr(pt, r15);			break;		      case PT_R16: case PT_R17: case PT_R18: case PT_R19:		      case PT_R20: case PT_R21: case PT_R22: case PT_R23:		      case PT_R24: case PT_R25: case PT_R26: case PT_R27:		      case PT_R28: case PT_R29: case PT_R30: case PT_R31:			ptr = pt_reg_addr(pt, r16) + (addr - PT_R16);			break;		      case PT_B0:			ptr = pt_reg_addr(pt, b0);			break;		      case PT_B6:			ptr = pt_reg_addr(pt, b6);			break;		      case PT_B7:			ptr = pt_reg_addr(pt, b7);			break;		      case PT_F6:  case PT_F6+8: case PT_F7: case PT_F7+8:		      case PT_F8:  case PT_F8+8: case PT_F9: case PT_F9+8:			ptr = pt_reg_addr(pt, f6) + (addr - PT_F6);			break;		      case PT_AR_BSPSTORE:			ptr = pt_reg_addr(pt, ar_bspstore);			break;		      case PT_AR_RSC:			ptr = pt_reg_addr(pt, ar_rsc);			break;		      case PT_AR_UNAT:			ptr = pt_reg_addr(pt, ar_unat);			break;		      case PT_AR_PFS:			ptr = pt_reg_addr(pt, ar_pfs);			break;		      case PT_AR_CCV:			ptr = pt_reg_addr(pt, ar_ccv);			break;		      case PT_AR_FPSR:			ptr = pt_reg_addr(pt, ar_fpsr);			break;		      case PT_CR_IIP:			ptr = pt_reg_addr(pt, cr_iip);			break;		      case PT_PR:			ptr = pt_reg_addr(pt, pr);			break;			/* scratch register */		      default:			/* disallow accessing anything else... */			dprintk("ptrace: rejecting access to register "				"address 0x%lx\n", addr);			return -1;		}	} else if (addr <= PT_AR_SSD) {		ptr = pt_reg_addr(pt, ar_csd) + (addr - PT_AR_CSD);	} else {		/* access debug registers */		if (addr >= PT_IBR) {			regnum = (addr - PT_IBR) >> 3;			ptr = &child->thread.ibr[0];		} else {			regnum = (addr - PT_DBR) >> 3;			ptr = &child->thread.dbr[0];		}		if (regnum >= 8) {			dprintk("ptrace: rejecting access to register "				"address 0x%lx\n", addr);			return -1;		}#ifdef CONFIG_PERFMON		/*		 * Check if debug registers are used by perfmon. This		 * test must be done once we know that we can do the		 * operation, i.e. the arguments are all valid, but		 * before we start modifying the state.		 *		 * Perfmon needs to keep a count of how many processes		 * are trying to modify the debug registers for system		 * wide monitoring sessions.		 *		 * We also include read access here, because they may		 * cause the PMU-installed debug register state		 * (dbr[], ibr[]) to be reset. The two arrays are also		 * used by perfmon, but we do not use		 * IA64_THREAD_DBG_VALID. The registers are restored		 * by the PMU context switch code.		 */		if (pfm_use_debug_registers(child)) return -1;#endif		if (!(child->thread.flags & IA64_THREAD_DBG_VALID)) {			child->thread.flags |= IA64_THREAD_DBG_VALID;			memset(child->thread.dbr, 0,			       sizeof(child->thread.dbr));			memset(child->thread.ibr, 0,			       sizeof(child->thread.ibr));		}		ptr += regnum;		if ((regnum & 1) && write_access) {			/* don't let the user set kernel-level breakpoints: */			*ptr = *data & ~(7UL << 56);			return 0;		}	}	if (write_access)		*ptr = *data;	else		*data = *ptr;	return 0;}
4520	/local/tlutelli/issta_data/temp/c/2005_temp/2005/4520/4ea78729b8dbfc400fe165a57b90a394a7275a54/ptrace.c/clean/arch/ia64/kernel/ptrace.c