upgrade to linux 2.6.10-1.12_FC2
[linux-2.6.git] / arch / um / kernel / frame_kern.c
1 /* 
2  * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3  * Licensed under the GPL
4  */
5
6 #include "asm/ptrace.h"
7 #include "asm/uaccess.h"
8 #include "asm/signal.h"
9 #include "asm/ucontext.h"
10 #include "frame_kern.h"
11 #include "sigcontext.h"
12 #include "sysdep/ptrace.h"
13 #include "choose-mode.h"
14 #include "mode.h"
15
16 static int copy_restorer(void (*restorer)(void), unsigned long start, 
17                          unsigned long sr_index, int sr_relative)
18 {
19         unsigned long sr;
20
21         if(sr_relative){
22                 sr = (unsigned long) restorer;
23                 sr += start + sr_index;
24                 restorer = (void (*)(void)) sr;
25         }
26
27         return(copy_to_user((void *) (start + sr_index), &restorer, 
28                             sizeof(restorer)));
29 }
30
31 extern int userspace_pid[];
32
33 static int copy_sc_to_user(void *to, void *fp, struct pt_regs *from, 
34                            struct arch_frame_data *arch)
35 {
36         return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), 
37                                               arch),
38                            copy_sc_to_user_skas(userspace_pid[0], to, fp,
39                                                 &from->regs,
40                                                 current->thread.cr2,
41                                                 current->thread.err)));
42 }
43
44 static int copy_ucontext_to_user(struct ucontext *uc, void *fp, sigset_t *set,
45                                  unsigned long sp)
46 {
47         int err = 0;
48
49         err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp);
50         err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags);
51         err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size);
52         err |= copy_sc_to_user(&uc->uc_mcontext, fp, &current->thread.regs,
53                                &signal_frame_si.common.arch);
54         err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set));
55         return(err);
56 }
57
58 int setup_signal_stack_si(unsigned long stack_top, int sig, 
59                           struct k_sigaction *ka, struct pt_regs *regs,
60                           siginfo_t *info, sigset_t *mask)
61 {
62         unsigned long start;
63         void *restorer;
64         void *sip, *ucp, *fp;
65
66         start = stack_top - signal_frame_si.common.len;
67         sip = (void *) (start + signal_frame_si.si_index);
68         ucp = (void *) (start + signal_frame_si.uc_index);
69         fp = (void *) (((unsigned long) ucp) + sizeof(struct ucontext));
70
71         restorer = NULL;
72         if(ka->sa.sa_flags & SA_RESTORER)
73                 restorer = ka->sa.sa_restorer;
74
75         if(restorer == NULL)
76                 panic("setup_signal_stack_si - no restorer");
77
78         if(copy_to_user((void *) start, signal_frame_si.common.data,
79                         signal_frame_si.common.len) ||
80            copy_to_user((void *) (start + signal_frame_si.common.sig_index), 
81                         &sig, sizeof(sig)) ||
82            copy_siginfo_to_user(sip, info) ||
83            copy_to_user((void *) (start + signal_frame_si.sip_index), &sip,
84                         sizeof(sip)) ||
85            copy_ucontext_to_user(ucp, fp, mask, PT_REGS_SP(regs)) ||
86            copy_to_user((void *) (start + signal_frame_si.ucp_index), &ucp,
87                         sizeof(ucp)) ||
88            copy_restorer(restorer, start, signal_frame_si.common.sr_index,
89                          signal_frame_si.common.sr_relative))
90                 return(1);
91         
92         PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
93         PT_REGS_SP(regs) = start + signal_frame_si.common.sp_index;
94         return(0);
95 }
96
97 int setup_signal_stack_sc(unsigned long stack_top, int sig, 
98                           struct k_sigaction *ka, struct pt_regs *regs,
99                           sigset_t *mask)
100 {
101         struct frame_common *frame = &signal_frame_sc_sr.common;
102         void *restorer;
103         void *user_sc;
104         int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
105         unsigned long sigs, sr;
106         unsigned long start = stack_top - frame->len - sig_size;
107
108         restorer = NULL;
109         if(ka->sa.sa_flags & SA_RESTORER)
110                 restorer = ka->sa.sa_restorer;
111
112         user_sc = (void *) (start + signal_frame_sc_sr.sc_index);
113         if(restorer == NULL){
114                 frame = &signal_frame_sc.common;
115                 user_sc = (void *) (start + signal_frame_sc.sc_index);
116                 sr = (unsigned long) frame->data;
117                 sr += frame->sr_index;
118                 sr = *((unsigned long *) sr);
119                 restorer = ((void (*)(void)) sr);
120         }
121
122         sigs = start + frame->len;
123         if(copy_to_user((void *) start, frame->data, frame->len) ||
124            copy_to_user((void *) (start + frame->sig_index), &sig, 
125                         sizeof(sig)) ||
126            copy_sc_to_user(user_sc, NULL, regs, 
127                            &signal_frame_sc.common.arch) ||
128            copy_to_user(sc_sigmask(user_sc), mask, sizeof(mask->sig[0])) ||
129            copy_to_user((void *) sigs, &mask->sig[1], sig_size) ||
130            copy_restorer(restorer, start, frame->sr_index, frame->sr_relative))
131                 return(1);
132
133         PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
134         PT_REGS_SP(regs) = start + frame->sp_index;
135
136         return(0);
137 }
138
139 /*
140  * Overrides for Emacs so that we follow Linus's tabbing style.
141  * Emacs will notice this stuff at the end of the file and automatically
142  * adjust the settings for this buffer only.  This must remain at the end
143  * of the file.
144  * ---------------------------------------------------------------------------
145  * Local variables:
146  * c-file-style: "linux"
147  * End:
148  */