diff options
Diffstat (limited to 'arch/um/kernel/tt')
25 files changed, 0 insertions, 2896 deletions
diff --git a/arch/um/kernel/tt/Makefile b/arch/um/kernel/tt/Makefile deleted file mode 100644 index 6939e5af8472..000000000000 --- a/arch/um/kernel/tt/Makefile +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | # | ||
2 | # Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) | ||
3 | # Licensed under the GPL | ||
4 | # | ||
5 | |||
6 | obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \ | ||
7 | syscall_kern.o syscall_user.o tlb.o tracer.o trap_user.o \ | ||
8 | uaccess.o uaccess_user.o | ||
9 | |||
10 | obj-$(CONFIG_PT_PROXY) += gdb_kern.o ptproxy/ | ||
11 | |||
12 | USER_OBJS := gdb.o tracer.o | ||
13 | |||
14 | include arch/um/scripts/Makefile.rules | ||
diff --git a/arch/um/kernel/tt/exec_kern.c b/arch/um/kernel/tt/exec_kern.c deleted file mode 100644 index 40126cb51801..000000000000 --- a/arch/um/kernel/tt/exec_kern.c +++ /dev/null | |||
@@ -1,84 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include "linux/kernel.h" | ||
7 | #include "linux/mm.h" | ||
8 | #include "asm/signal.h" | ||
9 | #include "asm/ptrace.h" | ||
10 | #include "asm/uaccess.h" | ||
11 | #include "asm/pgalloc.h" | ||
12 | #include "asm/tlbflush.h" | ||
13 | #include "kern_util.h" | ||
14 | #include "irq_user.h" | ||
15 | #include "mem_user.h" | ||
16 | #include "os.h" | ||
17 | #include "tlb.h" | ||
18 | #include "mode.h" | ||
19 | |||
20 | static int exec_tramp(void *sig_stack) | ||
21 | { | ||
22 | init_new_thread_stack(sig_stack, NULL); | ||
23 | init_new_thread_signals(); | ||
24 | os_stop_process(os_getpid()); | ||
25 | return(0); | ||
26 | } | ||
27 | |||
28 | void flush_thread_tt(void) | ||
29 | { | ||
30 | unsigned long stack; | ||
31 | int new_pid; | ||
32 | |||
33 | stack = alloc_stack(0, 0); | ||
34 | if(stack == 0){ | ||
35 | printk(KERN_ERR | ||
36 | "flush_thread : failed to allocate temporary stack\n"); | ||
37 | do_exit(SIGKILL); | ||
38 | } | ||
39 | |||
40 | new_pid = start_fork_tramp(task_stack_page(current), stack, 0, exec_tramp); | ||
41 | if(new_pid < 0){ | ||
42 | printk(KERN_ERR | ||
43 | "flush_thread : new thread failed, errno = %d\n", | ||
44 | -new_pid); | ||
45 | do_exit(SIGKILL); | ||
46 | } | ||
47 | |||
48 | if(current_thread->cpu == 0) | ||
49 | forward_interrupts(new_pid); | ||
50 | current->thread.request.op = OP_EXEC; | ||
51 | current->thread.request.u.exec.pid = new_pid; | ||
52 | unprotect_stack((unsigned long) current_thread); | ||
53 | os_usr1_process(os_getpid()); | ||
54 | change_sig(SIGUSR1, 1); | ||
55 | |||
56 | change_sig(SIGUSR1, 0); | ||
57 | enable_timer(); | ||
58 | free_page(stack); | ||
59 | protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1); | ||
60 | stack_protections((unsigned long) current_thread); | ||
61 | force_flush_all(); | ||
62 | unblock_signals(); | ||
63 | } | ||
64 | |||
65 | void start_thread_tt(struct pt_regs *regs, unsigned long eip, | ||
66 | unsigned long esp) | ||
67 | { | ||
68 | set_fs(USER_DS); | ||
69 | flush_tlb_mm(current->mm); | ||
70 | PT_REGS_IP(regs) = eip; | ||
71 | PT_REGS_SP(regs) = esp; | ||
72 | PT_FIX_EXEC_STACK(esp); | ||
73 | } | ||
74 | |||
75 | /* | ||
76 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
77 | * Emacs will notice this stuff at the end of the file and automatically | ||
78 | * adjust the settings for this buffer only. This must remain at the end | ||
79 | * of the file. | ||
80 | * --------------------------------------------------------------------------- | ||
81 | * Local variables: | ||
82 | * c-file-style: "linux" | ||
83 | * End: | ||
84 | */ | ||
diff --git a/arch/um/kernel/tt/exec_user.c b/arch/um/kernel/tt/exec_user.c deleted file mode 100644 index 7b5f2181cf51..000000000000 --- a/arch/um/kernel/tt/exec_user.c +++ /dev/null | |||
@@ -1,56 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <stdio.h> | ||
7 | #include <unistd.h> | ||
8 | #include <stdlib.h> | ||
9 | #include <sched.h> | ||
10 | #include <errno.h> | ||
11 | #include <sys/wait.h> | ||
12 | #include <signal.h> | ||
13 | #include "kern_util.h" | ||
14 | #include "user.h" | ||
15 | #include "ptrace_user.h" | ||
16 | #include "os.h" | ||
17 | |||
18 | void do_exec(int old_pid, int new_pid) | ||
19 | { | ||
20 | unsigned long regs[FRAME_SIZE]; | ||
21 | int err; | ||
22 | |||
23 | if((ptrace(PTRACE_ATTACH, new_pid, 0, 0) < 0) || | ||
24 | (ptrace(PTRACE_CONT, new_pid, 0, 0) < 0)) | ||
25 | tracer_panic("do_exec failed to attach proc - errno = %d", | ||
26 | errno); | ||
27 | |||
28 | CATCH_EINTR(err = waitpid(new_pid, 0, WUNTRACED)); | ||
29 | if (err < 0) | ||
30 | tracer_panic("do_exec failed to attach proc in waitpid - errno = %d", | ||
31 | errno); | ||
32 | |||
33 | if(ptrace_getregs(old_pid, regs) < 0) | ||
34 | tracer_panic("do_exec failed to get registers - errno = %d", | ||
35 | errno); | ||
36 | |||
37 | os_kill_ptraced_process(old_pid, 0); | ||
38 | |||
39 | if (ptrace(PTRACE_OLDSETOPTIONS, new_pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0) | ||
40 | tracer_panic("do_exec: PTRACE_SETOPTIONS failed, errno = %d", errno); | ||
41 | |||
42 | if(ptrace_setregs(new_pid, regs) < 0) | ||
43 | tracer_panic("do_exec failed to start new proc - errno = %d", | ||
44 | errno); | ||
45 | } | ||
46 | |||
47 | /* | ||
48 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
49 | * Emacs will notice this stuff at the end of the file and automatically | ||
50 | * adjust the settings for this buffer only. This must remain at the end | ||
51 | * of the file. | ||
52 | * --------------------------------------------------------------------------- | ||
53 | * Local variables: | ||
54 | * c-file-style: "linux" | ||
55 | * End: | ||
56 | */ | ||
diff --git a/arch/um/kernel/tt/gdb.c b/arch/um/kernel/tt/gdb.c deleted file mode 100644 index 030e4658f36b..000000000000 --- a/arch/um/kernel/tt/gdb.c +++ /dev/null | |||
@@ -1,280 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <stdio.h> | ||
7 | #include <stdlib.h> | ||
8 | #include <errno.h> | ||
9 | #include <string.h> | ||
10 | #include <signal.h> | ||
11 | #include <sys/types.h> | ||
12 | #include "ptrace_user.h" | ||
13 | #include "uml-config.h" | ||
14 | #include "kern_constants.h" | ||
15 | #include "chan_user.h" | ||
16 | #include "init.h" | ||
17 | #include "user.h" | ||
18 | #include "debug.h" | ||
19 | #include "kern_util.h" | ||
20 | #include "tt.h" | ||
21 | #include "sysdep/thread.h" | ||
22 | #include "os.h" | ||
23 | |||
24 | extern int debugger_pid; | ||
25 | extern int debugger_fd; | ||
26 | extern int debugger_parent; | ||
27 | |||
28 | int detach(int pid, int sig) | ||
29 | { | ||
30 | return(ptrace(PTRACE_DETACH, pid, 0, sig)); | ||
31 | } | ||
32 | |||
33 | int attach(int pid) | ||
34 | { | ||
35 | int err; | ||
36 | |||
37 | err = ptrace(PTRACE_ATTACH, pid, 0, 0); | ||
38 | if(err < 0) return(-errno); | ||
39 | else return(err); | ||
40 | } | ||
41 | |||
42 | int cont(int pid) | ||
43 | { | ||
44 | return(ptrace(PTRACE_CONT, pid, 0, 0)); | ||
45 | } | ||
46 | |||
47 | #ifdef UML_CONFIG_PT_PROXY | ||
48 | |||
49 | int debugger_signal(int status, pid_t pid) | ||
50 | { | ||
51 | return(debugger_proxy(status, pid)); | ||
52 | } | ||
53 | |||
54 | void child_signal(pid_t pid, int status) | ||
55 | { | ||
56 | child_proxy(pid, status); | ||
57 | } | ||
58 | |||
59 | static void gdb_announce(char *dev_name, int dev) | ||
60 | { | ||
61 | printf("gdb assigned device '%s'\n", dev_name); | ||
62 | } | ||
63 | |||
64 | static struct chan_opts opts = { | ||
65 | .announce = gdb_announce, | ||
66 | .xterm_title = "UML kernel debugger", | ||
67 | .raw = 0, | ||
68 | .tramp_stack = 0, | ||
69 | .in_kernel = 0, | ||
70 | }; | ||
71 | |||
72 | /* Accessed by the tracing thread, which automatically serializes access */ | ||
73 | static void *xterm_data; | ||
74 | static int xterm_fd; | ||
75 | |||
76 | extern void *xterm_init(char *, int, struct chan_opts *); | ||
77 | extern int xterm_open(int, int, int, void *, char **); | ||
78 | extern void xterm_close(int, void *); | ||
79 | |||
80 | int open_gdb_chan(void) | ||
81 | { | ||
82 | char stack[UM_KERN_PAGE_SIZE], *dummy; | ||
83 | |||
84 | opts.tramp_stack = (unsigned long) stack; | ||
85 | xterm_data = xterm_init("", 0, &opts); | ||
86 | xterm_fd = xterm_open(1, 1, 1, xterm_data, &dummy); | ||
87 | return(xterm_fd); | ||
88 | } | ||
89 | |||
90 | static void exit_debugger_cb(void *unused) | ||
91 | { | ||
92 | if(debugger_pid != -1){ | ||
93 | if(gdb_pid != -1){ | ||
94 | fake_child_exit(); | ||
95 | gdb_pid = -1; | ||
96 | } | ||
97 | else kill_child_dead(debugger_pid); | ||
98 | debugger_pid = -1; | ||
99 | if(debugger_parent != -1) | ||
100 | detach(debugger_parent, SIGINT); | ||
101 | } | ||
102 | if(xterm_data != NULL) xterm_close(xterm_fd, xterm_data); | ||
103 | } | ||
104 | |||
105 | static void exit_debugger(void) | ||
106 | { | ||
107 | initial_thread_cb(exit_debugger_cb, NULL); | ||
108 | } | ||
109 | |||
110 | __uml_exitcall(exit_debugger); | ||
111 | |||
112 | struct gdb_data { | ||
113 | char *str; | ||
114 | int err; | ||
115 | }; | ||
116 | |||
117 | extern char *linux_prog; | ||
118 | |||
119 | static void config_gdb_cb(void *arg) | ||
120 | { | ||
121 | struct gdb_data *data = arg; | ||
122 | void *task; | ||
123 | int pid; | ||
124 | |||
125 | data->err = -1; | ||
126 | if(debugger_pid != -1) exit_debugger_cb(NULL); | ||
127 | if(!strncmp(data->str, "pid,", strlen("pid,"))){ | ||
128 | data->str += strlen("pid,"); | ||
129 | pid = strtoul(data->str, NULL, 0); | ||
130 | task = cpu_tasks[0].task; | ||
131 | debugger_pid = attach_debugger(TASK_EXTERN_PID(task), pid, 0); | ||
132 | if(debugger_pid != -1){ | ||
133 | data->err = 0; | ||
134 | gdb_pid = pid; | ||
135 | } | ||
136 | return; | ||
137 | } | ||
138 | data->err = 0; | ||
139 | debugger_pid = start_debugger(linux_prog, 0, 0, &debugger_fd); | ||
140 | init_proxy(debugger_pid, 0, 0); | ||
141 | } | ||
142 | |||
143 | int gdb_config(char *str, char **error_out) | ||
144 | { | ||
145 | struct gdb_data data; | ||
146 | |||
147 | if(*str++ != '=') return(-1); | ||
148 | data.str = str; | ||
149 | initial_thread_cb(config_gdb_cb, &data); | ||
150 | return(data.err); | ||
151 | } | ||
152 | |||
153 | void remove_gdb_cb(void *unused) | ||
154 | { | ||
155 | exit_debugger_cb(NULL); | ||
156 | } | ||
157 | |||
158 | int gdb_remove(int unused, char **error_out) | ||
159 | { | ||
160 | initial_thread_cb(remove_gdb_cb, NULL); | ||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | void signal_usr1(int sig) | ||
165 | { | ||
166 | if(debugger_pid != -1){ | ||
167 | printf("The debugger is already running\n"); | ||
168 | return; | ||
169 | } | ||
170 | debugger_pid = start_debugger(linux_prog, 0, 0, &debugger_fd); | ||
171 | init_proxy(debugger_pid, 0, 0); | ||
172 | } | ||
173 | |||
174 | int init_ptrace_proxy(int idle_pid, int startup, int stop) | ||
175 | { | ||
176 | int pid, status; | ||
177 | |||
178 | pid = start_debugger(linux_prog, startup, stop, &debugger_fd); | ||
179 | status = wait_for_stop(idle_pid, SIGSTOP, PTRACE_CONT, NULL); | ||
180 | if(pid < 0){ | ||
181 | cont(idle_pid); | ||
182 | return(-1); | ||
183 | } | ||
184 | init_proxy(pid, 1, status); | ||
185 | return(pid); | ||
186 | } | ||
187 | |||
188 | int attach_debugger(int idle_pid, int pid, int stop) | ||
189 | { | ||
190 | int status = 0, err; | ||
191 | |||
192 | err = attach(pid); | ||
193 | if(err < 0){ | ||
194 | printf("Failed to attach pid %d, errno = %d\n", pid, -err); | ||
195 | return(-1); | ||
196 | } | ||
197 | if(stop) status = wait_for_stop(idle_pid, SIGSTOP, PTRACE_CONT, NULL); | ||
198 | init_proxy(pid, 1, status); | ||
199 | return(pid); | ||
200 | } | ||
201 | |||
202 | #ifdef notdef /* Put this back in when it does something useful */ | ||
203 | static int __init uml_gdb_init_setup(char *line, int *add) | ||
204 | { | ||
205 | gdb_init = uml_strdup(line); | ||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | __uml_setup("gdb=", uml_gdb_init_setup, | ||
210 | "gdb=<channel description>\n\n" | ||
211 | ); | ||
212 | #endif | ||
213 | |||
214 | static int __init uml_gdb_pid_setup(char *line, int *add) | ||
215 | { | ||
216 | gdb_pid = strtoul(line, NULL, 0); | ||
217 | *add = 0; | ||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | __uml_setup("gdb-pid=", uml_gdb_pid_setup, | ||
222 | "gdb-pid=<pid>\n" | ||
223 | " gdb-pid is used to attach an external debugger to UML. This may be\n" | ||
224 | " an already-running gdb or a debugger-like process like strace.\n\n" | ||
225 | ); | ||
226 | |||
227 | #else | ||
228 | |||
229 | int debugger_signal(int status, pid_t pid){ return(0); } | ||
230 | void child_signal(pid_t pid, int status){ } | ||
231 | int init_ptrace_proxy(int idle_pid, int startup, int stop) | ||
232 | { | ||
233 | printf("debug requested when CONFIG_PT_PROXY is off\n"); | ||
234 | kill_child_dead(idle_pid); | ||
235 | exit(1); | ||
236 | } | ||
237 | |||
238 | void signal_usr1(int sig) | ||
239 | { | ||
240 | printf("debug requested when CONFIG_PT_PROXY is off\n"); | ||
241 | } | ||
242 | |||
243 | int attach_debugger(int idle_pid, int pid, int stop) | ||
244 | { | ||
245 | printf("attach_debugger called when CONFIG_PT_PROXY " | ||
246 | "is off\n"); | ||
247 | return(-1); | ||
248 | } | ||
249 | |||
250 | int config_gdb(char *str) | ||
251 | { | ||
252 | return(-1); | ||
253 | } | ||
254 | |||
255 | int remove_gdb(void) | ||
256 | { | ||
257 | return(-1); | ||
258 | } | ||
259 | |||
260 | int init_parent_proxy(int pid) | ||
261 | { | ||
262 | return(-1); | ||
263 | } | ||
264 | |||
265 | void debugger_parent_signal(int status, int pid) | ||
266 | { | ||
267 | } | ||
268 | |||
269 | #endif | ||
270 | |||
271 | /* | ||
272 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
273 | * Emacs will notice this stuff at the end of the file and automatically | ||
274 | * adjust the settings for this buffer only. This must remain at the end | ||
275 | * of the file. | ||
276 | * --------------------------------------------------------------------------- | ||
277 | * Local variables: | ||
278 | * c-file-style: "linux" | ||
279 | * End: | ||
280 | */ | ||
diff --git a/arch/um/kernel/tt/gdb_kern.c b/arch/um/kernel/tt/gdb_kern.c deleted file mode 100644 index 03b06bc00771..000000000000 --- a/arch/um/kernel/tt/gdb_kern.c +++ /dev/null | |||
@@ -1,40 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include "linux/init.h" | ||
7 | #include "mconsole_kern.h" | ||
8 | |||
9 | #ifdef CONFIG_MCONSOLE | ||
10 | |||
11 | extern int gdb_config(char *str, char **error_out); | ||
12 | extern int gdb_remove(int n, char **error_out); | ||
13 | |||
14 | static struct mc_device gdb_mc = { | ||
15 | .list = INIT_LIST_HEAD(gdb_mc.list), | ||
16 | .name = "gdb", | ||
17 | .config = gdb_config, | ||
18 | .remove = gdb_remove, | ||
19 | }; | ||
20 | |||
21 | int gdb_mc_init(void) | ||
22 | { | ||
23 | mconsole_register_dev(&gdb_mc); | ||
24 | return(0); | ||
25 | } | ||
26 | |||
27 | __initcall(gdb_mc_init); | ||
28 | |||
29 | #endif | ||
30 | |||
31 | /* | ||
32 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
33 | * Emacs will notice this stuff at the end of the file and automatically | ||
34 | * adjust the settings for this buffer only. This must remain at the end | ||
35 | * of the file. | ||
36 | * --------------------------------------------------------------------------- | ||
37 | * Local variables: | ||
38 | * c-file-style: "linux" | ||
39 | * End: | ||
40 | */ | ||
diff --git a/arch/um/kernel/tt/include/mode-tt.h b/arch/um/kernel/tt/include/mode-tt.h deleted file mode 100644 index e171e15fead5..000000000000 --- a/arch/um/kernel/tt/include/mode-tt.h +++ /dev/null | |||
@@ -1,34 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #ifndef __MODE_TT_H__ | ||
7 | #define __MODE_TT_H__ | ||
8 | |||
9 | #include "sysdep/ptrace.h" | ||
10 | |||
11 | enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB }; | ||
12 | |||
13 | extern int tracing_pid; | ||
14 | |||
15 | extern int tracer(int (*init_proc)(void *), void *sp); | ||
16 | extern void sig_handler_common_tt(int sig, void *sc); | ||
17 | extern void syscall_handler_tt(int sig, union uml_pt_regs *regs); | ||
18 | extern void reboot_tt(void); | ||
19 | extern void halt_tt(void); | ||
20 | extern int is_tracer_winch(int pid, int fd, void *data); | ||
21 | extern void kill_off_processes_tt(void); | ||
22 | |||
23 | #endif | ||
24 | |||
25 | /* | ||
26 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
27 | * Emacs will notice this stuff at the end of the file and automatically | ||
28 | * adjust the settings for this buffer only. This must remain at the end | ||
29 | * of the file. | ||
30 | * --------------------------------------------------------------------------- | ||
31 | * Local variables: | ||
32 | * c-file-style: "linux" | ||
33 | * End: | ||
34 | */ | ||
diff --git a/arch/um/kernel/tt/ksyms.c b/arch/um/kernel/tt/ksyms.c deleted file mode 100644 index 84a9385a8fef..000000000000 --- a/arch/um/kernel/tt/ksyms.c +++ /dev/null | |||
@@ -1,29 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include "linux/module.h" | ||
7 | #include "asm/uaccess.h" | ||
8 | #include "mode.h" | ||
9 | |||
10 | EXPORT_SYMBOL(__do_copy_from_user); | ||
11 | EXPORT_SYMBOL(__do_copy_to_user); | ||
12 | EXPORT_SYMBOL(__do_strncpy_from_user); | ||
13 | EXPORT_SYMBOL(__do_strnlen_user); | ||
14 | EXPORT_SYMBOL(__do_clear_user); | ||
15 | EXPORT_SYMBOL(clear_user_tt); | ||
16 | |||
17 | EXPORT_SYMBOL(tracing_pid); | ||
18 | EXPORT_SYMBOL(honeypot); | ||
19 | |||
20 | /* | ||
21 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
22 | * Emacs will notice this stuff at the end of the file and automatically | ||
23 | * adjust the settings for this buffer only. This must remain at the end | ||
24 | * of the file. | ||
25 | * --------------------------------------------------------------------------- | ||
26 | * Local variables: | ||
27 | * c-file-style: "linux" | ||
28 | * End: | ||
29 | */ | ||
diff --git a/arch/um/kernel/tt/mem.c b/arch/um/kernel/tt/mem.c deleted file mode 100644 index d0c3c4975f28..000000000000 --- a/arch/um/kernel/tt/mem.c +++ /dev/null | |||
@@ -1,34 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include "linux/stddef.h" | ||
7 | #include "linux/mm.h" | ||
8 | #include "asm/uaccess.h" | ||
9 | #include "mem_user.h" | ||
10 | #include "kern_util.h" | ||
11 | #include "kern.h" | ||
12 | #include "tt.h" | ||
13 | |||
14 | void before_mem_tt(unsigned long brk_start) | ||
15 | { | ||
16 | if(debug) | ||
17 | remap_data(UML_ROUND_DOWN(&_stext), UML_ROUND_UP(&_etext), 1); | ||
18 | remap_data(UML_ROUND_DOWN(&_sdata), UML_ROUND_UP(&_edata), 1); | ||
19 | remap_data(UML_ROUND_DOWN(&__bss_start), UML_ROUND_UP(&_end), 1); | ||
20 | } | ||
21 | |||
22 | #define SIZE ((CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS) * 0x20000000) | ||
23 | #define START (CONFIG_TOP_ADDR - SIZE) | ||
24 | |||
25 | unsigned long set_task_sizes_tt(unsigned long *task_size_out) | ||
26 | { | ||
27 | unsigned long host_task_size; | ||
28 | |||
29 | /* Round up to the nearest 4M */ | ||
30 | host_task_size = ROUND_4M((unsigned long) &host_task_size); | ||
31 | *task_size_out = START; | ||
32 | |||
33 | return host_task_size; | ||
34 | } | ||
diff --git a/arch/um/kernel/tt/mem_user.c b/arch/um/kernel/tt/mem_user.c deleted file mode 100644 index 9774f6360c32..000000000000 --- a/arch/um/kernel/tt/mem_user.c +++ /dev/null | |||
@@ -1,49 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <stdlib.h> | ||
7 | #include <stdio.h> | ||
8 | #include <unistd.h> | ||
9 | #include <string.h> | ||
10 | #include <errno.h> | ||
11 | #include <sys/mman.h> | ||
12 | #include "tt.h" | ||
13 | #include "mem_user.h" | ||
14 | #include "os.h" | ||
15 | |||
16 | void remap_data(void *segment_start, void *segment_end, int w) | ||
17 | { | ||
18 | void *addr; | ||
19 | unsigned long size; | ||
20 | int data, prot; | ||
21 | |||
22 | if(w) prot = PROT_WRITE; | ||
23 | else prot = 0; | ||
24 | prot |= PROT_READ | PROT_EXEC; | ||
25 | size = (unsigned long) segment_end - | ||
26 | (unsigned long) segment_start; | ||
27 | data = create_mem_file(size); | ||
28 | addr = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, data, 0); | ||
29 | if(addr == MAP_FAILED){ | ||
30 | perror("mapping new data segment"); | ||
31 | exit(1); | ||
32 | } | ||
33 | memcpy(addr, segment_start, size); | ||
34 | if(switcheroo(data, prot, addr, segment_start, size) < 0){ | ||
35 | printf("switcheroo failed\n"); | ||
36 | exit(1); | ||
37 | } | ||
38 | } | ||
39 | |||
40 | /* | ||
41 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
42 | * Emacs will notice this stuff at the end of the file and automatically | ||
43 | * adjust the settings for this buffer only. This must remain at the end | ||
44 | * of the file. | ||
45 | * --------------------------------------------------------------------------- | ||
46 | * Local variables: | ||
47 | * c-file-style: "linux" | ||
48 | * End: | ||
49 | */ | ||
diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c deleted file mode 100644 index 74347adf81bf..000000000000 --- a/arch/um/kernel/tt/process_kern.c +++ /dev/null | |||
@@ -1,461 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include "linux/sched.h" | ||
7 | #include "linux/signal.h" | ||
8 | #include "linux/kernel.h" | ||
9 | #include "linux/interrupt.h" | ||
10 | #include "linux/ptrace.h" | ||
11 | #include "asm/system.h" | ||
12 | #include "asm/pgalloc.h" | ||
13 | #include "asm/ptrace.h" | ||
14 | #include "asm/tlbflush.h" | ||
15 | #include "irq_user.h" | ||
16 | #include "kern_util.h" | ||
17 | #include "os.h" | ||
18 | #include "kern.h" | ||
19 | #include "sigcontext.h" | ||
20 | #include "mem_user.h" | ||
21 | #include "tlb.h" | ||
22 | #include "mode.h" | ||
23 | #include "mode_kern.h" | ||
24 | #include "init.h" | ||
25 | #include "tt.h" | ||
26 | |||
27 | void switch_to_tt(void *prev, void *next) | ||
28 | { | ||
29 | struct task_struct *from, *to, *prev_sched; | ||
30 | unsigned long flags; | ||
31 | int err, vtalrm, alrm, prof, cpu; | ||
32 | char c; | ||
33 | |||
34 | from = prev; | ||
35 | to = next; | ||
36 | |||
37 | cpu = task_thread_info(from)->cpu; | ||
38 | if(cpu == 0) | ||
39 | forward_interrupts(to->thread.mode.tt.extern_pid); | ||
40 | #ifdef CONFIG_SMP | ||
41 | forward_ipi(cpu_data[cpu].ipi_pipe[0], to->thread.mode.tt.extern_pid); | ||
42 | #endif | ||
43 | local_irq_save(flags); | ||
44 | |||
45 | vtalrm = change_sig(SIGVTALRM, 0); | ||
46 | alrm = change_sig(SIGALRM, 0); | ||
47 | prof = change_sig(SIGPROF, 0); | ||
48 | |||
49 | forward_pending_sigio(to->thread.mode.tt.extern_pid); | ||
50 | |||
51 | c = 0; | ||
52 | |||
53 | /* Notice that here we "up" the semaphore on which "to" is waiting, and | ||
54 | * below (the read) we wait on this semaphore (which is implemented by | ||
55 | * switch_pipe) and go sleeping. Thus, after that, we have resumed in | ||
56 | * "to", and can't use any more the value of "from" (which is outdated), | ||
57 | * nor the value in "to" (since it was the task which stole us the CPU, | ||
58 | * which we don't care about). */ | ||
59 | |||
60 | err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c)); | ||
61 | if(err != sizeof(c)) | ||
62 | panic("write of switch_pipe failed, err = %d", -err); | ||
63 | |||
64 | if(from->thread.mode.tt.switch_pipe[0] == -1) | ||
65 | os_kill_process(os_getpid(), 0); | ||
66 | |||
67 | err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c, | ||
68 | sizeof(c)); | ||
69 | if(err != sizeof(c)) | ||
70 | panic("read of switch_pipe failed, errno = %d", -err); | ||
71 | |||
72 | /* If the process that we have just scheduled away from has exited, | ||
73 | * then it needs to be killed here. The reason is that, even though | ||
74 | * it will kill itself when it next runs, that may be too late. Its | ||
75 | * stack will be freed, possibly before then, and if that happens, | ||
76 | * we have a use-after-free situation. So, it gets killed here | ||
77 | * in case it has not already killed itself. | ||
78 | */ | ||
79 | prev_sched = current->thread.prev_sched; | ||
80 | if(prev_sched->thread.mode.tt.switch_pipe[0] == -1) | ||
81 | os_kill_process(prev_sched->thread.mode.tt.extern_pid, 1); | ||
82 | |||
83 | change_sig(SIGVTALRM, vtalrm); | ||
84 | change_sig(SIGALRM, alrm); | ||
85 | change_sig(SIGPROF, prof); | ||
86 | |||
87 | arch_switch_to_tt(prev_sched, current); | ||
88 | |||
89 | flush_tlb_all(); | ||
90 | local_irq_restore(flags); | ||
91 | } | ||
92 | |||
93 | void release_thread_tt(struct task_struct *task) | ||
94 | { | ||
95 | int pid = task->thread.mode.tt.extern_pid; | ||
96 | |||
97 | /* | ||
98 | * We first have to kill the other process, before | ||
99 | * closing its switch_pipe. Else it might wake up | ||
100 | * and receive "EOF" before we could kill it. | ||
101 | */ | ||
102 | if(os_getpid() != pid) | ||
103 | os_kill_process(pid, 0); | ||
104 | |||
105 | os_close_file(task->thread.mode.tt.switch_pipe[0]); | ||
106 | os_close_file(task->thread.mode.tt.switch_pipe[1]); | ||
107 | /* use switch_pipe as flag: thread is released */ | ||
108 | task->thread.mode.tt.switch_pipe[0] = -1; | ||
109 | } | ||
110 | |||
111 | void suspend_new_thread(int fd) | ||
112 | { | ||
113 | int err; | ||
114 | char c; | ||
115 | |||
116 | os_stop_process(os_getpid()); | ||
117 | err = os_read_file(fd, &c, sizeof(c)); | ||
118 | if(err != sizeof(c)) | ||
119 | panic("read failed in suspend_new_thread, err = %d", -err); | ||
120 | } | ||
121 | |||
122 | void schedule_tail(struct task_struct *prev); | ||
123 | |||
124 | static void new_thread_handler(int sig) | ||
125 | { | ||
126 | unsigned long disable; | ||
127 | int (*fn)(void *); | ||
128 | void *arg; | ||
129 | |||
130 | fn = current->thread.request.u.thread.proc; | ||
131 | arg = current->thread.request.u.thread.arg; | ||
132 | |||
133 | UPT_SC(¤t->thread.regs.regs) = (void *) (&sig + 1); | ||
134 | disable = (1 << (SIGVTALRM - 1)) | (1 << (SIGALRM - 1)) | | ||
135 | (1 << (SIGIO - 1)) | (1 << (SIGPROF - 1)); | ||
136 | SC_SIGMASK(UPT_SC(¤t->thread.regs.regs)) &= ~disable; | ||
137 | |||
138 | suspend_new_thread(current->thread.mode.tt.switch_pipe[0]); | ||
139 | |||
140 | force_flush_all(); | ||
141 | if(current->thread.prev_sched != NULL) | ||
142 | schedule_tail(current->thread.prev_sched); | ||
143 | current->thread.prev_sched = NULL; | ||
144 | |||
145 | init_new_thread_signals(); | ||
146 | enable_timer(); | ||
147 | free_page(current->thread.temp_stack); | ||
148 | set_cmdline("(kernel thread)"); | ||
149 | |||
150 | change_sig(SIGUSR1, 1); | ||
151 | change_sig(SIGPROF, 1); | ||
152 | local_irq_enable(); | ||
153 | if(!run_kernel_thread(fn, arg, ¤t->thread.exec_buf)) | ||
154 | do_exit(0); | ||
155 | |||
156 | /* XXX No set_user_mode here because a newly execed process will | ||
157 | * immediately segfault on its non-existent IP, coming straight back | ||
158 | * to the signal handler, which will call set_user_mode on its way | ||
159 | * out. This should probably change since it's confusing. | ||
160 | */ | ||
161 | } | ||
162 | |||
163 | static int new_thread_proc(void *stack) | ||
164 | { | ||
165 | /* local_irq_disable is needed to block out signals until this thread is | ||
166 | * properly scheduled. Otherwise, the tracing thread will get mighty | ||
167 | * upset about any signals that arrive before that. | ||
168 | * This has the complication that it sets the saved signal mask in | ||
169 | * the sigcontext to block signals. This gets restored when this | ||
170 | * thread (or a descendant, since they get a copy of this sigcontext) | ||
171 | * returns to userspace. | ||
172 | * So, this is compensated for elsewhere. | ||
173 | * XXX There is still a small window until local_irq_disable() actually | ||
174 | * finishes where signals are possible - shouldn't be a problem in | ||
175 | * practice since SIGIO hasn't been forwarded here yet, and the | ||
176 | * local_irq_disable should finish before a SIGVTALRM has time to be | ||
177 | * delivered. | ||
178 | */ | ||
179 | |||
180 | local_irq_disable(); | ||
181 | init_new_thread_stack(stack, new_thread_handler); | ||
182 | os_usr1_process(os_getpid()); | ||
183 | change_sig(SIGUSR1, 1); | ||
184 | return(0); | ||
185 | } | ||
186 | |||
187 | /* Signal masking - signals are blocked at the start of fork_tramp. They | ||
188 | * are re-enabled when finish_fork_handler is entered by fork_tramp hitting | ||
189 | * itself with a SIGUSR1. set_user_mode has to be run with SIGUSR1 off, | ||
190 | * so it is blocked before it's called. They are re-enabled on sigreturn | ||
191 | * despite the fact that they were blocked when the SIGUSR1 was issued because | ||
192 | * copy_thread copies the parent's sigcontext, including the signal mask | ||
193 | * onto the signal frame. | ||
194 | */ | ||
195 | |||
196 | void finish_fork_handler(int sig) | ||
197 | { | ||
198 | UPT_SC(¤t->thread.regs.regs) = (void *) (&sig + 1); | ||
199 | suspend_new_thread(current->thread.mode.tt.switch_pipe[0]); | ||
200 | |||
201 | force_flush_all(); | ||
202 | if(current->thread.prev_sched != NULL) | ||
203 | schedule_tail(current->thread.prev_sched); | ||
204 | current->thread.prev_sched = NULL; | ||
205 | |||
206 | enable_timer(); | ||
207 | change_sig(SIGVTALRM, 1); | ||
208 | local_irq_enable(); | ||
209 | if(current->mm != current->parent->mm) | ||
210 | protect_memory(uml_reserved, high_physmem - uml_reserved, 1, | ||
211 | 1, 0, 1); | ||
212 | stack_protections((unsigned long) current_thread); | ||
213 | |||
214 | free_page(current->thread.temp_stack); | ||
215 | local_irq_disable(); | ||
216 | change_sig(SIGUSR1, 0); | ||
217 | set_user_mode(current); | ||
218 | } | ||
219 | |||
220 | int fork_tramp(void *stack) | ||
221 | { | ||
222 | local_irq_disable(); | ||
223 | arch_init_thread(); | ||
224 | init_new_thread_stack(stack, finish_fork_handler); | ||
225 | |||
226 | os_usr1_process(os_getpid()); | ||
227 | change_sig(SIGUSR1, 1); | ||
228 | return(0); | ||
229 | } | ||
230 | |||
231 | int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp, | ||
232 | unsigned long stack_top, struct task_struct * p, | ||
233 | struct pt_regs *regs) | ||
234 | { | ||
235 | int (*tramp)(void *); | ||
236 | int new_pid, err; | ||
237 | unsigned long stack; | ||
238 | |||
239 | if(current->thread.forking) | ||
240 | tramp = fork_tramp; | ||
241 | else { | ||
242 | tramp = new_thread_proc; | ||
243 | p->thread.request.u.thread = current->thread.request.u.thread; | ||
244 | } | ||
245 | |||
246 | err = os_pipe(p->thread.mode.tt.switch_pipe, 1, 1); | ||
247 | if(err < 0){ | ||
248 | printk("copy_thread : pipe failed, err = %d\n", -err); | ||
249 | return(err); | ||
250 | } | ||
251 | |||
252 | stack = alloc_stack(0, 0); | ||
253 | if(stack == 0){ | ||
254 | printk(KERN_ERR "copy_thread : failed to allocate " | ||
255 | "temporary stack\n"); | ||
256 | return(-ENOMEM); | ||
257 | } | ||
258 | |||
259 | clone_flags &= CLONE_VM; | ||
260 | p->thread.temp_stack = stack; | ||
261 | new_pid = start_fork_tramp(task_stack_page(p), stack, clone_flags, tramp); | ||
262 | if(new_pid < 0){ | ||
263 | printk(KERN_ERR "copy_thread : clone failed - errno = %d\n", | ||
264 | -new_pid); | ||
265 | return(new_pid); | ||
266 | } | ||
267 | |||
268 | if(current->thread.forking){ | ||
269 | sc_to_sc(UPT_SC(&p->thread.regs.regs), UPT_SC(®s->regs)); | ||
270 | SC_SET_SYSCALL_RETURN(UPT_SC(&p->thread.regs.regs), 0); | ||
271 | if(sp != 0) | ||
272 | SC_SP(UPT_SC(&p->thread.regs.regs)) = sp; | ||
273 | } | ||
274 | p->thread.mode.tt.extern_pid = new_pid; | ||
275 | |||
276 | current->thread.request.op = OP_FORK; | ||
277 | current->thread.request.u.fork.pid = new_pid; | ||
278 | os_usr1_process(os_getpid()); | ||
279 | |||
280 | /* Enable the signal and then disable it to ensure that it is handled | ||
281 | * here, and nowhere else. | ||
282 | */ | ||
283 | change_sig(SIGUSR1, 1); | ||
284 | |||
285 | change_sig(SIGUSR1, 0); | ||
286 | err = 0; | ||
287 | return(err); | ||
288 | } | ||
289 | |||
290 | void reboot_tt(void) | ||
291 | { | ||
292 | current->thread.request.op = OP_REBOOT; | ||
293 | os_usr1_process(os_getpid()); | ||
294 | change_sig(SIGUSR1, 1); | ||
295 | } | ||
296 | |||
297 | void halt_tt(void) | ||
298 | { | ||
299 | current->thread.request.op = OP_HALT; | ||
300 | os_usr1_process(os_getpid()); | ||
301 | change_sig(SIGUSR1, 1); | ||
302 | } | ||
303 | |||
304 | void kill_off_processes_tt(void) | ||
305 | { | ||
306 | struct task_struct *p; | ||
307 | int me; | ||
308 | |||
309 | me = os_getpid(); | ||
310 | for_each_process(p){ | ||
311 | if(p->thread.mode.tt.extern_pid != me) | ||
312 | os_kill_process(p->thread.mode.tt.extern_pid, 0); | ||
313 | } | ||
314 | if(init_task.thread.mode.tt.extern_pid != me) | ||
315 | os_kill_process(init_task.thread.mode.tt.extern_pid, 0); | ||
316 | } | ||
317 | |||
318 | void initial_thread_cb_tt(void (*proc)(void *), void *arg) | ||
319 | { | ||
320 | if(os_getpid() == tracing_pid){ | ||
321 | (*proc)(arg); | ||
322 | } | ||
323 | else { | ||
324 | current->thread.request.op = OP_CB; | ||
325 | current->thread.request.u.cb.proc = proc; | ||
326 | current->thread.request.u.cb.arg = arg; | ||
327 | os_usr1_process(os_getpid()); | ||
328 | change_sig(SIGUSR1, 1); | ||
329 | |||
330 | change_sig(SIGUSR1, 0); | ||
331 | } | ||
332 | } | ||
333 | |||
334 | int do_proc_op(void *t, int proc_id) | ||
335 | { | ||
336 | struct task_struct *task; | ||
337 | struct thread_struct *thread; | ||
338 | int op, pid; | ||
339 | |||
340 | task = t; | ||
341 | thread = &task->thread; | ||
342 | op = thread->request.op; | ||
343 | switch(op){ | ||
344 | case OP_NONE: | ||
345 | case OP_TRACE_ON: | ||
346 | break; | ||
347 | case OP_EXEC: | ||
348 | pid = thread->request.u.exec.pid; | ||
349 | do_exec(thread->mode.tt.extern_pid, pid); | ||
350 | thread->mode.tt.extern_pid = pid; | ||
351 | cpu_tasks[task_thread_info(task)->cpu].pid = pid; | ||
352 | break; | ||
353 | case OP_FORK: | ||
354 | attach_process(thread->request.u.fork.pid); | ||
355 | break; | ||
356 | case OP_CB: | ||
357 | (*thread->request.u.cb.proc)(thread->request.u.cb.arg); | ||
358 | break; | ||
359 | case OP_REBOOT: | ||
360 | case OP_HALT: | ||
361 | break; | ||
362 | default: | ||
363 | tracer_panic("Bad op in do_proc_op"); | ||
364 | break; | ||
365 | } | ||
366 | thread->request.op = OP_NONE; | ||
367 | return(op); | ||
368 | } | ||
369 | |||
370 | void init_idle_tt(void) | ||
371 | { | ||
372 | default_idle(); | ||
373 | } | ||
374 | |||
375 | extern void start_kernel(void); | ||
376 | |||
377 | static int start_kernel_proc(void *unused) | ||
378 | { | ||
379 | int pid; | ||
380 | |||
381 | block_signals(); | ||
382 | pid = os_getpid(); | ||
383 | |||
384 | cpu_tasks[0].pid = pid; | ||
385 | cpu_tasks[0].task = current; | ||
386 | #ifdef CONFIG_SMP | ||
387 | cpu_online_map = cpumask_of_cpu(0); | ||
388 | #endif | ||
389 | if(debug) os_stop_process(pid); | ||
390 | start_kernel(); | ||
391 | return(0); | ||
392 | } | ||
393 | |||
394 | void set_tracing(void *task, int tracing) | ||
395 | { | ||
396 | ((struct task_struct *) task)->thread.mode.tt.tracing = tracing; | ||
397 | } | ||
398 | |||
399 | int is_tracing(void *t) | ||
400 | { | ||
401 | return (((struct task_struct *) t)->thread.mode.tt.tracing); | ||
402 | } | ||
403 | |||
404 | int set_user_mode(void *t) | ||
405 | { | ||
406 | struct task_struct *task; | ||
407 | |||
408 | task = t ? t : current; | ||
409 | if(task->thread.mode.tt.tracing) | ||
410 | return(1); | ||
411 | task->thread.request.op = OP_TRACE_ON; | ||
412 | os_usr1_process(os_getpid()); | ||
413 | return(0); | ||
414 | } | ||
415 | |||
416 | void set_init_pid(int pid) | ||
417 | { | ||
418 | int err; | ||
419 | |||
420 | init_task.thread.mode.tt.extern_pid = pid; | ||
421 | err = os_pipe(init_task.thread.mode.tt.switch_pipe, 1, 1); | ||
422 | if(err) | ||
423 | panic("Can't create switch pipe for init_task, errno = %d", | ||
424 | -err); | ||
425 | } | ||
426 | |||
427 | int start_uml_tt(void) | ||
428 | { | ||
429 | void *sp; | ||
430 | int pages; | ||
431 | |||
432 | pages = (1 << CONFIG_KERNEL_STACK_ORDER); | ||
433 | sp = task_stack_page(&init_task) + | ||
434 | pages * PAGE_SIZE - sizeof(unsigned long); | ||
435 | return(tracer(start_kernel_proc, sp)); | ||
436 | } | ||
437 | |||
438 | int external_pid_tt(struct task_struct *task) | ||
439 | { | ||
440 | return(task->thread.mode.tt.extern_pid); | ||
441 | } | ||
442 | |||
443 | int thread_pid_tt(struct task_struct *task) | ||
444 | { | ||
445 | return(task->thread.mode.tt.extern_pid); | ||
446 | } | ||
447 | |||
448 | int is_valid_pid(int pid) | ||
449 | { | ||
450 | struct task_struct *task; | ||
451 | |||
452 | read_lock(&tasklist_lock); | ||
453 | for_each_process(task){ | ||
454 | if(task->thread.mode.tt.extern_pid == pid){ | ||
455 | read_unlock(&tasklist_lock); | ||
456 | return(1); | ||
457 | } | ||
458 | } | ||
459 | read_unlock(&tasklist_lock); | ||
460 | return(0); | ||
461 | } | ||
diff --git a/arch/um/kernel/tt/ptproxy/Makefile b/arch/um/kernel/tt/ptproxy/Makefile deleted file mode 100644 index 3ad5b774de59..000000000000 --- a/arch/um/kernel/tt/ptproxy/Makefile +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | # | ||
2 | # Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | # Licensed under the GPL | ||
4 | # | ||
5 | |||
6 | obj-y = proxy.o ptrace.o sysdep.o wait.o | ||
7 | |||
8 | USER_OBJS := $(obj-y) | ||
9 | |||
10 | include arch/um/scripts/Makefile.rules | ||
diff --git a/arch/um/kernel/tt/ptproxy/proxy.c b/arch/um/kernel/tt/ptproxy/proxy.c deleted file mode 100644 index 420c23f311f3..000000000000 --- a/arch/um/kernel/tt/ptproxy/proxy.c +++ /dev/null | |||
@@ -1,377 +0,0 @@ | |||
1 | /********************************************************************** | ||
2 | proxy.c | ||
3 | |||
4 | Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing | ||
5 | terms and conditions. | ||
6 | |||
7 | Jeff Dike (jdike@karaya.com) : Modified for integration into uml | ||
8 | **********************************************************************/ | ||
9 | |||
10 | /* XXX This file shouldn't refer to CONFIG_* */ | ||
11 | |||
12 | #include <errno.h> | ||
13 | #include <stdio.h> | ||
14 | #include <stdlib.h> | ||
15 | #include <unistd.h> | ||
16 | #include <signal.h> | ||
17 | #include <string.h> | ||
18 | #include <termios.h> | ||
19 | #include <sys/wait.h> | ||
20 | #include <sys/types.h> | ||
21 | #include <sys/ioctl.h> | ||
22 | #include <asm/unistd.h> | ||
23 | #include "ptrace_user.h" | ||
24 | |||
25 | #include "ptproxy.h" | ||
26 | #include "sysdep.h" | ||
27 | #include "wait.h" | ||
28 | |||
29 | #include "user.h" | ||
30 | #include "os.h" | ||
31 | #include "tempfile.h" | ||
32 | |||
33 | static int debugger_wait(debugger_state *debugger, int *status, int options, | ||
34 | int (*syscall)(debugger_state *debugger, pid_t child), | ||
35 | int (*normal_return)(debugger_state *debugger, | ||
36 | pid_t unused), | ||
37 | int (*wait_return)(debugger_state *debugger, | ||
38 | pid_t unused)) | ||
39 | { | ||
40 | if(debugger->real_wait){ | ||
41 | debugger->handle_trace = normal_return; | ||
42 | syscall_continue(debugger->pid); | ||
43 | debugger->real_wait = 0; | ||
44 | return(1); | ||
45 | } | ||
46 | debugger->wait_status_ptr = status; | ||
47 | debugger->wait_options = options; | ||
48 | if((debugger->debugee != NULL) && debugger->debugee->event){ | ||
49 | syscall_continue(debugger->pid); | ||
50 | wait_for_stop(debugger->pid, SIGTRAP, PTRACE_SYSCALL, | ||
51 | NULL); | ||
52 | (*wait_return)(debugger, -1); | ||
53 | return(0); | ||
54 | } | ||
55 | else if(debugger->wait_options & WNOHANG){ | ||
56 | syscall_cancel(debugger->pid, 0); | ||
57 | debugger->handle_trace = syscall; | ||
58 | return(0); | ||
59 | } | ||
60 | else { | ||
61 | syscall_pause(debugger->pid); | ||
62 | debugger->handle_trace = wait_return; | ||
63 | debugger->waiting = 1; | ||
64 | } | ||
65 | return(1); | ||
66 | } | ||
67 | |||
68 | /* | ||
69 | * Handle debugger trap, i.e. syscall. | ||
70 | */ | ||
71 | |||
72 | int debugger_syscall(debugger_state *debugger, pid_t child) | ||
73 | { | ||
74 | long arg1, arg2, arg3, arg4, arg5, result; | ||
75 | int syscall, ret = 0; | ||
76 | |||
77 | syscall = get_syscall(debugger->pid, &arg1, &arg2, &arg3, &arg4, | ||
78 | &arg5); | ||
79 | |||
80 | switch(syscall){ | ||
81 | case __NR_execve: | ||
82 | /* execve never returns */ | ||
83 | debugger->handle_trace = debugger_syscall; | ||
84 | break; | ||
85 | |||
86 | case __NR_ptrace: | ||
87 | if(debugger->debugee->pid != 0) arg2 = debugger->debugee->pid; | ||
88 | if(!debugger->debugee->in_context) | ||
89 | child = debugger->debugee->pid; | ||
90 | result = proxy_ptrace(debugger, arg1, arg2, arg3, arg4, child, | ||
91 | &ret); | ||
92 | syscall_cancel(debugger->pid, result); | ||
93 | debugger->handle_trace = debugger_syscall; | ||
94 | return(ret); | ||
95 | |||
96 | #ifdef __NR_waitpid | ||
97 | case __NR_waitpid: | ||
98 | #endif | ||
99 | case __NR_wait4: | ||
100 | if(!debugger_wait(debugger, (int *) arg2, arg3, | ||
101 | debugger_syscall, debugger_normal_return, | ||
102 | proxy_wait_return)) | ||
103 | return(0); | ||
104 | break; | ||
105 | |||
106 | case __NR_kill: | ||
107 | if(!debugger->debugee->in_context) | ||
108 | child = debugger->debugee->pid; | ||
109 | if(arg1 == debugger->debugee->pid){ | ||
110 | result = kill(child, arg2); | ||
111 | syscall_cancel(debugger->pid, result); | ||
112 | debugger->handle_trace = debugger_syscall; | ||
113 | return(0); | ||
114 | } | ||
115 | else debugger->handle_trace = debugger_normal_return; | ||
116 | break; | ||
117 | |||
118 | default: | ||
119 | debugger->handle_trace = debugger_normal_return; | ||
120 | } | ||
121 | |||
122 | syscall_continue(debugger->pid); | ||
123 | return(0); | ||
124 | } | ||
125 | |||
126 | /* Used by the tracing thread */ | ||
127 | static debugger_state parent; | ||
128 | static int parent_syscall(debugger_state *debugger, int pid); | ||
129 | |||
130 | int init_parent_proxy(int pid) | ||
131 | { | ||
132 | parent = ((debugger_state) { .pid = pid, | ||
133 | .wait_options = 0, | ||
134 | .wait_status_ptr = NULL, | ||
135 | .waiting = 0, | ||
136 | .real_wait = 0, | ||
137 | .expecting_child = 0, | ||
138 | .handle_trace = parent_syscall, | ||
139 | .debugee = NULL } ); | ||
140 | return(0); | ||
141 | } | ||
142 | |||
143 | int parent_normal_return(debugger_state *debugger, pid_t unused) | ||
144 | { | ||
145 | debugger->handle_trace = parent_syscall; | ||
146 | syscall_continue(debugger->pid); | ||
147 | return(0); | ||
148 | } | ||
149 | |||
150 | static int parent_syscall(debugger_state *debugger, int pid) | ||
151 | { | ||
152 | long arg1, arg2, arg3, arg4, arg5; | ||
153 | int syscall; | ||
154 | |||
155 | syscall = get_syscall(pid, &arg1, &arg2, &arg3, &arg4, &arg5); | ||
156 | |||
157 | if((syscall == __NR_wait4) | ||
158 | #ifdef __NR_waitpid | ||
159 | || (syscall == __NR_waitpid) | ||
160 | #endif | ||
161 | ){ | ||
162 | debugger_wait(&parent, (int *) arg2, arg3, parent_syscall, | ||
163 | parent_normal_return, parent_wait_return); | ||
164 | } | ||
165 | else ptrace(PTRACE_SYSCALL, pid, 0, 0); | ||
166 | return(0); | ||
167 | } | ||
168 | |||
169 | int debugger_normal_return(debugger_state *debugger, pid_t unused) | ||
170 | { | ||
171 | debugger->handle_trace = debugger_syscall; | ||
172 | syscall_continue(debugger->pid); | ||
173 | return(0); | ||
174 | } | ||
175 | |||
176 | void debugger_cancelled_return(debugger_state *debugger, int result) | ||
177 | { | ||
178 | debugger->handle_trace = debugger_syscall; | ||
179 | syscall_set_result(debugger->pid, result); | ||
180 | syscall_continue(debugger->pid); | ||
181 | } | ||
182 | |||
183 | /* Used by the tracing thread */ | ||
184 | static debugger_state debugger; | ||
185 | static debugee_state debugee; | ||
186 | |||
187 | void init_proxy (pid_t debugger_pid, int stopped, int status) | ||
188 | { | ||
189 | debugger.pid = debugger_pid; | ||
190 | debugger.handle_trace = debugger_syscall; | ||
191 | debugger.debugee = &debugee; | ||
192 | debugger.waiting = 0; | ||
193 | debugger.real_wait = 0; | ||
194 | debugger.expecting_child = 0; | ||
195 | |||
196 | debugee.pid = 0; | ||
197 | debugee.traced = 0; | ||
198 | debugee.stopped = stopped; | ||
199 | debugee.event = 0; | ||
200 | debugee.zombie = 0; | ||
201 | debugee.died = 0; | ||
202 | debugee.wait_status = status; | ||
203 | debugee.in_context = 1; | ||
204 | } | ||
205 | |||
206 | int debugger_proxy(int status, int pid) | ||
207 | { | ||
208 | int ret = 0, sig; | ||
209 | |||
210 | if(WIFSTOPPED(status)){ | ||
211 | sig = WSTOPSIG(status); | ||
212 | if (sig == SIGTRAP) | ||
213 | ret = (*debugger.handle_trace)(&debugger, pid); | ||
214 | |||
215 | else if(sig == SIGCHLD){ | ||
216 | if(debugger.expecting_child){ | ||
217 | ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig); | ||
218 | debugger.expecting_child = 0; | ||
219 | } | ||
220 | else if(debugger.waiting) | ||
221 | real_wait_return(&debugger); | ||
222 | else { | ||
223 | ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig); | ||
224 | debugger.real_wait = 1; | ||
225 | } | ||
226 | } | ||
227 | else ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig); | ||
228 | } | ||
229 | else if(WIFEXITED(status)){ | ||
230 | tracer_panic("debugger (pid %d) exited with status %d", | ||
231 | debugger.pid, WEXITSTATUS(status)); | ||
232 | } | ||
233 | else if(WIFSIGNALED(status)){ | ||
234 | tracer_panic("debugger (pid %d) exited with signal %d", | ||
235 | debugger.pid, WTERMSIG(status)); | ||
236 | } | ||
237 | else { | ||
238 | tracer_panic("proxy got unknown status (0x%x) on debugger " | ||
239 | "(pid %d)", status, debugger.pid); | ||
240 | } | ||
241 | return(ret); | ||
242 | } | ||
243 | |||
244 | void child_proxy(pid_t pid, int status) | ||
245 | { | ||
246 | debugee.event = 1; | ||
247 | debugee.wait_status = status; | ||
248 | |||
249 | if(WIFSTOPPED(status)){ | ||
250 | debugee.stopped = 1; | ||
251 | debugger.expecting_child = 1; | ||
252 | kill(debugger.pid, SIGCHLD); | ||
253 | } | ||
254 | else if(WIFEXITED(status) || WIFSIGNALED(status)){ | ||
255 | debugee.zombie = 1; | ||
256 | debugger.expecting_child = 1; | ||
257 | kill(debugger.pid, SIGCHLD); | ||
258 | } | ||
259 | else panic("proxy got unknown status (0x%x) on child (pid %d)", | ||
260 | status, pid); | ||
261 | } | ||
262 | |||
263 | void debugger_parent_signal(int status, int pid) | ||
264 | { | ||
265 | int sig; | ||
266 | |||
267 | if(WIFSTOPPED(status)){ | ||
268 | sig = WSTOPSIG(status); | ||
269 | if(sig == SIGTRAP) (*parent.handle_trace)(&parent, pid); | ||
270 | else ptrace(PTRACE_SYSCALL, pid, 0, sig); | ||
271 | } | ||
272 | } | ||
273 | |||
274 | void fake_child_exit(void) | ||
275 | { | ||
276 | int status, pid; | ||
277 | |||
278 | child_proxy(1, W_EXITCODE(0, 0)); | ||
279 | while(debugger.waiting == 1){ | ||
280 | CATCH_EINTR(pid = waitpid(debugger.pid, &status, WUNTRACED)); | ||
281 | if(pid != debugger.pid){ | ||
282 | printk("fake_child_exit - waitpid failed, " | ||
283 | "errno = %d\n", errno); | ||
284 | return; | ||
285 | } | ||
286 | debugger_proxy(status, debugger.pid); | ||
287 | } | ||
288 | CATCH_EINTR(pid = waitpid(debugger.pid, &status, WUNTRACED)); | ||
289 | if(pid != debugger.pid){ | ||
290 | printk("fake_child_exit - waitpid failed, " | ||
291 | "errno = %d\n", errno); | ||
292 | return; | ||
293 | } | ||
294 | if(ptrace(PTRACE_DETACH, debugger.pid, 0, SIGCONT) < 0) | ||
295 | printk("fake_child_exit - PTRACE_DETACH failed, errno = %d\n", | ||
296 | errno); | ||
297 | } | ||
298 | |||
299 | char gdb_init_string[] = | ||
300 | "att 1 \n\ | ||
301 | b panic \n\ | ||
302 | b stop \n\ | ||
303 | handle SIGWINCH nostop noprint pass \n\ | ||
304 | "; | ||
305 | |||
306 | int start_debugger(char *prog, int startup, int stop, int *fd_out) | ||
307 | { | ||
308 | int slave, child; | ||
309 | |||
310 | slave = open_gdb_chan(); | ||
311 | child = fork(); | ||
312 | if(child == 0){ | ||
313 | char *tempname = NULL; | ||
314 | int fd; | ||
315 | |||
316 | if(setsid() < 0) perror("setsid"); | ||
317 | if((dup2(slave, 0) < 0) || (dup2(slave, 1) < 0) || | ||
318 | (dup2(slave, 2) < 0)){ | ||
319 | printk("start_debugger : dup2 failed, errno = %d\n", | ||
320 | errno); | ||
321 | exit(1); | ||
322 | } | ||
323 | if(ioctl(0, TIOCSCTTY, 0) < 0){ | ||
324 | printk("start_debugger : TIOCSCTTY failed, " | ||
325 | "errno = %d\n", errno); | ||
326 | exit(1); | ||
327 | } | ||
328 | if(tcsetpgrp (1, os_getpid()) < 0){ | ||
329 | printk("start_debugger : tcsetpgrp failed, " | ||
330 | "errno = %d\n", errno); | ||
331 | #ifdef notdef | ||
332 | exit(1); | ||
333 | #endif | ||
334 | } | ||
335 | fd = make_tempfile("/tmp/gdb_init-XXXXXX", &tempname, 0); | ||
336 | if(fd < 0){ | ||
337 | printk("start_debugger : make_tempfile failed," | ||
338 | "err = %d\n", -fd); | ||
339 | exit(1); | ||
340 | } | ||
341 | os_write_file(fd, gdb_init_string, | ||
342 | sizeof(gdb_init_string) - 1); | ||
343 | if(startup){ | ||
344 | if(stop){ | ||
345 | os_write_file(fd, "b start_kernel\n", | ||
346 | strlen("b start_kernel\n")); | ||
347 | } | ||
348 | os_write_file(fd, "c\n", strlen("c\n")); | ||
349 | } | ||
350 | if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){ | ||
351 | printk("start_debugger : PTRACE_TRACEME failed, " | ||
352 | "errno = %d\n", errno); | ||
353 | exit(1); | ||
354 | } | ||
355 | execlp("gdb", "gdb", "--command", tempname, prog, NULL); | ||
356 | printk("start_debugger : exec of gdb failed, errno = %d\n", | ||
357 | errno); | ||
358 | } | ||
359 | if(child < 0){ | ||
360 | printk("start_debugger : fork for gdb failed, errno = %d\n", | ||
361 | errno); | ||
362 | return(-1); | ||
363 | } | ||
364 | *fd_out = slave; | ||
365 | return(child); | ||
366 | } | ||
367 | |||
368 | /* | ||
369 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
370 | * Emacs will notice this stuff at the end of the file and automatically | ||
371 | * adjust the settings for this buffer only. This must remain at the end | ||
372 | * of the file. | ||
373 | * --------------------------------------------------------------------------- | ||
374 | * Local variables: | ||
375 | * c-file-style: "linux" | ||
376 | * End: | ||
377 | */ | ||
diff --git a/arch/um/kernel/tt/ptproxy/ptproxy.h b/arch/um/kernel/tt/ptproxy/ptproxy.h deleted file mode 100644 index 5eb0285b1968..000000000000 --- a/arch/um/kernel/tt/ptproxy/ptproxy.h +++ /dev/null | |||
@@ -1,61 +0,0 @@ | |||
1 | /********************************************************************** | ||
2 | ptproxy.h | ||
3 | |||
4 | Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing | ||
5 | terms and conditions. | ||
6 | **********************************************************************/ | ||
7 | |||
8 | #ifndef __PTPROXY_H | ||
9 | #define __PTPROXY_H | ||
10 | |||
11 | #include <sys/types.h> | ||
12 | |||
13 | typedef struct debugger debugger_state; | ||
14 | typedef struct debugee debugee_state; | ||
15 | |||
16 | struct debugger | ||
17 | { | ||
18 | pid_t pid; | ||
19 | int wait_options; | ||
20 | int *wait_status_ptr; | ||
21 | unsigned int waiting : 1; | ||
22 | unsigned int real_wait : 1; | ||
23 | unsigned int expecting_child : 1; | ||
24 | int (*handle_trace) (debugger_state *, pid_t); | ||
25 | |||
26 | debugee_state *debugee; | ||
27 | }; | ||
28 | |||
29 | struct debugee | ||
30 | { | ||
31 | pid_t pid; | ||
32 | int wait_status; | ||
33 | unsigned int died : 1; | ||
34 | unsigned int event : 1; | ||
35 | unsigned int stopped : 1; | ||
36 | unsigned int trace_singlestep : 1; | ||
37 | unsigned int trace_syscall : 1; | ||
38 | unsigned int traced : 1; | ||
39 | unsigned int zombie : 1; | ||
40 | unsigned int in_context : 1; | ||
41 | }; | ||
42 | |||
43 | extern int debugger_syscall(debugger_state *debugger, pid_t pid); | ||
44 | extern int debugger_normal_return (debugger_state *debugger, pid_t unused); | ||
45 | |||
46 | extern long proxy_ptrace (struct debugger *, int, pid_t, long, long, pid_t, | ||
47 | int *strace_out); | ||
48 | extern void debugger_cancelled_return(debugger_state *debugger, int result); | ||
49 | |||
50 | #endif | ||
51 | |||
52 | /* | ||
53 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
54 | * Emacs will notice this stuff at the end of the file and automatically | ||
55 | * adjust the settings for this buffer only. This must remain at the end | ||
56 | * of the file. | ||
57 | * --------------------------------------------------------------------------- | ||
58 | * Local variables: | ||
59 | * c-file-style: "linux" | ||
60 | * End: | ||
61 | */ | ||
diff --git a/arch/um/kernel/tt/ptproxy/ptrace.c b/arch/um/kernel/tt/ptproxy/ptrace.c deleted file mode 100644 index 4b4f6179b212..000000000000 --- a/arch/um/kernel/tt/ptproxy/ptrace.c +++ /dev/null | |||
@@ -1,237 +0,0 @@ | |||
1 | /********************************************************************** | ||
2 | ptrace.c | ||
3 | |||
4 | Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing | ||
5 | terms and conditions. | ||
6 | |||
7 | Jeff Dike (jdike@karaya.com) : Modified for integration into uml | ||
8 | **********************************************************************/ | ||
9 | |||
10 | #include <errno.h> | ||
11 | #include <unistd.h> | ||
12 | #include <signal.h> | ||
13 | #include <sys/types.h> | ||
14 | #include <sys/time.h> | ||
15 | #include <sys/wait.h> | ||
16 | |||
17 | #include "ptproxy.h" | ||
18 | #include "debug.h" | ||
19 | #include "kern_util.h" | ||
20 | #include "ptrace_user.h" | ||
21 | #include "tt.h" | ||
22 | #include "os.h" | ||
23 | |||
24 | long proxy_ptrace(struct debugger *debugger, int arg1, pid_t arg2, | ||
25 | long arg3, long arg4, pid_t child, int *ret) | ||
26 | { | ||
27 | sigset_t relay; | ||
28 | long result; | ||
29 | int status; | ||
30 | |||
31 | *ret = 0; | ||
32 | if(debugger->debugee->died) return(-ESRCH); | ||
33 | |||
34 | switch(arg1){ | ||
35 | case PTRACE_ATTACH: | ||
36 | if(debugger->debugee->traced) return(-EPERM); | ||
37 | |||
38 | debugger->debugee->pid = arg2; | ||
39 | debugger->debugee->traced = 1; | ||
40 | |||
41 | if(is_valid_pid(arg2) && (arg2 != child)){ | ||
42 | debugger->debugee->in_context = 0; | ||
43 | kill(arg2, SIGSTOP); | ||
44 | debugger->debugee->event = 1; | ||
45 | debugger->debugee->wait_status = W_STOPCODE(SIGSTOP); | ||
46 | } | ||
47 | else { | ||
48 | debugger->debugee->in_context = 1; | ||
49 | if(debugger->debugee->stopped) | ||
50 | child_proxy(child, W_STOPCODE(SIGSTOP)); | ||
51 | else kill(child, SIGSTOP); | ||
52 | } | ||
53 | |||
54 | return(0); | ||
55 | |||
56 | case PTRACE_DETACH: | ||
57 | if(!debugger->debugee->traced) return(-EPERM); | ||
58 | |||
59 | debugger->debugee->traced = 0; | ||
60 | debugger->debugee->pid = 0; | ||
61 | if(!debugger->debugee->in_context) | ||
62 | kill(child, SIGCONT); | ||
63 | |||
64 | return(0); | ||
65 | |||
66 | case PTRACE_CONT: | ||
67 | if(!debugger->debugee->in_context) return(-EPERM); | ||
68 | *ret = PTRACE_CONT; | ||
69 | return(ptrace(PTRACE_CONT, child, arg3, arg4)); | ||
70 | |||
71 | #ifdef UM_HAVE_GETFPREGS | ||
72 | case PTRACE_GETFPREGS: | ||
73 | { | ||
74 | long regs[FP_FRAME_SIZE]; | ||
75 | int i, result; | ||
76 | |||
77 | result = ptrace(PTRACE_GETFPREGS, child, 0, regs); | ||
78 | if(result == -1) return(-errno); | ||
79 | |||
80 | for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) | ||
81 | ptrace(PTRACE_POKEDATA, debugger->pid, arg4 + 4 * i, | ||
82 | regs[i]); | ||
83 | return(result); | ||
84 | } | ||
85 | #endif | ||
86 | |||
87 | #ifdef UM_HAVE_GETFPXREGS | ||
88 | case PTRACE_GETFPXREGS: | ||
89 | { | ||
90 | long regs[FPX_FRAME_SIZE]; | ||
91 | int i, result; | ||
92 | |||
93 | result = ptrace(PTRACE_GETFPXREGS, child, 0, regs); | ||
94 | if(result == -1) return(-errno); | ||
95 | |||
96 | for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) | ||
97 | ptrace(PTRACE_POKEDATA, debugger->pid, arg4 + 4 * i, | ||
98 | regs[i]); | ||
99 | return(result); | ||
100 | } | ||
101 | #endif | ||
102 | |||
103 | #ifdef UM_HAVE_GETREGS | ||
104 | case PTRACE_GETREGS: | ||
105 | { | ||
106 | long regs[FRAME_SIZE]; | ||
107 | int i, result; | ||
108 | |||
109 | result = ptrace(PTRACE_GETREGS, child, 0, regs); | ||
110 | if(result == -1) return(-errno); | ||
111 | |||
112 | for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) | ||
113 | ptrace (PTRACE_POKEDATA, debugger->pid, | ||
114 | arg4 + 4 * i, regs[i]); | ||
115 | return(result); | ||
116 | } | ||
117 | break; | ||
118 | #endif | ||
119 | |||
120 | case PTRACE_KILL: | ||
121 | result = ptrace(PTRACE_KILL, child, arg3, arg4); | ||
122 | if(result == -1) return(-errno); | ||
123 | |||
124 | return(result); | ||
125 | |||
126 | case PTRACE_PEEKDATA: | ||
127 | case PTRACE_PEEKTEXT: | ||
128 | case PTRACE_PEEKUSR: | ||
129 | /* The value being read out could be -1, so we have to | ||
130 | * check errno to see if there's an error, and zero it | ||
131 | * beforehand so we're not faked out by an old error | ||
132 | */ | ||
133 | |||
134 | errno = 0; | ||
135 | result = ptrace(arg1, child, arg3, 0); | ||
136 | if((result == -1) && (errno != 0)) return(-errno); | ||
137 | |||
138 | result = ptrace(PTRACE_POKEDATA, debugger->pid, arg4, result); | ||
139 | if(result == -1) return(-errno); | ||
140 | |||
141 | return(result); | ||
142 | |||
143 | case PTRACE_POKEDATA: | ||
144 | case PTRACE_POKETEXT: | ||
145 | case PTRACE_POKEUSR: | ||
146 | result = ptrace(arg1, child, arg3, arg4); | ||
147 | if(result == -1) return(-errno); | ||
148 | |||
149 | if(arg1 == PTRACE_POKEUSR) ptrace_pokeuser(arg3, arg4); | ||
150 | return(result); | ||
151 | |||
152 | #ifdef UM_HAVE_SETFPREGS | ||
153 | case PTRACE_SETFPREGS: | ||
154 | { | ||
155 | long regs[FP_FRAME_SIZE]; | ||
156 | int i; | ||
157 | |||
158 | for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) | ||
159 | regs[i] = ptrace (PTRACE_PEEKDATA, debugger->pid, | ||
160 | arg4 + 4 * i, 0); | ||
161 | result = ptrace(PTRACE_SETFPREGS, child, 0, regs); | ||
162 | if(result == -1) return(-errno); | ||
163 | |||
164 | return(result); | ||
165 | } | ||
166 | #endif | ||
167 | |||
168 | #ifdef UM_HAVE_SETFPXREGS | ||
169 | case PTRACE_SETFPXREGS: | ||
170 | { | ||
171 | long regs[FPX_FRAME_SIZE]; | ||
172 | int i; | ||
173 | |||
174 | for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) | ||
175 | regs[i] = ptrace (PTRACE_PEEKDATA, debugger->pid, | ||
176 | arg4 + 4 * i, 0); | ||
177 | result = ptrace(PTRACE_SETFPXREGS, child, 0, regs); | ||
178 | if(result == -1) return(-errno); | ||
179 | |||
180 | return(result); | ||
181 | } | ||
182 | #endif | ||
183 | |||
184 | #ifdef UM_HAVE_SETREGS | ||
185 | case PTRACE_SETREGS: | ||
186 | { | ||
187 | long regs[FRAME_SIZE]; | ||
188 | int i; | ||
189 | |||
190 | for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) | ||
191 | regs[i] = ptrace(PTRACE_PEEKDATA, debugger->pid, | ||
192 | arg4 + 4 * i, 0); | ||
193 | result = ptrace(PTRACE_SETREGS, child, 0, regs); | ||
194 | if(result == -1) return(-errno); | ||
195 | |||
196 | return(result); | ||
197 | } | ||
198 | #endif | ||
199 | |||
200 | case PTRACE_SINGLESTEP: | ||
201 | if(!debugger->debugee->in_context) return(-EPERM); | ||
202 | sigemptyset(&relay); | ||
203 | sigaddset(&relay, SIGSEGV); | ||
204 | sigaddset(&relay, SIGILL); | ||
205 | sigaddset(&relay, SIGBUS); | ||
206 | result = ptrace(PTRACE_SINGLESTEP, child, arg3, arg4); | ||
207 | if(result == -1) return(-errno); | ||
208 | |||
209 | status = wait_for_stop(child, SIGTRAP, PTRACE_SINGLESTEP, | ||
210 | &relay); | ||
211 | child_proxy(child, status); | ||
212 | return(result); | ||
213 | |||
214 | case PTRACE_SYSCALL: | ||
215 | if(!debugger->debugee->in_context) return(-EPERM); | ||
216 | result = ptrace(PTRACE_SYSCALL, child, arg3, arg4); | ||
217 | if(result == -1) return(-errno); | ||
218 | |||
219 | *ret = PTRACE_SYSCALL; | ||
220 | return(result); | ||
221 | |||
222 | case PTRACE_TRACEME: | ||
223 | default: | ||
224 | return(-EINVAL); | ||
225 | } | ||
226 | } | ||
227 | |||
228 | /* | ||
229 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
230 | * Emacs will notice this stuff at the end of the file and automatically | ||
231 | * adjust the settings for this buffer only. This must remain at the end | ||
232 | * of the file. | ||
233 | * --------------------------------------------------------------------------- | ||
234 | * Local variables: | ||
235 | * c-file-style: "linux" | ||
236 | * End: | ||
237 | */ | ||
diff --git a/arch/um/kernel/tt/ptproxy/sysdep.c b/arch/um/kernel/tt/ptproxy/sysdep.c deleted file mode 100644 index e0e1ab0588ad..000000000000 --- a/arch/um/kernel/tt/ptproxy/sysdep.c +++ /dev/null | |||
@@ -1,70 +0,0 @@ | |||
1 | /********************************************************************** | ||
2 | sysdep.c | ||
3 | |||
4 | Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing | ||
5 | terms and conditions. | ||
6 | **********************************************************************/ | ||
7 | |||
8 | #include <stdio.h> | ||
9 | #include <string.h> | ||
10 | #include <stdlib.h> | ||
11 | #include <signal.h> | ||
12 | #include <errno.h> | ||
13 | #include <sys/types.h> | ||
14 | #include <linux/unistd.h> | ||
15 | #include "ptrace_user.h" | ||
16 | #include "user.h" | ||
17 | #include "os.h" | ||
18 | |||
19 | int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, long *arg4, | ||
20 | long *arg5) | ||
21 | { | ||
22 | *arg1 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG1_OFFSET, 0); | ||
23 | *arg2 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG2_OFFSET, 0); | ||
24 | *arg3 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG3_OFFSET, 0); | ||
25 | *arg4 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG4_OFFSET, 0); | ||
26 | *arg5 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG5_OFFSET, 0); | ||
27 | return(ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET, 0)); | ||
28 | } | ||
29 | |||
30 | void syscall_cancel(pid_t pid, int result) | ||
31 | { | ||
32 | if((ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, | ||
33 | __NR_getpid) < 0) || | ||
34 | (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) || | ||
35 | (wait_for_stop(pid, SIGTRAP, PTRACE_SYSCALL, NULL) < 0) || | ||
36 | (ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, result) < 0) || | ||
37 | (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)) | ||
38 | printk("ptproxy: couldn't cancel syscall: errno = %d\n", | ||
39 | errno); | ||
40 | } | ||
41 | |||
42 | void syscall_set_result(pid_t pid, long result) | ||
43 | { | ||
44 | ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, result); | ||
45 | } | ||
46 | |||
47 | void syscall_continue(pid_t pid) | ||
48 | { | ||
49 | ptrace(PTRACE_SYSCALL, pid, 0, 0); | ||
50 | } | ||
51 | |||
52 | int syscall_pause(pid_t pid) | ||
53 | { | ||
54 | if(ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, __NR_pause) < 0){ | ||
55 | printk("syscall_change - ptrace failed, errno = %d\n", errno); | ||
56 | return(-1); | ||
57 | } | ||
58 | return(0); | ||
59 | } | ||
60 | |||
61 | /* | ||
62 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
63 | * Emacs will notice this stuff at the end of the file and automatically | ||
64 | * adjust the settings for this buffer only. This must remain at the end | ||
65 | * of the file. | ||
66 | * --------------------------------------------------------------------------- | ||
67 | * Local variables: | ||
68 | * c-file-style: "linux" | ||
69 | * End: | ||
70 | */ | ||
diff --git a/arch/um/kernel/tt/ptproxy/sysdep.h b/arch/um/kernel/tt/ptproxy/sysdep.h deleted file mode 100644 index 735f488049aa..000000000000 --- a/arch/um/kernel/tt/ptproxy/sysdep.h +++ /dev/null | |||
@@ -1,25 +0,0 @@ | |||
1 | /********************************************************************** | ||
2 | sysdep.h | ||
3 | |||
4 | Copyright (C) 1999 Lars Brinkhoff. | ||
5 | Copyright (C) 2001 Jeff Dike (jdike@karaya.com) | ||
6 | See the file COPYING for licensing terms and conditions. | ||
7 | **********************************************************************/ | ||
8 | |||
9 | extern int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, | ||
10 | long *arg4, long *arg5); | ||
11 | extern void syscall_cancel (pid_t pid, long result); | ||
12 | extern void syscall_set_result (pid_t pid, long result); | ||
13 | extern void syscall_continue (pid_t pid); | ||
14 | extern int syscall_pause(pid_t pid); | ||
15 | |||
16 | /* | ||
17 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
18 | * Emacs will notice this stuff at the end of the file and automatically | ||
19 | * adjust the settings for this buffer only. This must remain at the end | ||
20 | * of the file. | ||
21 | * --------------------------------------------------------------------------- | ||
22 | * Local variables: | ||
23 | * c-file-style: "linux" | ||
24 | * End: | ||
25 | */ | ||
diff --git a/arch/um/kernel/tt/ptproxy/wait.c b/arch/um/kernel/tt/ptproxy/wait.c deleted file mode 100644 index bdd4af4b65fc..000000000000 --- a/arch/um/kernel/tt/ptproxy/wait.c +++ /dev/null | |||
@@ -1,85 +0,0 @@ | |||
1 | /********************************************************************** | ||
2 | wait.c | ||
3 | |||
4 | Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing | ||
5 | terms and conditions. | ||
6 | |||
7 | **********************************************************************/ | ||
8 | |||
9 | #include <errno.h> | ||
10 | #include <signal.h> | ||
11 | #include <sys/wait.h> | ||
12 | |||
13 | #include "ptproxy.h" | ||
14 | #include "sysdep.h" | ||
15 | #include "wait.h" | ||
16 | #include "ptrace_user.h" | ||
17 | #include "sysdep/ptrace.h" | ||
18 | #include "sysdep/sigcontext.h" | ||
19 | |||
20 | int proxy_wait_return(struct debugger *debugger, pid_t unused) | ||
21 | { | ||
22 | debugger->waiting = 0; | ||
23 | |||
24 | if(debugger->debugee->died || (debugger->wait_options & __WCLONE)){ | ||
25 | debugger_cancelled_return(debugger, -ECHILD); | ||
26 | return(0); | ||
27 | } | ||
28 | |||
29 | if(debugger->debugee->zombie && debugger->debugee->event) | ||
30 | debugger->debugee->died = 1; | ||
31 | |||
32 | if(debugger->debugee->event){ | ||
33 | debugger->debugee->event = 0; | ||
34 | ptrace(PTRACE_POKEDATA, debugger->pid, | ||
35 | debugger->wait_status_ptr, | ||
36 | debugger->debugee->wait_status); | ||
37 | /* if (wait4) | ||
38 | ptrace (PTRACE_POKEDATA, pid, rusage_ptr, ...); */ | ||
39 | debugger_cancelled_return(debugger, debugger->debugee->pid); | ||
40 | return(0); | ||
41 | } | ||
42 | |||
43 | /* pause will return -EINTR, which happens to be right for wait */ | ||
44 | debugger_normal_return(debugger, -1); | ||
45 | return(0); | ||
46 | } | ||
47 | |||
48 | int parent_wait_return(struct debugger *debugger, pid_t unused) | ||
49 | { | ||
50 | return(debugger_normal_return(debugger, -1)); | ||
51 | } | ||
52 | |||
53 | int real_wait_return(struct debugger *debugger) | ||
54 | { | ||
55 | unsigned long ip; | ||
56 | int pid; | ||
57 | |||
58 | pid = debugger->pid; | ||
59 | |||
60 | ip = ptrace(PTRACE_PEEKUSR, pid, PT_IP_OFFSET, 0); | ||
61 | IP_RESTART_SYSCALL(ip); | ||
62 | |||
63 | if(ptrace(PTRACE_POKEUSR, pid, PT_IP_OFFSET, ip) < 0) | ||
64 | tracer_panic("real_wait_return : Failed to restart system " | ||
65 | "call, errno = %d\n", errno); | ||
66 | |||
67 | if((ptrace(PTRACE_SYSCALL, debugger->pid, 0, SIGCHLD) < 0) || | ||
68 | (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) || | ||
69 | (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) || | ||
70 | debugger_normal_return(debugger, -1)) | ||
71 | tracer_panic("real_wait_return : gdb failed to wait, " | ||
72 | "errno = %d\n", errno); | ||
73 | return(0); | ||
74 | } | ||
75 | |||
76 | /* | ||
77 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
78 | * Emacs will notice this stuff at the end of the file and automatically | ||
79 | * adjust the settings for this buffer only. This must remain at the end | ||
80 | * of the file. | ||
81 | * --------------------------------------------------------------------------- | ||
82 | * Local variables: | ||
83 | * c-file-style: "linux" | ||
84 | * End: | ||
85 | */ | ||
diff --git a/arch/um/kernel/tt/ptproxy/wait.h b/arch/um/kernel/tt/ptproxy/wait.h deleted file mode 100644 index 542e73ee2cee..000000000000 --- a/arch/um/kernel/tt/ptproxy/wait.h +++ /dev/null | |||
@@ -1,15 +0,0 @@ | |||
1 | /********************************************************************** | ||
2 | wait.h | ||
3 | |||
4 | Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing | ||
5 | terms and conditions. | ||
6 | **********************************************************************/ | ||
7 | |||
8 | #ifndef __PTPROXY_WAIT_H | ||
9 | #define __PTPROXY_WAIT_H | ||
10 | |||
11 | extern int proxy_wait_return(struct debugger *debugger, pid_t unused); | ||
12 | extern int real_wait_return(struct debugger *debugger); | ||
13 | extern int parent_wait_return(struct debugger *debugger, pid_t unused); | ||
14 | |||
15 | #endif | ||
diff --git a/arch/um/kernel/tt/syscall_kern.c b/arch/um/kernel/tt/syscall_kern.c deleted file mode 100644 index 293caa6d0c2d..000000000000 --- a/arch/um/kernel/tt/syscall_kern.c +++ /dev/null | |||
@@ -1,46 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include "linux/types.h" | ||
7 | #include "linux/utime.h" | ||
8 | #include "linux/sys.h" | ||
9 | #include "linux/ptrace.h" | ||
10 | #include "asm/unistd.h" | ||
11 | #include "asm/ptrace.h" | ||
12 | #include "asm/uaccess.h" | ||
13 | #include "asm/stat.h" | ||
14 | #include "sysdep/syscalls.h" | ||
15 | #include "sysdep/sigcontext.h" | ||
16 | #include "kern_util.h" | ||
17 | #include "syscall.h" | ||
18 | |||
19 | void syscall_handler_tt(int sig, struct pt_regs *regs) | ||
20 | { | ||
21 | void *sc; | ||
22 | long result; | ||
23 | int syscall; | ||
24 | |||
25 | sc = UPT_SC(®s->regs); | ||
26 | SC_START_SYSCALL(sc); | ||
27 | |||
28 | syscall = UPT_SYSCALL_NR(®s->regs); | ||
29 | syscall_trace(®s->regs, 0); | ||
30 | |||
31 | current->thread.nsyscalls++; | ||
32 | nsyscalls++; | ||
33 | |||
34 | if((syscall >= NR_syscalls) || (syscall < 0)) | ||
35 | result = -ENOSYS; | ||
36 | else result = EXECUTE_SYSCALL(syscall, regs); | ||
37 | |||
38 | /* regs->sc may have changed while the system call ran (there may | ||
39 | * have been an interrupt or segfault), so it needs to be refreshed. | ||
40 | */ | ||
41 | UPT_SC(®s->regs) = sc; | ||
42 | |||
43 | SC_SET_SYSCALL_RETURN(sc, result); | ||
44 | |||
45 | syscall_trace(®s->regs, 1); | ||
46 | } | ||
diff --git a/arch/um/kernel/tt/syscall_user.c b/arch/um/kernel/tt/syscall_user.c deleted file mode 100644 index f52b47aff1d2..000000000000 --- a/arch/um/kernel/tt/syscall_user.c +++ /dev/null | |||
@@ -1,60 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <unistd.h> | ||
7 | #include <signal.h> | ||
8 | #include <errno.h> | ||
9 | #include <asm/unistd.h> | ||
10 | #include "sysdep/ptrace.h" | ||
11 | #include "sigcontext.h" | ||
12 | #include "ptrace_user.h" | ||
13 | #include "task.h" | ||
14 | #include "kern_util.h" | ||
15 | #include "syscall.h" | ||
16 | #include "tt.h" | ||
17 | |||
18 | void do_sigtrap(void *task) | ||
19 | { | ||
20 | UPT_SYSCALL_NR(TASK_REGS(task)) = -1; | ||
21 | } | ||
22 | |||
23 | void do_syscall(void *task, int pid, int local_using_sysemu) | ||
24 | { | ||
25 | unsigned long proc_regs[FRAME_SIZE]; | ||
26 | |||
27 | if(ptrace_getregs(pid, proc_regs) < 0) | ||
28 | tracer_panic("Couldn't read registers"); | ||
29 | |||
30 | UPT_SYSCALL_NR(TASK_REGS(task)) = PT_SYSCALL_NR(proc_regs); | ||
31 | |||
32 | #ifdef UPT_ORIGGPR2 | ||
33 | UPT_ORIGGPR2(TASK_REGS(task)) = REGS_ORIGGPR2(proc_regs); | ||
34 | #endif | ||
35 | |||
36 | if(((unsigned long *) PT_IP(proc_regs) >= &_stext) && | ||
37 | ((unsigned long *) PT_IP(proc_regs) <= &_etext)) | ||
38 | tracer_panic("I'm tracing myself and I can't get out"); | ||
39 | |||
40 | /* advanced sysemu mode set syscall number to -1 automatically */ | ||
41 | if (local_using_sysemu==2) | ||
42 | return; | ||
43 | |||
44 | /* syscall number -1 in sysemu skips syscall restarting in host */ | ||
45 | if(ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, | ||
46 | local_using_sysemu ? -1 : __NR_getpid) < 0) | ||
47 | tracer_panic("do_syscall : Nullifying syscall failed, " | ||
48 | "errno = %d", errno); | ||
49 | } | ||
50 | |||
51 | /* | ||
52 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
53 | * Emacs will notice this stuff at the end of the file and automatically | ||
54 | * adjust the settings for this buffer only. This must remain at the end | ||
55 | * of the file. | ||
56 | * --------------------------------------------------------------------------- | ||
57 | * Local variables: | ||
58 | * c-file-style: "linux" | ||
59 | * End: | ||
60 | */ | ||
diff --git a/arch/um/kernel/tt/tlb.c b/arch/um/kernel/tt/tlb.c deleted file mode 100644 index 7caa24fe05df..000000000000 --- a/arch/um/kernel/tt/tlb.c +++ /dev/null | |||
@@ -1,120 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Copyright 2003 PathScale, Inc. | ||
4 | * Licensed under the GPL | ||
5 | */ | ||
6 | |||
7 | #include "linux/stddef.h" | ||
8 | #include "linux/kernel.h" | ||
9 | #include "linux/sched.h" | ||
10 | #include "linux/mm.h" | ||
11 | #include "asm/page.h" | ||
12 | #include "asm/pgtable.h" | ||
13 | #include "asm/uaccess.h" | ||
14 | #include "asm/tlbflush.h" | ||
15 | #include "mem_user.h" | ||
16 | #include "os.h" | ||
17 | #include "tlb.h" | ||
18 | |||
19 | static int do_ops(union mm_context *mmu, struct host_vm_op *ops, int last, | ||
20 | int finished, void **flush) | ||
21 | { | ||
22 | struct host_vm_op *op; | ||
23 | int i, ret=0; | ||
24 | |||
25 | for(i = 0; i <= last && !ret; i++){ | ||
26 | op = &ops[i]; | ||
27 | switch(op->type){ | ||
28 | case MMAP: | ||
29 | ret = os_map_memory((void *) op->u.mmap.addr, | ||
30 | op->u.mmap.fd, op->u.mmap.offset, | ||
31 | op->u.mmap.len, op->u.mmap.r, | ||
32 | op->u.mmap.w, op->u.mmap.x); | ||
33 | break; | ||
34 | case MUNMAP: | ||
35 | ret = os_unmap_memory((void *) op->u.munmap.addr, | ||
36 | op->u.munmap.len); | ||
37 | break; | ||
38 | case MPROTECT: | ||
39 | ret = protect_memory(op->u.mprotect.addr, | ||
40 | op->u.munmap.len, | ||
41 | op->u.mprotect.r, | ||
42 | op->u.mprotect.w, | ||
43 | op->u.mprotect.x, 1); | ||
44 | protect_memory(op->u.mprotect.addr, op->u.munmap.len, | ||
45 | op->u.mprotect.r, op->u.mprotect.w, | ||
46 | op->u.mprotect.x, 1); | ||
47 | break; | ||
48 | default: | ||
49 | printk("Unknown op type %d in do_ops\n", op->type); | ||
50 | break; | ||
51 | } | ||
52 | } | ||
53 | |||
54 | return ret; | ||
55 | } | ||
56 | |||
57 | static void fix_range(struct mm_struct *mm, unsigned long start_addr, | ||
58 | unsigned long end_addr, int force) | ||
59 | { | ||
60 | if((current->thread.mode.tt.extern_pid != -1) && | ||
61 | (current->thread.mode.tt.extern_pid != os_getpid())) | ||
62 | panic("fix_range fixing wrong address space, current = 0x%p", | ||
63 | current); | ||
64 | |||
65 | fix_range_common(mm, start_addr, end_addr, force, do_ops); | ||
66 | } | ||
67 | |||
68 | atomic_t vmchange_seq = ATOMIC_INIT(1); | ||
69 | |||
70 | void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end) | ||
71 | { | ||
72 | if(flush_tlb_kernel_range_common(start, end)) | ||
73 | atomic_inc(&vmchange_seq); | ||
74 | } | ||
75 | |||
76 | void flush_tlb_kernel_vm_tt(void) | ||
77 | { | ||
78 | flush_tlb_kernel_range(start_vm, end_vm); | ||
79 | } | ||
80 | |||
81 | void __flush_tlb_one_tt(unsigned long addr) | ||
82 | { | ||
83 | flush_tlb_kernel_range(addr, addr + PAGE_SIZE); | ||
84 | } | ||
85 | |||
86 | void flush_tlb_range_tt(struct vm_area_struct *vma, unsigned long start, | ||
87 | unsigned long end) | ||
88 | { | ||
89 | if(vma->vm_mm != current->mm) return; | ||
90 | |||
91 | /* Assumes that the range start ... end is entirely within | ||
92 | * either process memory or kernel vm | ||
93 | */ | ||
94 | if((start >= start_vm) && (start < end_vm)){ | ||
95 | if(flush_tlb_kernel_range_common(start, end)) | ||
96 | atomic_inc(&vmchange_seq); | ||
97 | } | ||
98 | else fix_range(vma->vm_mm, start, end, 0); | ||
99 | } | ||
100 | |||
101 | void flush_tlb_mm_tt(struct mm_struct *mm) | ||
102 | { | ||
103 | unsigned long seq; | ||
104 | |||
105 | if(mm != current->mm) return; | ||
106 | |||
107 | fix_range(mm, 0, STACK_TOP, 0); | ||
108 | |||
109 | seq = atomic_read(&vmchange_seq); | ||
110 | if(current->thread.mode.tt.vm_seq == seq) | ||
111 | return; | ||
112 | current->thread.mode.tt.vm_seq = seq; | ||
113 | flush_tlb_kernel_range_common(start_vm, end_vm); | ||
114 | } | ||
115 | |||
116 | void force_flush_all_tt(void) | ||
117 | { | ||
118 | fix_range(current->mm, 0, STACK_TOP, 1); | ||
119 | flush_tlb_kernel_range_common(start_vm, end_vm); | ||
120 | } | ||
diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c deleted file mode 100644 index c23588393f6e..000000000000 --- a/arch/um/kernel/tt/tracer.c +++ /dev/null | |||
@@ -1,461 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <stdio.h> | ||
7 | #include <stdlib.h> | ||
8 | #include <stdarg.h> | ||
9 | #include <unistd.h> | ||
10 | #include <signal.h> | ||
11 | #include <errno.h> | ||
12 | #include <sched.h> | ||
13 | #include <string.h> | ||
14 | #include <sys/mman.h> | ||
15 | #include <sys/time.h> | ||
16 | #include <sys/wait.h> | ||
17 | #include "user.h" | ||
18 | #include "sysdep/ptrace.h" | ||
19 | #include "sigcontext.h" | ||
20 | #include "sysdep/sigcontext.h" | ||
21 | #include "os.h" | ||
22 | #include "mem_user.h" | ||
23 | #include "process.h" | ||
24 | #include "kern_util.h" | ||
25 | #include "chan_user.h" | ||
26 | #include "ptrace_user.h" | ||
27 | #include "irq_user.h" | ||
28 | #include "mode.h" | ||
29 | #include "tt.h" | ||
30 | |||
31 | static int tracer_winch[2]; | ||
32 | |||
33 | int is_tracer_winch(int pid, int fd, void *data) | ||
34 | { | ||
35 | if(pid != os_getpgrp()) | ||
36 | return(0); | ||
37 | |||
38 | register_winch_irq(tracer_winch[0], fd, -1, data); | ||
39 | return(1); | ||
40 | } | ||
41 | |||
42 | static void tracer_winch_handler(int sig) | ||
43 | { | ||
44 | int n; | ||
45 | char c = 1; | ||
46 | |||
47 | n = os_write_file(tracer_winch[1], &c, sizeof(c)); | ||
48 | if(n != sizeof(c)) | ||
49 | printk("tracer_winch_handler - write failed, err = %d\n", -n); | ||
50 | } | ||
51 | |||
52 | /* Called only by the tracing thread during initialization */ | ||
53 | |||
54 | static void setup_tracer_winch(void) | ||
55 | { | ||
56 | int err; | ||
57 | |||
58 | err = os_pipe(tracer_winch, 1, 1); | ||
59 | if(err < 0){ | ||
60 | printk("setup_tracer_winch : os_pipe failed, err = %d\n", -err); | ||
61 | return; | ||
62 | } | ||
63 | signal(SIGWINCH, tracer_winch_handler); | ||
64 | } | ||
65 | |||
66 | void attach_process(int pid) | ||
67 | { | ||
68 | if((ptrace(PTRACE_ATTACH, pid, 0, 0) < 0) || | ||
69 | (ptrace(PTRACE_CONT, pid, 0, 0) < 0)) | ||
70 | tracer_panic("OP_FORK failed to attach pid"); | ||
71 | wait_for_stop(pid, SIGSTOP, PTRACE_CONT, NULL); | ||
72 | if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0) | ||
73 | tracer_panic("OP_FORK: PTRACE_SETOPTIONS failed, errno = %d", errno); | ||
74 | if(ptrace(PTRACE_CONT, pid, 0, 0) < 0) | ||
75 | tracer_panic("OP_FORK failed to continue process"); | ||
76 | } | ||
77 | |||
78 | void tracer_panic(char *format, ...) | ||
79 | { | ||
80 | va_list ap; | ||
81 | |||
82 | va_start(ap, format); | ||
83 | vprintf(format, ap); | ||
84 | va_end(ap); | ||
85 | printf("\n"); | ||
86 | while(1) pause(); | ||
87 | } | ||
88 | |||
89 | static void tracer_segv(int sig, struct sigcontext sc) | ||
90 | { | ||
91 | struct faultinfo fi; | ||
92 | GET_FAULTINFO_FROM_SC(fi, &sc); | ||
93 | printf("Tracing thread segfault at address 0x%lx, ip 0x%lx\n", | ||
94 | FAULT_ADDRESS(fi), SC_IP(&sc)); | ||
95 | while(1) | ||
96 | pause(); | ||
97 | } | ||
98 | |||
99 | /* Changed early in boot, and then only read */ | ||
100 | int debug = 0; | ||
101 | int debug_stop = 1; | ||
102 | int debug_parent = 0; | ||
103 | int honeypot = 0; | ||
104 | |||
105 | static int signal_tramp(void *arg) | ||
106 | { | ||
107 | int (*proc)(void *); | ||
108 | |||
109 | if(honeypot && munmap((void *) (host_task_size - 0x10000000), | ||
110 | 0x10000000)) | ||
111 | panic("Unmapping stack failed"); | ||
112 | if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) | ||
113 | panic("ptrace PTRACE_TRACEME failed"); | ||
114 | os_stop_process(os_getpid()); | ||
115 | change_sig(SIGWINCH, 0); | ||
116 | signal(SIGUSR1, SIG_IGN); | ||
117 | change_sig(SIGCHLD, 0); | ||
118 | signal(SIGSEGV, (__sighandler_t) sig_handler); | ||
119 | set_cmdline("(idle thread)"); | ||
120 | set_init_pid(os_getpid()); | ||
121 | init_irq_signals(0); | ||
122 | proc = arg; | ||
123 | return((*proc)(NULL)); | ||
124 | } | ||
125 | |||
126 | static void sleeping_process_signal(int pid, int sig) | ||
127 | { | ||
128 | switch(sig){ | ||
129 | /* These two result from UML being ^Z-ed and bg-ed. PTRACE_CONT is | ||
130 | * right because the process must be in the kernel already. | ||
131 | */ | ||
132 | case SIGCONT: | ||
133 | case SIGTSTP: | ||
134 | if(ptrace(PTRACE_CONT, pid, 0, sig) < 0) | ||
135 | tracer_panic("sleeping_process_signal : Failed to " | ||
136 | "continue pid %d, signal = %d, " | ||
137 | "errno = %d\n", pid, sig, errno); | ||
138 | break; | ||
139 | |||
140 | /* This happens when the debugger (e.g. strace) is doing system call | ||
141 | * tracing on the kernel. During a context switch, the current task | ||
142 | * will be set to the incoming process and the outgoing process will | ||
143 | * hop into write and then read. Since it's not the current process | ||
144 | * any more, the trace of those will land here. So, we need to just | ||
145 | * PTRACE_SYSCALL it. | ||
146 | */ | ||
147 | case (SIGTRAP + 0x80): | ||
148 | if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) | ||
149 | tracer_panic("sleeping_process_signal : Failed to " | ||
150 | "PTRACE_SYSCALL pid %d, errno = %d\n", | ||
151 | pid, errno); | ||
152 | break; | ||
153 | case SIGSTOP: | ||
154 | break; | ||
155 | default: | ||
156 | tracer_panic("sleeping process %d got unexpected " | ||
157 | "signal : %d\n", pid, sig); | ||
158 | break; | ||
159 | } | ||
160 | } | ||
161 | |||
162 | /* Accessed only by the tracing thread */ | ||
163 | int debugger_pid = -1; | ||
164 | int debugger_parent = -1; | ||
165 | int debugger_fd = -1; | ||
166 | int gdb_pid = -1; | ||
167 | |||
168 | struct { | ||
169 | int pid; | ||
170 | int signal; | ||
171 | unsigned long addr; | ||
172 | struct timeval time; | ||
173 | } signal_record[1024][32]; | ||
174 | |||
175 | int signal_index[32]; | ||
176 | int nsignals = 0; | ||
177 | int debug_trace = 0; | ||
178 | |||
179 | extern void signal_usr1(int sig); | ||
180 | |||
181 | int tracing_pid = -1; | ||
182 | |||
183 | int tracer(int (*init_proc)(void *), void *sp) | ||
184 | { | ||
185 | void *task = NULL; | ||
186 | int status, pid = 0, sig = 0, cont_type, tracing = 0, op = 0; | ||
187 | int proc_id = 0, n, err, old_tracing = 0, strace = 0; | ||
188 | int local_using_sysemu = 0; | ||
189 | |||
190 | signal(SIGPIPE, SIG_IGN); | ||
191 | setup_tracer_winch(); | ||
192 | tracing_pid = os_getpid(); | ||
193 | printf("tracing thread pid = %d\n", tracing_pid); | ||
194 | |||
195 | pid = clone(signal_tramp, sp, CLONE_FILES | SIGCHLD, init_proc); | ||
196 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); | ||
197 | if(n < 0){ | ||
198 | printf("waitpid on idle thread failed, errno = %d\n", errno); | ||
199 | exit(1); | ||
200 | } | ||
201 | if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0) { | ||
202 | printf("Failed to PTRACE_SETOPTIONS for idle thread, errno = %d\n", errno); | ||
203 | exit(1); | ||
204 | } | ||
205 | if((ptrace(PTRACE_CONT, pid, 0, 0) < 0)){ | ||
206 | printf("Failed to continue idle thread, errno = %d\n", errno); | ||
207 | exit(1); | ||
208 | } | ||
209 | |||
210 | signal(SIGSEGV, (sighandler_t) tracer_segv); | ||
211 | signal(SIGUSR1, signal_usr1); | ||
212 | if(debug_trace){ | ||
213 | printf("Tracing thread pausing to be attached\n"); | ||
214 | stop(); | ||
215 | } | ||
216 | if(debug){ | ||
217 | if(gdb_pid != -1) | ||
218 | debugger_pid = attach_debugger(pid, gdb_pid, 1); | ||
219 | else debugger_pid = init_ptrace_proxy(pid, 1, debug_stop); | ||
220 | if(debug_parent){ | ||
221 | debugger_parent = os_process_parent(debugger_pid); | ||
222 | init_parent_proxy(debugger_parent); | ||
223 | err = attach(debugger_parent); | ||
224 | if(err){ | ||
225 | printf("Failed to attach debugger parent %d, " | ||
226 | "errno = %d\n", debugger_parent, -err); | ||
227 | debugger_parent = -1; | ||
228 | } | ||
229 | else { | ||
230 | if(ptrace(PTRACE_SYSCALL, debugger_parent, | ||
231 | 0, 0) < 0){ | ||
232 | printf("Failed to continue debugger " | ||
233 | "parent, errno = %d\n", errno); | ||
234 | debugger_parent = -1; | ||
235 | } | ||
236 | } | ||
237 | } | ||
238 | } | ||
239 | set_cmdline("(tracing thread)"); | ||
240 | while(1){ | ||
241 | CATCH_EINTR(pid = waitpid(-1, &status, WUNTRACED)); | ||
242 | if(pid <= 0){ | ||
243 | if(errno != ECHILD){ | ||
244 | printf("wait failed - errno = %d\n", errno); | ||
245 | } | ||
246 | continue; | ||
247 | } | ||
248 | if(pid == debugger_pid){ | ||
249 | int cont = 0; | ||
250 | |||
251 | if(WIFEXITED(status) || WIFSIGNALED(status)) | ||
252 | debugger_pid = -1; | ||
253 | /* XXX Figure out how to deal with gdb and SMP */ | ||
254 | else cont = debugger_signal(status, cpu_tasks[0].pid); | ||
255 | if(cont == PTRACE_SYSCALL) strace = 1; | ||
256 | continue; | ||
257 | } | ||
258 | else if(pid == debugger_parent){ | ||
259 | debugger_parent_signal(status, pid); | ||
260 | continue; | ||
261 | } | ||
262 | nsignals++; | ||
263 | if(WIFEXITED(status)) ; | ||
264 | #ifdef notdef | ||
265 | { | ||
266 | printf("Child %d exited with status %d\n", pid, | ||
267 | WEXITSTATUS(status)); | ||
268 | } | ||
269 | #endif | ||
270 | else if(WIFSIGNALED(status)){ | ||
271 | sig = WTERMSIG(status); | ||
272 | if(sig != 9){ | ||
273 | printf("Child %d exited with signal %d\n", pid, | ||
274 | sig); | ||
275 | } | ||
276 | } | ||
277 | else if(WIFSTOPPED(status)){ | ||
278 | proc_id = pid_to_processor_id(pid); | ||
279 | sig = WSTOPSIG(status); | ||
280 | if(proc_id == -1){ | ||
281 | sleeping_process_signal(pid, sig); | ||
282 | continue; | ||
283 | } | ||
284 | |||
285 | task = cpu_tasks[proc_id].task; | ||
286 | tracing = is_tracing(task); | ||
287 | old_tracing = tracing; | ||
288 | |||
289 | /* Assume: no syscall, when coming from user */ | ||
290 | if ( tracing ) | ||
291 | do_sigtrap(task); | ||
292 | |||
293 | switch(sig){ | ||
294 | case SIGUSR1: | ||
295 | sig = 0; | ||
296 | op = do_proc_op(task, proc_id); | ||
297 | switch(op){ | ||
298 | /* | ||
299 | * This is called when entering user mode; after | ||
300 | * this, we start intercepting syscalls. | ||
301 | * | ||
302 | * In fact, a process is started in kernel mode, | ||
303 | * so with is_tracing() == 0 (and that is reset | ||
304 | * when executing syscalls, since UML kernel has | ||
305 | * the right to do syscalls); | ||
306 | */ | ||
307 | case OP_TRACE_ON: | ||
308 | arch_leave_kernel(task, pid); | ||
309 | tracing = 1; | ||
310 | break; | ||
311 | case OP_REBOOT: | ||
312 | case OP_HALT: | ||
313 | unmap_physmem(); | ||
314 | kmalloc_ok = 0; | ||
315 | os_kill_ptraced_process(pid, 0); | ||
316 | /* Now let's reap remaining zombies */ | ||
317 | errno = 0; | ||
318 | do { | ||
319 | waitpid(-1, &status, | ||
320 | WUNTRACED); | ||
321 | } while (errno != ECHILD); | ||
322 | return(op == OP_REBOOT); | ||
323 | case OP_NONE: | ||
324 | printf("Detaching pid %d\n", pid); | ||
325 | detach(pid, SIGSTOP); | ||
326 | continue; | ||
327 | default: | ||
328 | break; | ||
329 | } | ||
330 | /* OP_EXEC switches host processes on us, | ||
331 | * we want to continue the new one. | ||
332 | */ | ||
333 | pid = cpu_tasks[proc_id].pid; | ||
334 | break; | ||
335 | case (SIGTRAP + 0x80): | ||
336 | if(!tracing && (debugger_pid != -1)){ | ||
337 | child_signal(pid, status & 0x7fff); | ||
338 | continue; | ||
339 | } | ||
340 | tracing = 0; | ||
341 | /* local_using_sysemu has been already set | ||
342 | * below, since if we are here, is_tracing() on | ||
343 | * the traced task was 1, i.e. the process had | ||
344 | * already run through one iteration of the | ||
345 | * loop which executed a OP_TRACE_ON request.*/ | ||
346 | do_syscall(task, pid, local_using_sysemu); | ||
347 | sig = SIGUSR2; | ||
348 | break; | ||
349 | case SIGTRAP: | ||
350 | if(!tracing && (debugger_pid != -1)){ | ||
351 | child_signal(pid, status); | ||
352 | continue; | ||
353 | } | ||
354 | tracing = 0; | ||
355 | break; | ||
356 | case SIGPROF: | ||
357 | if(tracing) sig = 0; | ||
358 | break; | ||
359 | case SIGCHLD: | ||
360 | case SIGHUP: | ||
361 | sig = 0; | ||
362 | break; | ||
363 | case SIGSEGV: | ||
364 | case SIGIO: | ||
365 | case SIGALRM: | ||
366 | case SIGVTALRM: | ||
367 | case SIGFPE: | ||
368 | case SIGBUS: | ||
369 | case SIGILL: | ||
370 | case SIGWINCH: | ||
371 | |||
372 | default: | ||
373 | tracing = 0; | ||
374 | break; | ||
375 | } | ||
376 | set_tracing(task, tracing); | ||
377 | |||
378 | if(!tracing && old_tracing) | ||
379 | arch_enter_kernel(task, pid); | ||
380 | |||
381 | if(!tracing && (debugger_pid != -1) && (sig != 0) && | ||
382 | (sig != SIGALRM) && (sig != SIGVTALRM) && | ||
383 | (sig != SIGSEGV) && (sig != SIGTRAP) && | ||
384 | (sig != SIGUSR2) && (sig != SIGIO) && | ||
385 | (sig != SIGFPE)){ | ||
386 | child_signal(pid, status); | ||
387 | continue; | ||
388 | } | ||
389 | |||
390 | local_using_sysemu = get_using_sysemu(); | ||
391 | |||
392 | if(tracing) | ||
393 | cont_type = SELECT_PTRACE_OPERATION(local_using_sysemu, | ||
394 | singlestepping(task)); | ||
395 | else if((debugger_pid != -1) && strace) | ||
396 | cont_type = PTRACE_SYSCALL; | ||
397 | else | ||
398 | cont_type = PTRACE_CONT; | ||
399 | |||
400 | if(ptrace(cont_type, pid, 0, sig) != 0){ | ||
401 | tracer_panic("ptrace failed to continue " | ||
402 | "process - errno = %d\n", | ||
403 | errno); | ||
404 | } | ||
405 | } | ||
406 | } | ||
407 | return(0); | ||
408 | } | ||
409 | |||
410 | static int __init uml_debug_setup(char *line, int *add) | ||
411 | { | ||
412 | char *next; | ||
413 | |||
414 | debug = 1; | ||
415 | *add = 0; | ||
416 | if(*line != '=') return(0); | ||
417 | line++; | ||
418 | |||
419 | while(line != NULL){ | ||
420 | next = strchr(line, ','); | ||
421 | if(next) *next++ = '\0'; | ||
422 | |||
423 | if(!strcmp(line, "go")) debug_stop = 0; | ||
424 | else if(!strcmp(line, "parent")) debug_parent = 1; | ||
425 | else printf("Unknown debug option : '%s'\n", line); | ||
426 | |||
427 | line = next; | ||
428 | } | ||
429 | return(0); | ||
430 | } | ||
431 | |||
432 | __uml_setup("debug", uml_debug_setup, | ||
433 | "debug\n" | ||
434 | " Starts up the kernel under the control of gdb. See the \n" | ||
435 | " kernel debugging tutorial and the debugging session pages\n" | ||
436 | " at http://user-mode-linux.sourceforge.net/ for more information.\n\n" | ||
437 | ); | ||
438 | |||
439 | static int __init uml_debugtrace_setup(char *line, int *add) | ||
440 | { | ||
441 | debug_trace = 1; | ||
442 | return 0; | ||
443 | } | ||
444 | __uml_setup("debugtrace", uml_debugtrace_setup, | ||
445 | "debugtrace\n" | ||
446 | " Causes the tracing thread to pause until it is attached by a\n" | ||
447 | " debugger and continued. This is mostly for debugging crashes\n" | ||
448 | " early during boot, and should be pretty much obsoleted by\n" | ||
449 | " the debug switch.\n\n" | ||
450 | ); | ||
451 | |||
452 | /* | ||
453 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
454 | * Emacs will notice this stuff at the end of the file and automatically | ||
455 | * adjust the settings for this buffer only. This must remain at the end | ||
456 | * of the file. | ||
457 | * --------------------------------------------------------------------------- | ||
458 | * Local variables: | ||
459 | * c-file-style: "linux" | ||
460 | * End: | ||
461 | */ | ||
diff --git a/arch/um/kernel/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c deleted file mode 100644 index 3032eb5e2467..000000000000 --- a/arch/um/kernel/tt/trap_user.c +++ /dev/null | |||
@@ -1,70 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <stdlib.h> | ||
7 | #include <errno.h> | ||
8 | #include <signal.h> | ||
9 | #include "sysdep/ptrace.h" | ||
10 | #include "sysdep/sigcontext.h" | ||
11 | #include "kern_util.h" | ||
12 | #include "task.h" | ||
13 | #include "tt.h" | ||
14 | #include "os.h" | ||
15 | |||
16 | void sig_handler_common_tt(int sig, void *sc_ptr) | ||
17 | { | ||
18 | struct sigcontext *sc = sc_ptr; | ||
19 | struct tt_regs save_regs, *r; | ||
20 | int save_errno = errno, is_user = 0; | ||
21 | void (*handler)(int, union uml_pt_regs *); | ||
22 | |||
23 | /* This is done because to allow SIGSEGV to be delivered inside a SEGV | ||
24 | * handler. This can happen in copy_user, and if SEGV is disabled, | ||
25 | * the process will die. | ||
26 | */ | ||
27 | if(sig == SIGSEGV) | ||
28 | change_sig(SIGSEGV, 1); | ||
29 | |||
30 | r = &TASK_REGS(get_current())->tt; | ||
31 | if ( sig == SIGFPE || sig == SIGSEGV || | ||
32 | sig == SIGBUS || sig == SIGILL || | ||
33 | sig == SIGTRAP ) { | ||
34 | GET_FAULTINFO_FROM_SC(r->faultinfo, sc); | ||
35 | } | ||
36 | save_regs = *r; | ||
37 | if (sc) | ||
38 | is_user = user_context(SC_SP(sc)); | ||
39 | r->sc = sc; | ||
40 | if(sig != SIGUSR2) | ||
41 | r->syscall = -1; | ||
42 | |||
43 | handler = sig_info[sig]; | ||
44 | |||
45 | /* unblock SIGALRM, SIGVTALRM, SIGIO if sig isn't IRQ signal */ | ||
46 | if (sig != SIGIO && sig != SIGWINCH && | ||
47 | sig != SIGVTALRM && sig != SIGALRM) | ||
48 | unblock_signals(); | ||
49 | |||
50 | handler(sig, (union uml_pt_regs *) r); | ||
51 | |||
52 | if(is_user){ | ||
53 | interrupt_end(); | ||
54 | block_signals(); | ||
55 | set_user_mode(NULL); | ||
56 | } | ||
57 | *r = save_regs; | ||
58 | errno = save_errno; | ||
59 | } | ||
60 | |||
61 | /* | ||
62 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
63 | * Emacs will notice this stuff at the end of the file and automatically | ||
64 | * adjust the settings for this buffer only. This must remain at the end | ||
65 | * of the file. | ||
66 | * --------------------------------------------------------------------------- | ||
67 | * Local variables: | ||
68 | * c-file-style: "linux" | ||
69 | * End: | ||
70 | */ | ||
diff --git a/arch/um/kernel/tt/uaccess.c b/arch/um/kernel/tt/uaccess.c deleted file mode 100644 index 1cb60726567e..000000000000 --- a/arch/um/kernel/tt/uaccess.c +++ /dev/null | |||
@@ -1,73 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include "linux/sched.h" | ||
7 | #include "asm/uaccess.h" | ||
8 | |||
9 | int copy_from_user_tt(void *to, const void __user *from, int n) | ||
10 | { | ||
11 | if(!access_ok(VERIFY_READ, from, n)) | ||
12 | return(n); | ||
13 | |||
14 | return(__do_copy_from_user(to, from, n, ¤t->thread.fault_addr, | ||
15 | ¤t->thread.fault_catcher)); | ||
16 | } | ||
17 | |||
18 | int copy_to_user_tt(void __user *to, const void *from, int n) | ||
19 | { | ||
20 | if(!access_ok(VERIFY_WRITE, to, n)) | ||
21 | return(n); | ||
22 | |||
23 | return(__do_copy_to_user(to, from, n, ¤t->thread.fault_addr, | ||
24 | ¤t->thread.fault_catcher)); | ||
25 | } | ||
26 | |||
27 | int strncpy_from_user_tt(char *dst, const char __user *src, int count) | ||
28 | { | ||
29 | int n; | ||
30 | |||
31 | if(!access_ok(VERIFY_READ, src, 1)) | ||
32 | return(-EFAULT); | ||
33 | |||
34 | n = __do_strncpy_from_user(dst, src, count, | ||
35 | ¤t->thread.fault_addr, | ||
36 | ¤t->thread.fault_catcher); | ||
37 | if(n < 0) return(-EFAULT); | ||
38 | return(n); | ||
39 | } | ||
40 | |||
41 | int __clear_user_tt(void __user *mem, int len) | ||
42 | { | ||
43 | return(__do_clear_user(mem, len, | ||
44 | ¤t->thread.fault_addr, | ||
45 | ¤t->thread.fault_catcher)); | ||
46 | } | ||
47 | |||
48 | int clear_user_tt(void __user *mem, int len) | ||
49 | { | ||
50 | if(!access_ok(VERIFY_WRITE, mem, len)) | ||
51 | return(len); | ||
52 | |||
53 | return(__do_clear_user(mem, len, ¤t->thread.fault_addr, | ||
54 | ¤t->thread.fault_catcher)); | ||
55 | } | ||
56 | |||
57 | int strnlen_user_tt(const void __user *str, int len) | ||
58 | { | ||
59 | return(__do_strnlen_user(str, len, | ||
60 | ¤t->thread.fault_addr, | ||
61 | ¤t->thread.fault_catcher)); | ||
62 | } | ||
63 | |||
64 | /* | ||
65 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
66 | * Emacs will notice this stuff at the end of the file and automatically | ||
67 | * adjust the settings for this buffer only. This must remain at the end | ||
68 | * of the file. | ||
69 | * --------------------------------------------------------------------------- | ||
70 | * Local variables: | ||
71 | * c-file-style: "linux" | ||
72 | * End: | ||
73 | */ | ||
diff --git a/arch/um/kernel/tt/uaccess_user.c b/arch/um/kernel/tt/uaccess_user.c deleted file mode 100644 index 0e5c82c5e5b7..000000000000 --- a/arch/um/kernel/tt/uaccess_user.c +++ /dev/null | |||
@@ -1,105 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk) | ||
3 | * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) | ||
4 | * Licensed under the GPL | ||
5 | */ | ||
6 | |||
7 | #include <string.h> | ||
8 | #include "uml_uaccess.h" | ||
9 | #include "task.h" | ||
10 | #include "kern_util.h" | ||
11 | #include "os.h" | ||
12 | #include "longjmp.h" | ||
13 | |||
14 | int __do_copy_from_user(void *to, const void *from, int n, | ||
15 | void **fault_addr, void **fault_catcher) | ||
16 | { | ||
17 | struct tt_regs save = TASK_REGS(get_current())->tt; | ||
18 | unsigned long fault; | ||
19 | int faulted; | ||
20 | |||
21 | fault = __do_user_copy(to, from, n, fault_addr, fault_catcher, | ||
22 | __do_copy, &faulted); | ||
23 | TASK_REGS(get_current())->tt = save; | ||
24 | |||
25 | if(!faulted) | ||
26 | return 0; | ||
27 | else if (fault) | ||
28 | return n - (fault - (unsigned long) from); | ||
29 | else | ||
30 | /* In case of a general protection fault, we don't have the | ||
31 | * fault address, so NULL is used instead. Pretend we didn't | ||
32 | * copy anything. */ | ||
33 | return n; | ||
34 | } | ||
35 | |||
36 | static void __do_strncpy(void *dst, const void *src, int count) | ||
37 | { | ||
38 | strncpy(dst, src, count); | ||
39 | } | ||
40 | |||
41 | int __do_strncpy_from_user(char *dst, const char *src, unsigned long count, | ||
42 | void **fault_addr, void **fault_catcher) | ||
43 | { | ||
44 | struct tt_regs save = TASK_REGS(get_current())->tt; | ||
45 | unsigned long fault; | ||
46 | int faulted; | ||
47 | |||
48 | fault = __do_user_copy(dst, src, count, fault_addr, fault_catcher, | ||
49 | __do_strncpy, &faulted); | ||
50 | TASK_REGS(get_current())->tt = save; | ||
51 | |||
52 | if(!faulted) return(strlen(dst)); | ||
53 | else return(-1); | ||
54 | } | ||
55 | |||
56 | static void __do_clear(void *to, const void *from, int n) | ||
57 | { | ||
58 | memset(to, 0, n); | ||
59 | } | ||
60 | |||
61 | int __do_clear_user(void *mem, unsigned long len, | ||
62 | void **fault_addr, void **fault_catcher) | ||
63 | { | ||
64 | struct tt_regs save = TASK_REGS(get_current())->tt; | ||
65 | unsigned long fault; | ||
66 | int faulted; | ||
67 | |||
68 | fault = __do_user_copy(mem, NULL, len, fault_addr, fault_catcher, | ||
69 | __do_clear, &faulted); | ||
70 | TASK_REGS(get_current())->tt = save; | ||
71 | |||
72 | if(!faulted) return(0); | ||
73 | else return(len - (fault - (unsigned long) mem)); | ||
74 | } | ||
75 | |||
76 | int __do_strnlen_user(const char *str, unsigned long n, | ||
77 | void **fault_addr, void **fault_catcher) | ||
78 | { | ||
79 | struct tt_regs save = TASK_REGS(get_current())->tt; | ||
80 | int ret; | ||
81 | unsigned long *faddrp = (unsigned long *)fault_addr; | ||
82 | jmp_buf jbuf; | ||
83 | |||
84 | *fault_catcher = &jbuf; | ||
85 | if(UML_SETJMP(&jbuf) == 0) | ||
86 | ret = strlen(str) + 1; | ||
87 | else ret = *faddrp - (unsigned long) str; | ||
88 | |||
89 | *fault_addr = NULL; | ||
90 | *fault_catcher = NULL; | ||
91 | |||
92 | TASK_REGS(get_current())->tt = save; | ||
93 | return ret; | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
98 | * Emacs will notice this stuff at the end of the file and automatically | ||
99 | * adjust the settings for this buffer only. This must remain at the end | ||
100 | * of the file. | ||
101 | * --------------------------------------------------------------------------- | ||
102 | * Local variables: | ||
103 | * c-file-style: "linux" | ||
104 | * End: | ||
105 | */ | ||