File: [Development] / linux-2.6-xfs / arch / um / kernel / Attic / frame_kern.c (download)
Revision 1.2, Fri Oct 1 15:10:15 2004 UTC (13 years ago) by nathans.longdrop.melbourne.sgi.com
Branch: MAIN
Changes since 1.1: +4 -2
lines
Upgrade kernel to 2.6.9-rc3 and kdb to 4.4
Merge of 2.6.x-xfs-melb:linux:19628a by kenmcd.
|
/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#include "asm/ptrace.h"
#include "asm/uaccess.h"
#include "asm/signal.h"
#include "asm/ucontext.h"
#include "frame_kern.h"
#include "sigcontext.h"
#include "sysdep/ptrace.h"
#include "choose-mode.h"
#include "mode.h"
static int copy_restorer(void (*restorer)(void), unsigned long start,
unsigned long sr_index, int sr_relative)
{
unsigned long sr;
if(sr_relative){
sr = (unsigned long) restorer;
sr += start + sr_index;
restorer = (void (*)(void)) sr;
}
return(copy_to_user((void *) (start + sr_index), &restorer,
sizeof(restorer)));
}
extern int userspace_pid[];
static int copy_sc_to_user(void *to, void *fp, struct pt_regs *from,
struct arch_frame_data *arch)
{
return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs),
arch),
copy_sc_to_user_skas(userspace_pid[0], to, fp,
&from->regs,
current->thread.cr2,
current->thread.err)));
}
static int copy_ucontext_to_user(struct ucontext *uc, void *fp, sigset_t *set,
unsigned long sp)
{
int err = 0;
err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp);
err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags);
err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size);
err |= copy_sc_to_user(&uc->uc_mcontext, fp, ¤t->thread.regs,
&signal_frame_si.common.arch);
err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set));
return(err);
}
int setup_signal_stack_si(unsigned long stack_top, int sig,
unsigned long handler, void (*restorer)(void),
struct pt_regs *regs, siginfo_t *info,
sigset_t *mask)
{
unsigned long start;
void *sip, *ucp, *fp;
start = stack_top - signal_frame_si.common.len;
sip = (void *) (start + signal_frame_si.si_index);
ucp = (void *) (start + signal_frame_si.uc_index);
fp = (void *) (((unsigned long) ucp) + sizeof(struct ucontext));
if(restorer == NULL)
panic("setup_signal_stack_si - no restorer");
if(copy_to_user((void *) start, signal_frame_si.common.data,
signal_frame_si.common.len) ||
copy_to_user((void *) (start + signal_frame_si.common.sig_index),
&sig, sizeof(sig)) ||
copy_siginfo_to_user(sip, info) ||
copy_to_user((void *) (start + signal_frame_si.sip_index), &sip,
sizeof(sip)) ||
copy_ucontext_to_user(ucp, fp, mask, PT_REGS_SP(regs)) ||
copy_to_user((void *) (start + signal_frame_si.ucp_index), &ucp,
sizeof(ucp)) ||
copy_restorer(restorer, start, signal_frame_si.common.sr_index,
signal_frame_si.common.sr_relative))
return(1);
PT_REGS_IP(regs) = handler;
PT_REGS_SP(regs) = start + signal_frame_si.common.sp_index;
return(0);
}
int setup_signal_stack_sc(unsigned long stack_top, int sig,
unsigned long handler, void (*restorer)(void),
struct pt_regs *regs, sigset_t *mask)
{
struct frame_common *frame = &signal_frame_sc_sr.common;
void *user_sc;
int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
unsigned long sigs, sr;
unsigned long start = stack_top - frame->len - sig_size;
user_sc = (void *) (start + signal_frame_sc_sr.sc_index);
if(restorer == NULL){
frame = &signal_frame_sc.common;
user_sc = (void *) (start + signal_frame_sc.sc_index);
sr = (unsigned long) frame->data;
sr += frame->sr_index;
sr = *((unsigned long *) sr);
restorer = ((void (*)(void)) sr);
}
sigs = start + frame->len;
if(copy_to_user((void *) start, frame->data, frame->len) ||
copy_to_user((void *) (start + frame->sig_index), &sig,
sizeof(sig)) ||
copy_sc_to_user(user_sc, NULL, regs,
&signal_frame_sc.common.arch) ||
copy_to_user(sc_sigmask(user_sc), mask, sizeof(mask->sig[0])) ||
copy_to_user((void *) sigs, &mask->sig[1], sig_size) ||
copy_restorer(restorer, start, frame->sr_index, frame->sr_relative))
return(1);
PT_REGS_IP(regs) = handler;
PT_REGS_SP(regs) = start + frame->sp_index;
return(0);
}
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
* adjust the settings for this buffer only. This must remain at the end
* of the file.
* ---------------------------------------------------------------------------
* Local variables:
* c-file-style: "linux"
* End:
*/