aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/kernel/tt
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/kernel/tt')
-rw-r--r--arch/um/kernel/tt/Makefile14
-rw-r--r--arch/um/kernel/tt/exec_kern.c84
-rw-r--r--arch/um/kernel/tt/exec_user.c56
-rw-r--r--arch/um/kernel/tt/gdb.c280
-rw-r--r--arch/um/kernel/tt/gdb_kern.c40
-rw-r--r--arch/um/kernel/tt/include/mode-tt.h34
-rw-r--r--arch/um/kernel/tt/ksyms.c29
-rw-r--r--arch/um/kernel/tt/mem.c34
-rw-r--r--arch/um/kernel/tt/mem_user.c49
-rw-r--r--arch/um/kernel/tt/process_kern.c461
-rw-r--r--arch/um/kernel/tt/ptproxy/Makefile10
-rw-r--r--arch/um/kernel/tt/ptproxy/proxy.c377
-rw-r--r--arch/um/kernel/tt/ptproxy/ptproxy.h61
-rw-r--r--arch/um/kernel/tt/ptproxy/ptrace.c237
-rw-r--r--arch/um/kernel/tt/ptproxy/sysdep.c70
-rw-r--r--arch/um/kernel/tt/ptproxy/sysdep.h25
-rw-r--r--arch/um/kernel/tt/ptproxy/wait.c85
-rw-r--r--arch/um/kernel/tt/ptproxy/wait.h15
-rw-r--r--arch/um/kernel/tt/syscall_kern.c46
-rw-r--r--arch/um/kernel/tt/syscall_user.c60
-rw-r--r--arch/um/kernel/tt/tlb.c120
-rw-r--r--arch/um/kernel/tt/tracer.c461
-rw-r--r--arch/um/kernel/tt/trap_user.c70
-rw-r--r--arch/um/kernel/tt/uaccess.c73
-rw-r--r--arch/um/kernel/tt/uaccess_user.c105
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
6obj-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
10obj-$(CONFIG_PT_PROXY) += gdb_kern.o ptproxy/
11
12USER_OBJS := gdb.o tracer.o
13
14include 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
20static 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
28void 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
65void 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
18void 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
24extern int debugger_pid;
25extern int debugger_fd;
26extern int debugger_parent;
27
28int detach(int pid, int sig)
29{
30 return(ptrace(PTRACE_DETACH, pid, 0, sig));
31}
32
33int 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
42int cont(int pid)
43{
44 return(ptrace(PTRACE_CONT, pid, 0, 0));
45}
46
47#ifdef UML_CONFIG_PT_PROXY
48
49int debugger_signal(int status, pid_t pid)
50{
51 return(debugger_proxy(status, pid));
52}
53
54void child_signal(pid_t pid, int status)
55{
56 child_proxy(pid, status);
57}
58
59static void gdb_announce(char *dev_name, int dev)
60{
61 printf("gdb assigned device '%s'\n", dev_name);
62}
63
64static 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 */
73static void *xterm_data;
74static int xterm_fd;
75
76extern void *xterm_init(char *, int, struct chan_opts *);
77extern int xterm_open(int, int, int, void *, char **);
78extern void xterm_close(int, void *);
79
80int 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
90static 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
105static void exit_debugger(void)
106{
107 initial_thread_cb(exit_debugger_cb, NULL);
108}
109
110__uml_exitcall(exit_debugger);
111
112struct gdb_data {
113 char *str;
114 int err;
115};
116
117extern char *linux_prog;
118
119static 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
143int 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
153void remove_gdb_cb(void *unused)
154{
155 exit_debugger_cb(NULL);
156}
157
158int gdb_remove(int unused, char **error_out)
159{
160 initial_thread_cb(remove_gdb_cb, NULL);
161 return 0;
162}
163
164void 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
174int 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
188int 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 */
203static 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
214static 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
229int debugger_signal(int status, pid_t pid){ return(0); }
230void child_signal(pid_t pid, int status){ }
231int 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
238void signal_usr1(int sig)
239{
240 printf("debug requested when CONFIG_PT_PROXY is off\n");
241}
242
243int 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
250int config_gdb(char *str)
251{
252 return(-1);
253}
254
255int remove_gdb(void)
256{
257 return(-1);
258}
259
260int init_parent_proxy(int pid)
261{
262 return(-1);
263}
264
265void 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
11extern int gdb_config(char *str, char **error_out);
12extern int gdb_remove(int n, char **error_out);
13
14static 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
21int 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
11enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB };
12
13extern int tracing_pid;
14
15extern int tracer(int (*init_proc)(void *), void *sp);
16extern void sig_handler_common_tt(int sig, void *sc);
17extern void syscall_handler_tt(int sig, union uml_pt_regs *regs);
18extern void reboot_tt(void);
19extern void halt_tt(void);
20extern int is_tracer_winch(int pid, int fd, void *data);
21extern 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
10EXPORT_SYMBOL(__do_copy_from_user);
11EXPORT_SYMBOL(__do_copy_to_user);
12EXPORT_SYMBOL(__do_strncpy_from_user);
13EXPORT_SYMBOL(__do_strnlen_user);
14EXPORT_SYMBOL(__do_clear_user);
15EXPORT_SYMBOL(clear_user_tt);
16
17EXPORT_SYMBOL(tracing_pid);
18EXPORT_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
14void 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
25unsigned 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
16void 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
27void 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
93void 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
111void 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
122void schedule_tail(struct task_struct *prev);
123
124static 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(&current->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(&current->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, &current->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
163static 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
196void finish_fork_handler(int sig)
197{
198 UPT_SC(&current->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
220int 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
231int 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(&regs->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
290void reboot_tt(void)
291{
292 current->thread.request.op = OP_REBOOT;
293 os_usr1_process(os_getpid());
294 change_sig(SIGUSR1, 1);
295}
296
297void halt_tt(void)
298{
299 current->thread.request.op = OP_HALT;
300 os_usr1_process(os_getpid());
301 change_sig(SIGUSR1, 1);
302}
303
304void 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
318void 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
334int 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
370void init_idle_tt(void)
371{
372 default_idle();
373}
374
375extern void start_kernel(void);
376
377static 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
394void set_tracing(void *task, int tracing)
395{
396 ((struct task_struct *) task)->thread.mode.tt.tracing = tracing;
397}
398
399int is_tracing(void *t)
400{
401 return (((struct task_struct *) t)->thread.mode.tt.tracing);
402}
403
404int 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
416void 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
427int 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
438int external_pid_tt(struct task_struct *task)
439{
440 return(task->thread.mode.tt.extern_pid);
441}
442
443int thread_pid_tt(struct task_struct *task)
444{
445 return(task->thread.mode.tt.extern_pid);
446}
447
448int 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
6obj-y = proxy.o ptrace.o sysdep.o wait.o
7
8USER_OBJS := $(obj-y)
9
10include 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/**********************************************************************
2proxy.c
3
4Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
5terms and conditions.
6
7Jeff 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
33static 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
72int 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 */
127static debugger_state parent;
128static int parent_syscall(debugger_state *debugger, int pid);
129
130int 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
143int 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
150static 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
169int 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
176void 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 */
184static debugger_state debugger;
185static debugee_state debugee;
186
187void 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
206int 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
244void 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
263void 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
274void 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
299char gdb_init_string[] =
300"att 1 \n\
301b panic \n\
302b stop \n\
303handle SIGWINCH nostop noprint pass \n\
304";
305
306int 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/**********************************************************************
2ptproxy.h
3
4Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
5terms and conditions.
6**********************************************************************/
7
8#ifndef __PTPROXY_H
9#define __PTPROXY_H
10
11#include <sys/types.h>
12
13typedef struct debugger debugger_state;
14typedef struct debugee debugee_state;
15
16struct 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
29struct 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
43extern int debugger_syscall(debugger_state *debugger, pid_t pid);
44extern int debugger_normal_return (debugger_state *debugger, pid_t unused);
45
46extern long proxy_ptrace (struct debugger *, int, pid_t, long, long, pid_t,
47 int *strace_out);
48extern 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/**********************************************************************
2ptrace.c
3
4Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
5terms and conditions.
6
7Jeff 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
24long 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/**********************************************************************
2sysdep.c
3
4Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
5terms 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
19int 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
30void 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
42void syscall_set_result(pid_t pid, long result)
43{
44 ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, result);
45}
46
47void syscall_continue(pid_t pid)
48{
49 ptrace(PTRACE_SYSCALL, pid, 0, 0);
50}
51
52int 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/**********************************************************************
2sysdep.h
3
4Copyright (C) 1999 Lars Brinkhoff.
5Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
6See the file COPYING for licensing terms and conditions.
7**********************************************************************/
8
9extern int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3,
10 long *arg4, long *arg5);
11extern void syscall_cancel (pid_t pid, long result);
12extern void syscall_set_result (pid_t pid, long result);
13extern void syscall_continue (pid_t pid);
14extern 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/**********************************************************************
2wait.c
3
4Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
5terms 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
20int 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
48int parent_wait_return(struct debugger *debugger, pid_t unused)
49{
50 return(debugger_normal_return(debugger, -1));
51}
52
53int 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/**********************************************************************
2wait.h
3
4Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
5terms and conditions.
6**********************************************************************/
7
8#ifndef __PTPROXY_WAIT_H
9#define __PTPROXY_WAIT_H
10
11extern int proxy_wait_return(struct debugger *debugger, pid_t unused);
12extern int real_wait_return(struct debugger *debugger);
13extern 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
19void syscall_handler_tt(int sig, struct pt_regs *regs)
20{
21 void *sc;
22 long result;
23 int syscall;
24
25 sc = UPT_SC(&regs->regs);
26 SC_START_SYSCALL(sc);
27
28 syscall = UPT_SYSCALL_NR(&regs->regs);
29 syscall_trace(&regs->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(&regs->regs) = sc;
42
43 SC_SET_SYSCALL_RETURN(sc, result);
44
45 syscall_trace(&regs->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
18void do_sigtrap(void *task)
19{
20 UPT_SYSCALL_NR(TASK_REGS(task)) = -1;
21}
22
23void 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
19static 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
57static 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
68atomic_t vmchange_seq = ATOMIC_INIT(1);
69
70void 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
76void flush_tlb_kernel_vm_tt(void)
77{
78 flush_tlb_kernel_range(start_vm, end_vm);
79}
80
81void __flush_tlb_one_tt(unsigned long addr)
82{
83 flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
84}
85
86void 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
101void 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
116void 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
31static int tracer_winch[2];
32
33int 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
42static 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
54static 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
66void 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
78void 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
89static 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 */
100int debug = 0;
101int debug_stop = 1;
102int debug_parent = 0;
103int honeypot = 0;
104
105static 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
126static 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 */
163int debugger_pid = -1;
164int debugger_parent = -1;
165int debugger_fd = -1;
166int gdb_pid = -1;
167
168struct {
169 int pid;
170 int signal;
171 unsigned long addr;
172 struct timeval time;
173} signal_record[1024][32];
174
175int signal_index[32];
176int nsignals = 0;
177int debug_trace = 0;
178
179extern void signal_usr1(int sig);
180
181int tracing_pid = -1;
182
183int 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
410static 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
439static 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
16void 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
9int 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, &current->thread.fault_addr,
15 &current->thread.fault_catcher));
16}
17
18int 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, &current->thread.fault_addr,
24 &current->thread.fault_catcher));
25}
26
27int 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 &current->thread.fault_addr,
36 &current->thread.fault_catcher);
37 if(n < 0) return(-EFAULT);
38 return(n);
39}
40
41int __clear_user_tt(void __user *mem, int len)
42{
43 return(__do_clear_user(mem, len,
44 &current->thread.fault_addr,
45 &current->thread.fault_catcher));
46}
47
48int 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, &current->thread.fault_addr,
54 &current->thread.fault_catcher));
55}
56
57int strnlen_user_tt(const void __user *str, int len)
58{
59 return(__do_strnlen_user(str, len,
60 &current->thread.fault_addr,
61 &current->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
14int __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
36static void __do_strncpy(void *dst, const void *src, int count)
37{
38 strncpy(dst, src, count);
39}
40
41int __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
56static void __do_clear(void *to, const void *from, int n)
57{
58 memset(to, 0, n);
59}
60
61int __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
76int __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 */