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/ucontext.h"
10 #include "frame_kern.h"
11 #include "sigcontext.h"
12 #include "sysdep/ptrace.h"
13 #include "choose-mode.h"
16 static int copy_restorer(void (*restorer
)(void), unsigned long start
,
17 unsigned long sr_index
, int sr_relative
)
22 sr
= (unsigned long) restorer
;
23 sr
+= start
+ sr_index
;
24 restorer
= (void (*)(void)) sr
;
27 return(copy_to_user((void *) (start
+ sr_index
), &restorer
,
31 extern int userspace_pid
[];
33 static int copy_sc_to_user(void *to
, void *fp
, struct pt_regs
*from
,
34 struct arch_frame_data
*arch
)
36 return(CHOOSE_MODE(copy_sc_to_user_tt(to
, fp
, UPT_SC(&from
->regs
),
38 copy_sc_to_user_skas(userspace_pid
[0], to
, fp
,
41 current
->thread
.err
)));
44 static int copy_ucontext_to_user(struct ucontext
*uc
, void *fp
, sigset_t
*set
,
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
, ¤t
->thread
.regs
,
53 &signal_frame_si
.common
.arch
);
54 err
|= copy_to_user(&uc
->uc_sigmask
, set
, sizeof(*set
));
58 int setup_signal_stack_si(unsigned long stack_top
, int sig
,
59 unsigned long handler
, void (*restorer
)(void),
60 struct pt_regs
*regs
, siginfo_t
*info
,
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
));
72 panic("setup_signal_stack_si - no restorer");
74 if(copy_to_user((void *) start
, signal_frame_si
.common
.data
,
75 signal_frame_si
.common
.len
) ||
76 copy_to_user((void *) (start
+ signal_frame_si
.common
.sig_index
),
78 copy_siginfo_to_user(sip
, info
) ||
79 copy_to_user((void *) (start
+ signal_frame_si
.sip_index
), &sip
,
81 copy_ucontext_to_user(ucp
, fp
, mask
, PT_REGS_SP(regs
)) ||
82 copy_to_user((void *) (start
+ signal_frame_si
.ucp_index
), &ucp
,
84 copy_restorer(restorer
, start
, signal_frame_si
.common
.sr_index
,
85 signal_frame_si
.common
.sr_relative
))
88 PT_REGS_IP(regs
) = handler
;
89 PT_REGS_SP(regs
) = start
+ signal_frame_si
.common
.sp_index
;
93 int setup_signal_stack_sc(unsigned long stack_top
, int sig
,
94 unsigned long handler
, void (*restorer
)(void),
95 struct pt_regs
*regs
, sigset_t
*mask
)
97 struct frame_common
*frame
= &signal_frame_sc_sr
.common
;
99 int sig_size
= (_NSIG_WORDS
- 1) * sizeof(unsigned long);
100 unsigned long sigs
, sr
;
101 unsigned long start
= stack_top
- frame
->len
- sig_size
;
103 user_sc
= (void *) (start
+ signal_frame_sc_sr
.sc_index
);
104 if(restorer
== NULL
){
105 frame
= &signal_frame_sc
.common
;
106 user_sc
= (void *) (start
+ signal_frame_sc
.sc_index
);
107 sr
= (unsigned long) frame
->data
;
108 sr
+= frame
->sr_index
;
109 sr
= *((unsigned long *) sr
);
110 restorer
= ((void (*)(void)) sr
);
113 sigs
= start
+ frame
->len
;
114 if(copy_to_user((void *) start
, frame
->data
, frame
->len
) ||
115 copy_to_user((void *) (start
+ frame
->sig_index
), &sig
,
117 copy_sc_to_user(user_sc
, NULL
, regs
,
118 &signal_frame_sc
.common
.arch
) ||
119 copy_to_user(sc_sigmask(user_sc
), mask
, sizeof(mask
->sig
[0])) ||
120 copy_to_user((void *) sigs
, &mask
->sig
[1], sig_size
) ||
121 copy_restorer(restorer
, start
, frame
->sr_index
, frame
->sr_relative
))
124 PT_REGS_IP(regs
) = handler
;
125 PT_REGS_SP(regs
) = start
+ frame
->sp_index
;
131 * Overrides for Emacs so that we follow Linus's tabbing style.
132 * Emacs will notice this stuff at the end of the file and automatically
133 * adjust the settings for this buffer only. This must remain at the end
135 * ---------------------------------------------------------------------------
137 * c-file-style: "linux"