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) ...@@ -200,14 +200,20 @@ ia64_decrement_ip (struct pt_regs *regs)
*/ */
static unsigned long static unsigned long
get_rnat (struct pt_regs *pt, struct switch_stack *sw, 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; unsigned long *kbsp, *ubspstore, *rnat0_kaddr, *rnat1_kaddr, shift;
long num_regs; long num_regs, nbits;
kbsp = (unsigned long *) sw->ar_bspstore; kbsp = (unsigned long *) sw->ar_bspstore;
ubspstore = (unsigned long *) pt->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 * 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 * 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, ...@@ -221,20 +227,26 @@ get_rnat (struct pt_regs *pt, struct switch_stack *sw,
if (ubspstore + 63 > urnat_addr) { if (ubspstore + 63 > urnat_addr) {
/* some bits need to be merged in from pt->ar_rnat */ /* 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); 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; rnat0 = sw->ar_rnat;
} else if (rnat0_kaddr > krbs) { else if (rnat0_kaddr > krbs)
rnat0 = *rnat0_kaddr; rnat0 = *rnat0_kaddr;
} urnat |= (rnat0 & m) >> shift;
if (rnat1_kaddr >= kbsp) {
m = mask >> (63 - shift);
if (rnat1_kaddr >= kbsp)
rnat1 = sw->ar_rnat; rnat1 = sw->ar_rnat;
} else if (rnat1_kaddr > krbs) { else if (rnat1_kaddr > krbs)
rnat1 = *rnat1_kaddr; rnat1 = *rnat1_kaddr;
} urnat |= (rnat1 & m) << (63 - shift);
urnat |= ((rnat1 << (63 - shift)) | (rnat0 >> shift)) & ~umask;
return urnat; return urnat;
} }
...@@ -243,60 +255,58 @@ get_rnat (struct pt_regs *pt, struct switch_stack *sw, ...@@ -243,60 +255,58 @@ get_rnat (struct pt_regs *pt, struct switch_stack *sw,
*/ */
static void static void
put_rnat (struct pt_regs *pt, struct switch_stack *sw, 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 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; long num_regs, nbits;
ndirty = ia64_rse_num_regs(krbs, krbs + (pt->loadrs >> 19));
nbits = ndirty % 63;
kbsp = (unsigned long *) sw->ar_bspstore; kbsp = (unsigned long *) sw->ar_bspstore;
ubspstore = (unsigned long *) pt->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 * 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 * 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. * 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); slot0_kaddr = ia64_rse_skip_regs(krbs, num_regs);
shift = ia64_rse_slot_num(slot0_kaddr); shift = ia64_rse_slot_num(slot0_kaddr);
rnat1_kaddr = ia64_rse_rnat_addr(slot0_kaddr); rnat1_kaddr = ia64_rse_rnat_addr(slot0_kaddr);
rnat0_kaddr = rnat1_kaddr - 64; rnat0_kaddr = rnat1_kaddr - 64;
printk("%s: ubspstore=%p urnat_addr=%p\n", __FUNCTION__, ubspstore, urnat_addr);
if (ubspstore + 63 > urnat_addr) { if (ubspstore + 63 > urnat_addr) {
/* some bits need to be place in pt->ar_rnat: */ /* some bits need to be place in pt->ar_rnat: */
slot = ia64_rse_slot_num(ubspstore); umask = ((1UL << ia64_rse_slot_num(ubspstore)) - 1) & mask;
umask = ((1UL << slot) - 1);
pt->ar_rnat = (pt->ar_rnat & ~umask) | (urnat & umask); pt->ar_rnat = (pt->ar_rnat & ~umask) | (urnat & umask);
nbits -= slot; mask &= ~umask;
if (nbits <= 0) if (!mask)
return; return;
} }
mask = (1UL << nbits) - 1;
/* /*
* Note: Section 11.1 of the EAS guarantees that bit 63 of an * 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. * rnat slot is ignored. so we don't have to clear it here.
*/ */
rnat0 = (urnat << shift); rnat0 = (urnat << shift);
m = mask << 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); 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)); *rnat0_kaddr = ((*rnat0_kaddr & ~m) | (rnat0 & m));
}
rnat1 = (urnat >> (63 - shift)); rnat1 = (urnat >> (63 - shift));
m = mask >> (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); 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)); *rnat1_kaddr = ((*rnat1_kaddr & ~m) | (rnat1 & m));
}
} }
/* /*
...@@ -329,7 +339,7 @@ ia64_peek (struct task_struct *child, struct switch_stack *child_stack, unsigned ...@@ -329,7 +339,7 @@ ia64_peek (struct task_struct *child, struct switch_stack *child_stack, unsigned
* read the corresponding bits in the kernel RBS. * read the corresponding bits in the kernel RBS.
*/ */
rnat_addr = ia64_rse_rnat_addr(laddr); 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) { if (laddr == rnat_addr) {
/* return NaT collection word itself */ /* return NaT collection word itself */
...@@ -380,7 +390,7 @@ ia64_poke (struct task_struct *child, struct switch_stack *child_stack, unsigned ...@@ -380,7 +390,7 @@ ia64_poke (struct task_struct *child, struct switch_stack *child_stack, unsigned
* => write the corresponding bits in the kernel RBS. * => write the corresponding bits in the kernel RBS.
*/ */
if (ia64_rse_is_rnat_slot(laddr)) 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 { else {
if (laddr < urbs_end) { if (laddr < urbs_end) {
regnum = ia64_rse_num_regs(bspstore, laddr); 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