Commit 4ff8a356 authored by Al Viro's avatar Al Viro

ia64: switch to ->regset_get()

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 5a806e0a
...@@ -1489,9 +1489,17 @@ access_elf_reg(struct task_struct *target, struct unw_frame_info *info, ...@@ -1489,9 +1489,17 @@ access_elf_reg(struct task_struct *target, struct unw_frame_info *info,
return access_elf_areg(target, info, addr, data, write_access); return access_elf_areg(target, info, addr, data, write_access);
} }
struct regset_membuf {
struct membuf to;
int ret;
};
void do_gpregs_get(struct unw_frame_info *info, void *arg) void do_gpregs_get(struct unw_frame_info *info, void *arg)
{ {
struct regset_getset *dst = arg; struct regset_membuf *dst = arg;
struct membuf to = dst->to;
unsigned int n;
elf_greg_t reg;
if (unw_unwind_to_user(info) < 0) if (unw_unwind_to_user(info) < 0)
return; return;
...@@ -1509,35 +1517,13 @@ void do_gpregs_get(struct unw_frame_info *info, void *arg) ...@@ -1509,35 +1517,13 @@ void do_gpregs_get(struct unw_frame_info *info, void *arg)
/* Skip r0 */ /* Skip r0 */
if (dst->count > 0 && dst->pos < ELF_GR_OFFSET(1)) { membuf_zero(&to, 8);
dst->ret = user_regset_copyout_zero(&dst->pos, &dst->count, for (n = 8; to.left && n < ELF_AR_END_OFFSET; n += 8) {
&dst->u.get.kbuf, if (access_elf_reg(info->task, info, n, &reg, 0) < 0) {
&dst->u.get.ubuf, dst->ret = -EIO;
0, ELF_GR_OFFSET(1));
if (dst->ret)
return; return;
}
while (dst->count && dst->pos < ELF_AR_END_OFFSET) {
unsigned int n, from, to;
elf_greg_t tmp[16];
from = dst->pos;
to = from + min(dst->count, (unsigned)sizeof(tmp));
if (to > ELF_AR_END_OFFSET)
to = ELF_AR_END_OFFSET;
for (n = 0; from < to; from += sizeof(elf_greg_t), n++) {
if (access_elf_reg(dst->target, info, from,
&tmp[n], 0) < 0) {
dst->ret = -EIO;
return;
}
} }
dst->ret = user_regset_copyout(&dst->pos, &dst->count, membuf_store(&to, reg);
&dst->u.get.kbuf, &dst->u.get.ubuf, tmp,
dst->pos, to);
if (dst->ret)
return;
} }
} }
...@@ -1588,60 +1574,36 @@ void do_gpregs_set(struct unw_frame_info *info, void *arg) ...@@ -1588,60 +1574,36 @@ void do_gpregs_set(struct unw_frame_info *info, void *arg)
void do_fpregs_get(struct unw_frame_info *info, void *arg) void do_fpregs_get(struct unw_frame_info *info, void *arg)
{ {
struct regset_getset *dst = arg; struct task_struct *task = info->task;
struct task_struct *task = dst->target; struct regset_membuf *dst = arg;
elf_fpreg_t tmp[30]; struct membuf to = dst->to;
int index, min_copy, i; elf_fpreg_t reg;
unsigned int n;
if (unw_unwind_to_user(info) < 0) if (unw_unwind_to_user(info) < 0)
return; return;
/* Skip pos 0 and 1 */ /* Skip pos 0 and 1 */
if (dst->count > 0 && dst->pos < ELF_FP_OFFSET(2)) { membuf_zero(&to, 2 * sizeof(elf_fpreg_t));
dst->ret = user_regset_copyout_zero(&dst->pos, &dst->count,
&dst->u.get.kbuf,
&dst->u.get.ubuf,
0, ELF_FP_OFFSET(2));
if (dst->count == 0 || dst->ret)
return;
}
/* fr2-fr31 */ /* fr2-fr31 */
if (dst->count > 0 && dst->pos < ELF_FP_OFFSET(32)) { for (n = 2; to.left && n < 32; n++) {
index = (dst->pos - ELF_FP_OFFSET(2)) / sizeof(elf_fpreg_t); if (unw_get_fr(info, n, &reg)) {
dst->ret = -EIO;
min_copy = min(((unsigned int)ELF_FP_OFFSET(32)),
dst->pos + dst->count);
for (i = dst->pos; i < min_copy; i += sizeof(elf_fpreg_t),
index++)
if (unw_get_fr(info, i / sizeof(elf_fpreg_t),
&tmp[index])) {
dst->ret = -EIO;
return;
}
dst->ret = user_regset_copyout(&dst->pos, &dst->count,
&dst->u.get.kbuf, &dst->u.get.ubuf, tmp,
ELF_FP_OFFSET(2), ELF_FP_OFFSET(32));
if (dst->count == 0 || dst->ret)
return; return;
}
membuf_write(&to, &reg, sizeof(reg));
} }
/* fph */ /* fph */
if (dst->count > 0) { if (!to.left)
ia64_flush_fph(dst->target); return;
if (task->thread.flags & IA64_THREAD_FPH_VALID)
dst->ret = user_regset_copyout( ia64_flush_fph(task);
&dst->pos, &dst->count, if (task->thread.flags & IA64_THREAD_FPH_VALID)
&dst->u.get.kbuf, &dst->u.get.ubuf, membuf_write(&to, &task->thread.fph, 96 * sizeof(reg));
&dst->target->thread.fph, else
ELF_FP_OFFSET(32), -1); membuf_zero(&to, 96 * sizeof(reg));
else
/* Zero fill instead. */
dst->ret = user_regset_copyout_zero(
&dst->pos, &dst->count,
&dst->u.get.kbuf, &dst->u.get.ubuf,
ELF_FP_OFFSET(32), -1);
}
} }
void do_fpregs_set(struct unw_frame_info *info, void *arg) void do_fpregs_set(struct unw_frame_info *info, void *arg)
...@@ -1717,6 +1679,20 @@ void do_fpregs_set(struct unw_frame_info *info, void *arg) ...@@ -1717,6 +1679,20 @@ void do_fpregs_set(struct unw_frame_info *info, void *arg)
} }
} }
static void
unwind_and_call(void (*call)(struct unw_frame_info *, void *),
struct task_struct *target, void *data)
{
if (target == current)
unw_init_running(call, data);
else {
struct unw_frame_info info;
memset(&info, 0, sizeof(info));
unw_init_from_blocked_task(&info, target);
(*call)(&info, data);
}
}
static int static int
do_regset_call(void (*call)(struct unw_frame_info *, void *), do_regset_call(void (*call)(struct unw_frame_info *, void *),
struct task_struct *target, struct task_struct *target,
...@@ -1728,27 +1704,18 @@ do_regset_call(void (*call)(struct unw_frame_info *, void *), ...@@ -1728,27 +1704,18 @@ do_regset_call(void (*call)(struct unw_frame_info *, void *),
.pos = pos, .count = count, .pos = pos, .count = count,
.u.set = { .kbuf = kbuf, .ubuf = ubuf }, .u.set = { .kbuf = kbuf, .ubuf = ubuf },
.ret = 0 }; .ret = 0 };
unwind_and_call(call, target, &info);
if (target == current)
unw_init_running(call, &info);
else {
struct unw_frame_info ufi;
memset(&ufi, 0, sizeof(ufi));
unw_init_from_blocked_task(&ufi, target);
(*call)(&ufi, &info);
}
return info.ret; return info.ret;
} }
static int static int
gpregs_get(struct task_struct *target, gpregs_get(struct task_struct *target,
const struct user_regset *regset, const struct user_regset *regset,
unsigned int pos, unsigned int count, struct membuf to)
void *kbuf, void __user *ubuf)
{ {
return do_regset_call(do_gpregs_get, target, regset, pos, count, struct regset_membuf info = {.to = to};
kbuf, ubuf); unwind_and_call(do_gpregs_get, target, &info);
return info.ret;
} }
static int gpregs_set(struct task_struct *target, static int gpregs_set(struct task_struct *target,
...@@ -1790,11 +1757,11 @@ fpregs_active(struct task_struct *target, const struct user_regset *regset) ...@@ -1790,11 +1757,11 @@ fpregs_active(struct task_struct *target, const struct user_regset *regset)
static int fpregs_get(struct task_struct *target, static int fpregs_get(struct task_struct *target,
const struct user_regset *regset, const struct user_regset *regset,
unsigned int pos, unsigned int count, struct membuf to)
void *kbuf, void __user *ubuf)
{ {
return do_regset_call(do_fpregs_get, target, regset, pos, count, struct regset_membuf info = {.to = to};
kbuf, ubuf); unwind_and_call(do_fpregs_get, target, &info);
return info.ret;
} }
static int fpregs_set(struct task_struct *target, static int fpregs_set(struct task_struct *target,
...@@ -2033,14 +2000,14 @@ static const struct user_regset native_regsets[] = { ...@@ -2033,14 +2000,14 @@ static const struct user_regset native_regsets[] = {
.core_note_type = NT_PRSTATUS, .core_note_type = NT_PRSTATUS,
.n = ELF_NGREG, .n = ELF_NGREG,
.size = sizeof(elf_greg_t), .align = sizeof(elf_greg_t), .size = sizeof(elf_greg_t), .align = sizeof(elf_greg_t),
.get = gpregs_get, .set = gpregs_set, .regset_get = gpregs_get, .set = gpregs_set,
.writeback = gpregs_writeback .writeback = gpregs_writeback
}, },
{ {
.core_note_type = NT_PRFPREG, .core_note_type = NT_PRFPREG,
.n = ELF_NFPREG, .n = ELF_NFPREG,
.size = sizeof(elf_fpreg_t), .align = sizeof(elf_fpreg_t), .size = sizeof(elf_fpreg_t), .align = sizeof(elf_fpreg_t),
.get = fpregs_get, .set = fpregs_set, .active = fpregs_active .regset_get = fpregs_get, .set = fpregs_set, .active = fpregs_active
}, },
}; };
......
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