Commit c9b85512 authored by David Mosberger's avatar David Mosberger

ia64: Add support to the kernel unwinder for the ".save rp, r0" idiom.

Based on patch by Keith Owens.
parent 69aeca90
......@@ -56,8 +56,7 @@ halt_msg:
GLOBAL_ENTRY(_start)
start_ap:
.prologue
.save rp, r4 // terminate unwind chain with a NULL rp
mov r4=r0
.save rp, r0 // terminate unwind chain with a NULL rp
.body
rsm psr.i | psr.ic
......@@ -818,8 +817,7 @@ END(ia64_delay_loop)
GLOBAL_ENTRY(start_kernel_thread)
.prologue
.save rp, r4 // this is the end of the call-chain
mov r4=r0
.save rp, r0 // this is the end of the call-chain
.body
alloc r2 = ar.pfs, 0, 0, 2, 0
mov out0 = r9
......
......@@ -89,6 +89,8 @@ static struct {
/* list of unwind tables (one per load-module) */
struct unw_table *tables;
unsigned long r0; /* constant 0 for r0 */
/* table of registers that prologues can save (and order in which they're saved): */
const unsigned char save_order[8];
......@@ -239,7 +241,11 @@ static struct {
#endif
};
/* Unwind accessors. */
static inline int
read_only (unsigned long *addr)
{
return (addr == &unw.r0);
}
/*
* Returns offset of rREG in struct pt_regs.
......@@ -274,6 +280,8 @@ get_scratch_regs (struct unw_frame_info *info)
return (struct pt_regs *) info->pt;
}
/* Unwind accessors. */
int
unw_access_gr (struct unw_frame_info *info, int regnum, unsigned long *val, char *nat, int write)
{
......@@ -377,11 +385,15 @@ unw_access_gr (struct unw_frame_info *info, int regnum, unsigned long *val, char
}
if (write) {
*addr = *val;
if (*nat)
*nat_addr |= nat_mask;
else
*nat_addr &= ~nat_mask;
if (read_only(addr))
UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n");
else {
*addr = *val;
if (*nat)
*nat_addr |= nat_mask;
else
*nat_addr &= ~nat_mask;
}
} else {
if ((*nat_addr & nat_mask) == 0) {
*val = *addr;
......@@ -420,7 +432,10 @@ unw_access_br (struct unw_frame_info *info, int regnum, unsigned long *val, int
return -1;
}
if (write)
*addr = *val;
if (read_only(addr))
UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n");
else
*addr = *val;
else
*val = *addr;
return 0;
......@@ -465,7 +480,10 @@ unw_access_fr (struct unw_frame_info *info, int regnum, struct ia64_fpreg *val,
}
if (write)
*addr = *val;
if (read_only(addr))
UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n");
else
*addr = *val;
else
*val = *addr;
return 0;
......@@ -557,9 +575,12 @@ unw_access_ar (struct unw_frame_info *info, int regnum, unsigned long *val, int
return -1;
}
if (write)
*addr = *val;
else
if (write) {
if (read_only(addr))
UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n");
else
*addr = *val;
} else
*val = *addr;
return 0;
}
......@@ -574,9 +595,12 @@ unw_access_pr (struct unw_frame_info *info, unsigned long *val, int write)
if (!addr)
addr = &info->sw->pr;
if (write)
*addr = *val;
else
if (write) {
if (read_only(addr))
UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n");
else
*addr = *val;
} else
*val = *addr;
return 0;
}
......@@ -1407,6 +1431,9 @@ compile_reg (struct unw_state_record *sr, int i, struct unw_script *script)
need_nat_info = 0;
}
val = unw.preg_index[UNW_REG_R4 + (rval - 4)];
} else if (rval == 0) {
opc = UNW_INSN_MOVE_CONST;
val = 0;
} else {
/* register got spilled to a scratch register */
opc = UNW_INSN_MOVE_SCRATCH;
......@@ -1729,6 +1756,17 @@ run_script (struct unw_script *script, struct unw_frame_info *state)
}
break;
case UNW_INSN_MOVE_CONST:
if (val == 0)
s[dst] = (unsigned long) &unw.r0;
else {
s[dst] = 0;
UNW_DPRINT(0, "unwind.%s: UNW_INSN_MOVE_CONST bad val=%ld\n",
__FUNCTION__, val);
}
break;
case UNW_INSN_MOVE_STACKED:
s[dst] = (unsigned long) ia64_rse_skip_regs((unsigned long *)state->bsp,
val);
......
......@@ -133,6 +133,7 @@ enum unw_insn_opcode {
UNW_INSN_SETNAT_TYPE, /* s[dst+1].nat.type = val */
UNW_INSN_LOAD, /* s[dst] = *s[val] */
UNW_INSN_MOVE_SCRATCH, /* s[dst] = scratch reg "val" */
UNW_INSN_MOVE_CONST, /* s[dst] = constant reg "val" */
};
struct unw_insn {
......
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