diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/um/kernel/skas |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/um/kernel/skas')
22 files changed, 1703 insertions, 0 deletions
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile new file mode 100644 index 000000000000..d37d1bfcd6f7 --- /dev/null +++ b/arch/um/kernel/skas/Makefile | |||
@@ -0,0 +1,13 @@ | |||
1 | # | ||
2 | # Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com) | ||
3 | # Licensed under the GPL | ||
4 | # | ||
5 | |||
6 | obj-y := exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \ | ||
7 | syscall_kern.o syscall_user.o time.o tlb.o trap_user.o uaccess.o \ | ||
8 | |||
9 | subdir- := util | ||
10 | |||
11 | USER_OBJS := process.o time.o | ||
12 | |||
13 | include arch/um/scripts/Makefile.rules | ||
diff --git a/arch/um/kernel/skas/exec_kern.c b/arch/um/kernel/skas/exec_kern.c new file mode 100644 index 000000000000..c6b4d5dba789 --- /dev/null +++ b/arch/um/kernel/skas/exec_kern.c | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include "linux/kernel.h" | ||
7 | #include "asm/current.h" | ||
8 | #include "asm/page.h" | ||
9 | #include "asm/signal.h" | ||
10 | #include "asm/ptrace.h" | ||
11 | #include "asm/uaccess.h" | ||
12 | #include "asm/mmu_context.h" | ||
13 | #include "tlb.h" | ||
14 | #include "skas.h" | ||
15 | #include "um_mmu.h" | ||
16 | #include "os.h" | ||
17 | |||
18 | void flush_thread_skas(void) | ||
19 | { | ||
20 | force_flush_all(); | ||
21 | switch_mm_skas(current->mm->context.skas.mm_fd); | ||
22 | } | ||
23 | |||
24 | void start_thread_skas(struct pt_regs *regs, unsigned long eip, | ||
25 | unsigned long esp) | ||
26 | { | ||
27 | set_fs(USER_DS); | ||
28 | PT_REGS_IP(regs) = eip; | ||
29 | PT_REGS_SP(regs) = esp; | ||
30 | } | ||
31 | |||
32 | /* | ||
33 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
34 | * Emacs will notice this stuff at the end of the file and automatically | ||
35 | * adjust the settings for this buffer only. This must remain at the end | ||
36 | * of the file. | ||
37 | * --------------------------------------------------------------------------- | ||
38 | * Local variables: | ||
39 | * c-file-style: "linux" | ||
40 | * End: | ||
41 | */ | ||
diff --git a/arch/um/kernel/skas/include/mmu-skas.h b/arch/um/kernel/skas/include/mmu-skas.h new file mode 100644 index 000000000000..4cd60d7213f3 --- /dev/null +++ b/arch/um/kernel/skas/include/mmu-skas.h | |||
@@ -0,0 +1,24 @@ | |||
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 | struct mmu_context_skas { | ||
10 | int mm_fd; | ||
11 | }; | ||
12 | |||
13 | #endif | ||
14 | |||
15 | /* | ||
16 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
17 | * Emacs will notice this stuff at the end of the file and automatically | ||
18 | * adjust the settings for this buffer only. This must remain at the end | ||
19 | * of the file. | ||
20 | * --------------------------------------------------------------------------- | ||
21 | * Local variables: | ||
22 | * c-file-style: "linux" | ||
23 | * End: | ||
24 | */ | ||
diff --git a/arch/um/kernel/skas/include/mode-skas.h b/arch/um/kernel/skas/include/mode-skas.h new file mode 100644 index 000000000000..c1e33bd788db --- /dev/null +++ b/arch/um/kernel/skas/include/mode-skas.h | |||
@@ -0,0 +1,34 @@ | |||
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 | |||
11 | extern unsigned long exec_regs[]; | ||
12 | extern unsigned long exec_fp_regs[]; | ||
13 | extern unsigned long exec_fpx_regs[]; | ||
14 | extern int have_fpx_regs; | ||
15 | |||
16 | extern void user_time_init_skas(void); | ||
17 | extern void sig_handler_common_skas(int sig, void *sc_ptr); | ||
18 | extern void halt_skas(void); | ||
19 | extern void reboot_skas(void); | ||
20 | extern void kill_off_processes_skas(void); | ||
21 | extern int is_skas_winch(int pid, int fd, void *data); | ||
22 | |||
23 | #endif | ||
24 | |||
25 | /* | ||
26 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
27 | * Emacs will notice this stuff at the end of the file and automatically | ||
28 | * adjust the settings for this buffer only. This must remain at the end | ||
29 | * of the file. | ||
30 | * --------------------------------------------------------------------------- | ||
31 | * Local variables: | ||
32 | * c-file-style: "linux" | ||
33 | * End: | ||
34 | */ | ||
diff --git a/arch/um/kernel/skas/include/mode_kern-skas.h b/arch/um/kernel/skas/include/mode_kern-skas.h new file mode 100644 index 000000000000..94c564962378 --- /dev/null +++ b/arch/um/kernel/skas/include/mode_kern-skas.h | |||
@@ -0,0 +1,53 @@ | |||
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 | |||
13 | extern void flush_thread_skas(void); | ||
14 | extern void *switch_to_skas(void *prev, void *next); | ||
15 | extern void start_thread_skas(struct pt_regs *regs, unsigned long eip, | ||
16 | unsigned long esp); | ||
17 | extern 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); | ||
20 | extern void release_thread_skas(struct task_struct *task); | ||
21 | extern void exit_thread_skas(void); | ||
22 | extern void initial_thread_cb_skas(void (*proc)(void *), void *arg); | ||
23 | extern void init_idle_skas(void); | ||
24 | extern void flush_tlb_kernel_range_skas(unsigned long start, | ||
25 | unsigned long end); | ||
26 | extern void flush_tlb_kernel_vm_skas(void); | ||
27 | extern void __flush_tlb_one_skas(unsigned long addr); | ||
28 | extern void flush_tlb_range_skas(struct vm_area_struct *vma, | ||
29 | unsigned long start, unsigned long end); | ||
30 | extern void flush_tlb_mm_skas(struct mm_struct *mm); | ||
31 | extern void force_flush_all_skas(void); | ||
32 | extern long execute_syscall_skas(void *r); | ||
33 | extern void before_mem_skas(unsigned long unused); | ||
34 | extern unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out, | ||
35 | unsigned long *task_size_out); | ||
36 | extern int start_uml_skas(void); | ||
37 | extern int external_pid_skas(struct task_struct *task); | ||
38 | extern int thread_pid_skas(struct task_struct *task); | ||
39 | |||
40 | #define kmem_end_skas (host_task_size - 1024 * 1024) | ||
41 | |||
42 | #endif | ||
43 | |||
44 | /* | ||
45 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
46 | * Emacs will notice this stuff at the end of the file and automatically | ||
47 | * adjust the settings for this buffer only. This must remain at the end | ||
48 | * of the file. | ||
49 | * --------------------------------------------------------------------------- | ||
50 | * Local variables: | ||
51 | * c-file-style: "linux" | ||
52 | * End: | ||
53 | */ | ||
diff --git a/arch/um/kernel/skas/include/proc_mm.h b/arch/um/kernel/skas/include/proc_mm.h new file mode 100644 index 000000000000..cce61a679052 --- /dev/null +++ b/arch/um/kernel/skas/include/proc_mm.h | |||
@@ -0,0 +1,55 @@ | |||
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 | |||
14 | struct 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 | |||
23 | struct mm_munmap { | ||
24 | unsigned long addr; | ||
25 | unsigned long len; | ||
26 | }; | ||
27 | |||
28 | struct mm_mprotect { | ||
29 | unsigned long addr; | ||
30 | unsigned long len; | ||
31 | unsigned int prot; | ||
32 | }; | ||
33 | |||
34 | struct 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 new file mode 100644 index 000000000000..f0702c2c7204 --- /dev/null +++ b/arch/um/kernel/skas/include/skas.h | |||
@@ -0,0 +1,46 @@ | |||
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 "sysdep/ptrace.h" | ||
10 | |||
11 | extern int userspace_pid[]; | ||
12 | |||
13 | extern void switch_threads(void *me, void *next); | ||
14 | extern void thread_wait(void *sw, void *fb); | ||
15 | extern void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, | ||
16 | void (*handler)(int)); | ||
17 | extern int start_idle_thread(void *stack, void *switch_buf_ptr, | ||
18 | void **fork_buf_ptr); | ||
19 | extern int user_thread(unsigned long stack, int flags); | ||
20 | extern void userspace(union uml_pt_regs *regs); | ||
21 | extern void new_thread_proc(void *stack, void (*handler)(int sig)); | ||
22 | extern void remove_sigstack(void); | ||
23 | extern void new_thread_handler(int sig); | ||
24 | extern void handle_syscall(union uml_pt_regs *regs); | ||
25 | extern void map(int fd, unsigned long virt, unsigned long len, int r, int w, | ||
26 | int x, int phys_fd, unsigned long long offset); | ||
27 | extern int unmap(int fd, void *addr, unsigned long len); | ||
28 | extern int protect(int fd, unsigned long addr, unsigned long len, | ||
29 | int r, int w, int x); | ||
30 | extern void user_signal(int sig, union uml_pt_regs *regs); | ||
31 | extern int new_mm(int from); | ||
32 | extern void start_userspace(int cpu); | ||
33 | extern long execute_syscall_skas(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/skas/include/uaccess-skas.h b/arch/um/kernel/skas/include/uaccess-skas.h new file mode 100644 index 000000000000..11986c9b9ddf --- /dev/null +++ b/arch/um/kernel/skas/include/uaccess-skas.h | |||
@@ -0,0 +1,45 @@ | |||
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 | #include "asm/fixmap.h" | ||
11 | |||
12 | #define access_ok_skas(type, addr, size) \ | ||
13 | ((segment_eq(get_fs(), KERNEL_DS)) || \ | ||
14 | (((unsigned long) (addr) < TASK_SIZE) && \ | ||
15 | ((unsigned long) (addr) + (size) <= TASK_SIZE)) || \ | ||
16 | ((type == VERIFY_READ ) && \ | ||
17 | ((unsigned long) (addr) >= FIXADDR_USER_START) && \ | ||
18 | ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \ | ||
19 | ((unsigned long) (addr) + (size) >= (unsigned long)(addr)))) | ||
20 | |||
21 | static inline int verify_area_skas(int type, const void * addr, | ||
22 | unsigned long size) | ||
23 | { | ||
24 | return(access_ok_skas(type, addr, size) ? 0 : -EFAULT); | ||
25 | } | ||
26 | |||
27 | extern int copy_from_user_skas(void *to, const void *from, int n); | ||
28 | extern int copy_to_user_skas(void *to, const void *from, int n); | ||
29 | extern int strncpy_from_user_skas(char *dst, const char *src, int count); | ||
30 | extern int __clear_user_skas(void *mem, int len); | ||
31 | extern int clear_user_skas(void *mem, int len); | ||
32 | extern int strnlen_user_skas(const void *str, int len); | ||
33 | |||
34 | #endif | ||
35 | |||
36 | /* | ||
37 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
38 | * Emacs will notice this stuff at the end of the file and automatically | ||
39 | * adjust the settings for this buffer only. This must remain at the end | ||
40 | * of the file. | ||
41 | * --------------------------------------------------------------------------- | ||
42 | * Local variables: | ||
43 | * c-file-style: "linux" | ||
44 | * End: | ||
45 | */ | ||
diff --git a/arch/um/kernel/skas/mem.c b/arch/um/kernel/skas/mem.c new file mode 100644 index 000000000000..438db2f43456 --- /dev/null +++ b/arch/um/kernel/skas/mem.c | |||
@@ -0,0 +1,35 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include "linux/config.h" | ||
7 | #include "linux/mm.h" | ||
8 | #include "mem_user.h" | ||
9 | |||
10 | unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out, | ||
11 | unsigned long *task_size_out) | ||
12 | { | ||
13 | /* Round up to the nearest 4M */ | ||
14 | unsigned long top = ROUND_4M((unsigned long) &arg); | ||
15 | |||
16 | #ifdef CONFIG_HOST_TASK_SIZE | ||
17 | *host_size_out = CONFIG_HOST_TASK_SIZE; | ||
18 | *task_size_out = CONFIG_HOST_TASK_SIZE; | ||
19 | #else | ||
20 | *host_size_out = top; | ||
21 | *task_size_out = top; | ||
22 | #endif | ||
23 | return(((unsigned long) set_task_sizes_skas) & ~0xffffff); | ||
24 | } | ||
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/mem_user.c b/arch/um/kernel/skas/mem_user.c new file mode 100644 index 000000000000..1310bf1e88d1 --- /dev/null +++ b/arch/um/kernel/skas/mem_user.c | |||
@@ -0,0 +1,102 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <errno.h> | ||
7 | #include <sys/mman.h> | ||
8 | #include "mem_user.h" | ||
9 | #include "mem.h" | ||
10 | #include "user.h" | ||
11 | #include "os.h" | ||
12 | #include "proc_mm.h" | ||
13 | |||
14 | void map(int fd, unsigned long virt, unsigned long len, int r, int w, | ||
15 | int x, int phys_fd, unsigned long long offset) | ||
16 | { | ||
17 | struct proc_mm_op map; | ||
18 | int prot, n; | ||
19 | |||
20 | prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | | ||
21 | (x ? PROT_EXEC : 0); | ||
22 | |||
23 | map = ((struct proc_mm_op) { .op = MM_MMAP, | ||
24 | .u = | ||
25 | { .mmap = | ||
26 | { .addr = virt, | ||
27 | .len = len, | ||
28 | .prot = prot, | ||
29 | .flags = MAP_SHARED | | ||
30 | MAP_FIXED, | ||
31 | .fd = phys_fd, | ||
32 | .offset = offset | ||
33 | } } } ); | ||
34 | n = os_write_file(fd, &map, sizeof(map)); | ||
35 | if(n != sizeof(map)) | ||
36 | printk("map : /proc/mm map failed, err = %d\n", -n); | ||
37 | } | ||
38 | |||
39 | int unmap(int fd, void *addr, unsigned long len) | ||
40 | { | ||
41 | struct proc_mm_op unmap; | ||
42 | int n; | ||
43 | |||
44 | unmap = ((struct proc_mm_op) { .op = MM_MUNMAP, | ||
45 | .u = | ||
46 | { .munmap = | ||
47 | { .addr = (unsigned long) addr, | ||
48 | .len = len } } } ); | ||
49 | n = os_write_file(fd, &unmap, sizeof(unmap)); | ||
50 | if(n != sizeof(unmap)) { | ||
51 | if(n < 0) | ||
52 | return(n); | ||
53 | else if(n > 0) | ||
54 | return(-EIO); | ||
55 | } | ||
56 | |||
57 | return(0); | ||
58 | } | ||
59 | |||
60 | int protect(int fd, unsigned long addr, unsigned long len, int r, int w, | ||
61 | int x, int must_succeed) | ||
62 | { | ||
63 | struct proc_mm_op protect; | ||
64 | int prot, n; | ||
65 | |||
66 | prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | | ||
67 | (x ? PROT_EXEC : 0); | ||
68 | |||
69 | protect = ((struct proc_mm_op) { .op = MM_MPROTECT, | ||
70 | .u = | ||
71 | { .mprotect = | ||
72 | { .addr = (unsigned long) addr, | ||
73 | .len = len, | ||
74 | .prot = prot } } } ); | ||
75 | |||
76 | n = os_write_file(fd, &protect, sizeof(protect)); | ||
77 | if(n != sizeof(protect)) { | ||
78 | if(n == 0) return(0); | ||
79 | |||
80 | if(must_succeed) | ||
81 | panic("protect failed, err = %d", -n); | ||
82 | |||
83 | return(-EIO); | ||
84 | } | ||
85 | |||
86 | return(0); | ||
87 | } | ||
88 | |||
89 | void before_mem_skas(unsigned long unused) | ||
90 | { | ||
91 | } | ||
92 | |||
93 | /* | ||
94 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
95 | * Emacs will notice this stuff at the end of the file and automatically | ||
96 | * adjust the settings for this buffer only. This must remain at the end | ||
97 | * of the file. | ||
98 | * --------------------------------------------------------------------------- | ||
99 | * Local variables: | ||
100 | * c-file-style: "linux" | ||
101 | * End: | ||
102 | */ | ||
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c new file mode 100644 index 000000000000..6cb9a6d028a9 --- /dev/null +++ b/arch/um/kernel/skas/mmu.c | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include "linux/sched.h" | ||
7 | #include "linux/list.h" | ||
8 | #include "linux/spinlock.h" | ||
9 | #include "linux/slab.h" | ||
10 | #include "asm/current.h" | ||
11 | #include "asm/segment.h" | ||
12 | #include "asm/mmu.h" | ||
13 | #include "os.h" | ||
14 | #include "skas.h" | ||
15 | |||
16 | int init_new_context_skas(struct task_struct *task, struct mm_struct *mm) | ||
17 | { | ||
18 | int from; | ||
19 | |||
20 | if((current->mm != NULL) && (current->mm != &init_mm)) | ||
21 | from = current->mm->context.skas.mm_fd; | ||
22 | else from = -1; | ||
23 | |||
24 | mm->context.skas.mm_fd = new_mm(from); | ||
25 | if(mm->context.skas.mm_fd < 0){ | ||
26 | printk("init_new_context_skas - new_mm failed, errno = %d\n", | ||
27 | mm->context.skas.mm_fd); | ||
28 | return(mm->context.skas.mm_fd); | ||
29 | } | ||
30 | |||
31 | return(0); | ||
32 | } | ||
33 | |||
34 | void destroy_context_skas(struct mm_struct *mm) | ||
35 | { | ||
36 | os_close_file(mm->context.skas.mm_fd); | ||
37 | } | ||
38 | |||
39 | /* | ||
40 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
41 | * Emacs will notice this stuff at the end of the file and automatically | ||
42 | * adjust the settings for this buffer only. This must remain at the end | ||
43 | * of the file. | ||
44 | * --------------------------------------------------------------------------- | ||
45 | * Local variables: | ||
46 | * c-file-style: "linux" | ||
47 | * End: | ||
48 | */ | ||
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c new file mode 100644 index 000000000000..b4ffaaa81241 --- /dev/null +++ b/arch/um/kernel/skas/process.c | |||
@@ -0,0 +1,339 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <stdlib.h> | ||
7 | #include <unistd.h> | ||
8 | #include <errno.h> | ||
9 | #include <signal.h> | ||
10 | #include <setjmp.h> | ||
11 | #include <sched.h> | ||
12 | #include <sys/wait.h> | ||
13 | #include <sys/mman.h> | ||
14 | #include <sys/user.h> | ||
15 | #include <asm/unistd.h> | ||
16 | #include "user.h" | ||
17 | #include "ptrace_user.h" | ||
18 | #include "time_user.h" | ||
19 | #include "sysdep/ptrace.h" | ||
20 | #include "user_util.h" | ||
21 | #include "kern_util.h" | ||
22 | #include "skas.h" | ||
23 | #include "sysdep/sigcontext.h" | ||
24 | #include "os.h" | ||
25 | #include "proc_mm.h" | ||
26 | #include "skas_ptrace.h" | ||
27 | #include "chan_user.h" | ||
28 | #include "signal_user.h" | ||
29 | #include "registers.h" | ||
30 | |||
31 | int is_skas_winch(int pid, int fd, void *data) | ||
32 | { | ||
33 | if(pid != os_getpid()) | ||
34 | return(0); | ||
35 | |||
36 | register_winch_irq(-1, fd, -1, data); | ||
37 | return(1); | ||
38 | } | ||
39 | |||
40 | static void handle_segv(int pid) | ||
41 | { | ||
42 | struct ptrace_faultinfo fault; | ||
43 | int err; | ||
44 | |||
45 | err = ptrace(PTRACE_FAULTINFO, pid, 0, &fault); | ||
46 | if(err) | ||
47 | panic("handle_segv - PTRACE_FAULTINFO failed, errno = %d\n", | ||
48 | errno); | ||
49 | |||
50 | segv(fault.addr, 0, FAULT_WRITE(fault.is_write), 1, NULL); | ||
51 | } | ||
52 | |||
53 | /*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/ | ||
54 | static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu) | ||
55 | { | ||
56 | int err, status; | ||
57 | |||
58 | /* Mark this as a syscall */ | ||
59 | UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->skas.regs); | ||
60 | |||
61 | if (!local_using_sysemu) | ||
62 | { | ||
63 | err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid); | ||
64 | if(err < 0) | ||
65 | panic("handle_trap - nullifying syscall failed errno = %d\n", | ||
66 | errno); | ||
67 | |||
68 | err = ptrace(PTRACE_SYSCALL, pid, 0, 0); | ||
69 | if(err < 0) | ||
70 | panic("handle_trap - continuing to end of syscall failed, " | ||
71 | "errno = %d\n", errno); | ||
72 | |||
73 | CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); | ||
74 | if((err < 0) || !WIFSTOPPED(status) || | ||
75 | (WSTOPSIG(status) != SIGTRAP + 0x80)) | ||
76 | panic("handle_trap - failed to wait at end of syscall, " | ||
77 | "errno = %d, status = %d\n", errno, status); | ||
78 | } | ||
79 | |||
80 | handle_syscall(regs); | ||
81 | } | ||
82 | |||
83 | static int userspace_tramp(void *arg) | ||
84 | { | ||
85 | init_new_thread_signals(0); | ||
86 | enable_timer(); | ||
87 | ptrace(PTRACE_TRACEME, 0, 0, 0); | ||
88 | os_stop_process(os_getpid()); | ||
89 | return(0); | ||
90 | } | ||
91 | |||
92 | /* Each element set once, and only accessed by a single processor anyway */ | ||
93 | #undef NR_CPUS | ||
94 | #define NR_CPUS 1 | ||
95 | int userspace_pid[NR_CPUS]; | ||
96 | |||
97 | void start_userspace(int cpu) | ||
98 | { | ||
99 | void *stack; | ||
100 | unsigned long sp; | ||
101 | int pid, status, n; | ||
102 | |||
103 | stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, | ||
104 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); | ||
105 | if(stack == MAP_FAILED) | ||
106 | panic("start_userspace : mmap failed, errno = %d", errno); | ||
107 | sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *); | ||
108 | |||
109 | pid = clone(userspace_tramp, (void *) sp, | ||
110 | CLONE_FILES | CLONE_VM | SIGCHLD, NULL); | ||
111 | if(pid < 0) | ||
112 | panic("start_userspace : clone failed, errno = %d", errno); | ||
113 | |||
114 | do { | ||
115 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); | ||
116 | if(n < 0) | ||
117 | panic("start_userspace : wait failed, errno = %d", | ||
118 | errno); | ||
119 | } while(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM)); | ||
120 | |||
121 | if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) | ||
122 | panic("start_userspace : expected SIGSTOP, got status = %d", | ||
123 | status); | ||
124 | |||
125 | if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, (void *)PTRACE_O_TRACESYSGOOD) < 0) | ||
126 | panic("start_userspace : PTRACE_SETOPTIONS failed, errno=%d\n", | ||
127 | errno); | ||
128 | |||
129 | if(munmap(stack, PAGE_SIZE) < 0) | ||
130 | panic("start_userspace : munmap failed, errno = %d\n", errno); | ||
131 | |||
132 | userspace_pid[cpu] = pid; | ||
133 | } | ||
134 | |||
135 | void userspace(union uml_pt_regs *regs) | ||
136 | { | ||
137 | int err, status, op, pid = userspace_pid[0]; | ||
138 | int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/ | ||
139 | |||
140 | while(1){ | ||
141 | restore_registers(pid, regs); | ||
142 | |||
143 | /* Now we set local_using_sysemu to be used for one loop */ | ||
144 | local_using_sysemu = get_using_sysemu(); | ||
145 | |||
146 | op = SELECT_PTRACE_OPERATION(local_using_sysemu, singlestepping(NULL)); | ||
147 | |||
148 | err = ptrace(op, pid, 0, 0); | ||
149 | if(err) | ||
150 | panic("userspace - could not resume userspace process, " | ||
151 | "pid=%d, ptrace operation = %d, errno = %d\n", | ||
152 | op, errno); | ||
153 | |||
154 | CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); | ||
155 | if(err < 0) | ||
156 | panic("userspace - waitpid failed, errno = %d\n", | ||
157 | errno); | ||
158 | |||
159 | regs->skas.is_user = 1; | ||
160 | save_registers(pid, regs); | ||
161 | UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */ | ||
162 | |||
163 | if(WIFSTOPPED(status)){ | ||
164 | switch(WSTOPSIG(status)){ | ||
165 | case SIGSEGV: | ||
166 | handle_segv(pid); | ||
167 | break; | ||
168 | case SIGTRAP + 0x80: | ||
169 | handle_trap(pid, regs, local_using_sysemu); | ||
170 | break; | ||
171 | case SIGTRAP: | ||
172 | relay_signal(SIGTRAP, regs); | ||
173 | break; | ||
174 | case SIGIO: | ||
175 | case SIGVTALRM: | ||
176 | case SIGILL: | ||
177 | case SIGBUS: | ||
178 | case SIGFPE: | ||
179 | case SIGWINCH: | ||
180 | user_signal(WSTOPSIG(status), regs); | ||
181 | break; | ||
182 | default: | ||
183 | printk("userspace - child stopped with signal " | ||
184 | "%d\n", WSTOPSIG(status)); | ||
185 | } | ||
186 | interrupt_end(); | ||
187 | |||
188 | /* Avoid -ERESTARTSYS handling in host */ | ||
189 | PT_SYSCALL_NR(regs->skas.regs) = -1; | ||
190 | } | ||
191 | } | ||
192 | } | ||
193 | |||
194 | void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, | ||
195 | void (*handler)(int)) | ||
196 | { | ||
197 | unsigned long flags; | ||
198 | sigjmp_buf switch_buf, fork_buf; | ||
199 | |||
200 | *switch_buf_ptr = &switch_buf; | ||
201 | *fork_buf_ptr = &fork_buf; | ||
202 | |||
203 | /* Somewhat subtle - siglongjmp restores the signal mask before doing | ||
204 | * the longjmp. This means that when jumping from one stack to another | ||
205 | * when the target stack has interrupts enabled, an interrupt may occur | ||
206 | * on the source stack. This is bad when starting up a process because | ||
207 | * it's not supposed to get timer ticks until it has been scheduled. | ||
208 | * So, we disable interrupts around the sigsetjmp to ensure that | ||
209 | * they can't happen until we get back here where they are safe. | ||
210 | */ | ||
211 | flags = get_signals(); | ||
212 | block_signals(); | ||
213 | if(sigsetjmp(fork_buf, 1) == 0) | ||
214 | new_thread_proc(stack, handler); | ||
215 | |||
216 | remove_sigstack(); | ||
217 | |||
218 | set_signals(flags); | ||
219 | } | ||
220 | |||
221 | void thread_wait(void *sw, void *fb) | ||
222 | { | ||
223 | sigjmp_buf buf, **switch_buf = sw, *fork_buf; | ||
224 | |||
225 | *switch_buf = &buf; | ||
226 | fork_buf = fb; | ||
227 | if(sigsetjmp(buf, 1) == 0) | ||
228 | siglongjmp(*fork_buf, 1); | ||
229 | } | ||
230 | |||
231 | void switch_threads(void *me, void *next) | ||
232 | { | ||
233 | sigjmp_buf my_buf, **me_ptr = me, *next_buf = next; | ||
234 | |||
235 | *me_ptr = &my_buf; | ||
236 | if(sigsetjmp(my_buf, 1) == 0) | ||
237 | siglongjmp(*next_buf, 1); | ||
238 | } | ||
239 | |||
240 | static sigjmp_buf initial_jmpbuf; | ||
241 | |||
242 | /* XXX Make these percpu */ | ||
243 | static void (*cb_proc)(void *arg); | ||
244 | static void *cb_arg; | ||
245 | static sigjmp_buf *cb_back; | ||
246 | |||
247 | int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) | ||
248 | { | ||
249 | sigjmp_buf **switch_buf = switch_buf_ptr; | ||
250 | int n; | ||
251 | |||
252 | *fork_buf_ptr = &initial_jmpbuf; | ||
253 | n = sigsetjmp(initial_jmpbuf, 1); | ||
254 | if(n == 0) | ||
255 | new_thread_proc((void *) stack, new_thread_handler); | ||
256 | else if(n == 1) | ||
257 | remove_sigstack(); | ||
258 | else if(n == 2){ | ||
259 | (*cb_proc)(cb_arg); | ||
260 | siglongjmp(*cb_back, 1); | ||
261 | } | ||
262 | else if(n == 3){ | ||
263 | kmalloc_ok = 0; | ||
264 | return(0); | ||
265 | } | ||
266 | else if(n == 4){ | ||
267 | kmalloc_ok = 0; | ||
268 | return(1); | ||
269 | } | ||
270 | siglongjmp(**switch_buf, 1); | ||
271 | } | ||
272 | |||
273 | void remove_sigstack(void) | ||
274 | { | ||
275 | stack_t stack = ((stack_t) { .ss_flags = SS_DISABLE, | ||
276 | .ss_sp = NULL, | ||
277 | .ss_size = 0 }); | ||
278 | |||
279 | if(sigaltstack(&stack, NULL) != 0) | ||
280 | panic("disabling signal stack failed, errno = %d\n", errno); | ||
281 | } | ||
282 | |||
283 | void initial_thread_cb_skas(void (*proc)(void *), void *arg) | ||
284 | { | ||
285 | sigjmp_buf here; | ||
286 | |||
287 | cb_proc = proc; | ||
288 | cb_arg = arg; | ||
289 | cb_back = &here; | ||
290 | |||
291 | block_signals(); | ||
292 | if(sigsetjmp(here, 1) == 0) | ||
293 | siglongjmp(initial_jmpbuf, 2); | ||
294 | unblock_signals(); | ||
295 | |||
296 | cb_proc = NULL; | ||
297 | cb_arg = NULL; | ||
298 | cb_back = NULL; | ||
299 | } | ||
300 | |||
301 | void halt_skas(void) | ||
302 | { | ||
303 | block_signals(); | ||
304 | siglongjmp(initial_jmpbuf, 3); | ||
305 | } | ||
306 | |||
307 | void reboot_skas(void) | ||
308 | { | ||
309 | block_signals(); | ||
310 | siglongjmp(initial_jmpbuf, 4); | ||
311 | } | ||
312 | |||
313 | void switch_mm_skas(int mm_fd) | ||
314 | { | ||
315 | int err; | ||
316 | |||
317 | #warning need cpu pid in switch_mm_skas | ||
318 | err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, mm_fd); | ||
319 | if(err) | ||
320 | panic("switch_mm_skas - PTRACE_SWITCH_MM failed, errno = %d\n", | ||
321 | errno); | ||
322 | } | ||
323 | |||
324 | void kill_off_processes_skas(void) | ||
325 | { | ||
326 | #warning need to loop over userspace_pids in kill_off_processes_skas | ||
327 | os_kill_ptraced_process(userspace_pid[0], 1); | ||
328 | } | ||
329 | |||
330 | /* | ||
331 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
332 | * Emacs will notice this stuff at the end of the file and automatically | ||
333 | * adjust the settings for this buffer only. This must remain at the end | ||
334 | * of the file. | ||
335 | * --------------------------------------------------------------------------- | ||
336 | * Local variables: | ||
337 | * c-file-style: "linux" | ||
338 | * End: | ||
339 | */ | ||
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c new file mode 100644 index 000000000000..5d096ea63b97 --- /dev/null +++ b/arch/um/kernel/skas/process_kern.c | |||
@@ -0,0 +1,213 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include "linux/sched.h" | ||
7 | #include "linux/slab.h" | ||
8 | #include "linux/ptrace.h" | ||
9 | #include "linux/proc_fs.h" | ||
10 | #include "linux/file.h" | ||
11 | #include "linux/errno.h" | ||
12 | #include "linux/init.h" | ||
13 | #include "asm/uaccess.h" | ||
14 | #include "asm/atomic.h" | ||
15 | #include "kern_util.h" | ||
16 | #include "time_user.h" | ||
17 | #include "signal_user.h" | ||
18 | #include "skas.h" | ||
19 | #include "os.h" | ||
20 | #include "user_util.h" | ||
21 | #include "tlb.h" | ||
22 | #include "kern.h" | ||
23 | #include "mode.h" | ||
24 | #include "proc_mm.h" | ||
25 | #include "registers.h" | ||
26 | |||
27 | void *switch_to_skas(void *prev, void *next) | ||
28 | { | ||
29 | struct task_struct *from, *to; | ||
30 | |||
31 | from = prev; | ||
32 | to = next; | ||
33 | |||
34 | /* XXX need to check runqueues[cpu].idle */ | ||
35 | if(current->pid == 0) | ||
36 | switch_timers(0); | ||
37 | |||
38 | to->thread.prev_sched = from; | ||
39 | set_current(to); | ||
40 | |||
41 | switch_threads(&from->thread.mode.skas.switch_buf, | ||
42 | to->thread.mode.skas.switch_buf); | ||
43 | |||
44 | if(current->pid == 0) | ||
45 | switch_timers(1); | ||
46 | |||
47 | return(current->thread.prev_sched); | ||
48 | } | ||
49 | |||
50 | extern void schedule_tail(struct task_struct *prev); | ||
51 | |||
52 | void new_thread_handler(int sig) | ||
53 | { | ||
54 | int (*fn)(void *), n; | ||
55 | void *arg; | ||
56 | |||
57 | fn = current->thread.request.u.thread.proc; | ||
58 | arg = current->thread.request.u.thread.arg; | ||
59 | change_sig(SIGUSR1, 1); | ||
60 | thread_wait(¤t->thread.mode.skas.switch_buf, | ||
61 | current->thread.mode.skas.fork_buf); | ||
62 | |||
63 | if(current->thread.prev_sched != NULL) | ||
64 | schedule_tail(current->thread.prev_sched); | ||
65 | current->thread.prev_sched = NULL; | ||
66 | |||
67 | /* The return value is 1 if the kernel thread execs a process, | ||
68 | * 0 if it just exits | ||
69 | */ | ||
70 | n = run_kernel_thread(fn, arg, ¤t->thread.exec_buf); | ||
71 | if(n == 1) | ||
72 | userspace(¤t->thread.regs.regs); | ||
73 | else do_exit(0); | ||
74 | } | ||
75 | |||
76 | void new_thread_proc(void *stack, void (*handler)(int sig)) | ||
77 | { | ||
78 | init_new_thread_stack(stack, handler); | ||
79 | os_usr1_process(os_getpid()); | ||
80 | } | ||
81 | |||
82 | void release_thread_skas(struct task_struct *task) | ||
83 | { | ||
84 | } | ||
85 | |||
86 | void exit_thread_skas(void) | ||
87 | { | ||
88 | } | ||
89 | |||
90 | void fork_handler(int sig) | ||
91 | { | ||
92 | change_sig(SIGUSR1, 1); | ||
93 | thread_wait(¤t->thread.mode.skas.switch_buf, | ||
94 | current->thread.mode.skas.fork_buf); | ||
95 | |||
96 | force_flush_all(); | ||
97 | if(current->thread.prev_sched == NULL) | ||
98 | panic("blech"); | ||
99 | |||
100 | schedule_tail(current->thread.prev_sched); | ||
101 | current->thread.prev_sched = NULL; | ||
102 | |||
103 | userspace(¤t->thread.regs.regs); | ||
104 | } | ||
105 | |||
106 | int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp, | ||
107 | unsigned long stack_top, struct task_struct * p, | ||
108 | struct pt_regs *regs) | ||
109 | { | ||
110 | void (*handler)(int); | ||
111 | |||
112 | if(current->thread.forking){ | ||
113 | memcpy(&p->thread.regs.regs.skas, | ||
114 | ¤t->thread.regs.regs.skas, | ||
115 | sizeof(p->thread.regs.regs.skas)); | ||
116 | REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0); | ||
117 | if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp; | ||
118 | |||
119 | handler = fork_handler; | ||
120 | } | ||
121 | else { | ||
122 | init_thread_registers(&p->thread.regs.regs); | ||
123 | p->thread.request.u.thread = current->thread.request.u.thread; | ||
124 | handler = new_thread_handler; | ||
125 | } | ||
126 | |||
127 | new_thread(p->thread_info, &p->thread.mode.skas.switch_buf, | ||
128 | &p->thread.mode.skas.fork_buf, handler); | ||
129 | return(0); | ||
130 | } | ||
131 | |||
132 | int new_mm(int from) | ||
133 | { | ||
134 | struct proc_mm_op copy; | ||
135 | int n, fd; | ||
136 | |||
137 | fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0); | ||
138 | if(fd < 0) | ||
139 | return(fd); | ||
140 | |||
141 | if(from != -1){ | ||
142 | copy = ((struct proc_mm_op) { .op = MM_COPY_SEGMENTS, | ||
143 | .u = | ||
144 | { .copy_segments = from } } ); | ||
145 | n = os_write_file(fd, ©, sizeof(copy)); | ||
146 | if(n != sizeof(copy)) | ||
147 | printk("new_mm : /proc/mm copy_segments failed, " | ||
148 | "err = %d\n", -n); | ||
149 | } | ||
150 | |||
151 | return(fd); | ||
152 | } | ||
153 | |||
154 | void init_idle_skas(void) | ||
155 | { | ||
156 | cpu_tasks[current_thread->cpu].pid = os_getpid(); | ||
157 | default_idle(); | ||
158 | } | ||
159 | |||
160 | extern void start_kernel(void); | ||
161 | |||
162 | static int start_kernel_proc(void *unused) | ||
163 | { | ||
164 | int pid; | ||
165 | |||
166 | block_signals(); | ||
167 | pid = os_getpid(); | ||
168 | |||
169 | cpu_tasks[0].pid = pid; | ||
170 | cpu_tasks[0].task = current; | ||
171 | #ifdef CONFIG_SMP | ||
172 | cpu_online_map = cpumask_of_cpu(0); | ||
173 | #endif | ||
174 | start_kernel(); | ||
175 | return(0); | ||
176 | } | ||
177 | |||
178 | int start_uml_skas(void) | ||
179 | { | ||
180 | start_userspace(0); | ||
181 | |||
182 | init_new_thread_signals(1); | ||
183 | uml_idle_timer(); | ||
184 | |||
185 | init_task.thread.request.u.thread.proc = start_kernel_proc; | ||
186 | init_task.thread.request.u.thread.arg = NULL; | ||
187 | return(start_idle_thread(init_task.thread_info, | ||
188 | &init_task.thread.mode.skas.switch_buf, | ||
189 | &init_task.thread.mode.skas.fork_buf)); | ||
190 | } | ||
191 | |||
192 | int external_pid_skas(struct task_struct *task) | ||
193 | { | ||
194 | #warning Need to look up userspace_pid by cpu | ||
195 | return(userspace_pid[0]); | ||
196 | } | ||
197 | |||
198 | int thread_pid_skas(struct task_struct *task) | ||
199 | { | ||
200 | #warning Need to look up userspace_pid by cpu | ||
201 | return(userspace_pid[0]); | ||
202 | } | ||
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/skas/syscall_kern.c b/arch/um/kernel/skas/syscall_kern.c new file mode 100644 index 000000000000..bdf040ce5b8e --- /dev/null +++ b/arch/um/kernel/skas/syscall_kern.c | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include "linux/sys.h" | ||
7 | #include "linux/ptrace.h" | ||
8 | #include "asm/errno.h" | ||
9 | #include "asm/unistd.h" | ||
10 | #include "asm/ptrace.h" | ||
11 | #include "asm/current.h" | ||
12 | #include "sysdep/syscalls.h" | ||
13 | #include "kern_util.h" | ||
14 | |||
15 | extern syscall_handler_t *sys_call_table[]; | ||
16 | |||
17 | long execute_syscall_skas(void *r) | ||
18 | { | ||
19 | struct pt_regs *regs = r; | ||
20 | long res; | ||
21 | int syscall; | ||
22 | |||
23 | current->thread.nsyscalls++; | ||
24 | nsyscalls++; | ||
25 | syscall = UPT_SYSCALL_NR(®s->regs); | ||
26 | |||
27 | if((syscall >= NR_syscalls) || (syscall < 0)) | ||
28 | res = -ENOSYS; | ||
29 | else res = EXECUTE_SYSCALL(syscall, regs); | ||
30 | |||
31 | return(res); | ||
32 | } | ||
33 | |||
34 | /* | ||
35 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
36 | * Emacs will notice this stuff at the end of the file and automatically | ||
37 | * adjust the settings for this buffer only. This must remain at the end | ||
38 | * of the file. | ||
39 | * --------------------------------------------------------------------------- | ||
40 | * Local variables: | ||
41 | * c-file-style: "linux" | ||
42 | * End: | ||
43 | */ | ||
diff --git a/arch/um/kernel/skas/syscall_user.c b/arch/um/kernel/skas/syscall_user.c new file mode 100644 index 000000000000..2828e6e37721 --- /dev/null +++ b/arch/um/kernel/skas/syscall_user.c | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <stdlib.h> | ||
7 | #include <signal.h> | ||
8 | #include "kern_util.h" | ||
9 | #include "uml-config.h" | ||
10 | #include "syscall_user.h" | ||
11 | #include "sysdep/ptrace.h" | ||
12 | #include "sysdep/sigcontext.h" | ||
13 | #include "skas.h" | ||
14 | |||
15 | void handle_syscall(union uml_pt_regs *regs) | ||
16 | { | ||
17 | long result; | ||
18 | #if UML_CONFIG_SYSCALL_DEBUG | ||
19 | int index; | ||
20 | |||
21 | index = record_syscall_start(UPT_SYSCALL_NR(regs)); | ||
22 | #endif | ||
23 | |||
24 | syscall_trace(regs, 0); | ||
25 | result = execute_syscall_skas(regs); | ||
26 | |||
27 | REGS_SET_SYSCALL_RETURN(regs->skas.regs, result); | ||
28 | |||
29 | syscall_trace(regs, 1); | ||
30 | #if UML_CONFIG_SYSCALL_DEBUG | ||
31 | record_syscall_end(index, result); | ||
32 | #endif | ||
33 | } | ||
34 | |||
35 | /* | ||
36 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
37 | * Emacs will notice this stuff at the end of the file and automatically | ||
38 | * adjust the settings for this buffer only. This must remain at the end | ||
39 | * of the file. | ||
40 | * --------------------------------------------------------------------------- | ||
41 | * Local variables: | ||
42 | * c-file-style: "linux" | ||
43 | * End: | ||
44 | */ | ||
diff --git a/arch/um/kernel/skas/time.c b/arch/um/kernel/skas/time.c new file mode 100644 index 000000000000..98091494b897 --- /dev/null +++ b/arch/um/kernel/skas/time.c | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <sys/signal.h> | ||
7 | #include <sys/time.h> | ||
8 | #include "time_user.h" | ||
9 | #include "process.h" | ||
10 | #include "user.h" | ||
11 | |||
12 | void user_time_init_skas(void) | ||
13 | { | ||
14 | if(signal(SIGALRM, (__sighandler_t) alarm_handler) == SIG_ERR) | ||
15 | panic("Couldn't set SIGALRM handler"); | ||
16 | if(signal(SIGVTALRM, (__sighandler_t) alarm_handler) == SIG_ERR) | ||
17 | panic("Couldn't set SIGVTALRM handler"); | ||
18 | set_interval(ITIMER_VIRTUAL); | ||
19 | } | ||
20 | |||
21 | /* | ||
22 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
23 | * Emacs will notice this stuff at the end of the file and automatically | ||
24 | * adjust the settings for this buffer only. This must remain at the end | ||
25 | * of the file. | ||
26 | * --------------------------------------------------------------------------- | ||
27 | * Local variables: | ||
28 | * c-file-style: "linux" | ||
29 | * End: | ||
30 | */ | ||
diff --git a/arch/um/kernel/skas/tlb.c b/arch/um/kernel/skas/tlb.c new file mode 100644 index 000000000000..b8c5e71763d1 --- /dev/null +++ b/arch/um/kernel/skas/tlb.c | |||
@@ -0,0 +1,85 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Copyright 2003 PathScale, Inc. | ||
4 | * Licensed under the GPL | ||
5 | */ | ||
6 | |||
7 | #include "linux/stddef.h" | ||
8 | #include "linux/sched.h" | ||
9 | #include "linux/mm.h" | ||
10 | #include "asm/page.h" | ||
11 | #include "asm/pgtable.h" | ||
12 | #include "asm/mmu.h" | ||
13 | #include "user_util.h" | ||
14 | #include "mem_user.h" | ||
15 | #include "mem.h" | ||
16 | #include "skas.h" | ||
17 | #include "os.h" | ||
18 | #include "tlb.h" | ||
19 | |||
20 | static void do_ops(int fd, struct host_vm_op *ops, int last) | ||
21 | { | ||
22 | struct host_vm_op *op; | ||
23 | int i; | ||
24 | |||
25 | for(i = 0; i <= last; i++){ | ||
26 | op = &ops[i]; | ||
27 | switch(op->type){ | ||
28 | case MMAP: | ||
29 | map(fd, op->u.mmap.addr, op->u.mmap.len, | ||
30 | op->u.mmap.r, op->u.mmap.w, op->u.mmap.x, | ||
31 | op->u.mmap.fd, op->u.mmap.offset); | ||
32 | break; | ||
33 | case MUNMAP: | ||
34 | unmap(fd, (void *) op->u.munmap.addr, | ||
35 | op->u.munmap.len); | ||
36 | break; | ||
37 | case MPROTECT: | ||
38 | protect(fd, op->u.mprotect.addr, op->u.mprotect.len, | ||
39 | op->u.mprotect.r, op->u.mprotect.w, | ||
40 | op->u.mprotect.x); | ||
41 | break; | ||
42 | default: | ||
43 | printk("Unknown op type %d in do_ops\n", op->type); | ||
44 | break; | ||
45 | } | ||
46 | } | ||
47 | } | ||
48 | |||
49 | static void fix_range(struct mm_struct *mm, unsigned long start_addr, | ||
50 | unsigned long end_addr, int force) | ||
51 | { | ||
52 | int fd = mm->context.skas.mm_fd; | ||
53 | |||
54 | fix_range_common(mm, start_addr, end_addr, force, fd, do_ops); | ||
55 | } | ||
56 | |||
57 | void __flush_tlb_one_skas(unsigned long addr) | ||
58 | { | ||
59 | flush_tlb_kernel_range_common(addr, addr + PAGE_SIZE); | ||
60 | } | ||
61 | |||
62 | void flush_tlb_range_skas(struct vm_area_struct *vma, unsigned long start, | ||
63 | unsigned long end) | ||
64 | { | ||
65 | if(vma->vm_mm == NULL) | ||
66 | flush_tlb_kernel_range_common(start, end); | ||
67 | else fix_range(vma->vm_mm, start, end, 0); | ||
68 | } | ||
69 | |||
70 | void flush_tlb_mm_skas(struct mm_struct *mm) | ||
71 | { | ||
72 | /* Don't bother flushing if this address space is about to be | ||
73 | * destroyed. | ||
74 | */ | ||
75 | if(atomic_read(&mm->mm_users) == 0) | ||
76 | return; | ||
77 | |||
78 | fix_range(mm, 0, host_task_size, 0); | ||
79 | flush_tlb_kernel_range_common(start_vm, end_vm); | ||
80 | } | ||
81 | |||
82 | void force_flush_all_skas(void) | ||
83 | { | ||
84 | fix_range(current->mm, 0, host_task_size, 1); | ||
85 | } | ||
diff --git a/arch/um/kernel/skas/trap_user.c b/arch/um/kernel/skas/trap_user.c new file mode 100644 index 000000000000..8e9b46d4702e --- /dev/null +++ b/arch/um/kernel/skas/trap_user.c | |||
@@ -0,0 +1,71 @@ | |||
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 "sysdep/ptrace.h" | ||
9 | #include "signal_user.h" | ||
10 | #include "user_util.h" | ||
11 | #include "kern_util.h" | ||
12 | #include "task.h" | ||
13 | #include "sigcontext.h" | ||
14 | |||
15 | void sig_handler_common_skas(int sig, void *sc_ptr) | ||
16 | { | ||
17 | struct sigcontext *sc = sc_ptr; | ||
18 | struct skas_regs *r; | ||
19 | struct signal_info *info; | ||
20 | int save_errno = errno; | ||
21 | int save_user; | ||
22 | |||
23 | /* This is done because to allow SIGSEGV to be delivered inside a SEGV | ||
24 | * handler. This can happen in copy_user, and if SEGV is disabled, | ||
25 | * the process will die. | ||
26 | * XXX Figure out why this is better than SA_NODEFER | ||
27 | */ | ||
28 | if(sig == SIGSEGV) | ||
29 | change_sig(SIGSEGV, 1); | ||
30 | |||
31 | r = &TASK_REGS(get_current())->skas; | ||
32 | save_user = r->is_user; | ||
33 | r->is_user = 0; | ||
34 | r->fault_addr = SC_FAULT_ADDR(sc); | ||
35 | r->fault_type = SC_FAULT_TYPE(sc); | ||
36 | r->trap_type = SC_TRAP_TYPE(sc); | ||
37 | |||
38 | change_sig(SIGUSR1, 1); | ||
39 | info = &sig_info[sig]; | ||
40 | if(!info->is_irq) unblock_signals(); | ||
41 | |||
42 | (*info->handler)(sig, (union uml_pt_regs *) r); | ||
43 | |||
44 | errno = save_errno; | ||
45 | r->is_user = save_user; | ||
46 | } | ||
47 | |||
48 | void user_signal(int sig, union uml_pt_regs *regs) | ||
49 | { | ||
50 | struct signal_info *info; | ||
51 | |||
52 | regs->skas.is_user = 1; | ||
53 | regs->skas.fault_addr = 0; | ||
54 | regs->skas.fault_type = 0; | ||
55 | regs->skas.trap_type = 0; | ||
56 | info = &sig_info[sig]; | ||
57 | (*info->handler)(sig, regs); | ||
58 | |||
59 | unblock_signals(); | ||
60 | } | ||
61 | |||
62 | /* | ||
63 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
64 | * Emacs will notice this stuff at the end of the file and automatically | ||
65 | * adjust the settings for this buffer only. This must remain at the end | ||
66 | * of the file. | ||
67 | * --------------------------------------------------------------------------- | ||
68 | * Local variables: | ||
69 | * c-file-style: "linux" | ||
70 | * End: | ||
71 | */ | ||
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c new file mode 100644 index 000000000000..7575ec489b63 --- /dev/null +++ b/arch/um/kernel/skas/uaccess.c | |||
@@ -0,0 +1,259 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include "linux/stddef.h" | ||
7 | #include "linux/kernel.h" | ||
8 | #include "linux/string.h" | ||
9 | #include "linux/fs.h" | ||
10 | #include "linux/highmem.h" | ||
11 | #include "asm/page.h" | ||
12 | #include "asm/pgtable.h" | ||
13 | #include "asm/uaccess.h" | ||
14 | #include "kern_util.h" | ||
15 | #include "user_util.h" | ||
16 | |||
17 | extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr, | ||
18 | pte_t *pte_out); | ||
19 | |||
20 | static unsigned long maybe_map(unsigned long virt, int is_write) | ||
21 | { | ||
22 | pte_t pte; | ||
23 | int err; | ||
24 | |||
25 | void *phys = um_virt_to_phys(current, virt, &pte); | ||
26 | int dummy_code; | ||
27 | |||
28 | if(IS_ERR(phys) || (is_write && !pte_write(pte))){ | ||
29 | err = handle_page_fault(virt, 0, is_write, 1, &dummy_code); | ||
30 | if(err) | ||
31 | return(0); | ||
32 | phys = um_virt_to_phys(current, virt, NULL); | ||
33 | } | ||
34 | return((unsigned long) phys); | ||
35 | } | ||
36 | |||
37 | static int do_op(unsigned long addr, int len, int is_write, | ||
38 | int (*op)(unsigned long addr, int len, void *arg), void *arg) | ||
39 | { | ||
40 | struct page *page; | ||
41 | int n; | ||
42 | |||
43 | addr = maybe_map(addr, is_write); | ||
44 | if(addr == -1) | ||
45 | return(-1); | ||
46 | |||
47 | page = phys_to_page(addr); | ||
48 | addr = (unsigned long) kmap(page) + (addr & ~PAGE_MASK); | ||
49 | n = (*op)(addr, len, arg); | ||
50 | kunmap(page); | ||
51 | |||
52 | return(n); | ||
53 | } | ||
54 | |||
55 | static void do_buffer_op(void *jmpbuf, void *arg_ptr) | ||
56 | { | ||
57 | va_list args; | ||
58 | unsigned long addr; | ||
59 | int len, is_write, size, remain, n; | ||
60 | int (*op)(unsigned long, int, void *); | ||
61 | void *arg; | ||
62 | int *res; | ||
63 | |||
64 | /* Some old gccs recognize __va_copy, but not va_copy */ | ||
65 | __va_copy(args, *(va_list *)arg_ptr); | ||
66 | addr = va_arg(args, unsigned long); | ||
67 | len = va_arg(args, int); | ||
68 | is_write = va_arg(args, int); | ||
69 | op = va_arg(args, void *); | ||
70 | arg = va_arg(args, void *); | ||
71 | res = va_arg(args, int *); | ||
72 | va_end(args); | ||
73 | size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len); | ||
74 | remain = len; | ||
75 | |||
76 | current->thread.fault_catcher = jmpbuf; | ||
77 | n = do_op(addr, size, is_write, op, arg); | ||
78 | if(n != 0){ | ||
79 | *res = (n < 0 ? remain : 0); | ||
80 | goto out; | ||
81 | } | ||
82 | |||
83 | addr += size; | ||
84 | remain -= size; | ||
85 | if(remain == 0){ | ||
86 | *res = 0; | ||
87 | goto out; | ||
88 | } | ||
89 | |||
90 | while(addr < ((addr + remain) & PAGE_MASK)){ | ||
91 | n = do_op(addr, PAGE_SIZE, is_write, op, arg); | ||
92 | if(n != 0){ | ||
93 | *res = (n < 0 ? remain : 0); | ||
94 | goto out; | ||
95 | } | ||
96 | |||
97 | addr += PAGE_SIZE; | ||
98 | remain -= PAGE_SIZE; | ||
99 | } | ||
100 | if(remain == 0){ | ||
101 | *res = 0; | ||
102 | goto out; | ||
103 | } | ||
104 | |||
105 | n = do_op(addr, remain, is_write, op, arg); | ||
106 | if(n != 0) | ||
107 | *res = (n < 0 ? remain : 0); | ||
108 | else *res = 0; | ||
109 | out: | ||
110 | current->thread.fault_catcher = NULL; | ||
111 | } | ||
112 | |||
113 | static int buffer_op(unsigned long addr, int len, int is_write, | ||
114 | int (*op)(unsigned long addr, int len, void *arg), | ||
115 | void *arg) | ||
116 | { | ||
117 | int faulted, res; | ||
118 | |||
119 | faulted = setjmp_wrapper(do_buffer_op, addr, len, is_write, op, arg, | ||
120 | &res); | ||
121 | if(!faulted) | ||
122 | return(res); | ||
123 | |||
124 | return(addr + len - (unsigned long) current->thread.fault_addr); | ||
125 | } | ||
126 | |||
127 | static int copy_chunk_from_user(unsigned long from, int len, void *arg) | ||
128 | { | ||
129 | unsigned long *to_ptr = arg, to = *to_ptr; | ||
130 | |||
131 | memcpy((void *) to, (void *) from, len); | ||
132 | *to_ptr += len; | ||
133 | return(0); | ||
134 | } | ||
135 | |||
136 | int copy_from_user_skas(void *to, const void __user *from, int n) | ||
137 | { | ||
138 | if(segment_eq(get_fs(), KERNEL_DS)){ | ||
139 | memcpy(to, (__force void*)from, n); | ||
140 | return(0); | ||
141 | } | ||
142 | |||
143 | return(access_ok_skas(VERIFY_READ, from, n) ? | ||
144 | buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to): | ||
145 | n); | ||
146 | } | ||
147 | |||
148 | static int copy_chunk_to_user(unsigned long to, int len, void *arg) | ||
149 | { | ||
150 | unsigned long *from_ptr = arg, from = *from_ptr; | ||
151 | |||
152 | memcpy((void *) to, (void *) from, len); | ||
153 | *from_ptr += len; | ||
154 | return(0); | ||
155 | } | ||
156 | |||
157 | int copy_to_user_skas(void __user *to, const void *from, int n) | ||
158 | { | ||
159 | if(segment_eq(get_fs(), KERNEL_DS)){ | ||
160 | memcpy((__force void*)to, from, n); | ||
161 | return(0); | ||
162 | } | ||
163 | |||
164 | return(access_ok_skas(VERIFY_WRITE, to, n) ? | ||
165 | buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) : | ||
166 | n); | ||
167 | } | ||
168 | |||
169 | static int strncpy_chunk_from_user(unsigned long from, int len, void *arg) | ||
170 | { | ||
171 | char **to_ptr = arg, *to = *to_ptr; | ||
172 | int n; | ||
173 | |||
174 | strncpy(to, (void *) from, len); | ||
175 | n = strnlen(to, len); | ||
176 | *to_ptr += n; | ||
177 | |||
178 | if(n < len) | ||
179 | return(1); | ||
180 | return(0); | ||
181 | } | ||
182 | |||
183 | int strncpy_from_user_skas(char *dst, const char __user *src, int count) | ||
184 | { | ||
185 | int n; | ||
186 | char *ptr = dst; | ||
187 | |||
188 | if(segment_eq(get_fs(), KERNEL_DS)){ | ||
189 | strncpy(dst, (__force void*)src, count); | ||
190 | return(strnlen(dst, count)); | ||
191 | } | ||
192 | |||
193 | if(!access_ok_skas(VERIFY_READ, src, 1)) | ||
194 | return(-EFAULT); | ||
195 | |||
196 | n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user, | ||
197 | &ptr); | ||
198 | if(n != 0) | ||
199 | return(-EFAULT); | ||
200 | return(strnlen(dst, count)); | ||
201 | } | ||
202 | |||
203 | static int clear_chunk(unsigned long addr, int len, void *unused) | ||
204 | { | ||
205 | memset((void *) addr, 0, len); | ||
206 | return(0); | ||
207 | } | ||
208 | |||
209 | int __clear_user_skas(void __user *mem, int len) | ||
210 | { | ||
211 | return(buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL)); | ||
212 | } | ||
213 | |||
214 | int clear_user_skas(void __user *mem, int len) | ||
215 | { | ||
216 | if(segment_eq(get_fs(), KERNEL_DS)){ | ||
217 | memset((__force void*)mem, 0, len); | ||
218 | return(0); | ||
219 | } | ||
220 | |||
221 | return(access_ok_skas(VERIFY_WRITE, mem, len) ? | ||
222 | buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len); | ||
223 | } | ||
224 | |||
225 | static int strnlen_chunk(unsigned long str, int len, void *arg) | ||
226 | { | ||
227 | int *len_ptr = arg, n; | ||
228 | |||
229 | n = strnlen((void *) str, len); | ||
230 | *len_ptr += n; | ||
231 | |||
232 | if(n < len) | ||
233 | return(1); | ||
234 | return(0); | ||
235 | } | ||
236 | |||
237 | int strnlen_user_skas(const void __user *str, int len) | ||
238 | { | ||
239 | int count = 0, n; | ||
240 | |||
241 | if(segment_eq(get_fs(), KERNEL_DS)) | ||
242 | return(strnlen((__force char*)str, len) + 1); | ||
243 | |||
244 | n = buffer_op((unsigned long) str, len, 0, strnlen_chunk, &count); | ||
245 | if(n == 0) | ||
246 | return(count + 1); | ||
247 | return(-EFAULT); | ||
248 | } | ||
249 | |||
250 | /* | ||
251 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
252 | * Emacs will notice this stuff at the end of the file and automatically | ||
253 | * adjust the settings for this buffer only. This must remain at the end | ||
254 | * of the file. | ||
255 | * --------------------------------------------------------------------------- | ||
256 | * Local variables: | ||
257 | * c-file-style: "linux" | ||
258 | * End: | ||
259 | */ | ||
diff --git a/arch/um/kernel/skas/util/Makefile b/arch/um/kernel/skas/util/Makefile new file mode 100644 index 000000000000..17f5909d60f7 --- /dev/null +++ b/arch/um/kernel/skas/util/Makefile | |||
@@ -0,0 +1,4 @@ | |||
1 | hostprogs-y := mk_ptregs | ||
2 | always := $(hostprogs-y) | ||
3 | |||
4 | mk_ptregs-objs := mk_ptregs-$(SUBARCH).o | ||
diff --git a/arch/um/kernel/skas/util/mk_ptregs-i386.c b/arch/um/kernel/skas/util/mk_ptregs-i386.c new file mode 100644 index 000000000000..0788dd05bcac --- /dev/null +++ b/arch/um/kernel/skas/util/mk_ptregs-i386.c | |||
@@ -0,0 +1,51 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <asm/ptrace.h> | ||
3 | #include <asm/user.h> | ||
4 | |||
5 | #define PRINT_REG(name, val) printf("#define HOST_%s %d\n", (name), (val)) | ||
6 | |||
7 | int main(int argc, char **argv) | ||
8 | { | ||
9 | printf("/* Automatically generated by " | ||
10 | "arch/um/kernel/skas/util/mk_ptregs */\n"); | ||
11 | printf("\n"); | ||
12 | printf("#ifndef __SKAS_PT_REGS_\n"); | ||
13 | printf("#define __SKAS_PT_REGS_\n"); | ||
14 | printf("\n"); | ||
15 | printf("#define HOST_FRAME_SIZE %d\n", FRAME_SIZE); | ||
16 | printf("#define HOST_FP_SIZE %d\n", | ||
17 | sizeof(struct user_i387_struct) / sizeof(unsigned long)); | ||
18 | printf("#define HOST_XFP_SIZE %d\n", | ||
19 | sizeof(struct user_fxsr_struct) / sizeof(unsigned long)); | ||
20 | |||
21 | PRINT_REG("IP", EIP); | ||
22 | PRINT_REG("SP", UESP); | ||
23 | PRINT_REG("EFLAGS", EFL); | ||
24 | PRINT_REG("EAX", EAX); | ||
25 | PRINT_REG("EBX", EBX); | ||
26 | PRINT_REG("ECX", ECX); | ||
27 | PRINT_REG("EDX", EDX); | ||
28 | PRINT_REG("ESI", ESI); | ||
29 | PRINT_REG("EDI", EDI); | ||
30 | PRINT_REG("EBP", EBP); | ||
31 | PRINT_REG("CS", CS); | ||
32 | PRINT_REG("SS", SS); | ||
33 | PRINT_REG("DS", DS); | ||
34 | PRINT_REG("FS", FS); | ||
35 | PRINT_REG("ES", ES); | ||
36 | PRINT_REG("GS", GS); | ||
37 | printf("\n"); | ||
38 | printf("#endif\n"); | ||
39 | return(0); | ||
40 | } | ||
41 | |||
42 | /* | ||
43 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
44 | * Emacs will notice this stuff at the end of the file and automatically | ||
45 | * adjust the settings for this buffer only. This must remain at the end | ||
46 | * of the file. | ||
47 | * --------------------------------------------------------------------------- | ||
48 | * Local variables: | ||
49 | * c-file-style: "linux" | ||
50 | * End: | ||
51 | */ | ||
diff --git a/arch/um/kernel/skas/util/mk_ptregs-x86_64.c b/arch/um/kernel/skas/util/mk_ptregs-x86_64.c new file mode 100644 index 000000000000..67aee92a70ef --- /dev/null +++ b/arch/um/kernel/skas/util/mk_ptregs-x86_64.c | |||
@@ -0,0 +1,68 @@ | |||
1 | /* | ||
2 | * Copyright 2003 PathScale, Inc. | ||
3 | * | ||
4 | * Licensed under the GPL | ||
5 | */ | ||
6 | |||
7 | #include <stdio.h> | ||
8 | #define __FRAME_OFFSETS | ||
9 | #include <asm/ptrace.h> | ||
10 | |||
11 | #define PRINT_REG(name, val) \ | ||
12 | printf("#define HOST_%s (%d / sizeof(unsigned long))\n", (name), (val)) | ||
13 | |||
14 | int main(int argc, char **argv) | ||
15 | { | ||
16 | printf("/* Automatically generated by " | ||
17 | "arch/um/kernel/skas/util/mk_ptregs */\n"); | ||
18 | printf("\n"); | ||
19 | printf("#ifndef __SKAS_PT_REGS_\n"); | ||
20 | printf("#define __SKAS_PT_REGS_\n"); | ||
21 | printf("#define HOST_FRAME_SIZE (%d / sizeof(unsigned long))\n", | ||
22 | FRAME_SIZE); | ||
23 | PRINT_REG("RBX", RBX); | ||
24 | PRINT_REG("RCX", RCX); | ||
25 | PRINT_REG("RDI", RDI); | ||
26 | PRINT_REG("RSI", RSI); | ||
27 | PRINT_REG("RDX", RDX); | ||
28 | PRINT_REG("RBP", RBP); | ||
29 | PRINT_REG("RAX", RAX); | ||
30 | PRINT_REG("R8", R8); | ||
31 | PRINT_REG("R9", R9); | ||
32 | PRINT_REG("R10", R10); | ||
33 | PRINT_REG("R11", R11); | ||
34 | PRINT_REG("R12", R12); | ||
35 | PRINT_REG("R13", R13); | ||
36 | PRINT_REG("R14", R14); | ||
37 | PRINT_REG("R15", R15); | ||
38 | PRINT_REG("ORIG_RAX", ORIG_RAX); | ||
39 | PRINT_REG("CS", CS); | ||
40 | PRINT_REG("SS", SS); | ||
41 | PRINT_REG("EFLAGS", EFLAGS); | ||
42 | #if 0 | ||
43 | PRINT_REG("FS", FS); | ||
44 | PRINT_REG("GS", GS); | ||
45 | PRINT_REG("DS", DS); | ||
46 | PRINT_REG("ES", ES); | ||
47 | #endif | ||
48 | |||
49 | PRINT_REG("IP", RIP); | ||
50 | PRINT_REG("SP", RSP); | ||
51 | printf("#define HOST_FP_SIZE 0\n"); | ||
52 | printf("#define HOST_XFP_SIZE 0\n"); | ||
53 | printf("\n"); | ||
54 | printf("\n"); | ||
55 | printf("#endif\n"); | ||
56 | return(0); | ||
57 | } | ||
58 | |||
59 | /* | ||
60 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
61 | * Emacs will notice this stuff at the end of the file and automatically | ||
62 | * adjust the settings for this buffer only. This must remain at the end | ||
63 | * of the file. | ||
64 | * --------------------------------------------------------------------------- | ||
65 | * Local variables: | ||
66 | * c-file-style: "linux" | ||
67 | * End: | ||
68 | */ | ||