2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
6 #include "asm/ptrace.h"
7 #include "asm/uaccess.h"
8 #include "asm/signal.h"
9 #include "asm/uaccess.h"
10 #include "asm/ucontext.h"
11 #include "frame_kern.h"
12 #include "sigcontext.h"
13 #include "sysdep/ptrace.h"
14 #include "choose-mode.h"
17 static int copy_restorer(void (*restorer)(void), unsigned long start,
18 unsigned long sr_index, int sr_relative)
23 sr = (unsigned long) restorer;
24 sr += start + sr_index;
25 restorer = (void (*)(void)) sr;
28 return(copy_to_user((void *) (start + sr_index), &restorer,
32 static int copy_sc_to_user(void *to, void *fp, struct pt_regs *from,
33 struct arch_frame_data *arch)
35 return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs),
37 copy_sc_to_user_skas(to, fp, &from->regs,
39 current->thread.err)));
42 static int copy_ucontext_to_user(struct ucontext *uc, void *fp, sigset_t *set,
47 err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp);
48 err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags);
49 err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size);
50 err |= copy_sc_to_user(&uc->uc_mcontext, fp, ¤t->thread.regs,
51 &signal_frame_si.common.arch);
52 err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set));
56 int setup_signal_stack_si(unsigned long stack_top, int sig,
57 unsigned long handler, void (*restorer)(void),
58 struct pt_regs *regs, siginfo_t *info,
64 start = stack_top - signal_frame_si.common.len;
65 sip = (void *) (start + signal_frame_si.si_index);
66 ucp = (void *) (start + signal_frame_si.uc_index);
67 fp = (void *) (((unsigned long) ucp) + sizeof(struct ucontext));
70 panic("setup_signal_stack_si - no restorer");
72 if(copy_to_user((void *) start, signal_frame_si.common.data,
73 signal_frame_si.common.len) ||
74 copy_to_user((void *) (start + signal_frame_si.common.sig_index),
76 copy_siginfo_to_user(sip, info) ||
77 copy_to_user((void *) (start + signal_frame_si.sip_index), &sip,
79 copy_ucontext_to_user(ucp, fp, mask, PT_REGS_SP(regs)) ||
80 copy_to_user((void *) (start + signal_frame_si.ucp_index), &ucp,
82 copy_restorer(restorer, start, signal_frame_si.common.sr_index,
83 signal_frame_si.common.sr_relative))
86 PT_REGS_IP(regs) = handler;
87 PT_REGS_SP(regs) = start + signal_frame_si.common.sp_index;
91 int setup_signal_stack_sc(unsigned long stack_top, int sig,
92 unsigned long handler, void (*restorer)(void),
93 struct pt_regs *regs, sigset_t *mask)
95 struct frame_common *frame = &signal_frame_sc_sr.common;
97 int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
98 unsigned long sigs, sr;
99 unsigned long start = stack_top - frame->len - sig_size;
101 user_sc = (void *) (start + signal_frame_sc_sr.sc_index);
102 if(restorer == NULL){
103 frame = &signal_frame_sc.common;
104 user_sc = (void *) (start + signal_frame_sc.sc_index);
105 sr = (unsigned long) frame->data;
106 sr += frame->sr_index;
107 sr = *((unsigned long *) sr);
108 restorer = ((void (*)(void)) sr);
111 sigs = start + frame->len;
112 if(copy_to_user((void *) start, frame->data, frame->len) ||
113 copy_to_user((void *) (start + frame->sig_index), &sig,
115 copy_sc_to_user(user_sc, NULL, regs,
116 &signal_frame_sc.common.arch) ||
117 copy_to_user(sc_sigmask(user_sc), mask, sizeof(mask->sig[0])) ||
118 copy_to_user((void *) sigs, &mask->sig[1], sig_size) ||
119 copy_restorer(restorer, start, frame->sr_index, frame->sr_relative))
122 PT_REGS_IP(regs) = handler;
123 PT_REGS_SP(regs) = start + frame->sp_index;
129 * Overrides for Emacs so that we follow Linus's tabbing style.
130 * Emacs will notice this stuff at the end of the file and automatically
131 * adjust the settings for this buffer only. This must remain at the end
133 * ---------------------------------------------------------------------------
135 * c-file-style: "linux"