aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/kernel
diff options
context:
space:
mode:
authorAnton Altaparmakov <aia21@cantab.net>2006-01-19 11:39:33 -0500
committerAnton Altaparmakov <aia21@cantab.net>2006-01-19 11:39:33 -0500
commit944d79559d154c12becde0dab327016cf438f46c (patch)
tree50c101806f4d3b6585222dda060559eb4f3e005a /arch/um/kernel
parentd087e4bdd24ebe3ae3d0b265b6573ec901af4b4b (diff)
parent0f36b018b2e314d45af86449f1a97facb1fbe300 (diff)
Merge branch 'master' of /usr/src/ntfs-2.6/
Diffstat (limited to 'arch/um/kernel')
-rw-r--r--arch/um/kernel/Makefile7
-rw-r--r--arch/um/kernel/asm-offsets.c2
-rw-r--r--arch/um/kernel/exec_kern.c1
-rw-r--r--arch/um/kernel/irq_user.c49
-rw-r--r--arch/um/kernel/process_kern.c29
-rw-r--r--arch/um/kernel/reboot.c2
-rw-r--r--arch/um/kernel/sigio_user.c85
-rw-r--r--arch/um/kernel/signal_kern.c92
-rw-r--r--arch/um/kernel/signal_user.c157
-rw-r--r--arch/um/kernel/skas/Makefile8
-rw-r--r--arch/um/kernel/skas/include/mm_id.h17
-rw-r--r--arch/um/kernel/skas/include/mmu-skas.h35
-rw-r--r--arch/um/kernel/skas/include/mode-skas.h33
-rw-r--r--arch/um/kernel/skas/include/mode_kern-skas.h52
-rw-r--r--arch/um/kernel/skas/include/proc_mm.h55
-rw-r--r--arch/um/kernel/skas/include/skas.h50
-rw-r--r--arch/um/kernel/skas/include/stub-data.h18
-rw-r--r--arch/um/kernel/skas/include/uaccess-skas.h32
-rw-r--r--arch/um/kernel/skas/mem_user.c281
-rw-r--r--arch/um/kernel/skas/mmu.c8
-rw-r--r--arch/um/kernel/skas/process.c16
-rw-r--r--arch/um/kernel/skas/process_kern.c40
-rw-r--r--arch/um/kernel/skas/trap_user.c78
-rw-r--r--arch/um/kernel/skas/uaccess.c2
-rw-r--r--arch/um/kernel/syscall.c4
-rw-r--r--arch/um/kernel/time.c9
-rw-r--r--arch/um/kernel/time_kern.c132
-rw-r--r--arch/um/kernel/trap_kern.c25
-rw-r--r--arch/um/kernel/trap_user.c98
-rw-r--r--arch/um/kernel/tt/exec_kern.c4
-rw-r--r--arch/um/kernel/tt/gdb.c1
-rw-r--r--arch/um/kernel/tt/include/debug.h18
-rw-r--r--arch/um/kernel/tt/include/mmu-tt.h23
-rw-r--r--arch/um/kernel/tt/include/tt.h46
-rw-r--r--arch/um/kernel/tt/include/uaccess-tt.h59
-rw-r--r--arch/um/kernel/tt/process_kern.c10
-rw-r--r--arch/um/kernel/tt/ptproxy/ptrace.c1
-rw-r--r--arch/um/kernel/tt/ptproxy/sysdep.c1
-rw-r--r--arch/um/kernel/tt/tracer.c1
-rw-r--r--arch/um/kernel/tt/trap_user.c21
-rw-r--r--arch/um/kernel/um_arch.c15
-rw-r--r--arch/um/kernel/umid.c323
-rw-r--r--arch/um/kernel/user_util.c174
43 files changed, 298 insertions, 1816 deletions
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index 3de9d21e36bf..693018ba80f1 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -9,9 +9,8 @@ clean-files :=
9obj-y = config.o exec_kern.o exitcode.o \ 9obj-y = config.o exec_kern.o exitcode.o \
10 init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \ 10 init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \
11 process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \ 11 process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \
12 signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o time.o \ 12 signal_kern.o smp.o syscall_kern.o sysrq.o \
13 time_kern.o tlb.o trap_kern.o trap_user.o uaccess.o um_arch.o \ 13 time_kern.o tlb.o trap_kern.o uaccess.o um_arch.o umid.o
14 umid.o user_util.o
15 14
16obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o 15obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
17obj-$(CONFIG_GPROF) += gprof_syms.o 16obj-$(CONFIG_GPROF) += gprof_syms.o
@@ -24,7 +23,7 @@ obj-$(CONFIG_MODE_SKAS) += skas/
24 23
25user-objs-$(CONFIG_TTY_LOG) += tty_log.o 24user-objs-$(CONFIG_TTY_LOG) += tty_log.o
26 25
27USER_OBJS := $(user-objs-y) config.o time.o tty_log.o umid.o user_util.o 26USER_OBJS := $(user-objs-y) config.o tty_log.o
28 27
29include arch/um/scripts/Makefile.rules 28include arch/um/scripts/Makefile.rules
30 29
diff --git a/arch/um/kernel/asm-offsets.c b/arch/um/kernel/asm-offsets.c
index c13a64a288f6..91ea538e1612 100644
--- a/arch/um/kernel/asm-offsets.c
+++ b/arch/um/kernel/asm-offsets.c
@@ -1 +1 @@
/* Dummy file to make kbuild happy - unused! */ #include "sysdep/kernel-offsets.h"
diff --git a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c
index efd222ffe20e..569fe8b9b053 100644
--- a/arch/um/kernel/exec_kern.c
+++ b/arch/um/kernel/exec_kern.c
@@ -17,7 +17,6 @@
17#include "irq_user.h" 17#include "irq_user.h"
18#include "tlb.h" 18#include "tlb.h"
19#include "os.h" 19#include "os.h"
20#include "time_user.h"
21#include "choose-mode.h" 20#include "choose-mode.h"
22#include "mode_kern.h" 21#include "mode_kern.h"
23 22
diff --git a/arch/um/kernel/irq_user.c b/arch/um/kernel/irq_user.c
index c3ccaf24f3e0..0e32f5f4a887 100644
--- a/arch/um/kernel/irq_user.c
+++ b/arch/um/kernel/irq_user.c
@@ -15,7 +15,6 @@
15#include "kern_util.h" 15#include "kern_util.h"
16#include "user.h" 16#include "user.h"
17#include "process.h" 17#include "process.h"
18#include "signal_user.h"
19#include "sigio.h" 18#include "sigio.h"
20#include "irq_user.h" 19#include "irq_user.h"
21#include "os.h" 20#include "os.h"
@@ -29,7 +28,6 @@ struct irq_fd {
29 int pid; 28 int pid;
30 int events; 29 int events;
31 int current_events; 30 int current_events;
32 int freed;
33}; 31};
34 32
35static struct irq_fd *active_fds = NULL; 33static struct irq_fd *active_fds = NULL;
@@ -41,9 +39,11 @@ static int pollfds_size = 0;
41 39
42extern int io_count, intr_count; 40extern int io_count, intr_count;
43 41
42extern void free_irqs(void);
43
44void sigio_handler(int sig, union uml_pt_regs *regs) 44void sigio_handler(int sig, union uml_pt_regs *regs)
45{ 45{
46 struct irq_fd *irq_fd, *next; 46 struct irq_fd *irq_fd;
47 int i, n; 47 int i, n;
48 48
49 if(smp_sigio_handler()) return; 49 if(smp_sigio_handler()) return;
@@ -66,29 +66,15 @@ void sigio_handler(int sig, union uml_pt_regs *regs)
66 irq_fd = irq_fd->next; 66 irq_fd = irq_fd->next;
67 } 67 }
68 68
69 for(irq_fd = active_fds; irq_fd != NULL; irq_fd = next){ 69 for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
70 next = irq_fd->next;
71 if(irq_fd->current_events != 0){ 70 if(irq_fd->current_events != 0){
72 irq_fd->current_events = 0; 71 irq_fd->current_events = 0;
73 do_IRQ(irq_fd->irq, regs); 72 do_IRQ(irq_fd->irq, regs);
74
75 /* This is here because the next irq may be
76 * freed in the handler. If a console goes
77 * away, both the read and write irqs will be
78 * freed. After do_IRQ, ->next will point to
79 * a good IRQ.
80 * Irqs can't be freed inside their handlers,
81 * so the next best thing is to have them
82 * marked as needing freeing, so that they
83 * can be freed here.
84 */
85 next = irq_fd->next;
86 if(irq_fd->freed){
87 free_irq(irq_fd->irq, irq_fd->id);
88 }
89 } 73 }
90 } 74 }
91 } 75 }
76
77 free_irqs();
92} 78}
93 79
94int activate_ipi(int fd, int pid) 80int activate_ipi(int fd, int pid)
@@ -136,8 +122,7 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
136 .irq = irq, 122 .irq = irq,
137 .pid = pid, 123 .pid = pid,
138 .events = events, 124 .events = events,
139 .current_events = 0, 125 .current_events = 0 } );
140 .freed = 0 } );
141 126
142 /* Critical section - locked by a spinlock because this stuff can 127 /* Critical section - locked by a spinlock because this stuff can
143 * be changed from interrupt handlers. The stuff above is done 128 * be changed from interrupt handlers. The stuff above is done
@@ -313,26 +298,6 @@ static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out)
313 return(irq); 298 return(irq);
314} 299}
315 300
316void free_irq_later(int irq, void *dev_id)
317{
318 struct irq_fd *irq_fd;
319 unsigned long flags;
320
321 flags = irq_lock();
322 for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
323 if((irq_fd->irq == irq) && (irq_fd->id == dev_id))
324 break;
325 }
326 if(irq_fd == NULL){
327 printk("free_irq_later found no irq, irq = %d, "
328 "dev_id = 0x%p\n", irq, dev_id);
329 goto out;
330 }
331 irq_fd->freed = 1;
332 out:
333 irq_unlock(flags);
334}
335
336void reactivate_fd(int fd, int irqnum) 301void reactivate_fd(int fd, int irqnum)
337{ 302{
338 struct irq_fd *irq; 303 struct irq_fd *irq;
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
index 34b54a3e2132..3113cab8675e 100644
--- a/arch/um/kernel/process_kern.c
+++ b/arch/um/kernel/process_kern.c
@@ -36,11 +36,9 @@
36#include "kern_util.h" 36#include "kern_util.h"
37#include "kern.h" 37#include "kern.h"
38#include "signal_kern.h" 38#include "signal_kern.h"
39#include "signal_user.h"
40#include "init.h" 39#include "init.h"
41#include "irq_user.h" 40#include "irq_user.h"
42#include "mem_user.h" 41#include "mem_user.h"
43#include "time_user.h"
44#include "tlb.h" 42#include "tlb.h"
45#include "frame_kern.h" 43#include "frame_kern.h"
46#include "sigcontext.h" 44#include "sigcontext.h"
@@ -108,7 +106,7 @@ void set_current(void *t)
108{ 106{
109 struct task_struct *task = t; 107 struct task_struct *task = t;
110 108
111 cpu_tasks[task->thread_info->cpu] = ((struct cpu_task) 109 cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task)
112 { external_pid(task), task }); 110 { external_pid(task), task });
113} 111}
114 112
@@ -289,17 +287,27 @@ EXPORT_SYMBOL(disable_hlt);
289 287
290void *um_kmalloc(int size) 288void *um_kmalloc(int size)
291{ 289{
292 return(kmalloc(size, GFP_KERNEL)); 290 return kmalloc(size, GFP_KERNEL);
293} 291}
294 292
295void *um_kmalloc_atomic(int size) 293void *um_kmalloc_atomic(int size)
296{ 294{
297 return(kmalloc(size, GFP_ATOMIC)); 295 return kmalloc(size, GFP_ATOMIC);
298} 296}
299 297
300void *um_vmalloc(int size) 298void *um_vmalloc(int size)
301{ 299{
302 return(vmalloc(size)); 300 return vmalloc(size);
301}
302
303void *um_vmalloc_atomic(int size)
304{
305 return __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM, PAGE_KERNEL);
306}
307
308int __cant_sleep(void) {
309 return in_atomic() || irqs_disabled() || in_interrupt();
310 /* Is in_interrupt() really needed? */
303} 311}
304 312
305unsigned long get_fault_addr(void) 313unsigned long get_fault_addr(void)
@@ -324,10 +332,6 @@ int user_context(unsigned long sp)
324 return(stack != (unsigned long) current_thread); 332 return(stack != (unsigned long) current_thread);
325} 333}
326 334
327extern void remove_umid_dir(void);
328
329__uml_exitcall(remove_umid_dir);
330
331extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end; 335extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end;
332 336
333void do_uml_exitcalls(void) 337void do_uml_exitcalls(void)
@@ -375,11 +379,6 @@ int smp_sigio_handler(void)
375 return(0); 379 return(0);
376} 380}
377 381
378int um_in_interrupt(void)
379{
380 return(in_interrupt());
381}
382
383int cpu(void) 382int cpu(void)
384{ 383{
385 return(current_thread->cpu); 384 return(current_thread->cpu);
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index a637e885c583..6f1a3a288117 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -12,6 +12,8 @@
12#include "mode.h" 12#include "mode.h"
13#include "choose-mode.h" 13#include "choose-mode.h"
14 14
15void (*pm_power_off)(void);
16
15#ifdef CONFIG_SMP 17#ifdef CONFIG_SMP
16static void kill_idlers(int me) 18static void kill_idlers(int me)
17{ 19{
diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c
index 48b1f644b9a6..f7b18e157d35 100644
--- a/arch/um/kernel/sigio_user.c
+++ b/arch/um/kernel/sigio_user.c
@@ -216,6 +216,8 @@ static int write_sigio_thread(void *unused)
216 "err = %d\n", -n); 216 "err = %d\n", -n);
217 } 217 }
218 } 218 }
219
220 return 0;
219} 221}
220 222
221static int need_poll(int n) 223static int need_poll(int n)
@@ -335,70 +337,103 @@ int ignore_sigio_fd(int fd)
335 return(err); 337 return(err);
336} 338}
337 339
338static int setup_initial_poll(int fd) 340static struct pollfd* setup_initial_poll(int fd)
339{ 341{
340 struct pollfd *p; 342 struct pollfd *p;
341 343
342 p = um_kmalloc_atomic(sizeof(struct pollfd)); 344 p = um_kmalloc(sizeof(struct pollfd));
343 if(p == NULL){ 345 if (p == NULL) {
344 printk("setup_initial_poll : failed to allocate poll\n"); 346 printk("setup_initial_poll : failed to allocate poll\n");
345 return(-1); 347 return NULL;
346 } 348 }
347 *p = ((struct pollfd) { .fd = fd, 349 *p = ((struct pollfd) { .fd = fd,
348 .events = POLLIN, 350 .events = POLLIN,
349 .revents = 0 }); 351 .revents = 0 });
350 current_poll = ((struct pollfds) { .poll = p, 352 return p;
351 .used = 1,
352 .size = 1 });
353 return(0);
354} 353}
355 354
356void write_sigio_workaround(void) 355void write_sigio_workaround(void)
357{ 356{
358 unsigned long stack; 357 unsigned long stack;
358 struct pollfd *p;
359 int err; 359 int err;
360 int l_write_sigio_fds[2];
361 int l_sigio_private[2];
362 int l_write_sigio_pid;
360 363
364 /* We call this *tons* of times - and most ones we must just fail. */
361 sigio_lock(); 365 sigio_lock();
362 if(write_sigio_pid != -1) 366 l_write_sigio_pid = write_sigio_pid;
363 goto out; 367 sigio_unlock();
368
369 if (l_write_sigio_pid != -1)
370 return;
364 371
365 err = os_pipe(write_sigio_fds, 1, 1); 372 err = os_pipe(l_write_sigio_fds, 1, 1);
366 if(err < 0){ 373 if(err < 0){
367 printk("write_sigio_workaround - os_pipe 1 failed, " 374 printk("write_sigio_workaround - os_pipe 1 failed, "
368 "err = %d\n", -err); 375 "err = %d\n", -err);
369 goto out; 376 return;
370 } 377 }
371 err = os_pipe(sigio_private, 1, 1); 378 err = os_pipe(l_sigio_private, 1, 1);
372 if(err < 0){ 379 if(err < 0){
373 printk("write_sigio_workaround - os_pipe 2 failed, " 380 printk("write_sigio_workaround - os_pipe 1 failed, "
374 "err = %d\n", -err); 381 "err = %d\n", -err);
375 goto out_close1; 382 goto out_close1;
376 } 383 }
377 if(setup_initial_poll(sigio_private[1])) 384
385 p = setup_initial_poll(l_sigio_private[1]);
386 if(!p)
378 goto out_close2; 387 goto out_close2;
379 388
380 write_sigio_pid = run_helper_thread(write_sigio_thread, NULL, 389 sigio_lock();
390
391 /* Did we race? Don't try to optimize this, please, it's not so likely
392 * to happen, and no more than once at the boot. */
393 if(write_sigio_pid != -1)
394 goto out_unlock;
395
396 write_sigio_pid = run_helper_thread(write_sigio_thread, NULL,
381 CLONE_FILES | CLONE_VM, &stack, 0); 397 CLONE_FILES | CLONE_VM, &stack, 0);
382 398
383 if(write_sigio_pid < 0) goto out_close2; 399 if (write_sigio_pid < 0)
400 goto out_clear;
384 401
385 if(write_sigio_irq(write_sigio_fds[0])) 402 if (write_sigio_irq(l_write_sigio_fds[0]))
386 goto out_kill; 403 goto out_kill;
387 404
388 out: 405 /* Success, finally. */
406 memcpy(write_sigio_fds, l_write_sigio_fds, sizeof(l_write_sigio_fds));
407 memcpy(sigio_private, l_sigio_private, sizeof(l_sigio_private));
408
409 current_poll = ((struct pollfds) { .poll = p,
410 .used = 1,
411 .size = 1 });
412
389 sigio_unlock(); 413 sigio_unlock();
390 return; 414 return;
391 415
392 out_kill: 416 out_kill:
393 os_kill_process(write_sigio_pid, 1); 417 l_write_sigio_pid = write_sigio_pid;
418 write_sigio_pid = -1;
419 sigio_unlock();
420 /* Going to call waitpid, avoid holding the lock. */
421 os_kill_process(l_write_sigio_pid, 1);
422 goto out_free;
423
424 out_clear:
394 write_sigio_pid = -1; 425 write_sigio_pid = -1;
426 out_unlock:
427 sigio_unlock();
428 out_free:
429 kfree(p);
395 out_close2: 430 out_close2:
396 os_close_file(sigio_private[0]); 431 os_close_file(l_sigio_private[0]);
397 os_close_file(sigio_private[1]); 432 os_close_file(l_sigio_private[1]);
398 out_close1: 433 out_close1:
399 os_close_file(write_sigio_fds[0]); 434 os_close_file(l_write_sigio_fds[0]);
400 os_close_file(write_sigio_fds[1]); 435 os_close_file(l_write_sigio_fds[1]);
401 sigio_unlock(); 436 return;
402} 437}
403 438
404int read_sigio_fd(int fd) 439int read_sigio_fd(int fd)
diff --git a/arch/um/kernel/signal_kern.c b/arch/um/kernel/signal_kern.c
index 03618bd13d55..da17b7541e08 100644
--- a/arch/um/kernel/signal_kern.c
+++ b/arch/um/kernel/signal_kern.c
@@ -22,7 +22,6 @@
22#include "asm/ucontext.h" 22#include "asm/ucontext.h"
23#include "kern_util.h" 23#include "kern_util.h"
24#include "signal_kern.h" 24#include "signal_kern.h"
25#include "signal_user.h"
26#include "kern.h" 25#include "kern.h"
27#include "frame_kern.h" 26#include "frame_kern.h"
28#include "sigcontext.h" 27#include "sigcontext.h"
@@ -100,31 +99,46 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
100 return err; 99 return err;
101} 100}
102 101
103static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset) 102static int kern_do_signal(struct pt_regs *regs)
104{ 103{
105 struct k_sigaction ka_copy; 104 struct k_sigaction ka_copy;
106 siginfo_t info; 105 siginfo_t info;
106 sigset_t *oldset;
107 int sig, handled_sig = 0; 107 int sig, handled_sig = 0;
108 108
109 if (test_thread_flag(TIF_RESTORE_SIGMASK))
110 oldset = &current->saved_sigmask;
111 else
112 oldset = &current->blocked;
113
109 while((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0){ 114 while((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0){
110 handled_sig = 1; 115 handled_sig = 1;
111 /* Whee! Actually deliver the signal. */ 116 /* Whee! Actually deliver the signal. */
112 if(!handle_signal(regs, sig, &ka_copy, &info, oldset)) 117 if(!handle_signal(regs, sig, &ka_copy, &info, oldset)){
118 /* a signal was successfully delivered; the saved
119 * sigmask will have been stored in the signal frame,
120 * and will be restored by sigreturn, so we can simply
121 * clear the TIF_RESTORE_SIGMASK flag */
122 if (test_thread_flag(TIF_RESTORE_SIGMASK))
123 clear_thread_flag(TIF_RESTORE_SIGMASK);
113 break; 124 break;
125 }
114 } 126 }
115 127
116 /* Did we come from a system call? */ 128 /* Did we come from a system call? */
117 if(!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)){ 129 if(!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)){
118 /* Restart the system call - no handlers present */ 130 /* Restart the system call - no handlers present */
119 if(PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOHAND || 131 switch(PT_REGS_SYSCALL_RET(regs)){
120 PT_REGS_SYSCALL_RET(regs) == -ERESTARTSYS || 132 case -ERESTARTNOHAND:
121 PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOINTR){ 133 case -ERESTARTSYS:
134 case -ERESTARTNOINTR:
122 PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs); 135 PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
123 PT_REGS_RESTART_SYSCALL(regs); 136 PT_REGS_RESTART_SYSCALL(regs);
124 } 137 break;
125 else if(PT_REGS_SYSCALL_RET(regs) == -ERESTART_RESTARTBLOCK){ 138 case -ERESTART_RESTARTBLOCK:
126 PT_REGS_SYSCALL_RET(regs) = __NR_restart_syscall; 139 PT_REGS_SYSCALL_RET(regs) = __NR_restart_syscall;
127 PT_REGS_RESTART_SYSCALL(regs); 140 PT_REGS_RESTART_SYSCALL(regs);
141 break;
128 } 142 }
129 } 143 }
130 144
@@ -138,12 +152,19 @@ static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset)
138 if(current->ptrace & PT_DTRACE) 152 if(current->ptrace & PT_DTRACE)
139 current->thread.singlestep_syscall = 153 current->thread.singlestep_syscall =
140 is_syscall(PT_REGS_IP(&current->thread.regs)); 154 is_syscall(PT_REGS_IP(&current->thread.regs));
155
156 /* if there's no signal to deliver, we just put the saved sigmask
157 * back */
158 if (!handled_sig && test_thread_flag(TIF_RESTORE_SIGMASK)) {
159 clear_thread_flag(TIF_RESTORE_SIGMASK);
160 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
161 }
141 return(handled_sig); 162 return(handled_sig);
142} 163}
143 164
144int do_signal(void) 165int do_signal(void)
145{ 166{
146 return(kern_do_signal(&current->thread.regs, &current->blocked)); 167 return(kern_do_signal(&current->thread.regs));
147} 168}
148 169
149/* 170/*
@@ -151,63 +172,20 @@ int do_signal(void)
151 */ 172 */
152long sys_sigsuspend(int history0, int history1, old_sigset_t mask) 173long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
153{ 174{
154 sigset_t saveset;
155
156 mask &= _BLOCKABLE; 175 mask &= _BLOCKABLE;
157 spin_lock_irq(&current->sighand->siglock); 176 spin_lock_irq(&current->sighand->siglock);
158 saveset = current->blocked; 177 current->saved_sigmask = current->blocked;
159 siginitset(&current->blocked, mask); 178 siginitset(&current->blocked, mask);
160 recalc_sigpending(); 179 recalc_sigpending();
161 spin_unlock_irq(&current->sighand->siglock); 180 spin_unlock_irq(&current->sighand->siglock);
162 181
163 PT_REGS_SYSCALL_RET(&current->thread.regs) = -EINTR; 182 current->state = TASK_INTERRUPTIBLE;
164 while (1) { 183 schedule();
165 current->state = TASK_INTERRUPTIBLE; 184 set_thread_flag(TIF_RESTORE_SIGMASK);
166 schedule(); 185 return -ERESTARTNOHAND;
167 if(kern_do_signal(&current->thread.regs, &saveset))
168 return(-EINTR);
169 }
170}
171
172long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
173{
174 sigset_t saveset, newset;
175
176 /* XXX: Don't preclude handling different sized sigset_t's. */
177 if (sigsetsize != sizeof(sigset_t))
178 return -EINVAL;
179
180 if (copy_from_user(&newset, unewset, sizeof(newset)))
181 return -EFAULT;
182 sigdelsetmask(&newset, ~_BLOCKABLE);
183
184 spin_lock_irq(&current->sighand->siglock);
185 saveset = current->blocked;
186 current->blocked = newset;
187 recalc_sigpending();
188 spin_unlock_irq(&current->sighand->siglock);
189
190 PT_REGS_SYSCALL_RET(&current->thread.regs) = -EINTR;
191 while (1) {
192 current->state = TASK_INTERRUPTIBLE;
193 schedule();
194 if (kern_do_signal(&current->thread.regs, &saveset))
195 return(-EINTR);
196 }
197} 186}
198 187
199long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) 188long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
200{ 189{
201 return(do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs))); 190 return(do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs)));
202} 191}
203
204/*
205 * Overrides for Emacs so that we follow Linus's tabbing style.
206 * Emacs will notice this stuff at the end of the file and automatically
207 * adjust the settings for this buffer only. This must remain at the end
208 * of the file.
209 * ---------------------------------------------------------------------------
210 * Local variables:
211 * c-file-style: "linux"
212 * End:
213 */
diff --git a/arch/um/kernel/signal_user.c b/arch/um/kernel/signal_user.c
deleted file mode 100644
index 62f457835fb1..000000000000
--- a/arch/um/kernel/signal_user.c
+++ /dev/null
@@ -1,157 +0,0 @@
1/*
2 * Copyright (C) 2000 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 <signal.h>
10#include <errno.h>
11#include <stdarg.h>
12#include <string.h>
13#include <sys/mman.h>
14#include "user_util.h"
15#include "kern_util.h"
16#include "user.h"
17#include "signal_user.h"
18#include "signal_kern.h"
19#include "sysdep/sigcontext.h"
20#include "sigcontext.h"
21
22void set_sigstack(void *sig_stack, int size)
23{
24 stack_t stack = ((stack_t) { .ss_flags = 0,
25 .ss_sp = (__ptr_t) sig_stack,
26 .ss_size = size - sizeof(void *) });
27
28 if(sigaltstack(&stack, NULL) != 0)
29 panic("enabling signal stack failed, errno = %d\n", errno);
30}
31
32void set_handler(int sig, void (*handler)(int), int flags, ...)
33{
34 struct sigaction action;
35 va_list ap;
36 int mask;
37
38 va_start(ap, flags);
39 action.sa_handler = handler;
40 sigemptyset(&action.sa_mask);
41 while((mask = va_arg(ap, int)) != -1){
42 sigaddset(&action.sa_mask, mask);
43 }
44 va_end(ap);
45 action.sa_flags = flags;
46 action.sa_restorer = NULL;
47 if(sigaction(sig, &action, NULL) < 0)
48 panic("sigaction failed");
49}
50
51int change_sig(int signal, int on)
52{
53 sigset_t sigset, old;
54
55 sigemptyset(&sigset);
56 sigaddset(&sigset, signal);
57 sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old);
58 return(!sigismember(&old, signal));
59}
60
61/* Both here and in set/get_signal we don't touch SIGPROF, because we must not
62 * disable profiling; it's safe because the profiling code does not interact
63 * with the kernel code at all.*/
64
65static void change_signals(int type)
66{
67 sigset_t mask;
68
69 sigemptyset(&mask);
70 sigaddset(&mask, SIGVTALRM);
71 sigaddset(&mask, SIGALRM);
72 sigaddset(&mask, SIGIO);
73 if(sigprocmask(type, &mask, NULL) < 0)
74 panic("Failed to change signal mask - errno = %d", errno);
75}
76
77void block_signals(void)
78{
79 change_signals(SIG_BLOCK);
80}
81
82void unblock_signals(void)
83{
84 change_signals(SIG_UNBLOCK);
85}
86
87/* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled
88 * together under SIGVTALRM_BIT. SIGPROF is excluded because we want to
89 * be able to profile all of UML, not just the non-critical sections. If
90 * profiling is not thread-safe, then that is not my problem. We can disable
91 * profiling when SMP is enabled in that case.
92 */
93#define SIGIO_BIT 0
94#define SIGVTALRM_BIT 1
95
96static int enable_mask(sigset_t *mask)
97{
98 int sigs;
99
100 sigs = sigismember(mask, SIGIO) ? 0 : 1 << SIGIO_BIT;
101 sigs |= sigismember(mask, SIGVTALRM) ? 0 : 1 << SIGVTALRM_BIT;
102 sigs |= sigismember(mask, SIGALRM) ? 0 : 1 << SIGVTALRM_BIT;
103 return(sigs);
104}
105
106int get_signals(void)
107{
108 sigset_t mask;
109
110 if(sigprocmask(SIG_SETMASK, NULL, &mask) < 0)
111 panic("Failed to get signal mask");
112 return(enable_mask(&mask));
113}
114
115int set_signals(int enable)
116{
117 sigset_t mask;
118 int ret;
119
120 sigemptyset(&mask);
121 if(enable & (1 << SIGIO_BIT))
122 sigaddset(&mask, SIGIO);
123 if(enable & (1 << SIGVTALRM_BIT)){
124 sigaddset(&mask, SIGVTALRM);
125 sigaddset(&mask, SIGALRM);
126 }
127
128 /* This is safe - sigprocmask is guaranteed to copy locally the
129 * value of new_set, do his work and then, at the end, write to
130 * old_set.
131 */
132 if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0)
133 panic("Failed to enable signals");
134 ret = enable_mask(&mask);
135 sigemptyset(&mask);
136 if((enable & (1 << SIGIO_BIT)) == 0)
137 sigaddset(&mask, SIGIO);
138 if((enable & (1 << SIGVTALRM_BIT)) == 0){
139 sigaddset(&mask, SIGVTALRM);
140 sigaddset(&mask, SIGALRM);
141 }
142 if(sigprocmask(SIG_BLOCK, &mask, NULL) < 0)
143 panic("Failed to block signals");
144
145 return(ret);
146}
147
148/*
149 * Overrides for Emacs so that we follow Linus's tabbing style.
150 * Emacs will notice this stuff at the end of the file and automatically
151 * adjust the settings for this buffer only. This must remain at the end
152 * of the file.
153 * ---------------------------------------------------------------------------
154 * Local variables:
155 * c-file-style: "linux"
156 * End:
157 */
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
index 8de471b59c1c..57181a920d48 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -1,12 +1,12 @@
1# 1#
2# Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com) 2# Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com)
3# Licensed under the GPL 3# Licensed under the GPL
4# 4#
5 5
6obj-y := clone.o exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \ 6obj-y := clone.o exec_kern.o mem.o mmu.o process_kern.o \
7 syscall.o tlb.o trap_user.o uaccess.o 7 syscall.o tlb.o uaccess.o
8 8
9USER_OBJS := process.o clone.o 9USER_OBJS := clone.o
10 10
11include arch/um/scripts/Makefile.rules 11include arch/um/scripts/Makefile.rules
12 12
diff --git a/arch/um/kernel/skas/include/mm_id.h b/arch/um/kernel/skas/include/mm_id.h
deleted file mode 100644
index 48dd0989ddaa..000000000000
--- a/arch/um/kernel/skas/include/mm_id.h
+++ /dev/null
@@ -1,17 +0,0 @@
1/*
2 * Copyright (C) 2005 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __MM_ID_H
7#define __MM_ID_H
8
9struct mm_id {
10 union {
11 int mm_fd;
12 int pid;
13 } u;
14 unsigned long stack;
15};
16
17#endif
diff --git a/arch/um/kernel/skas/include/mmu-skas.h b/arch/um/kernel/skas/include/mmu-skas.h
deleted file mode 100644
index 44110c521e49..000000000000
--- a/arch/um/kernel/skas/include/mmu-skas.h
+++ /dev/null
@@ -1,35 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __SKAS_MMU_H
7#define __SKAS_MMU_H
8
9#include "linux/config.h"
10#include "mm_id.h"
11#include "asm/ldt.h"
12
13struct mmu_context_skas {
14 struct mm_id id;
15 unsigned long last_page_table;
16#ifdef CONFIG_3_LEVEL_PGTABLES
17 unsigned long last_pmd;
18#endif
19 uml_ldt_t ldt;
20};
21
22extern void switch_mm_skas(struct mm_id * mm_idp);
23
24#endif
25
26/*
27 * Overrides for Emacs so that we follow Linus's tabbing style.
28 * Emacs will notice this stuff at the end of the file and automatically
29 * adjust the settings for this buffer only. This must remain at the end
30 * of the file.
31 * ---------------------------------------------------------------------------
32 * Local variables:
33 * c-file-style: "linux"
34 * End:
35 */
diff --git a/arch/um/kernel/skas/include/mode-skas.h b/arch/um/kernel/skas/include/mode-skas.h
deleted file mode 100644
index bcd26a6a3888..000000000000
--- a/arch/um/kernel/skas/include/mode-skas.h
+++ /dev/null
@@ -1,33 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __MODE_SKAS_H__
7#define __MODE_SKAS_H__
8
9#include <sysdep/ptrace.h>
10
11extern unsigned long exec_regs[];
12extern unsigned long exec_fp_regs[];
13extern unsigned long exec_fpx_regs[];
14extern int have_fpx_regs;
15
16extern void sig_handler_common_skas(int sig, void *sc_ptr);
17extern void halt_skas(void);
18extern void reboot_skas(void);
19extern void kill_off_processes_skas(void);
20extern int is_skas_winch(int pid, int fd, void *data);
21
22#endif
23
24/*
25 * Overrides for Emacs so that we follow Linus's tabbing style.
26 * Emacs will notice this stuff at the end of the file and automatically
27 * adjust the settings for this buffer only. This must remain at the end
28 * of the file.
29 * ---------------------------------------------------------------------------
30 * Local variables:
31 * c-file-style: "linux"
32 * End:
33 */
diff --git a/arch/um/kernel/skas/include/mode_kern-skas.h b/arch/um/kernel/skas/include/mode_kern-skas.h
deleted file mode 100644
index c97a80dfe370..000000000000
--- a/arch/um/kernel/skas/include/mode_kern-skas.h
+++ /dev/null
@@ -1,52 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __SKAS_MODE_KERN_H__
7#define __SKAS_MODE_KERN_H__
8
9#include "linux/sched.h"
10#include "asm/page.h"
11#include "asm/ptrace.h"
12
13extern void flush_thread_skas(void);
14extern void switch_to_skas(void *prev, void *next);
15extern void start_thread_skas(struct pt_regs *regs, unsigned long eip,
16 unsigned long esp);
17extern int copy_thread_skas(int nr, unsigned long clone_flags,
18 unsigned long sp, unsigned long stack_top,
19 struct task_struct *p, struct pt_regs *regs);
20extern void release_thread_skas(struct task_struct *task);
21extern void initial_thread_cb_skas(void (*proc)(void *), void *arg);
22extern void init_idle_skas(void);
23extern void flush_tlb_kernel_range_skas(unsigned long start,
24 unsigned long end);
25extern void flush_tlb_kernel_vm_skas(void);
26extern void __flush_tlb_one_skas(unsigned long addr);
27extern void flush_tlb_range_skas(struct vm_area_struct *vma,
28 unsigned long start, unsigned long end);
29extern void flush_tlb_mm_skas(struct mm_struct *mm);
30extern void force_flush_all_skas(void);
31extern long execute_syscall_skas(void *r);
32extern void before_mem_skas(unsigned long unused);
33extern unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out,
34 unsigned long *task_size_out);
35extern int start_uml_skas(void);
36extern int external_pid_skas(struct task_struct *task);
37extern int thread_pid_skas(struct task_struct *task);
38
39#define kmem_end_skas (host_task_size - 1024 * 1024)
40
41#endif
42
43/*
44 * Overrides for Emacs so that we follow Linus's tabbing style.
45 * Emacs will notice this stuff at the end of the file and automatically
46 * adjust the settings for this buffer only. This must remain at the end
47 * of the file.
48 * ---------------------------------------------------------------------------
49 * Local variables:
50 * c-file-style: "linux"
51 * End:
52 */
diff --git a/arch/um/kernel/skas/include/proc_mm.h b/arch/um/kernel/skas/include/proc_mm.h
deleted file mode 100644
index cce61a679052..000000000000
--- a/arch/um/kernel/skas/include/proc_mm.h
+++ /dev/null
@@ -1,55 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __SKAS_PROC_MM_H
7#define __SKAS_PROC_MM_H
8
9#define MM_MMAP 54
10#define MM_MUNMAP 55
11#define MM_MPROTECT 56
12#define MM_COPY_SEGMENTS 57
13
14struct mm_mmap {
15 unsigned long addr;
16 unsigned long len;
17 unsigned long prot;
18 unsigned long flags;
19 unsigned long fd;
20 unsigned long offset;
21};
22
23struct mm_munmap {
24 unsigned long addr;
25 unsigned long len;
26};
27
28struct mm_mprotect {
29 unsigned long addr;
30 unsigned long len;
31 unsigned int prot;
32};
33
34struct proc_mm_op {
35 int op;
36 union {
37 struct mm_mmap mmap;
38 struct mm_munmap munmap;
39 struct mm_mprotect mprotect;
40 int copy_segments;
41 } u;
42};
43
44#endif
45
46/*
47 * Overrides for Emacs so that we follow Linus's tabbing style.
48 * Emacs will notice this stuff at the end of the file and automatically
49 * adjust the settings for this buffer only. This must remain at the end
50 * of the file.
51 * ---------------------------------------------------------------------------
52 * Local variables:
53 * c-file-style: "linux"
54 * End:
55 */
diff --git a/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h
deleted file mode 100644
index daa2f85b684c..000000000000
--- a/arch/um/kernel/skas/include/skas.h
+++ /dev/null
@@ -1,50 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __SKAS_H
7#define __SKAS_H
8
9#include "mm_id.h"
10#include "sysdep/ptrace.h"
11
12extern int userspace_pid[];
13extern int proc_mm, ptrace_faultinfo, ptrace_ldt;
14extern int skas_needs_stub;
15
16extern void switch_threads(void *me, void *next);
17extern void thread_wait(void *sw, void *fb);
18extern void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
19 void (*handler)(int));
20extern int start_idle_thread(void *stack, void *switch_buf_ptr,
21 void **fork_buf_ptr);
22extern int user_thread(unsigned long stack, int flags);
23extern void userspace(union uml_pt_regs *regs);
24extern void new_thread_proc(void *stack, void (*handler)(int sig));
25extern void remove_sigstack(void);
26extern void new_thread_handler(int sig);
27extern void handle_syscall(union uml_pt_regs *regs);
28extern int map(struct mm_id * mm_idp, unsigned long virt,
29 unsigned long len, int r, int w, int x, int phys_fd,
30 unsigned long long offset, int done, void **data);
31extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len,
32 int done, void **data);
33extern int protect(struct mm_id * mm_idp, unsigned long addr,
34 unsigned long len, int r, int w, int x, int done,
35 void **data);
36extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
37extern int new_mm(int from, unsigned long stack);
38extern int start_userspace(unsigned long stub_stack);
39extern int copy_context_skas0(unsigned long stack, int pid);
40extern void get_skas_faultinfo(int pid, struct faultinfo * fi);
41extern long execute_syscall_skas(void *r);
42extern unsigned long current_stub_stack(void);
43extern long run_syscall_stub(struct mm_id * mm_idp,
44 int syscall, unsigned long *args, long expected,
45 void **addr, int done);
46extern long syscall_stub_data(struct mm_id * mm_idp,
47 unsigned long *data, int data_count,
48 void **addr, void **stub_addr);
49
50#endif
diff --git a/arch/um/kernel/skas/include/stub-data.h b/arch/um/kernel/skas/include/stub-data.h
deleted file mode 100644
index f6ed92c3727d..000000000000
--- a/arch/um/kernel/skas/include/stub-data.h
+++ /dev/null
@@ -1,18 +0,0 @@
1/*
2 * Copyright (C) 2005 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __STUB_DATA_H
7#define __STUB_DATA_H
8
9#include <sys/time.h>
10
11struct stub_data {
12 long offset;
13 int fd;
14 struct itimerval timer;
15 long err;
16};
17
18#endif
diff --git a/arch/um/kernel/skas/include/uaccess-skas.h b/arch/um/kernel/skas/include/uaccess-skas.h
deleted file mode 100644
index 64516c556cdf..000000000000
--- a/arch/um/kernel/skas/include/uaccess-skas.h
+++ /dev/null
@@ -1,32 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __SKAS_UACCESS_H
7#define __SKAS_UACCESS_H
8
9#include "asm/errno.h"
10
11/* No SKAS-specific checking. */
12#define access_ok_skas(type, addr, size) 0
13
14extern int copy_from_user_skas(void *to, const void __user *from, int n);
15extern int copy_to_user_skas(void __user *to, const void *from, int n);
16extern int strncpy_from_user_skas(char *dst, const char __user *src, int count);
17extern int __clear_user_skas(void __user *mem, int len);
18extern int clear_user_skas(void __user *mem, int len);
19extern int strnlen_user_skas(const void __user *str, int len);
20
21#endif
22
23/*
24 * Overrides for Emacs so that we follow Linus's tabbing style.
25 * Emacs will notice this stuff at the end of the file and automatically
26 * adjust the settings for this buffer only. This must remain at the end
27 * of the file.
28 * ---------------------------------------------------------------------------
29 * Local variables:
30 * c-file-style: "linux"
31 * End:
32 */
diff --git a/arch/um/kernel/skas/mem_user.c b/arch/um/kernel/skas/mem_user.c
deleted file mode 100644
index 1d89640bd502..000000000000
--- a/arch/um/kernel/skas/mem_user.c
+++ /dev/null
@@ -1,281 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include <signal.h>
7#include <errno.h>
8#include <string.h>
9#include <sys/mman.h>
10#include <sys/wait.h>
11#include <asm/page.h>
12#include <asm/unistd.h>
13#include "mem_user.h"
14#include "mem.h"
15#include "skas.h"
16#include "user.h"
17#include "os.h"
18#include "proc_mm.h"
19#include "ptrace_user.h"
20#include "user_util.h"
21#include "kern_util.h"
22#include "task.h"
23#include "registers.h"
24#include "uml-config.h"
25#include "sysdep/ptrace.h"
26#include "sysdep/stub.h"
27
28extern unsigned long batch_syscall_stub, __syscall_stub_start;
29
30extern void wait_stub_done(int pid, int sig, char * fname);
31
32static inline unsigned long *check_init_stack(struct mm_id * mm_idp,
33 unsigned long *stack)
34{
35 if(stack == NULL){
36 stack = (unsigned long *) mm_idp->stack + 2;
37 *stack = 0;
38 }
39 return stack;
40}
41
42extern int proc_mm;
43
44int single_count = 0;
45int multi_count = 0;
46int multi_op_count = 0;
47
48static long do_syscall_stub(struct mm_id *mm_idp, void **addr)
49{
50 unsigned long regs[MAX_REG_NR];
51 unsigned long *data;
52 unsigned long *syscall;
53 long ret, offset;
54 int n, pid = mm_idp->u.pid;
55
56 if(proc_mm)
57#warning Need to look up userspace_pid by cpu
58 pid = userspace_pid[0];
59
60 multi_count++;
61
62 get_safe_registers(regs);
63 regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
64 ((unsigned long) &batch_syscall_stub -
65 (unsigned long) &__syscall_stub_start);
66 n = ptrace_setregs(pid, regs);
67 if(n < 0)
68 panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n",
69 n);
70
71 wait_stub_done(pid, 0, "do_syscall_stub");
72
73 /* When the stub stops, we find the following values on the
74 * beginning of the stack:
75 * (long )return_value
76 * (long )offset to failed sycall-data (0, if no error)
77 */
78 ret = *((unsigned long *) mm_idp->stack);
79 offset = *((unsigned long *) mm_idp->stack + 1);
80 if (offset) {
81 data = (unsigned long *)(mm_idp->stack +
82 offset - UML_CONFIG_STUB_DATA);
83 syscall = (unsigned long *)((unsigned long)data + data[0]);
84 printk("do_syscall_stub: syscall %ld failed, return value = "
85 "0x%lx, expected return value = 0x%lx\n",
86 syscall[0], ret, syscall[7]);
87 printk(" syscall parameters: "
88 "0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n",
89 syscall[1], syscall[2], syscall[3],
90 syscall[4], syscall[5], syscall[6]);
91 for(n = 1; n < data[0]/sizeof(long); n++) {
92 if(n == 1)
93 printk(" additional syscall data:");
94 if(n % 4 == 1)
95 printk("\n ");
96 printk(" 0x%lx", data[n]);
97 }
98 if(n > 1)
99 printk("\n");
100 }
101 else ret = 0;
102
103 *addr = check_init_stack(mm_idp, NULL);
104
105 return ret;
106}
107
108long run_syscall_stub(struct mm_id * mm_idp, int syscall,
109 unsigned long *args, long expected, void **addr,
110 int done)
111{
112 unsigned long *stack = check_init_stack(mm_idp, *addr);
113
114 if(done && *addr == NULL)
115 single_count++;
116
117 *stack += sizeof(long);
118 stack += *stack / sizeof(long);
119
120 *stack++ = syscall;
121 *stack++ = args[0];
122 *stack++ = args[1];
123 *stack++ = args[2];
124 *stack++ = args[3];
125 *stack++ = args[4];
126 *stack++ = args[5];
127 *stack++ = expected;
128 *stack = 0;
129 multi_op_count++;
130
131 if(!done && ((((unsigned long) stack) & ~PAGE_MASK) <
132 PAGE_SIZE - 10 * sizeof(long))){
133 *addr = stack;
134 return 0;
135 }
136
137 return do_syscall_stub(mm_idp, addr);
138}
139
140long syscall_stub_data(struct mm_id * mm_idp,
141 unsigned long *data, int data_count,
142 void **addr, void **stub_addr)
143{
144 unsigned long *stack;
145 int ret = 0;
146
147 /* If *addr still is uninitialized, it *must* contain NULL.
148 * Thus in this case do_syscall_stub correctly won't be called.
149 */
150 if((((unsigned long) *addr) & ~PAGE_MASK) >=
151 PAGE_SIZE - (10 + data_count) * sizeof(long)) {
152 ret = do_syscall_stub(mm_idp, addr);
153 /* in case of error, don't overwrite data on stack */
154 if(ret)
155 return ret;
156 }
157
158 stack = check_init_stack(mm_idp, *addr);
159 *addr = stack;
160
161 *stack = data_count * sizeof(long);
162
163 memcpy(stack + 1, data, data_count * sizeof(long));
164
165 *stub_addr = (void *)(((unsigned long)(stack + 1) & ~PAGE_MASK) +
166 UML_CONFIG_STUB_DATA);
167
168 return 0;
169}
170
171int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len,
172 int r, int w, int x, int phys_fd, unsigned long long offset,
173 int done, void **data)
174{
175 int prot, ret;
176
177 prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
178 (x ? PROT_EXEC : 0);
179
180 if(proc_mm){
181 struct proc_mm_op map;
182 int fd = mm_idp->u.mm_fd;
183
184 map = ((struct proc_mm_op) { .op = MM_MMAP,
185 .u =
186 { .mmap =
187 { .addr = virt,
188 .len = len,
189 .prot = prot,
190 .flags = MAP_SHARED |
191 MAP_FIXED,
192 .fd = phys_fd,
193 .offset= offset
194 } } } );
195 ret = os_write_file(fd, &map, sizeof(map));
196 if(ret != sizeof(map))
197 printk("map : /proc/mm map failed, err = %d\n", -ret);
198 else ret = 0;
199 }
200 else {
201 unsigned long args[] = { virt, len, prot,
202 MAP_SHARED | MAP_FIXED, phys_fd,
203 MMAP_OFFSET(offset) };
204
205 ret = run_syscall_stub(mm_idp, STUB_MMAP_NR, args, virt,
206 data, done);
207 }
208
209 return ret;
210}
211
212int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, int done,
213 void **data)
214{
215 int ret;
216
217 if(proc_mm){
218 struct proc_mm_op unmap;
219 int fd = mm_idp->u.mm_fd;
220
221 unmap = ((struct proc_mm_op) { .op = MM_MUNMAP,
222 .u =
223 { .munmap =
224 { .addr =
225 (unsigned long) addr,
226 .len = len } } } );
227 ret = os_write_file(fd, &unmap, sizeof(unmap));
228 if(ret != sizeof(unmap))
229 printk("unmap - proc_mm write returned %d\n", ret);
230 else ret = 0;
231 }
232 else {
233 unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0,
234 0 };
235
236 ret = run_syscall_stub(mm_idp, __NR_munmap, args, 0,
237 data, done);
238 if(ret < 0)
239 printk("munmap stub failed, errno = %d\n", ret);
240 }
241
242 return ret;
243}
244
245int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len,
246 int r, int w, int x, int done, void **data)
247{
248 struct proc_mm_op protect;
249 int prot, ret;
250
251 prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
252 (x ? PROT_EXEC : 0);
253
254 if(proc_mm){
255 int fd = mm_idp->u.mm_fd;
256 protect = ((struct proc_mm_op) { .op = MM_MPROTECT,
257 .u =
258 { .mprotect =
259 { .addr =
260 (unsigned long) addr,
261 .len = len,
262 .prot = prot } } } );
263
264 ret = os_write_file(fd, &protect, sizeof(protect));
265 if(ret != sizeof(protect))
266 printk("protect failed, err = %d", -ret);
267 else ret = 0;
268 }
269 else {
270 unsigned long args[] = { addr, len, prot, 0, 0, 0 };
271
272 ret = run_syscall_stub(mm_idp, __NR_mprotect, args, 0,
273 data, done);
274 }
275
276 return ret;
277}
278
279void before_mem_skas(unsigned long unused)
280{
281}
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index 677871f1b37c..c5c9885a8297 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -78,7 +78,7 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
78 struct mmu_context_skas *from_mm = NULL; 78 struct mmu_context_skas *from_mm = NULL;
79 struct mmu_context_skas *to_mm = &mm->context.skas; 79 struct mmu_context_skas *to_mm = &mm->context.skas;
80 unsigned long stack = 0; 80 unsigned long stack = 0;
81 int from_fd, ret = -ENOMEM; 81 int ret = -ENOMEM;
82 82
83 if(skas_needs_stub){ 83 if(skas_needs_stub){
84 stack = get_zeroed_page(GFP_KERNEL); 84 stack = get_zeroed_page(GFP_KERNEL);
@@ -108,11 +108,7 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
108 from_mm = &current->mm->context.skas; 108 from_mm = &current->mm->context.skas;
109 109
110 if(proc_mm){ 110 if(proc_mm){
111 if(from_mm) 111 ret = new_mm(stack);
112 from_fd = from_mm->id.u.mm_fd;
113 else from_fd = -1;
114
115 ret = new_mm(from_fd, stack);
116 if(ret < 0){ 112 if(ret < 0){
117 printk("init_new_context_skas - new_mm failed, " 113 printk("init_new_context_skas - new_mm failed, "
118 "errno = %d\n", ret); 114 "errno = %d\n", ret);
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index 599d679bd4fc..eea1c9c4bb0f 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -18,7 +18,6 @@
18#include <asm/types.h> 18#include <asm/types.h>
19#include "user.h" 19#include "user.h"
20#include "ptrace_user.h" 20#include "ptrace_user.h"
21#include "time_user.h"
22#include "sysdep/ptrace.h" 21#include "sysdep/ptrace.h"
23#include "user_util.h" 22#include "user_util.h"
24#include "kern_util.h" 23#include "kern_util.h"
@@ -31,7 +30,6 @@
31#include "proc_mm.h" 30#include "proc_mm.h"
32#include "skas_ptrace.h" 31#include "skas_ptrace.h"
33#include "chan_user.h" 32#include "chan_user.h"
34#include "signal_user.h"
35#include "registers.h" 33#include "registers.h"
36#include "mem.h" 34#include "mem.h"
37#include "uml-config.h" 35#include "uml-config.h"
@@ -69,7 +67,7 @@ void wait_stub_done(int pid, int sig, char * fname)
69 67
70 if((n < 0) || !WIFSTOPPED(status) || 68 if((n < 0) || !WIFSTOPPED(status) ||
71 (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){ 69 (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){
72 unsigned long regs[FRAME_SIZE]; 70 unsigned long regs[HOST_FRAME_SIZE];
73 if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) 71 if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
74 printk("Failed to get registers from stub, " 72 printk("Failed to get registers from stub, "
75 "errno = %d\n", errno); 73 "errno = %d\n", errno);
@@ -77,7 +75,7 @@ void wait_stub_done(int pid, int sig, char * fname)
77 int i; 75 int i;
78 76
79 printk("Stub registers -\n"); 77 printk("Stub registers -\n");
80 for(i = 0; i < FRAME_SIZE; i++) 78 for(i = 0; i < HOST_FRAME_SIZE; i++)
81 printk("\t%d - %lx\n", i, regs[i]); 79 printk("\t%d - %lx\n", i, regs[i]);
82 } 80 }
83 panic("%s : failed to wait for SIGUSR1/SIGTRAP, " 81 panic("%s : failed to wait for SIGUSR1/SIGTRAP, "
@@ -514,16 +512,6 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
514 siglongjmp(**switch_buf, 1); 512 siglongjmp(**switch_buf, 1);
515} 513}
516 514
517void remove_sigstack(void)
518{
519 stack_t stack = ((stack_t) { .ss_flags = SS_DISABLE,
520 .ss_sp = NULL,
521 .ss_size = 0 });
522
523 if(sigaltstack(&stack, NULL) != 0)
524 panic("disabling signal stack failed, errno = %d\n", errno);
525}
526
527void initial_thread_cb_skas(void (*proc)(void *), void *arg) 515void initial_thread_cb_skas(void (*proc)(void *), void *arg)
528{ 516{
529 sigjmp_buf here; 517 sigjmp_buf here;
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
index 9c990253966c..3f70a2e12f06 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process_kern.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -13,15 +13,12 @@
13#include "asm/uaccess.h" 13#include "asm/uaccess.h"
14#include "asm/atomic.h" 14#include "asm/atomic.h"
15#include "kern_util.h" 15#include "kern_util.h"
16#include "time_user.h"
17#include "signal_user.h"
18#include "skas.h" 16#include "skas.h"
19#include "os.h" 17#include "os.h"
20#include "user_util.h" 18#include "user_util.h"
21#include "tlb.h" 19#include "tlb.h"
22#include "kern.h" 20#include "kern.h"
23#include "mode.h" 21#include "mode.h"
24#include "proc_mm.h"
25#include "registers.h" 22#include "registers.h"
26 23
27void switch_to_skas(void *prev, void *next) 24void switch_to_skas(void *prev, void *next)
@@ -35,7 +32,7 @@ void switch_to_skas(void *prev, void *next)
35 if(current->pid == 0) 32 if(current->pid == 0)
36 switch_timers(0); 33 switch_timers(0);
37 34
38 switch_threads(&from->thread.mode.skas.switch_buf, 35 switch_threads(&from->thread.mode.skas.switch_buf,
39 to->thread.mode.skas.switch_buf); 36 to->thread.mode.skas.switch_buf);
40 37
41 if(current->pid == 0) 38 if(current->pid == 0)
@@ -51,8 +48,8 @@ void new_thread_handler(int sig)
51 48
52 fn = current->thread.request.u.thread.proc; 49 fn = current->thread.request.u.thread.proc;
53 arg = current->thread.request.u.thread.arg; 50 arg = current->thread.request.u.thread.arg;
54 change_sig(SIGUSR1, 1); 51 os_usr1_signal(1);
55 thread_wait(&current->thread.mode.skas.switch_buf, 52 thread_wait(&current->thread.mode.skas.switch_buf,
56 current->thread.mode.skas.fork_buf); 53 current->thread.mode.skas.fork_buf);
57 54
58 if(current->thread.prev_sched != NULL) 55 if(current->thread.prev_sched != NULL)
@@ -83,8 +80,8 @@ void release_thread_skas(struct task_struct *task)
83 80
84void fork_handler(int sig) 81void fork_handler(int sig)
85{ 82{
86 change_sig(SIGUSR1, 1); 83 os_usr1_signal(1);
87 thread_wait(&current->thread.mode.skas.switch_buf, 84 thread_wait(&current->thread.mode.skas.switch_buf,
88 current->thread.mode.skas.fork_buf); 85 current->thread.mode.skas.fork_buf);
89 86
90 force_flush_all(); 87 force_flush_all();
@@ -94,13 +91,13 @@ void fork_handler(int sig)
94 schedule_tail(current->thread.prev_sched); 91 schedule_tail(current->thread.prev_sched);
95 current->thread.prev_sched = NULL; 92 current->thread.prev_sched = NULL;
96 93
97 /* Handle any immediate reschedules or signals */ 94/* Handle any immediate reschedules or signals */
98 interrupt_end(); 95 interrupt_end();
99 userspace(&current->thread.regs.regs); 96 userspace(&current->thread.regs.regs);
100} 97}
101 98
102int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp, 99int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
103 unsigned long stack_top, struct task_struct * p, 100 unsigned long stack_top, struct task_struct * p,
104 struct pt_regs *regs) 101 struct pt_regs *regs)
105{ 102{
106 void (*handler)(int); 103 void (*handler)(int);
@@ -119,32 +116,19 @@ int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
119 handler = new_thread_handler; 116 handler = new_thread_handler;
120 } 117 }
121 118
122 new_thread(p->thread_info, &p->thread.mode.skas.switch_buf, 119 new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf,
123 &p->thread.mode.skas.fork_buf, handler); 120 &p->thread.mode.skas.fork_buf, handler);
124 return(0); 121 return(0);
125} 122}
126 123
127extern void map_stub_pages(int fd, unsigned long code, 124int new_mm(unsigned long stack)
128 unsigned long data, unsigned long stack);
129int new_mm(int from, unsigned long stack)
130{ 125{
131 struct proc_mm_op copy; 126 int fd;
132 int n, fd;
133 127
134 fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0); 128 fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0);
135 if(fd < 0) 129 if(fd < 0)
136 return(fd); 130 return(fd);
137 131
138 if(from != -1){
139 copy = ((struct proc_mm_op) { .op = MM_COPY_SEGMENTS,
140 .u =
141 { .copy_segments = from } } );
142 n = os_write_file(fd, &copy, sizeof(copy));
143 if(n != sizeof(copy))
144 printk("new_mm : /proc/mm copy_segments failed, "
145 "err = %d\n", -n);
146 }
147
148 if(skas_needs_stub) 132 if(skas_needs_stub)
149 map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack); 133 map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack);
150 134
@@ -186,7 +170,7 @@ int start_uml_skas(void)
186 170
187 init_task.thread.request.u.thread.proc = start_kernel_proc; 171 init_task.thread.request.u.thread.proc = start_kernel_proc;
188 init_task.thread.request.u.thread.arg = NULL; 172 init_task.thread.request.u.thread.arg = NULL;
189 return(start_idle_thread(init_task.thread_info, 173 return(start_idle_thread(task_stack_page(&init_task),
190 &init_task.thread.mode.skas.switch_buf, 174 &init_task.thread.mode.skas.switch_buf,
191 &init_task.thread.mode.skas.fork_buf)); 175 &init_task.thread.mode.skas.fork_buf));
192} 176}
diff --git a/arch/um/kernel/skas/trap_user.c b/arch/um/kernel/skas/trap_user.c
deleted file mode 100644
index 9950a6716fe5..000000000000
--- a/arch/um/kernel/skas/trap_user.c
+++ /dev/null
@@ -1,78 +0,0 @@
1/*
2 * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
3 * Licensed under the GPL
4 */
5
6#include <signal.h>
7#include <errno.h>
8#include "signal_user.h"
9#include "user_util.h"
10#include "kern_util.h"
11#include "task.h"
12#include "sigcontext.h"
13#include "skas.h"
14#include "ptrace_user.h"
15#include "sysdep/ptrace.h"
16#include "sysdep/ptrace_user.h"
17
18void sig_handler_common_skas(int sig, void *sc_ptr)
19{
20 struct sigcontext *sc = sc_ptr;
21 struct skas_regs *r;
22 struct signal_info *info;
23 int save_errno = errno;
24 int save_user;
25
26 /* This is done because to allow SIGSEGV to be delivered inside a SEGV
27 * handler. This can happen in copy_user, and if SEGV is disabled,
28 * the process will die.
29 * XXX Figure out why this is better than SA_NODEFER
30 */
31 if(sig == SIGSEGV)
32 change_sig(SIGSEGV, 1);
33
34 r = &TASK_REGS(get_current())->skas;
35 save_user = r->is_user;
36 r->is_user = 0;
37 if ( sig == SIGFPE || sig == SIGSEGV ||
38 sig == SIGBUS || sig == SIGILL ||
39 sig == SIGTRAP ) {
40 GET_FAULTINFO_FROM_SC(r->faultinfo, sc);
41 }
42
43 change_sig(SIGUSR1, 1);
44 info = &sig_info[sig];
45 if(!info->is_irq) unblock_signals();
46
47 (*info->handler)(sig, (union uml_pt_regs *) r);
48
49 errno = save_errno;
50 r->is_user = save_user;
51}
52
53extern int ptrace_faultinfo;
54
55void user_signal(int sig, union uml_pt_regs *regs, int pid)
56{
57 struct signal_info *info;
58 int segv = ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) ||
59 (sig == SIGILL) || (sig == SIGTRAP));
60
61 if (segv)
62 get_skas_faultinfo(pid, &regs->skas.faultinfo);
63 info = &sig_info[sig];
64 (*info->handler)(sig, regs);
65
66 unblock_signals();
67}
68
69/*
70 * Overrides for Emacs so that we follow Linus's tabbing style.
71 * Emacs will notice this stuff at the end of the file and automatically
72 * adjust the settings for this buffer only. This must remain at the end
73 * of the file.
74 * ---------------------------------------------------------------------------
75 * Local variables:
76 * c-file-style: "linux"
77 * End:
78 */
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c
index a5a47528dec7..5992c3257167 100644
--- a/arch/um/kernel/skas/uaccess.c
+++ b/arch/um/kernel/skas/uaccess.c
@@ -13,7 +13,7 @@
13#include "asm/pgtable.h" 13#include "asm/pgtable.h"
14#include "asm/uaccess.h" 14#include "asm/uaccess.h"
15#include "kern_util.h" 15#include "kern_util.h"
16#include "user_util.h" 16#include "os.h"
17 17
18extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr, 18extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
19 pte_t *pte_out); 19 pte_t *pte_out);
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c
index 1429c131879d..1731d90e6850 100644
--- a/arch/um/kernel/syscall.c
+++ b/arch/um/kernel/syscall.c
@@ -25,12 +25,12 @@ int record_syscall_start(int syscall)
25 syscall_record[index].syscall = syscall; 25 syscall_record[index].syscall = syscall;
26 syscall_record[index].pid = current_pid(); 26 syscall_record[index].pid = current_pid();
27 syscall_record[index].result = 0xdeadbeef; 27 syscall_record[index].result = 0xdeadbeef;
28 syscall_record[index].start = os_usecs(); 28 syscall_record[index].start = os_nsecs();
29 return(index); 29 return(index);
30} 30}
31 31
32void record_syscall_end(int index, long result) 32void record_syscall_end(int index, long result)
33{ 33{
34 syscall_record[index].result = result; 34 syscall_record[index].result = result;
35 syscall_record[index].end = os_usecs(); 35 syscall_record[index].end = os_nsecs();
36} 36}
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index c40b611e3d93..8fa2ae7f3026 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -14,9 +14,9 @@
14#include "kern_util.h" 14#include "kern_util.h"
15#include "user.h" 15#include "user.h"
16#include "process.h" 16#include "process.h"
17#include "signal_user.h"
18#include "time_user.h" 17#include "time_user.h"
19#include "kern_constants.h" 18#include "kern_constants.h"
19#include "os.h"
20 20
21/* XXX This really needs to be declared and initialized in a kernel file since 21/* XXX This really needs to be declared and initialized in a kernel file since
22 * it's in <linux/time.h> 22 * it's in <linux/time.h>
@@ -99,7 +99,8 @@ void uml_idle_timer(void)
99 set_interval(ITIMER_REAL); 99 set_interval(ITIMER_REAL);
100} 100}
101 101
102extern int do_posix_clock_monotonic_gettime(struct timespec *tp); 102extern void ktime_get_ts(struct timespec *ts);
103#define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts)
103 104
104void time_init(void) 105void time_init(void)
105{ 106{
@@ -114,8 +115,8 @@ void time_init(void)
114 wall_to_monotonic.tv_nsec = -now.tv_nsec; 115 wall_to_monotonic.tv_nsec = -now.tv_nsec;
115} 116}
116 117
117/* Declared in linux/time.h, which can't be included here */ 118/* Defined in linux/ktimer.h, which can't be included here */
118extern void clock_was_set(void); 119#define clock_was_set() do { } while (0)
119 120
120void do_gettimeofday(struct timeval *tv) 121void do_gettimeofday(struct timeval *tv)
121{ 122{
diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c
index 020ca79b8d33..3c7626cdba4b 100644
--- a/arch/um/kernel/time_kern.c
+++ b/arch/um/kernel/time_kern.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -13,12 +13,12 @@
13#include "linux/interrupt.h" 13#include "linux/interrupt.h"
14#include "linux/init.h" 14#include "linux/init.h"
15#include "linux/delay.h" 15#include "linux/delay.h"
16#include "linux/hrtimer.h"
16#include "asm/irq.h" 17#include "asm/irq.h"
17#include "asm/param.h" 18#include "asm/param.h"
18#include "asm/current.h" 19#include "asm/current.h"
19#include "kern_util.h" 20#include "kern_util.h"
20#include "user_util.h" 21#include "user_util.h"
21#include "time_user.h"
22#include "mode.h" 22#include "mode.h"
23#include "os.h" 23#include "os.h"
24 24
@@ -39,7 +39,7 @@ unsigned long long sched_clock(void)
39int timer_irq_inited = 0; 39int timer_irq_inited = 0;
40 40
41static int first_tick; 41static int first_tick;
42static unsigned long long prev_usecs; 42static unsigned long long prev_nsecs;
43#ifdef CONFIG_UML_REAL_TIME_CLOCK 43#ifdef CONFIG_UML_REAL_TIME_CLOCK
44static long long delta; /* Deviation per interval */ 44static long long delta; /* Deviation per interval */
45#endif 45#endif
@@ -58,23 +58,23 @@ void timer_irq(union uml_pt_regs *regs)
58 if(first_tick){ 58 if(first_tick){
59#ifdef CONFIG_UML_REAL_TIME_CLOCK 59#ifdef CONFIG_UML_REAL_TIME_CLOCK
60 /* We've had 1 tick */ 60 /* We've had 1 tick */
61 unsigned long long usecs = os_usecs(); 61 unsigned long long nsecs = os_nsecs();
62 62
63 delta += usecs - prev_usecs; 63 delta += nsecs - prev_nsecs;
64 prev_usecs = usecs; 64 prev_nsecs = nsecs;
65 65
66 /* Protect against the host clock being set backwards */ 66 /* Protect against the host clock being set backwards */
67 if(delta < 0) 67 if(delta < 0)
68 delta = 0; 68 delta = 0;
69 69
70 ticks += (delta * HZ) / MILLION; 70 ticks += (delta * HZ) / BILLION;
71 delta -= (ticks * MILLION) / HZ; 71 delta -= (ticks * BILLION) / HZ;
72#else 72#else
73 ticks = 1; 73 ticks = 1;
74#endif 74#endif
75 } 75 }
76 else { 76 else {
77 prev_usecs = os_usecs(); 77 prev_nsecs = os_nsecs();
78 first_tick = 1; 78 first_tick = 1;
79 } 79 }
80 80
@@ -84,49 +84,102 @@ void timer_irq(union uml_pt_regs *regs)
84 } 84 }
85} 85}
86 86
87void boot_timer_handler(int sig) 87void do_boot_timer_handler(struct sigcontext * sc)
88{ 88{
89 struct pt_regs regs; 89 struct pt_regs regs;
90 90
91 CHOOSE_MODE((void) 91 CHOOSE_MODE((void) (UPT_SC(&regs.regs) = sc),
92 (UPT_SC(&regs.regs) = (struct sigcontext *) (&sig + 1)),
93 (void) (regs.regs.skas.is_user = 0)); 92 (void) (regs.regs.skas.is_user = 0));
94 do_timer(&regs); 93 do_timer(&regs);
95} 94}
96 95
96static DEFINE_SPINLOCK(timer_spinlock);
97
98static unsigned long long local_offset = 0;
99
100static inline unsigned long long get_time(void)
101{
102 unsigned long long nsecs;
103 unsigned long flags;
104
105 spin_lock_irqsave(&timer_spinlock, flags);
106 nsecs = os_nsecs();
107 nsecs += local_offset;
108 spin_unlock_irqrestore(&timer_spinlock, flags);
109
110 return nsecs;
111}
112
97irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs) 113irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs)
98{ 114{
115 unsigned long long nsecs;
99 unsigned long flags; 116 unsigned long flags;
100 117
101 do_timer(regs); 118 do_timer(regs);
119
102 write_seqlock_irqsave(&xtime_lock, flags); 120 write_seqlock_irqsave(&xtime_lock, flags);
103 timer(); 121 nsecs = get_time() + local_offset;
122 xtime.tv_sec = nsecs / NSEC_PER_SEC;
123 xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC;
104 write_sequnlock_irqrestore(&xtime_lock, flags); 124 write_sequnlock_irqrestore(&xtime_lock, flags);
125
105 return(IRQ_HANDLED); 126 return(IRQ_HANDLED);
106} 127}
107 128
108long um_time(int __user *tloc) 129long um_time(int __user *tloc)
109{ 130{
110 struct timeval now; 131 long ret = get_time() / NSEC_PER_SEC;
111 132
112 do_gettimeofday(&now); 133 if((tloc != NULL) && put_user(ret, tloc))
113 if (tloc) { 134 return -EFAULT;
114 if (put_user(now.tv_sec, tloc)) 135
115 now.tv_sec = -EFAULT; 136 return ret;
116 } 137}
117 return now.tv_sec; 138
139void do_gettimeofday(struct timeval *tv)
140{
141 unsigned long long nsecs = get_time();
142
143 tv->tv_sec = nsecs / NSEC_PER_SEC;
144 /* Careful about calculations here - this was originally done as
145 * (nsecs - tv->tv_sec * NSEC_PER_SEC) / NSEC_PER_USEC
146 * which gave bogus (> 1000000) values. Dunno why, suspect gcc
147 * (4.0.0) miscompiled it, or there's a subtle 64/32-bit conversion
148 * problem that I missed.
149 */
150 nsecs -= tv->tv_sec * NSEC_PER_SEC;
151 tv->tv_usec = (unsigned long) nsecs / NSEC_PER_USEC;
152}
153
154static inline void set_time(unsigned long long nsecs)
155{
156 unsigned long long now;
157 unsigned long flags;
158
159 spin_lock_irqsave(&timer_spinlock, flags);
160 now = os_nsecs();
161 local_offset = nsecs - now;
162 spin_unlock_irqrestore(&timer_spinlock, flags);
163
164 clock_was_set();
118} 165}
119 166
120long um_stime(int __user *tptr) 167long um_stime(int __user *tptr)
121{ 168{
122 int value; 169 int value;
123 struct timespec new;
124 170
125 if (get_user(value, tptr)) 171 if (get_user(value, tptr))
126 return -EFAULT; 172 return -EFAULT;
127 new.tv_sec = value; 173
128 new.tv_nsec = 0; 174 set_time((unsigned long long) value * NSEC_PER_SEC);
129 do_settimeofday(&new); 175
176 return 0;
177}
178
179int do_settimeofday(struct timespec *tv)
180{
181 set_time((unsigned long long) tv->tv_sec * NSEC_PER_SEC + tv->tv_nsec);
182
130 return 0; 183 return 0;
131} 184}
132 185
@@ -134,29 +187,15 @@ void timer_handler(int sig, union uml_pt_regs *regs)
134{ 187{
135 local_irq_disable(); 188 local_irq_disable();
136 irq_enter(); 189 irq_enter();
137 update_process_times(CHOOSE_MODE(user_context(UPT_SP(regs)), 190 update_process_times(CHOOSE_MODE(
138 (regs)->skas.is_user)); 191 (UPT_SC(regs) && user_context(UPT_SP(regs))),
192 (regs)->skas.is_user));
139 irq_exit(); 193 irq_exit();
140 local_irq_enable(); 194 local_irq_enable();
141 if(current_thread->cpu == 0) 195 if(current_thread->cpu == 0)
142 timer_irq(regs); 196 timer_irq(regs);
143} 197}
144 198
145static DEFINE_SPINLOCK(timer_spinlock);
146
147unsigned long time_lock(void)
148{
149 unsigned long flags;
150
151 spin_lock_irqsave(&timer_spinlock, flags);
152 return(flags);
153}
154
155void time_unlock(unsigned long flags)
156{
157 spin_unlock_irqrestore(&timer_spinlock, flags);
158}
159
160int __init timer_init(void) 199int __init timer_init(void)
161{ 200{
162 int err; 201 int err;
@@ -171,14 +210,3 @@ int __init timer_init(void)
171} 210}
172 211
173__initcall(timer_init); 212__initcall(timer_init);
174
175/*
176 * Overrides for Emacs so that we follow Linus's tabbing style.
177 * Emacs will notice this stuff at the end of the file and automatically
178 * adjust the settings for this buffer only. This must remain at the end
179 * of the file.
180 * ---------------------------------------------------------------------------
181 * Local variables:
182 * c-file-style: "linux"
183 * End:
184 */
diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c
index 0d4c10a73607..d56046c2aba2 100644
--- a/arch/um/kernel/trap_kern.c
+++ b/arch/um/kernel/trap_kern.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -26,9 +26,13 @@
26#include "mconsole_kern.h" 26#include "mconsole_kern.h"
27#include "mem.h" 27#include "mem.h"
28#include "mem_kern.h" 28#include "mem_kern.h"
29#include "sysdep/sigcontext.h"
30#include "sysdep/ptrace.h"
31#include "os.h"
29#ifdef CONFIG_MODE_SKAS 32#ifdef CONFIG_MODE_SKAS
30#include "skas.h" 33#include "skas.h"
31#endif 34#endif
35#include "os.h"
32 36
33/* Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by segv(). */ 37/* Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by segv(). */
34int handle_page_fault(unsigned long address, unsigned long ip, 38int handle_page_fault(unsigned long address, unsigned long ip,
@@ -125,6 +129,25 @@ out_of_memory:
125 goto out; 129 goto out;
126} 130}
127 131
132void segv_handler(int sig, union uml_pt_regs *regs)
133{
134 struct faultinfo * fi = UPT_FAULTINFO(regs);
135
136 if(UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)){
137 bad_segv(*fi, UPT_IP(regs));
138 return;
139 }
140 segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs);
141}
142
143struct kern_handlers handlinfo_kern = {
144 .relay_signal = relay_signal,
145 .winch = winch,
146 .bus_handler = relay_signal,
147 .page_fault = segv_handler,
148 .sigio_handler = sigio_handler,
149 .timer_handler = timer_handler
150};
128/* 151/*
129 * We give a *copy* of the faultinfo in the regs to segv. 152 * We give a *copy* of the faultinfo in the regs to segv.
130 * This must be done, since nesting SEGVs could overwrite 153 * This must be done, since nesting SEGVs could overwrite
diff --git a/arch/um/kernel/trap_user.c b/arch/um/kernel/trap_user.c
deleted file mode 100644
index e9ccd6b8d3c7..000000000000
--- a/arch/um/kernel/trap_user.c
+++ /dev/null
@@ -1,98 +0,0 @@
1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include <stdlib.h>
7#include <errno.h>
8#include <setjmp.h>
9#include <signal.h>
10#include <sys/time.h>
11#include <sys/wait.h>
12#include <asm/page.h>
13#include <asm/unistd.h>
14#include <asm/ptrace.h>
15#include "init.h"
16#include "sysdep/ptrace.h"
17#include "sigcontext.h"
18#include "sysdep/sigcontext.h"
19#include "irq_user.h"
20#include "signal_user.h"
21#include "time_user.h"
22#include "task.h"
23#include "mode.h"
24#include "choose-mode.h"
25#include "kern_util.h"
26#include "user_util.h"
27#include "os.h"
28
29void kill_child_dead(int pid)
30{
31 kill(pid, SIGKILL);
32 kill(pid, SIGCONT);
33 do {
34 int n;
35 CATCH_EINTR(n = waitpid(pid, NULL, 0));
36 if (n > 0)
37 kill(pid, SIGCONT);
38 else
39 break;
40 } while(1);
41}
42
43void segv_handler(int sig, union uml_pt_regs *regs)
44{
45 struct faultinfo * fi = UPT_FAULTINFO(regs);
46
47 if(UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)){
48 bad_segv(*fi, UPT_IP(regs));
49 return;
50 }
51 segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs);
52}
53
54void usr2_handler(int sig, union uml_pt_regs *regs)
55{
56 CHOOSE_MODE(syscall_handler_tt(sig, regs), (void) 0);
57}
58
59struct signal_info sig_info[] = {
60 [ SIGTRAP ] { .handler = relay_signal,
61 .is_irq = 0 },
62 [ SIGFPE ] { .handler = relay_signal,
63 .is_irq = 0 },
64 [ SIGILL ] { .handler = relay_signal,
65 .is_irq = 0 },
66 [ SIGWINCH ] { .handler = winch,
67 .is_irq = 1 },
68 [ SIGBUS ] { .handler = bus_handler,
69 .is_irq = 0 },
70 [ SIGSEGV] { .handler = segv_handler,
71 .is_irq = 0 },
72 [ SIGIO ] { .handler = sigio_handler,
73 .is_irq = 1 },
74 [ SIGVTALRM ] { .handler = timer_handler,
75 .is_irq = 1 },
76 [ SIGALRM ] { .handler = timer_handler,
77 .is_irq = 1 },
78 [ SIGUSR2 ] { .handler = usr2_handler,
79 .is_irq = 0 },
80};
81
82void do_longjmp(void *b, int val)
83{
84 sigjmp_buf *buf = b;
85
86 siglongjmp(*buf, val);
87}
88
89/*
90 * Overrides for Emacs so that we follow Linus's tabbing style.
91 * Emacs will notice this stuff at the end of the file and automatically
92 * adjust the settings for this buffer only. This must remain at the end
93 * of the file.
94 * ---------------------------------------------------------------------------
95 * Local variables:
96 * c-file-style: "linux"
97 * End:
98 */
diff --git a/arch/um/kernel/tt/exec_kern.c b/arch/um/kernel/tt/exec_kern.c
index 065b504a653b..5c1e4cc1c049 100644
--- a/arch/um/kernel/tt/exec_kern.c
+++ b/arch/um/kernel/tt/exec_kern.c
@@ -13,8 +13,6 @@
13#include "user_util.h" 13#include "user_util.h"
14#include "kern_util.h" 14#include "kern_util.h"
15#include "irq_user.h" 15#include "irq_user.h"
16#include "time_user.h"
17#include "signal_user.h"
18#include "mem_user.h" 16#include "mem_user.h"
19#include "os.h" 17#include "os.h"
20#include "tlb.h" 18#include "tlb.h"
@@ -40,7 +38,7 @@ void flush_thread_tt(void)
40 do_exit(SIGKILL); 38 do_exit(SIGKILL);
41 } 39 }
42 40
43 new_pid = start_fork_tramp(current->thread_info, stack, 0, exec_tramp); 41 new_pid = start_fork_tramp(task_stack_page(current), stack, 0, exec_tramp);
44 if(new_pid < 0){ 42 if(new_pid < 0){
45 printk(KERN_ERR 43 printk(KERN_ERR
46 "flush_thread : new thread failed, errno = %d\n", 44 "flush_thread : new thread failed, errno = %d\n",
diff --git a/arch/um/kernel/tt/gdb.c b/arch/um/kernel/tt/gdb.c
index 37e22d71a0d9..786e4edd86c5 100644
--- a/arch/um/kernel/tt/gdb.c
+++ b/arch/um/kernel/tt/gdb.c
@@ -20,6 +20,7 @@
20#include "user_util.h" 20#include "user_util.h"
21#include "tt.h" 21#include "tt.h"
22#include "sysdep/thread.h" 22#include "sysdep/thread.h"
23#include "os.h"
23 24
24extern int debugger_pid; 25extern int debugger_pid;
25extern int debugger_fd; 26extern int debugger_fd;
diff --git a/arch/um/kernel/tt/include/debug.h b/arch/um/kernel/tt/include/debug.h
deleted file mode 100644
index 738435461e13..000000000000
--- a/arch/um/kernel/tt/include/debug.h
+++ /dev/null
@@ -1,18 +0,0 @@
1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) and
3 * Lars Brinkhoff.
4 * Licensed under the GPL
5 */
6
7#ifndef __UML_TT_DEBUG_H
8#define __UML_TT_DEBUG_H
9
10extern int debugger_proxy(int status, pid_t pid);
11extern void child_proxy(pid_t pid, int status);
12extern void init_proxy (pid_t pid, int waiting, int status);
13extern int start_debugger(char *prog, int startup, int stop, int *debugger_fd);
14extern void fake_child_exit(void);
15extern int gdb_config(char *str);
16extern int gdb_remove(int unused);
17
18#endif
diff --git a/arch/um/kernel/tt/include/mmu-tt.h b/arch/um/kernel/tt/include/mmu-tt.h
deleted file mode 100644
index 0440510ab3fe..000000000000
--- a/arch/um/kernel/tt/include/mmu-tt.h
+++ /dev/null
@@ -1,23 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __TT_MMU_H
7#define __TT_MMU_H
8
9struct mmu_context_tt {
10};
11
12#endif
13
14/*
15 * Overrides for Emacs so that we follow Linus's tabbing style.
16 * Emacs will notice this stuff at the end of the file and automatically
17 * adjust the settings for this buffer only. This must remain at the end
18 * of the file.
19 * ---------------------------------------------------------------------------
20 * Local variables:
21 * c-file-style: "linux"
22 * End:
23 */
diff --git a/arch/um/kernel/tt/include/tt.h b/arch/um/kernel/tt/include/tt.h
deleted file mode 100644
index c667b67af405..000000000000
--- a/arch/um/kernel/tt/include/tt.h
+++ /dev/null
@@ -1,46 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __TT_H__
7#define __TT_H__
8
9#include "sysdep/ptrace.h"
10
11extern int gdb_pid;
12extern int debug;
13extern int debug_stop;
14extern int debug_trace;
15
16extern int honeypot;
17
18extern int fork_tramp(void *sig_stack);
19extern int do_proc_op(void *t, int proc_id);
20extern int tracer(int (*init_proc)(void *), void *sp);
21extern void attach_process(int pid);
22extern void tracer_panic(char *format, ...);
23extern void set_init_pid(int pid);
24extern int set_user_mode(void *task);
25extern void set_tracing(void *t, int tracing);
26extern int is_tracing(void *task);
27extern void syscall_handler(int sig, union uml_pt_regs *regs);
28extern void exit_kernel(int pid, void *task);
29extern void do_syscall(void *task, int pid, int local_using_sysemu);
30extern void do_sigtrap(void *task);
31extern int is_valid_pid(int pid);
32extern void remap_data(void *segment_start, void *segment_end, int w);
33extern long execute_syscall_tt(void *r);
34
35#endif
36
37/*
38 * Overrides for Emacs so that we follow Linus's tabbing style.
39 * Emacs will notice this stuff at the end of the file and automatically
40 * adjust the settings for this buffer only. This must remain at the end
41 * of the file.
42 * ---------------------------------------------------------------------------
43 * Local variables:
44 * c-file-style: "linux"
45 * End:
46 */
diff --git a/arch/um/kernel/tt/include/uaccess-tt.h b/arch/um/kernel/tt/include/uaccess-tt.h
deleted file mode 100644
index b9bfe9c481c4..000000000000
--- a/arch/um/kernel/tt/include/uaccess-tt.h
+++ /dev/null
@@ -1,59 +0,0 @@
1/*
2 * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __TT_UACCESS_H
7#define __TT_UACCESS_H
8
9#include "linux/string.h"
10#include "linux/sched.h"
11#include "asm/processor.h"
12#include "asm/errno.h"
13#include "asm/current.h"
14#include "asm/a.out.h"
15#include "uml_uaccess.h"
16
17#define ABOVE_KMEM (16 * 1024 * 1024)
18
19extern unsigned long end_vm;
20extern unsigned long uml_physmem;
21
22#define is_stack(addr, size) \
23 (((unsigned long) (addr) < STACK_TOP) && \
24 ((unsigned long) (addr) >= STACK_TOP - ABOVE_KMEM) && \
25 (((unsigned long) (addr) + (size)) <= STACK_TOP))
26
27#define access_ok_tt(type, addr, size) \
28 (is_stack(addr, size))
29
30extern unsigned long get_fault_addr(void);
31
32extern int __do_copy_from_user(void *to, const void *from, int n,
33 void **fault_addr, void **fault_catcher);
34extern int __do_strncpy_from_user(char *dst, const char *src, size_t n,
35 void **fault_addr, void **fault_catcher);
36extern int __do_clear_user(void *mem, size_t len, void **fault_addr,
37 void **fault_catcher);
38extern int __do_strnlen_user(const char *str, unsigned long n,
39 void **fault_addr, void **fault_catcher);
40
41extern int copy_from_user_tt(void *to, const void __user *from, int n);
42extern int copy_to_user_tt(void __user *to, const void *from, int n);
43extern int strncpy_from_user_tt(char *dst, const char __user *src, int count);
44extern int __clear_user_tt(void __user *mem, int len);
45extern int clear_user_tt(void __user *mem, int len);
46extern int strnlen_user_tt(const void __user *str, int len);
47
48#endif
49
50/*
51 * Overrides for Emacs so that we follow Linus's tabbing style.
52 * Emacs will notice this stuff at the end of the file and automatically
53 * adjust the settings for this buffer only. This must remain at the end
54 * of the file.
55 * ---------------------------------------------------------------------------
56 * Local variables:
57 * c-file-style: "linux"
58 * End:
59 */
diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c
index cfaa373a6e77..295c1ac817b3 100644
--- a/arch/um/kernel/tt/process_kern.c
+++ b/arch/um/kernel/tt/process_kern.c
@@ -13,13 +13,11 @@
13#include "asm/ptrace.h" 13#include "asm/ptrace.h"
14#include "asm/tlbflush.h" 14#include "asm/tlbflush.h"
15#include "irq_user.h" 15#include "irq_user.h"
16#include "signal_user.h"
17#include "kern_util.h" 16#include "kern_util.h"
18#include "user_util.h" 17#include "user_util.h"
19#include "os.h" 18#include "os.h"
20#include "kern.h" 19#include "kern.h"
21#include "sigcontext.h" 20#include "sigcontext.h"
22#include "time_user.h"
23#include "mem_user.h" 21#include "mem_user.h"
24#include "tlb.h" 22#include "tlb.h"
25#include "mode.h" 23#include "mode.h"
@@ -37,7 +35,7 @@ void switch_to_tt(void *prev, void *next)
37 from = prev; 35 from = prev;
38 to = next; 36 to = next;
39 37
40 cpu = from->thread_info->cpu; 38 cpu = task_thread_info(from)->cpu;
41 if(cpu == 0) 39 if(cpu == 0)
42 forward_interrupts(to->thread.mode.tt.extern_pid); 40 forward_interrupts(to->thread.mode.tt.extern_pid);
43#ifdef CONFIG_SMP 41#ifdef CONFIG_SMP
@@ -254,7 +252,7 @@ int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp,
254 252
255 clone_flags &= CLONE_VM; 253 clone_flags &= CLONE_VM;
256 p->thread.temp_stack = stack; 254 p->thread.temp_stack = stack;
257 new_pid = start_fork_tramp(p->thread_info, stack, clone_flags, tramp); 255 new_pid = start_fork_tramp(task_stack_page(p), stack, clone_flags, tramp);
258 if(new_pid < 0){ 256 if(new_pid < 0){
259 printk(KERN_ERR "copy_thread : clone failed - errno = %d\n", 257 printk(KERN_ERR "copy_thread : clone failed - errno = %d\n",
260 -new_pid); 258 -new_pid);
@@ -344,7 +342,7 @@ int do_proc_op(void *t, int proc_id)
344 pid = thread->request.u.exec.pid; 342 pid = thread->request.u.exec.pid;
345 do_exec(thread->mode.tt.extern_pid, pid); 343 do_exec(thread->mode.tt.extern_pid, pid);
346 thread->mode.tt.extern_pid = pid; 344 thread->mode.tt.extern_pid = pid;
347 cpu_tasks[task->thread_info->cpu].pid = pid; 345 cpu_tasks[task_thread_info(task)->cpu].pid = pid;
348 break; 346 break;
349 case OP_FORK: 347 case OP_FORK:
350 attach_process(thread->request.u.fork.pid); 348 attach_process(thread->request.u.fork.pid);
@@ -426,7 +424,7 @@ int start_uml_tt(void)
426 int pages; 424 int pages;
427 425
428 pages = (1 << CONFIG_KERNEL_STACK_ORDER); 426 pages = (1 << CONFIG_KERNEL_STACK_ORDER);
429 sp = (void *) ((unsigned long) init_task.thread_info) + 427 sp = task_stack_page(&init_task) +
430 pages * PAGE_SIZE - sizeof(unsigned long); 428 pages * PAGE_SIZE - sizeof(unsigned long);
431 return(tracer(start_kernel_proc, sp)); 429 return(tracer(start_kernel_proc, sp));
432} 430}
diff --git a/arch/um/kernel/tt/ptproxy/ptrace.c b/arch/um/kernel/tt/ptproxy/ptrace.c
index 528a5fc8d887..03774427d468 100644
--- a/arch/um/kernel/tt/ptproxy/ptrace.c
+++ b/arch/um/kernel/tt/ptproxy/ptrace.c
@@ -20,6 +20,7 @@ Jeff Dike (jdike@karaya.com) : Modified for integration into uml
20#include "kern_util.h" 20#include "kern_util.h"
21#include "ptrace_user.h" 21#include "ptrace_user.h"
22#include "tt.h" 22#include "tt.h"
23#include "os.h"
23 24
24long proxy_ptrace(struct debugger *debugger, int arg1, pid_t arg2, 25long proxy_ptrace(struct debugger *debugger, int arg1, pid_t arg2,
25 long arg3, long arg4, pid_t child, int *ret) 26 long arg3, long arg4, pid_t child, int *ret)
diff --git a/arch/um/kernel/tt/ptproxy/sysdep.c b/arch/um/kernel/tt/ptproxy/sysdep.c
index a5f0e01e214e..99f178319d03 100644
--- a/arch/um/kernel/tt/ptproxy/sysdep.c
+++ b/arch/um/kernel/tt/ptproxy/sysdep.c
@@ -15,6 +15,7 @@ terms and conditions.
15#include "ptrace_user.h" 15#include "ptrace_user.h"
16#include "user_util.h" 16#include "user_util.h"
17#include "user.h" 17#include "user.h"
18#include "os.h"
18 19
19int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, long *arg4, 20int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, long *arg4,
20 long *arg5) 21 long *arg5)
diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c
index d11e7399d7a1..71daae24e48a 100644
--- a/arch/um/kernel/tt/tracer.c
+++ b/arch/um/kernel/tt/tracer.c
@@ -19,7 +19,6 @@
19#include "sigcontext.h" 19#include "sigcontext.h"
20#include "sysdep/sigcontext.h" 20#include "sysdep/sigcontext.h"
21#include "os.h" 21#include "os.h"
22#include "signal_user.h"
23#include "user_util.h" 22#include "user_util.h"
24#include "mem_user.h" 23#include "mem_user.h"
25#include "process.h" 24#include "process.h"
diff --git a/arch/um/kernel/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c
index fc108615beaf..b5d9d64d91e4 100644
--- a/arch/um/kernel/tt/trap_user.c
+++ b/arch/um/kernel/tt/trap_user.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -8,18 +8,18 @@
8#include <signal.h> 8#include <signal.h>
9#include "sysdep/ptrace.h" 9#include "sysdep/ptrace.h"
10#include "sysdep/sigcontext.h" 10#include "sysdep/sigcontext.h"
11#include "signal_user.h"
12#include "user_util.h" 11#include "user_util.h"
13#include "kern_util.h" 12#include "kern_util.h"
14#include "task.h" 13#include "task.h"
15#include "tt.h" 14#include "tt.h"
15#include "os.h"
16 16
17void sig_handler_common_tt(int sig, void *sc_ptr) 17void sig_handler_common_tt(int sig, void *sc_ptr)
18{ 18{
19 struct sigcontext *sc = sc_ptr; 19 struct sigcontext *sc = sc_ptr;
20 struct tt_regs save_regs, *r; 20 struct tt_regs save_regs, *r;
21 struct signal_info *info; 21 int save_errno = errno, is_user = 0;
22 int save_errno = errno, is_user; 22 void (*handler)(int, union uml_pt_regs *);
23 23
24 /* This is done because to allow SIGSEGV to be delivered inside a SEGV 24 /* This is done because to allow SIGSEGV to be delivered inside a SEGV
25 * handler. This can happen in copy_user, and if SEGV is disabled, 25 * handler. This can happen in copy_user, and if SEGV is disabled,
@@ -35,15 +35,20 @@ void sig_handler_common_tt(int sig, void *sc_ptr)
35 GET_FAULTINFO_FROM_SC(r->faultinfo, sc); 35 GET_FAULTINFO_FROM_SC(r->faultinfo, sc);
36 } 36 }
37 save_regs = *r; 37 save_regs = *r;
38 is_user = user_context(SC_SP(sc)); 38 if (sc)
39 is_user = user_context(SC_SP(sc));
39 r->sc = sc; 40 r->sc = sc;
40 if(sig != SIGUSR2) 41 if(sig != SIGUSR2)
41 r->syscall = -1; 42 r->syscall = -1;
42 43
43 info = &sig_info[sig]; 44 handler = sig_info[sig];
44 if(!info->is_irq) unblock_signals(); 45
46 /* unblock SIGALRM, SIGVTALRM, SIGIO if sig isn't IRQ signal */
47 if (sig != SIGIO && sig != SIGWINCH &&
48 sig != SIGVTALRM && sig != SIGALRM)
49 unblock_signals();
45 50
46 (*info->handler)(sig, (union uml_pt_regs *) r); 51 handler(sig, (union uml_pt_regs *) r);
47 52
48 if(is_user){ 53 if(is_user){
49 interrupt_end(); 54 interrupt_end();
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 142a9493912b..e2d3ca445ef5 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -146,8 +146,8 @@ void set_cmdline(char *cmd)
146 146
147 if(CHOOSE_MODE(honeypot, 0)) return; 147 if(CHOOSE_MODE(honeypot, 0)) return;
148 148
149 umid = get_umid(1); 149 umid = get_umid();
150 if(umid != NULL){ 150 if(*umid != '\0'){
151 snprintf(argv1_begin, 151 snprintf(argv1_begin,
152 (argv1_end - argv1_begin) * sizeof(*ptr), 152 (argv1_end - argv1_begin) * sizeof(*ptr),
153 "(%s) ", umid); 153 "(%s) ", umid);
@@ -243,10 +243,6 @@ static int __init mode_tt_setup(char *line, int *add)
243 return(0); 243 return(0);
244} 244}
245 245
246#else
247
248#error Either CONFIG_MODE_TT or CONFIG_MODE_SKAS must be enabled
249
250#endif 246#endif
251#endif 247#endif
252#endif 248#endif
@@ -363,6 +359,11 @@ int linux_main(int argc, char **argv)
363 uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0, 359 uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0,
364 &host_task_size, &task_size); 360 &host_task_size, &task_size);
365 361
362 /*
363 * Setting up handlers to 'sig_info' struct
364 */
365 os_fill_handlinfo(handlinfo_kern);
366
366 brk_start = (unsigned long) sbrk(0); 367 brk_start = (unsigned long) sbrk(0);
367 CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start); 368 CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start);
368 /* Increase physical memory size for exec-shield users 369 /* Increase physical memory size for exec-shield users
diff --git a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c
index 0b21d59ba0cd..4eaee823bfd2 100644
--- a/arch/um/kernel/umid.c
+++ b/arch/um/kernel/umid.c
@@ -3,61 +3,30 @@
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include <stdio.h> 6#include "asm/errno.h"
7#include <unistd.h>
8#include <errno.h>
9#include <string.h>
10#include <stdlib.h>
11#include <dirent.h>
12#include <signal.h>
13#include <sys/stat.h>
14#include <sys/param.h>
15#include "user.h"
16#include "umid.h"
17#include "init.h" 7#include "init.h"
18#include "os.h" 8#include "os.h"
19#include "user_util.h" 9#include "kern.h"
20#include "choose-mode.h" 10#include "linux/kernel.h"
21 11
22#define UMID_LEN 64 12/* Changed by set_umid_arg */
23#define UML_DIR "~/.uml/"
24
25/* Changed by set_umid and make_umid, which are run early in boot */
26static char umid[UMID_LEN] = { 0 };
27
28/* Changed by set_uml_dir and make_uml_dir, which are run early in boot */
29static char *uml_dir = UML_DIR;
30
31/* Changed by set_umid */
32static int umid_is_random = 1;
33static int umid_inited = 0; 13static int umid_inited = 0;
34/* Have we created the files? Should we remove them? */
35static int umid_owned = 0;
36 14
37static int make_umid(int (*printer)(const char *fmt, ...)); 15static int __init set_umid_arg(char *name, int *add)
38
39static int __init set_umid(char *name, int is_random,
40 int (*printer)(const char *fmt, ...))
41{ 16{
42 if(umid_inited){ 17 int err;
43 (*printer)("Unique machine name can't be set twice\n");
44 return(-1);
45 }
46 18
47 if(strlen(name) > UMID_LEN - 1) 19 if(umid_inited)
48 (*printer)("Unique machine name is being truncated to %d " 20 return 0;
49 "characters\n", UMID_LEN);
50 strlcpy(umid, name, sizeof(umid));
51 21
52 umid_is_random = is_random;
53 umid_inited = 1;
54 return 0;
55}
56
57static int __init set_umid_arg(char *name, int *add)
58{
59 *add = 0; 22 *add = 0;
60 return(set_umid(name, 0, printf)); 23 err = set_umid(name);
24 if(err == -EEXIST)
25 printf("umid '%s' already in use\n", name);
26 else if(!err)
27 umid_inited = 1;
28
29 return 0;
61} 30}
62 31
63__uml_setup("umid=", set_umid_arg, 32__uml_setup("umid=", set_umid_arg,
@@ -66,265 +35,3 @@ __uml_setup("umid=", set_umid_arg,
66" is used for naming the pid file and management console socket.\n\n" 35" is used for naming the pid file and management console socket.\n\n"
67); 36);
68 37
69int __init umid_file_name(char *name, char *buf, int len)
70{
71 int n;
72
73 if(!umid_inited && make_umid(printk)) return(-1);
74
75 n = strlen(uml_dir) + strlen(umid) + strlen(name) + 1;
76 if(n > len){
77 printk("umid_file_name : buffer too short\n");
78 return(-1);
79 }
80
81 sprintf(buf, "%s%s/%s", uml_dir, umid, name);
82 return(0);
83}
84
85extern int tracing_pid;
86
87static void __init create_pid_file(void)
88{
89 char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
90 char pid[sizeof("nnnnn\0")];
91 int fd, n;
92
93 if(umid_file_name("pid", file, sizeof(file)))
94 return;
95
96 fd = os_open_file(file, of_create(of_excl(of_rdwr(OPENFLAGS()))),
97 0644);
98 if(fd < 0){
99 printf("Open of machine pid file \"%s\" failed: %s\n",
100 file, strerror(-fd));
101 return;
102 }
103
104 sprintf(pid, "%d\n", os_getpid());
105 n = os_write_file(fd, pid, strlen(pid));
106 if(n != strlen(pid))
107 printf("Write of pid file failed - err = %d\n", -n);
108 os_close_file(fd);
109}
110
111static int actually_do_remove(char *dir)
112{
113 DIR *directory;
114 struct dirent *ent;
115 int len;
116 char file[256];
117
118 directory = opendir(dir);
119 if(directory == NULL){
120 printk("actually_do_remove : couldn't open directory '%s', "
121 "errno = %d\n", dir, errno);
122 return(1);
123 }
124 while((ent = readdir(directory)) != NULL){
125 if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
126 continue;
127 len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1;
128 if(len > sizeof(file)){
129 printk("Not deleting '%s' from '%s' - name too long\n",
130 ent->d_name, dir);
131 continue;
132 }
133 sprintf(file, "%s/%s", dir, ent->d_name);
134 if(unlink(file) < 0){
135 printk("actually_do_remove : couldn't remove '%s' "
136 "from '%s', errno = %d\n", ent->d_name, dir,
137 errno);
138 return(1);
139 }
140 }
141 if(rmdir(dir) < 0){
142 printk("actually_do_remove : couldn't rmdir '%s', "
143 "errno = %d\n", dir, errno);
144 return(1);
145 }
146 return(0);
147}
148
149void remove_umid_dir(void)
150{
151 char dir[strlen(uml_dir) + UMID_LEN + 1];
152 if (!umid_owned)
153 return;
154
155 sprintf(dir, "%s%s", uml_dir, umid);
156 actually_do_remove(dir);
157}
158
159char *get_umid(int only_if_set)
160{
161 if(only_if_set && umid_is_random)
162 return NULL;
163 return umid;
164}
165
166static int not_dead_yet(char *dir)
167{
168 char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
169 char pid[sizeof("nnnnn\0")], *end;
170 int dead, fd, p, n;
171
172 sprintf(file, "%s/pid", dir);
173 dead = 0;
174 fd = os_open_file(file, of_read(OPENFLAGS()), 0);
175 if(fd < 0){
176 if(fd != -ENOENT){
177 printk("not_dead_yet : couldn't open pid file '%s', "
178 "err = %d\n", file, -fd);
179 return(1);
180 }
181 dead = 1;
182 }
183 if(fd > 0){
184 n = os_read_file(fd, pid, sizeof(pid));
185 if(n < 0){
186 printk("not_dead_yet : couldn't read pid file '%s', "
187 "err = %d\n", file, -n);
188 return(1);
189 }
190 p = strtoul(pid, &end, 0);
191 if(end == pid){
192 printk("not_dead_yet : couldn't parse pid file '%s', "
193 "errno = %d\n", file, errno);
194 dead = 1;
195 }
196 if(((kill(p, 0) < 0) && (errno == ESRCH)) ||
197 (p == CHOOSE_MODE(tracing_pid, os_getpid())))
198 dead = 1;
199 }
200 if(!dead)
201 return(1);
202 return(actually_do_remove(dir));
203}
204
205static int __init set_uml_dir(char *name, int *add)
206{
207 if((strlen(name) > 0) && (name[strlen(name) - 1] != '/')){
208 uml_dir = malloc(strlen(name) + 2);
209 if(uml_dir == NULL){
210 printf("Failed to malloc uml_dir - error = %d\n",
211 errno);
212 uml_dir = name;
213 /* Return 0 here because do_initcalls doesn't look at
214 * the return value.
215 */
216 return(0);
217 }
218 sprintf(uml_dir, "%s/", name);
219 }
220 else uml_dir = name;
221 return(0);
222}
223
224static int __init make_uml_dir(void)
225{
226 char dir[MAXPATHLEN + 1] = { '\0' };
227 int len;
228
229 if(*uml_dir == '~'){
230 char *home = getenv("HOME");
231
232 if(home == NULL){
233 printf("make_uml_dir : no value in environment for "
234 "$HOME\n");
235 exit(1);
236 }
237 strlcpy(dir, home, sizeof(dir));
238 uml_dir++;
239 }
240 strlcat(dir, uml_dir, sizeof(dir));
241 len = strlen(dir);
242 if (len > 0 && dir[len - 1] != '/')
243 strlcat(dir, "/", sizeof(dir));
244
245 uml_dir = malloc(strlen(dir) + 1);
246 if (uml_dir == NULL) {
247 printf("make_uml_dir : malloc failed, errno = %d\n", errno);
248 exit(1);
249 }
250 strcpy(uml_dir, dir);
251
252 if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){
253 printf("Failed to mkdir %s: %s\n", uml_dir, strerror(errno));
254 return(-1);
255 }
256 return 0;
257}
258
259static int __init make_umid(int (*printer)(const char *fmt, ...))
260{
261 int fd, err;
262 char tmp[strlen(uml_dir) + UMID_LEN + 1];
263
264 strlcpy(tmp, uml_dir, sizeof(tmp));
265
266 if(!umid_inited){
267 strcat(tmp, "XXXXXX");
268 fd = mkstemp(tmp);
269 if(fd < 0){
270 (*printer)("make_umid - mkstemp(%s) failed: %s\n",
271 tmp,strerror(errno));
272 return(1);
273 }
274
275 os_close_file(fd);
276 /* There's a nice tiny little race between this unlink and
277 * the mkdir below. It'd be nice if there were a mkstemp
278 * for directories.
279 */
280 unlink(tmp);
281 set_umid(&tmp[strlen(uml_dir)], 1, printer);
282 }
283
284 sprintf(tmp, "%s%s", uml_dir, umid);
285
286 err = mkdir(tmp, 0777);
287 if(err < 0){
288 if(errno == EEXIST){
289 if(not_dead_yet(tmp)){
290 (*printer)("umid '%s' is in use\n", umid);
291 umid_owned = 0;
292 return(-1);
293 }
294 err = mkdir(tmp, 0777);
295 }
296 }
297 if(err < 0){
298 (*printer)("Failed to create %s - errno = %d\n", umid, errno);
299 return(-1);
300 }
301
302 umid_owned = 1;
303 return 0;
304}
305
306__uml_setup("uml_dir=", set_uml_dir,
307"uml_dir=<directory>\n"
308" The location to place the pid and umid files.\n\n"
309);
310
311static int __init make_umid_setup(void)
312{
313 /* one function with the ordering we need ... */
314 make_uml_dir();
315 make_umid(printf);
316 create_pid_file();
317 return 0;
318}
319__uml_postsetup(make_umid_setup);
320
321/*
322 * Overrides for Emacs so that we follow Linus's tabbing style.
323 * Emacs will notice this stuff at the end of the file and automatically
324 * adjust the settings for this buffer only. This must remain at the end
325 * of the file.
326 * ---------------------------------------------------------------------------
327 * Local variables:
328 * c-file-style: "linux"
329 * End:
330 */
diff --git a/arch/um/kernel/user_util.c b/arch/um/kernel/user_util.c
deleted file mode 100644
index 4c231161f257..000000000000
--- a/arch/um/kernel/user_util.c
+++ /dev/null
@@ -1,174 +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 <stdlib.h>
8#include <unistd.h>
9#include <limits.h>
10#include <setjmp.h>
11#include <sys/mman.h>
12#include <sys/stat.h>
13#include <sys/utsname.h>
14#include <sys/param.h>
15#include <sys/time.h>
16#include "asm/types.h"
17#include <ctype.h>
18#include <signal.h>
19#include <wait.h>
20#include <errno.h>
21#include <stdarg.h>
22#include <sched.h>
23#include <termios.h>
24#include <string.h>
25#include "user_util.h"
26#include "kern_util.h"
27#include "user.h"
28#include "mem_user.h"
29#include "init.h"
30#include "ptrace_user.h"
31#include "uml-config.h"
32
33void stop(void)
34{
35 while(1) sleep(1000000);
36}
37
38void stack_protections(unsigned long address)
39{
40 int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
41
42 if(mprotect((void *) address, page_size(), prot) < 0)
43 panic("protecting stack failed, errno = %d", errno);
44}
45
46void task_protections(unsigned long address)
47{
48 unsigned long guard = address + page_size();
49 unsigned long stack = guard + page_size();
50 int prot = 0, pages;
51
52#ifdef notdef
53 if(mprotect((void *) stack, page_size(), prot) < 0)
54 panic("protecting guard page failed, errno = %d", errno);
55#endif
56 pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER) - 2;
57 prot = PROT_READ | PROT_WRITE | PROT_EXEC;
58 if(mprotect((void *) stack, pages * page_size(), prot) < 0)
59 panic("protecting stack failed, errno = %d", errno);
60}
61
62int wait_for_stop(int pid, int sig, int cont_type, void *relay)
63{
64 sigset_t *relay_signals = relay;
65 int status, ret;
66
67 while(1){
68 CATCH_EINTR(ret = waitpid(pid, &status, WUNTRACED));
69 if((ret < 0) ||
70 !WIFSTOPPED(status) || (WSTOPSIG(status) != sig)){
71 if(ret < 0){
72 printk("wait failed, errno = %d\n",
73 errno);
74 }
75 else if(WIFEXITED(status))
76 printk("process %d exited with status %d\n",
77 pid, WEXITSTATUS(status));
78 else if(WIFSIGNALED(status))
79 printk("process %d exited with signal %d\n",
80 pid, WTERMSIG(status));
81 else if((WSTOPSIG(status) == SIGVTALRM) ||
82 (WSTOPSIG(status) == SIGALRM) ||
83 (WSTOPSIG(status) == SIGIO) ||
84 (WSTOPSIG(status) == SIGPROF) ||
85 (WSTOPSIG(status) == SIGCHLD) ||
86 (WSTOPSIG(status) == SIGWINCH) ||
87 (WSTOPSIG(status) == SIGINT)){
88 ptrace(cont_type, pid, 0, WSTOPSIG(status));
89 continue;
90 }
91 else if((relay_signals != NULL) &&
92 sigismember(relay_signals, WSTOPSIG(status))){
93 ptrace(cont_type, pid, 0, WSTOPSIG(status));
94 continue;
95 }
96 else printk("process %d stopped with signal %d\n",
97 pid, WSTOPSIG(status));
98 panic("wait_for_stop failed to wait for %d to stop "
99 "with %d\n", pid, sig);
100 }
101 return(status);
102 }
103}
104
105int raw(int fd)
106{
107 struct termios tt;
108 int err;
109
110 CATCH_EINTR(err = tcgetattr(fd, &tt));
111 if(err < 0)
112 return -errno;
113
114 cfmakeraw(&tt);
115
116 CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt));
117 if(err < 0)
118 return -errno;
119
120 /* XXX tcsetattr could have applied only some changes
121 * (and cfmakeraw() is a set of changes) */
122 return(0);
123}
124
125void setup_machinename(char *machine_out)
126{
127 struct utsname host;
128
129 uname(&host);
130#if defined(UML_CONFIG_UML_X86) && !defined(UML_CONFIG_64BIT)
131 if (!strcmp(host.machine, "x86_64")) {
132 strcpy(machine_out, "i686");
133 return;
134 }
135#endif
136 strcpy(machine_out, host.machine);
137}
138
139char host_info[(_UTSNAME_LENGTH + 1) * 4 + _UTSNAME_NODENAME_LENGTH + 1];
140
141void setup_hostinfo(void)
142{
143 struct utsname host;
144
145 uname(&host);
146 sprintf(host_info, "%s %s %s %s %s", host.sysname, host.nodename,
147 host.release, host.version, host.machine);
148}
149
150int setjmp_wrapper(void (*proc)(void *, void *), ...)
151{
152 va_list args;
153 sigjmp_buf buf;
154 int n;
155
156 n = sigsetjmp(buf, 1);
157 if(n == 0){
158 va_start(args, proc);
159 (*proc)(&buf, &args);
160 }
161 va_end(args);
162 return(n);
163}
164
165/*
166 * Overrides for Emacs so that we follow Linus's tabbing style.
167 * Emacs will notice this stuff at the end of the file and automatically
168 * adjust the settings for this buffer only. This must remain at the end
169 * of the file.
170 * ---------------------------------------------------------------------------
171 * Local variables:
172 * c-file-style: "linux"
173 * End:
174 */