Commit 6ee903e0 authored by David Mosberger's avatar David Mosberger

ia64: Fix ptrace() RNaT accessors.

parent d9e58912
......@@ -200,14 +200,20 @@ ia64_decrement_ip (struct pt_regs *regs)
*/
static unsigned long
get_rnat (struct pt_regs *pt, struct switch_stack *sw,
unsigned long *krbs, unsigned long *urnat_addr)
unsigned long *krbs, unsigned long *urnat_addr, unsigned long *urbs_end)
{
unsigned long rnat0 = 0, rnat1 = 0, urnat = 0, *slot0_kaddr, umask = 0UL;
unsigned long rnat0 = 0, rnat1 = 0, urnat = 0, *slot0_kaddr, umask = 0, mask, m;
unsigned long *kbsp, *ubspstore, *rnat0_kaddr, *rnat1_kaddr, shift;
long num_regs;
long num_regs, nbits;
kbsp = (unsigned long *) sw->ar_bspstore;
ubspstore = (unsigned long *) pt->ar_bspstore;
if (urbs_end < urnat_addr)
nbits = ia64_rse_num_regs(urnat_addr - 63, urbs_end);
else
nbits = 63;
mask = (1UL << nbits) - 1;
/*
* First, figure out which bit number slot 0 in user-land maps to in the kernel
* rnat. Do this by figuring out how many register slots we're beyond the user's
......@@ -221,20 +227,26 @@ get_rnat (struct pt_regs *pt, struct switch_stack *sw,
if (ubspstore + 63 > urnat_addr) {
/* some bits need to be merged in from pt->ar_rnat */
umask = ((1UL << ia64_rse_slot_num(ubspstore)) - 1);
umask = ((1UL << ia64_rse_slot_num(ubspstore)) - 1) & mask;
urnat = (pt->ar_rnat & umask);
mask &= ~umask;
if (!mask)
return urnat;
}
if (rnat0_kaddr >= kbsp) {
m = mask << shift;
if (rnat0_kaddr >= kbsp)
rnat0 = sw->ar_rnat;
} else if (rnat0_kaddr > krbs) {
else if (rnat0_kaddr > krbs)
rnat0 = *rnat0_kaddr;
}
if (rnat1_kaddr >= kbsp) {
urnat |= (rnat0 & m) >> shift;
m = mask >> (63 - shift);
if (rnat1_kaddr >= kbsp)
rnat1 = sw->ar_rnat;
} else if (rnat1_kaddr > krbs) {
else if (rnat1_kaddr > krbs)
rnat1 = *rnat1_kaddr;
}
urnat |= ((rnat1 << (63 - shift)) | (rnat0 >> shift)) & ~umask;
urnat |= (rnat1 & m) << (63 - shift);
return urnat;
}
......@@ -243,60 +255,58 @@ get_rnat (struct pt_regs *pt, struct switch_stack *sw,
*/
static void
put_rnat (struct pt_regs *pt, struct switch_stack *sw,
unsigned long *krbs, unsigned long *urnat_addr, unsigned long urnat)
unsigned long *krbs, unsigned long *urnat_addr, unsigned long urnat,
unsigned long *urbs_end)
{
unsigned long rnat0 = 0, rnat1 = 0, *slot0_kaddr, umask = 0, mask, m;
unsigned long *kbsp, *ubspstore, *rnat0_kaddr, *rnat1_kaddr, shift, slot, ndirty;
unsigned long *kbsp, *ubspstore, *rnat0_kaddr, *rnat1_kaddr, shift;
long num_regs, nbits;
ndirty = ia64_rse_num_regs(krbs, krbs + (pt->loadrs >> 19));
nbits = ndirty % 63;
kbsp = (unsigned long *) sw->ar_bspstore;
ubspstore = (unsigned long *) pt->ar_bspstore;
if (urbs_end < urnat_addr)
nbits = ia64_rse_num_regs(urnat_addr - 63, urbs_end);
else
nbits = 63;
mask = (1UL << nbits) - 1;
/*
* First, figure out which bit number slot 0 in user-land maps to in the kernel
* rnat. Do this by figuring out how many register slots we're beyond the user's
* backingstore and then computing the equivalent address in kernel space.
*/
num_regs = (long) ia64_rse_num_regs(ubspstore, urnat_addr + 1);
num_regs = ia64_rse_num_regs(ubspstore, urnat_addr + 1);
slot0_kaddr = ia64_rse_skip_regs(krbs, num_regs);
shift = ia64_rse_slot_num(slot0_kaddr);
rnat1_kaddr = ia64_rse_rnat_addr(slot0_kaddr);
rnat0_kaddr = rnat1_kaddr - 64;
printk("%s: ubspstore=%p urnat_addr=%p\n", __FUNCTION__, ubspstore, urnat_addr);
if (ubspstore + 63 > urnat_addr) {
/* some bits need to be place in pt->ar_rnat: */
slot = ia64_rse_slot_num(ubspstore);
umask = ((1UL << slot) - 1);
umask = ((1UL << ia64_rse_slot_num(ubspstore)) - 1) & mask;
pt->ar_rnat = (pt->ar_rnat & ~umask) | (urnat & umask);
nbits -= slot;
if (nbits <= 0)
mask &= ~umask;
if (!mask)
return;
}
mask = (1UL << nbits) - 1;
/*
* Note: Section 11.1 of the EAS guarantees that bit 63 of an
* rnat slot is ignored. so we don't have to clear it here.
*/
rnat0 = (urnat << shift);
m = mask << shift;
printk("%s: rnat0=%016lx, m=%016lx, rnat0_kaddr=%p kbsp=%p\n", __FUNCTION__, rnat0, m, rnat0_kaddr, kbsp);
if (rnat0_kaddr >= kbsp) {
if (rnat0_kaddr >= kbsp)
sw->ar_rnat = (sw->ar_rnat & ~m) | (rnat0 & m);
} else if (rnat0_kaddr > krbs) {
else if (rnat0_kaddr > krbs)
*rnat0_kaddr = ((*rnat0_kaddr & ~m) | (rnat0 & m));
}
rnat1 = (urnat >> (63 - shift));
m = mask >> (63 - shift);
printk("%s: rnat1=%016lx, m=%016lx, rnat1_kaddr=%p kbsp=%p\n", __FUNCTION__, rnat1, m, rnat1_kaddr, kbsp);
if (rnat1_kaddr >= kbsp) {
if (rnat1_kaddr >= kbsp)
sw->ar_rnat = (sw->ar_rnat & ~m) | (rnat1 & m);
} else if (rnat1_kaddr > krbs) {
else if (rnat1_kaddr > krbs)
*rnat1_kaddr = ((*rnat1_kaddr & ~m) | (rnat1 & m));
}
}
/*
......@@ -329,7 +339,7 @@ ia64_peek (struct task_struct *child, struct switch_stack *child_stack, unsigned
* read the corresponding bits in the kernel RBS.
*/
rnat_addr = ia64_rse_rnat_addr(laddr);
ret = get_rnat(child_regs, child_stack, krbs, rnat_addr);
ret = get_rnat(child_regs, child_stack, krbs, rnat_addr, urbs_end);
if (laddr == rnat_addr) {
/* return NaT collection word itself */
......@@ -380,7 +390,7 @@ ia64_poke (struct task_struct *child, struct switch_stack *child_stack, unsigned
* => write the corresponding bits in the kernel RBS.
*/
if (ia64_rse_is_rnat_slot(laddr))
put_rnat(child_regs, child_stack, krbs, laddr, val);
put_rnat(child_regs, child_stack, krbs, laddr, val, urbs_end);
else {
if (laddr < urbs_end) {
regnum = ia64_rse_num_regs(bspstore, laddr);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment