aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/include/sysdep-i386/stub.h47
-rw-r--r--arch/um/include/sysdep-x86_64/stub.h39
-rw-r--r--arch/um/include/time_user.h1
-rw-r--r--arch/um/kernel/skas/Makefile7
-rw-r--r--arch/um/kernel/skas/clone.c44
-rw-r--r--arch/um/kernel/skas/include/skas.h1
-rw-r--r--arch/um/kernel/skas/include/stub-data.h18
-rw-r--r--arch/um/kernel/skas/mmu.c7
-rw-r--r--arch/um/kernel/skas/process.c63
-rw-r--r--arch/um/kernel/time.c7
10 files changed, 231 insertions, 3 deletions
diff --git a/arch/um/include/sysdep-i386/stub.h b/arch/um/include/sysdep-i386/stub.h
index fed9ff1cea52..d3699fe1c613 100644
--- a/arch/um/include/sysdep-i386/stub.h
+++ b/arch/um/include/sysdep-i386/stub.h
@@ -10,9 +10,56 @@
10#include <asm/unistd.h> 10#include <asm/unistd.h>
11 11
12extern void stub_segv_handler(int sig); 12extern void stub_segv_handler(int sig);
13extern void stub_clone_handler(void);
13 14
14#define STUB_SYSCALL_RET EAX 15#define STUB_SYSCALL_RET EAX
15#define STUB_MMAP_NR __NR_mmap2 16#define STUB_MMAP_NR __NR_mmap2
16#define MMAP_OFFSET(o) ((o) >> PAGE_SHIFT) 17#define MMAP_OFFSET(o) ((o) >> PAGE_SHIFT)
17 18
19static inline long stub_syscall2(long syscall, long arg1, long arg2)
20{
21 long ret;
22
23 __asm__("movl %0, %%ecx; " : : "g" (arg2) : "%ecx");
24 __asm__("movl %0, %%ebx; " : : "g" (arg1) : "%ebx");
25 __asm__("movl %0, %%eax; " : : "g" (syscall) : "%eax");
26 __asm__("int $0x80;" : : : "%eax");
27 __asm__ __volatile__("movl %%eax, %0; " : "=g" (ret) :);
28 return(ret);
29}
30
31static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3)
32{
33 __asm__("movl %0, %%edx; " : : "g" (arg3) : "%edx");
34 return(stub_syscall2(syscall, arg1, arg2));
35}
36
37static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3,
38 long arg4)
39{
40 __asm__("movl %0, %%esi; " : : "g" (arg4) : "%esi");
41 return(stub_syscall3(syscall, arg1, arg2, arg3));
42}
43
44static inline long stub_syscall6(long syscall, long arg1, long arg2, long arg3,
45 long arg4, long arg5, long arg6)
46{
47 long ret;
48 __asm__("movl %0, %%eax; " : : "g" (syscall) : "%eax");
49 __asm__("movl %0, %%ebx; " : : "g" (arg1) : "%ebx");
50 __asm__("movl %0, %%ecx; " : : "g" (arg2) : "%ecx");
51 __asm__("movl %0, %%edx; " : : "g" (arg3) : "%edx");
52 __asm__("movl %0, %%esi; " : : "g" (arg4) : "%esi");
53 __asm__("movl %0, %%edi; " : : "g" (arg5) : "%edi");
54 __asm__ __volatile__("pushl %%ebp ; movl %1, %%ebp; "
55 "int $0x80; popl %%ebp ; "
56 "movl %%eax, %0; " : "=g" (ret) : "g" (arg6) : "%eax");
57 return(ret);
58}
59
60static inline void trap_myself(void)
61{
62 __asm("int3");
63}
64
18#endif 65#endif
diff --git a/arch/um/include/sysdep-x86_64/stub.h b/arch/um/include/sysdep-x86_64/stub.h
index 6b5447ad590d..f599058d8263 100644
--- a/arch/um/include/sysdep-x86_64/stub.h
+++ b/arch/um/include/sysdep-x86_64/stub.h
@@ -11,9 +11,48 @@
11#include <sysdep/ptrace_user.h> 11#include <sysdep/ptrace_user.h>
12 12
13extern void stub_segv_handler(int sig); 13extern void stub_segv_handler(int sig);
14extern void stub_clone_handler(void);
14 15
15#define STUB_SYSCALL_RET PT_INDEX(RAX) 16#define STUB_SYSCALL_RET PT_INDEX(RAX)
16#define STUB_MMAP_NR __NR_mmap 17#define STUB_MMAP_NR __NR_mmap
17#define MMAP_OFFSET(o) (o) 18#define MMAP_OFFSET(o) (o)
18 19
20static inline long stub_syscall2(long syscall, long arg1, long arg2)
21{
22 long ret;
23
24 __asm__("movq %0, %%rsi; " : : "g" (arg2) : "%rsi");
25 __asm__("movq %0, %%rdi; " : : "g" (arg1) : "%rdi");
26 __asm__("movq %0, %%rax; " : : "g" (syscall) : "%rax");
27 __asm__("syscall;" : : : "%rax", "%r11", "%rcx");
28 __asm__ __volatile__("movq %%rax, %0; " : "=g" (ret) :);
29 return(ret);
30}
31
32static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3)
33{
34 __asm__("movq %0, %%rdx; " : : "g" (arg3) : "%rdx");
35 return(stub_syscall2(syscall, arg1, arg2));
36}
37
38static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3,
39 long arg4)
40{
41 __asm__("movq %0, %%r10; " : : "g" (arg4) : "%r10");
42 return(stub_syscall3(syscall, arg1, arg2, arg3));
43}
44
45static inline long stub_syscall6(long syscall, long arg1, long arg2, long arg3,
46 long arg4, long arg5, long arg6)
47{
48 __asm__("movq %0, %%r9; " : : "g" (arg6) : "%r9");
49 __asm__("movq %0, %%r8; " : : "g" (arg5) : "%r8");
50 return(stub_syscall4(syscall, arg1, arg2, arg3, arg4));
51}
52
53static inline void trap_myself(void)
54{
55 __asm("int3");
56}
57
19#endif 58#endif
diff --git a/arch/um/include/time_user.h b/arch/um/include/time_user.h
index f64ef77019a3..17d7ef2141f4 100644
--- a/arch/um/include/time_user.h
+++ b/arch/um/include/time_user.h
@@ -10,6 +10,7 @@ extern void timer(void);
10extern void switch_timers(int to_real); 10extern void switch_timers(int to_real);
11extern void idle_sleep(int secs); 11extern void idle_sleep(int secs);
12extern void enable_timer(void); 12extern void enable_timer(void);
13extern void prepare_timer(void * ptr);
13extern void disable_timer(void); 14extern void disable_timer(void);
14extern unsigned long time_lock(void); 15extern unsigned long time_lock(void);
15extern void time_unlock(unsigned long); 16extern void time_unlock(unsigned long);
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
index ff69c4b312c0..d296d55ade4b 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -3,11 +3,14 @@
3# Licensed under the GPL 3# Licensed under the GPL
4# 4#
5 5
6obj-y := exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \ 6obj-y := clone.o exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \
7 syscall_kern.o syscall_user.o tlb.o trap_user.o uaccess.o \ 7 syscall_kern.o syscall_user.o tlb.o trap_user.o uaccess.o \
8 8
9subdir- := util 9subdir- := util
10 10
11USER_OBJS := process.o 11USER_OBJS := process.o clone.o
12 12
13include arch/um/scripts/Makefile.rules 13include arch/um/scripts/Makefile.rules
14
15# clone.o is in the stub, so it can't be built with profiling
16$(obj)/clone.o : c_flags = -Wp,-MD,$(depfile) $(call unprofile,$(USER_CFLAGS))
diff --git a/arch/um/kernel/skas/clone.c b/arch/um/kernel/skas/clone.c
new file mode 100644
index 000000000000..4dc55f10cd18
--- /dev/null
+++ b/arch/um/kernel/skas/clone.c
@@ -0,0 +1,44 @@
1#include <sched.h>
2#include <signal.h>
3#include <sys/mman.h>
4#include <sys/time.h>
5#include <asm/unistd.h>
6#include <asm/page.h>
7#include "ptrace_user.h"
8#include "skas.h"
9#include "stub-data.h"
10#include "uml-config.h"
11#include "sysdep/stub.h"
12
13/* This is in a separate file because it needs to be compiled with any
14 * extraneous gcc flags (-pg, -fprofile-arcs, -ftest-coverage) disabled
15 */
16void __attribute__ ((__section__ (".__syscall_stub")))
17stub_clone_handler(void)
18{
19 long err;
20 struct stub_data *from = (struct stub_data *) UML_CONFIG_STUB_DATA;
21
22 err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD,
23 UML_CONFIG_STUB_DATA + PAGE_SIZE / 2 -
24 sizeof(void *));
25 if(err != 0)
26 goto out;
27
28 err = stub_syscall4(__NR_ptrace, PTRACE_TRACEME, 0, 0, 0);
29 if(err)
30 goto out;
31
32 err = stub_syscall3(__NR_setitimer, ITIMER_VIRTUAL,
33 (long) &from->timer, 0);
34 if(err)
35 goto out;
36
37 err = stub_syscall6(STUB_MMAP_NR, UML_CONFIG_STUB_DATA, PAGE_SIZE,
38 PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED,
39 from->fd, from->offset);
40 out:
41 /* save current result. Parent: pid; child: retcode of mmap */
42 from->err = err;
43 trap_myself();
44}
diff --git a/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h
index d91a60f3830a..d983ea842547 100644
--- a/arch/um/kernel/skas/include/skas.h
+++ b/arch/um/kernel/skas/include/skas.h
@@ -32,6 +32,7 @@ extern int protect(struct mm_id * mm_idp, unsigned long addr,
32extern void user_signal(int sig, union uml_pt_regs *regs, int pid); 32extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
33extern int new_mm(int from); 33extern int new_mm(int from);
34extern int start_userspace(unsigned long stub_stack); 34extern int start_userspace(unsigned long stub_stack);
35extern int copy_context_skas0(unsigned long stack, int pid);
35extern void get_skas_faultinfo(int pid, struct faultinfo * fi); 36extern void get_skas_faultinfo(int pid, struct faultinfo * fi);
36extern long execute_syscall_skas(void *r); 37extern long execute_syscall_skas(void *r);
37extern unsigned long current_stub_stack(void); 38extern unsigned long current_stub_stack(void);
diff --git a/arch/um/kernel/skas/include/stub-data.h b/arch/um/kernel/skas/include/stub-data.h
new file mode 100644
index 000000000000..f6ed92c3727d
--- /dev/null
+++ b/arch/um/kernel/skas/include/stub-data.h
@@ -0,0 +1,18 @@
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/mmu.c b/arch/um/kernel/skas/mmu.c
index 511a855c9ec0..d232daa42c31 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -75,6 +75,7 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
75int init_new_context_skas(struct task_struct *task, struct mm_struct *mm) 75int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
76{ 76{
77 struct mm_struct *cur_mm = current->mm; 77 struct mm_struct *cur_mm = current->mm;
78 struct mm_id *cur_mm_id = &cur_mm->context.skas.id;
78 struct mm_id *mm_id = &mm->context.skas.id; 79 struct mm_id *mm_id = &mm->context.skas.id;
79 unsigned long stack; 80 unsigned long stack;
80 int from, ret; 81 int from, ret;
@@ -115,7 +116,11 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
115 goto out_free; 116 goto out_free;
116 117
117 mm->nr_ptes--; 118 mm->nr_ptes--;
118 mm_id->u.pid = start_userspace(stack); 119
120 if((cur_mm != NULL) && (cur_mm != &init_mm))
121 mm_id->u.pid = copy_context_skas0(stack,
122 cur_mm_id->u.pid);
123 else mm_id->u.pid = start_userspace(stack);
119 } 124 }
120 125
121 return 0; 126 return 0;
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index 1647abb0d1aa..ba671dab8878 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -13,6 +13,7 @@
13#include <sys/wait.h> 13#include <sys/wait.h>
14#include <sys/mman.h> 14#include <sys/mman.h>
15#include <sys/user.h> 15#include <sys/user.h>
16#include <sys/time.h>
16#include <asm/unistd.h> 17#include <asm/unistd.h>
17#include <asm/types.h> 18#include <asm/types.h>
18#include "user.h" 19#include "user.h"
@@ -22,6 +23,7 @@
22#include "user_util.h" 23#include "user_util.h"
23#include "kern_util.h" 24#include "kern_util.h"
24#include "skas.h" 25#include "skas.h"
26#include "stub-data.h"
25#include "mm_id.h" 27#include "mm_id.h"
26#include "sysdep/sigcontext.h" 28#include "sysdep/sigcontext.h"
27#include "sysdep/stub.h" 29#include "sysdep/stub.h"
@@ -296,6 +298,67 @@ void userspace(union uml_pt_regs *regs)
296#define INIT_JMP_HALT 3 298#define INIT_JMP_HALT 3
297#define INIT_JMP_REBOOT 4 299#define INIT_JMP_REBOOT 4
298 300
301
302int copy_context_skas0(unsigned long new_stack, int pid)
303{
304 int err;
305 unsigned long regs[MAX_REG_NR];
306 unsigned long current_stack = current_stub_stack();
307 struct stub_data *data = (struct stub_data *) current_stack;
308 struct stub_data *child_data = (struct stub_data *) new_stack;
309 __u64 new_offset;
310 int new_fd = phys_mapping(to_phys((void *)new_stack), &new_offset);
311
312 /* prepare offset and fd of child's stack as argument for parent's
313 * and child's mmap2 calls
314 */
315 *data = ((struct stub_data) { .offset = MMAP_OFFSET(new_offset),
316 .fd = new_fd,
317 .timer = ((struct itimerval)
318 { { 0, 1000000 / hz() },
319 { 0, 1000000 / hz() }})});
320 get_safe_registers(regs);
321
322 /* Set parent's instruction pointer to start of clone-stub */
323 regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
324 (unsigned long) stub_clone_handler -
325 (unsigned long) &__syscall_stub_start;
326 regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + PAGE_SIZE -
327 sizeof(void *);
328 err = ptrace_setregs(pid, regs);
329 if(err < 0)
330 panic("copy_context_skas0 : PTRACE_SETREGS failed, "
331 "pid = %d, errno = %d\n", pid, errno);
332
333 /* set a well known return code for detection of child write failure */
334 child_data->err = 12345678;
335
336 /* Wait, until parent has finished its work: read child's pid from
337 * parent's stack, and check, if bad result.
338 */
339 wait_stub_done(pid, 0, "copy_context_skas0");
340
341 pid = data->err;
342 if(pid < 0)
343 panic("copy_context_skas0 - stub-parent reports error %d\n",
344 pid);
345
346 /* Wait, until child has finished too: read child's result from
347 * child's stack and check it.
348 */
349 wait_stub_done(pid, -1, "copy_context_skas0");
350 if (child_data->err != UML_CONFIG_STUB_DATA)
351 panic("copy_context_skas0 - stub-child reports error %d\n",
352 child_data->err);
353
354 if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
355 (void *)PTRACE_O_TRACESYSGOOD) < 0)
356 panic("copy_context_skas0 : PTRACE_SETOPTIONS failed, "
357 "errno = %d\n", errno);
358
359 return pid;
360}
361
299void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, 362void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
300 void (*handler)(int)) 363 void (*handler)(int))
301{ 364{
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index f829b309b63c..c40b611e3d93 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -48,6 +48,13 @@ void enable_timer(void)
48 set_interval(ITIMER_VIRTUAL); 48 set_interval(ITIMER_VIRTUAL);
49} 49}
50 50
51void prepare_timer(void * ptr)
52{
53 int usec = 1000000/hz();
54 *(struct itimerval *)ptr = ((struct itimerval) { { 0, usec },
55 { 0, usec }});
56}
57
51void disable_timer(void) 58void disable_timer(void)
52{ 59{
53 struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }}); 60 struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }});