extractedLnx/linux/arch/ia64/kernel/ptrace.c_access_uarea.c
static int
access_uarea (struct task_struct *child, unsigned long addr, unsigned long *data, int write_access)
{
unsigned long *ptr = NULL, *rbs, *bspstore, ndirty, regnum;
struct switch_stack *sw;
struct pt_regs *pt;
if ((addr & 0x7) != 0)
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_F9+16) {
/* accessing switch_stack or pt_regs: */
pt = ia64_task_regs(child);
sw = (struct switch_stack *) pt - 1;
switch (addr) {
case PT_NAT_BITS:
if (write_access)
ia64_put_nat_bits(pt, sw, *data);
else
*data = ia64_get_nat_bits(pt, sw);
return 0;
case PT_AR_BSP:
if (write_access)
/* FIXME? Account for lack of ``cover'' in the syscall case */
return sync_kernel_register_backing_store(child, *data, 1);
else {
rbs = (unsigned long *) child + IA64_RBS_OFFSET/8;
bspstore = (unsigned long *) pt->ar_bspstore;
ndirty = ia64_rse_num_regs(rbs, rbs + (pt->loadrs >> 19));
/*
* If we're in a system call, no ``cover'' was done. So to
* make things uniform, we'll add the appropriate displacement
* onto bsp if we're in a system call.
*/
if (!(pt->cr_ifs & (1UL << 63)))
ndirty += sw->ar_pfs & 0x7f;
*data = (unsigned long) ia64_rse_skip_regs(bspstore, ndirty);
return 0;
}
case PT_CFM:
if (write_access) {
if (pt->cr_ifs & (1UL << 63))
pt->cr_ifs = ((pt->cr_ifs & ~0x3fffffffffUL)
| (*data & 0x3fffffffffUL));
else
sw->ar_pfs = ((sw->ar_pfs & ~0x3fffffffffUL)
| (*data & 0x3fffffffffUL));
return 0;
} else {
if ((pt->cr_ifs & (1UL << 63)) == 0)
*data = sw->ar_pfs;
else
/* return only the CFM */
*data = pt->cr_ifs & 0x3fffffffffUL;
return 0;
}
case PT_CR_IPSR:
if (write_access)
pt->cr_ipsr = ((*data & IPSR_WRITE_MASK)
| (pt->cr_ipsr & ~IPSR_WRITE_MASK));
else
*data = (pt->cr_ipsr & IPSR_READ_MASK);
return 0;
case PT_AR_EC:
if (write_access)
sw->ar_pfs = (((*data & 0x3f) << 52)
| (sw->ar_pfs & ~(0x3fUL << 52)));
else
*data = (sw->ar_pfs >> 52) & 0x3f;
break;
case PT_R1: case PT_R2: case PT_R3:
case PT_R4: case PT_R5: case PT_R6: case PT_R7:
case PT_R8: case PT_R9: case PT_R10: case PT_R11:
case PT_R12: case PT_R13: case PT_R14: case PT_R15:
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:
case PT_B0: case PT_B1: case PT_B2: case PT_B3:
case PT_B4: case PT_B5: case PT_B6: case PT_B7:
case PT_F2: case PT_F2+8: case PT_F3: case PT_F3+8:
case PT_F4: case PT_F4+8: case PT_F5: case PT_F5+8:
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:
case PT_F10: case PT_F10+8: case PT_F11: case PT_F11+8:
case PT_F12: case PT_F12+8: case PT_F13: case PT_F13+8:
case PT_F14: case PT_F14+8: case PT_F15: case PT_F15+8:
case PT_F16: case PT_F16+8: case PT_F17: case PT_F17+8:
case PT_F18: case PT_F18+8: case PT_F19: case PT_F19+8:
case PT_F20: case PT_F20+8: case PT_F21: case PT_F21+8:
case PT_F22: case PT_F22+8: case PT_F23: case PT_F23+8:
case PT_F24: case PT_F24+8: case PT_F25: case PT_F25+8:
case PT_F26: case PT_F26+8: case PT_F27: case PT_F27+8:
case PT_F28: case PT_F28+8: case PT_F29: case PT_F29+8:
case PT_F30: case PT_F30+8: case PT_F31: case PT_F31+8:
case PT_AR_BSPSTORE:
case PT_AR_RSC: case PT_AR_UNAT: case PT_AR_PFS: case PT_AR_RNAT:
case PT_AR_CCV: case PT_AR_FPSR: case PT_CR_IIP: case PT_PR:
case PT_AR_LC:
ptr = (unsigned long *) ((long) sw + addr - PT_NAT_BITS);
break;
default:
/* disallow accessing anything else... */
return -1;
}
} else {
/* access debug registers */
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);
}
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)
return -1;
ptr += regnum;
if (write_access)
/* don't let the user set kernel-level breakpoints... */
*ptr = *data & ~(7UL << 56);
else
*data = *ptr;
return 0;
}
if (write_access)
*ptr = *data;
else
*data = *ptr;
return 0;
}
Generated by GNU enscript 1.6.4.