diff options
author | Gennady Sharapov <Gennady.V.Sharapov@intel.com> | 2006-01-18 20:42:45 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-18 22:20:19 -0500 |
commit | f45d9fc9d80678c2ee22c578e503055207c46fd0 (patch) | |
tree | e67a7783c2866af94092801a519f04bb77109ade /arch/um | |
parent | 4abfbf4034b419736de5797a3860ab0bcf5c5c8d (diff) |
[PATCH] uml: move libc-dependent skas memory mapping code
The serial UML OS-abstraction layer patch (um/kernel/skas dir).
This moves all systemcalls from skas/mem_user.c file under os-Linux dir and
join skas/mem_user.c and skas/mem.c files.
Signed-off-by: Gennady Sharapov <gennady.v.sharapov@intel.com>
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/um')
-rw-r--r-- | arch/um/include/os.h | 17 | ||||
-rw-r--r-- | arch/um/include/skas/skas.h | 14 | ||||
-rw-r--r-- | arch/um/kernel/skas/Makefile | 4 | ||||
-rw-r--r-- | arch/um/os-Linux/skas/Makefile | 4 | ||||
-rw-r--r-- | arch/um/os-Linux/skas/mem.c (renamed from arch/um/kernel/skas/mem_user.c) | 202 |
5 files changed, 123 insertions, 118 deletions
diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 624938ad9e14..8006e085b675 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h | |||
@@ -11,6 +11,7 @@ | |||
11 | #include "../os/include/file.h" | 11 | #include "../os/include/file.h" |
12 | #include "sysdep/ptrace.h" | 12 | #include "sysdep/ptrace.h" |
13 | #include "kern_util.h" | 13 | #include "kern_util.h" |
14 | #include "skas/mm_id.h" | ||
14 | 15 | ||
15 | #define OS_TYPE_FILE 1 | 16 | #define OS_TYPE_FILE 1 |
16 | #define OS_TYPE_DIR 2 | 17 | #define OS_TYPE_DIR 2 |
@@ -255,4 +256,20 @@ extern void user_time_init(void); | |||
255 | extern void uml_idle_timer(void); | 256 | extern void uml_idle_timer(void); |
256 | extern unsigned long long os_nsecs(void); | 257 | extern unsigned long long os_nsecs(void); |
257 | 258 | ||
259 | /* skas/mem.c */ | ||
260 | extern long run_syscall_stub(struct mm_id * mm_idp, | ||
261 | int syscall, unsigned long *args, long expected, | ||
262 | void **addr, int done); | ||
263 | extern long syscall_stub_data(struct mm_id * mm_idp, | ||
264 | unsigned long *data, int data_count, | ||
265 | void **addr, void **stub_addr); | ||
266 | extern int map(struct mm_id * mm_idp, unsigned long virt, | ||
267 | unsigned long len, int r, int w, int x, int phys_fd, | ||
268 | unsigned long long offset, int done, void **data); | ||
269 | extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, | ||
270 | int done, void **data); | ||
271 | extern int protect(struct mm_id * mm_idp, unsigned long addr, | ||
272 | unsigned long len, int r, int w, int x, int done, | ||
273 | void **data); | ||
274 | |||
258 | #endif | 275 | #endif |
diff --git a/arch/um/include/skas/skas.h b/arch/um/include/skas/skas.h index 158f322248e3..7418f2addda2 100644 --- a/arch/um/include/skas/skas.h +++ b/arch/um/include/skas/skas.h | |||
@@ -24,14 +24,6 @@ extern void userspace(union uml_pt_regs *regs); | |||
24 | extern void new_thread_proc(void *stack, void (*handler)(int sig)); | 24 | extern void new_thread_proc(void *stack, void (*handler)(int sig)); |
25 | extern void new_thread_handler(int sig); | 25 | extern void new_thread_handler(int sig); |
26 | extern void handle_syscall(union uml_pt_regs *regs); | 26 | extern void handle_syscall(union uml_pt_regs *regs); |
27 | extern int map(struct mm_id * mm_idp, unsigned long virt, | ||
28 | unsigned long len, int r, int w, int x, int phys_fd, | ||
29 | unsigned long long offset, int done, void **data); | ||
30 | extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, | ||
31 | int done, void **data); | ||
32 | extern int protect(struct mm_id * mm_idp, unsigned long addr, | ||
33 | unsigned long len, int r, int w, int x, int done, | ||
34 | void **data); | ||
35 | extern void user_signal(int sig, union uml_pt_regs *regs, int pid); | 27 | extern void user_signal(int sig, union uml_pt_regs *regs, int pid); |
36 | extern int new_mm(unsigned long stack); | 28 | extern int new_mm(unsigned long stack); |
37 | extern int start_userspace(unsigned long stub_stack); | 29 | extern int start_userspace(unsigned long stub_stack); |
@@ -39,11 +31,5 @@ extern int copy_context_skas0(unsigned long stack, int pid); | |||
39 | extern void get_skas_faultinfo(int pid, struct faultinfo * fi); | 31 | extern void get_skas_faultinfo(int pid, struct faultinfo * fi); |
40 | extern long execute_syscall_skas(void *r); | 32 | extern long execute_syscall_skas(void *r); |
41 | extern unsigned long current_stub_stack(void); | 33 | extern unsigned long current_stub_stack(void); |
42 | extern long run_syscall_stub(struct mm_id * mm_idp, | ||
43 | int syscall, unsigned long *args, long expected, | ||
44 | void **addr, int done); | ||
45 | extern long syscall_stub_data(struct mm_id * mm_idp, | ||
46 | unsigned long *data, int data_count, | ||
47 | void **addr, void **stub_addr); | ||
48 | 34 | ||
49 | #endif | 35 | #endif |
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile index 7a9fc16d71d4..eb664c67c3f4 100644 --- a/arch/um/kernel/skas/Makefile +++ b/arch/um/kernel/skas/Makefile | |||
@@ -1,9 +1,9 @@ | |||
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 | ||
6 | obj-y := clone.o exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \ | 6 | obj-y := clone.o exec_kern.o mem.o mmu.o process.o process_kern.o \ |
7 | syscall.o tlb.o uaccess.o | 7 | syscall.o tlb.o uaccess.o |
8 | 8 | ||
9 | USER_OBJS := process.o clone.o | 9 | USER_OBJS := process.o clone.o |
diff --git a/arch/um/os-Linux/skas/Makefile b/arch/um/os-Linux/skas/Makefile index eab5386d60a7..79cc6c72aa92 100644 --- a/arch/um/os-Linux/skas/Makefile +++ b/arch/um/os-Linux/skas/Makefile | |||
@@ -3,8 +3,8 @@ | |||
3 | # Licensed under the GPL | 3 | # Licensed under the GPL |
4 | # | 4 | # |
5 | 5 | ||
6 | obj-y := trap.o | 6 | obj-y := mem.o trap.o |
7 | 7 | ||
8 | USER_OBJS := trap.o | 8 | USER_OBJS := mem.o trap.o |
9 | 9 | ||
10 | include arch/um/scripts/Makefile.rules | 10 | include arch/um/scripts/Makefile.rules |
diff --git a/arch/um/kernel/skas/mem_user.c b/arch/um/os-Linux/skas/mem.c index 1d89640bd502..9890e9090f58 100644 --- a/arch/um/kernel/skas/mem_user.c +++ b/arch/um/os-Linux/skas/mem.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 | */ |
@@ -32,7 +32,7 @@ extern void wait_stub_done(int pid, int sig, char * fname); | |||
32 | static inline unsigned long *check_init_stack(struct mm_id * mm_idp, | 32 | static inline unsigned long *check_init_stack(struct mm_id * mm_idp, |
33 | unsigned long *stack) | 33 | unsigned long *stack) |
34 | { | 34 | { |
35 | if(stack == NULL){ | 35 | if(stack == NULL) { |
36 | stack = (unsigned long *) mm_idp->stack + 2; | 36 | stack = (unsigned long *) mm_idp->stack + 2; |
37 | *stack = 0; | 37 | *stack = 0; |
38 | } | 38 | } |
@@ -45,13 +45,14 @@ int single_count = 0; | |||
45 | int multi_count = 0; | 45 | int multi_count = 0; |
46 | int multi_op_count = 0; | 46 | int multi_op_count = 0; |
47 | 47 | ||
48 | static long do_syscall_stub(struct mm_id *mm_idp, void **addr) | 48 | static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) |
49 | { | 49 | { |
50 | unsigned long regs[MAX_REG_NR]; | 50 | unsigned long regs[MAX_REG_NR]; |
51 | unsigned long *data; | 51 | int n; |
52 | unsigned long *syscall; | ||
53 | long ret, offset; | 52 | long ret, offset; |
54 | int n, pid = mm_idp->u.pid; | 53 | unsigned long * data; |
54 | unsigned long * syscall; | ||
55 | int pid = mm_idp->u.pid; | ||
55 | 56 | ||
56 | if(proc_mm) | 57 | if(proc_mm) |
57 | #warning Need to look up userspace_pid by cpu | 58 | #warning Need to look up userspace_pid by cpu |
@@ -59,10 +60,11 @@ static long do_syscall_stub(struct mm_id *mm_idp, void **addr) | |||
59 | 60 | ||
60 | multi_count++; | 61 | multi_count++; |
61 | 62 | ||
62 | get_safe_registers(regs); | 63 | get_safe_registers(regs); |
63 | regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + | 64 | regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + |
64 | ((unsigned long) &batch_syscall_stub - | 65 | ((unsigned long) &batch_syscall_stub - |
65 | (unsigned long) &__syscall_stub_start); | 66 | (unsigned long) &__syscall_stub_start); |
67 | |||
66 | n = ptrace_setregs(pid, regs); | 68 | n = ptrace_setregs(pid, regs); |
67 | if(n < 0) | 69 | if(n < 0) |
68 | panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n", | 70 | panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n", |
@@ -80,6 +82,8 @@ static long do_syscall_stub(struct mm_id *mm_idp, void **addr) | |||
80 | if (offset) { | 82 | if (offset) { |
81 | data = (unsigned long *)(mm_idp->stack + | 83 | data = (unsigned long *)(mm_idp->stack + |
82 | offset - UML_CONFIG_STUB_DATA); | 84 | offset - UML_CONFIG_STUB_DATA); |
85 | printk("do_syscall_stub : ret = %d, offset = %d, " | ||
86 | "data = 0x%x\n", ret, offset, data); | ||
83 | syscall = (unsigned long *)((unsigned long)data + data[0]); | 87 | syscall = (unsigned long *)((unsigned long)data + data[0]); |
84 | printk("do_syscall_stub: syscall %ld failed, return value = " | 88 | printk("do_syscall_stub: syscall %ld failed, return value = " |
85 | "0x%lx, expected return value = 0x%lx\n", | 89 | "0x%lx, expected return value = 0x%lx\n", |
@@ -107,32 +111,32 @@ static long do_syscall_stub(struct mm_id *mm_idp, void **addr) | |||
107 | 111 | ||
108 | long run_syscall_stub(struct mm_id * mm_idp, int syscall, | 112 | long run_syscall_stub(struct mm_id * mm_idp, int syscall, |
109 | unsigned long *args, long expected, void **addr, | 113 | unsigned long *args, long expected, void **addr, |
110 | int done) | 114 | int done) |
111 | { | 115 | { |
112 | unsigned long *stack = check_init_stack(mm_idp, *addr); | 116 | unsigned long *stack = check_init_stack(mm_idp, *addr); |
113 | 117 | ||
114 | if(done && *addr == NULL) | 118 | if(done && *addr == NULL) |
115 | single_count++; | 119 | single_count++; |
116 | 120 | ||
117 | *stack += sizeof(long); | 121 | *stack += sizeof(long); |
118 | stack += *stack / sizeof(long); | 122 | stack += *stack / sizeof(long); |
119 | 123 | ||
120 | *stack++ = syscall; | 124 | *stack++ = syscall; |
121 | *stack++ = args[0]; | 125 | *stack++ = args[0]; |
122 | *stack++ = args[1]; | 126 | *stack++ = args[1]; |
123 | *stack++ = args[2]; | 127 | *stack++ = args[2]; |
124 | *stack++ = args[3]; | 128 | *stack++ = args[3]; |
125 | *stack++ = args[4]; | 129 | *stack++ = args[4]; |
126 | *stack++ = args[5]; | 130 | *stack++ = args[5]; |
127 | *stack++ = expected; | 131 | *stack++ = expected; |
128 | *stack = 0; | 132 | *stack = 0; |
129 | multi_op_count++; | 133 | multi_op_count++; |
130 | 134 | ||
131 | if(!done && ((((unsigned long) stack) & ~PAGE_MASK) < | 135 | if(!done && ((((unsigned long) stack) & ~PAGE_MASK) < |
132 | PAGE_SIZE - 10 * sizeof(long))){ | 136 | PAGE_SIZE - 10 * sizeof(long))){ |
133 | *addr = stack; | 137 | *addr = stack; |
134 | return 0; | 138 | return 0; |
135 | } | 139 | } |
136 | 140 | ||
137 | return do_syscall_stub(mm_idp, addr); | 141 | return do_syscall_stub(mm_idp, addr); |
138 | } | 142 | } |
@@ -150,7 +154,7 @@ long syscall_stub_data(struct mm_id * mm_idp, | |||
150 | if((((unsigned long) *addr) & ~PAGE_MASK) >= | 154 | if((((unsigned long) *addr) & ~PAGE_MASK) >= |
151 | PAGE_SIZE - (10 + data_count) * sizeof(long)) { | 155 | PAGE_SIZE - (10 + data_count) * sizeof(long)) { |
152 | ret = do_syscall_stub(mm_idp, addr); | 156 | ret = do_syscall_stub(mm_idp, addr); |
153 | /* in case of error, don't overwrite data on stack */ | 157 | /* in case of error, don't overwrite data on stack */ |
154 | if(ret) | 158 | if(ret) |
155 | return ret; | 159 | return ret; |
156 | } | 160 | } |
@@ -172,39 +176,39 @@ int 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, | 176 | int r, int w, int x, int phys_fd, unsigned long long offset, |
173 | int done, void **data) | 177 | int done, void **data) |
174 | { | 178 | { |
175 | int prot, ret; | 179 | int prot, ret; |
176 | 180 | ||
177 | prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | | 181 | prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | |
178 | (x ? PROT_EXEC : 0); | 182 | (x ? PROT_EXEC : 0); |
179 | 183 | ||
180 | if(proc_mm){ | 184 | if(proc_mm){ |
181 | struct proc_mm_op map; | 185 | struct proc_mm_op map; |
182 | int fd = mm_idp->u.mm_fd; | 186 | int fd = mm_idp->u.mm_fd; |
183 | 187 | ||
184 | map = ((struct proc_mm_op) { .op = MM_MMAP, | 188 | map = ((struct proc_mm_op) { .op = MM_MMAP, |
185 | .u = | 189 | .u = |
186 | { .mmap = | 190 | { .mmap = |
187 | { .addr = virt, | 191 | { .addr = virt, |
188 | .len = len, | 192 | .len = len, |
189 | .prot = prot, | 193 | .prot = prot, |
190 | .flags = MAP_SHARED | | 194 | .flags = MAP_SHARED | |
191 | MAP_FIXED, | 195 | MAP_FIXED, |
192 | .fd = phys_fd, | 196 | .fd = phys_fd, |
193 | .offset= offset | 197 | .offset= offset |
194 | } } } ); | 198 | } } } ); |
195 | ret = os_write_file(fd, &map, sizeof(map)); | 199 | ret = os_write_file(fd, &map, sizeof(map)); |
196 | if(ret != sizeof(map)) | 200 | if(ret != sizeof(map)) |
197 | printk("map : /proc/mm map failed, err = %d\n", -ret); | 201 | printk("map : /proc/mm map failed, err = %d\n", -ret); |
198 | else ret = 0; | 202 | else ret = 0; |
199 | } | 203 | } |
200 | else { | 204 | else { |
201 | unsigned long args[] = { virt, len, prot, | 205 | unsigned long args[] = { virt, len, prot, |
202 | MAP_SHARED | MAP_FIXED, phys_fd, | 206 | MAP_SHARED | MAP_FIXED, phys_fd, |
203 | MMAP_OFFSET(offset) }; | 207 | MMAP_OFFSET(offset) }; |
204 | 208 | ||
205 | ret = run_syscall_stub(mm_idp, STUB_MMAP_NR, args, virt, | 209 | ret = run_syscall_stub(mm_idp, STUB_MMAP_NR, args, virt, |
206 | data, done); | 210 | data, done); |
207 | } | 211 | } |
208 | 212 | ||
209 | return ret; | 213 | return ret; |
210 | } | 214 | } |
@@ -212,68 +216,66 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, | |||
212 | int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, int done, | 216 | int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, int done, |
213 | void **data) | 217 | void **data) |
214 | { | 218 | { |
215 | int ret; | 219 | int ret; |
216 | 220 | ||
217 | if(proc_mm){ | 221 | if(proc_mm){ |
218 | struct proc_mm_op unmap; | 222 | struct proc_mm_op unmap; |
219 | int fd = mm_idp->u.mm_fd; | 223 | int fd = mm_idp->u.mm_fd; |
220 | 224 | ||
221 | unmap = ((struct proc_mm_op) { .op = MM_MUNMAP, | 225 | unmap = ((struct proc_mm_op) { .op = MM_MUNMAP, |
222 | .u = | 226 | .u = |
223 | { .munmap = | 227 | { .munmap = |
224 | { .addr = | 228 | { .addr = |
225 | (unsigned long) addr, | 229 | (unsigned long) addr, |
226 | .len = len } } } ); | 230 | .len = len } } } ); |
227 | ret = os_write_file(fd, &unmap, sizeof(unmap)); | 231 | ret = os_write_file(fd, &unmap, sizeof(unmap)); |
228 | if(ret != sizeof(unmap)) | 232 | if(ret != sizeof(unmap)) |
229 | printk("unmap - proc_mm write returned %d\n", ret); | 233 | printk("unmap - proc_mm write returned %d\n", ret); |
230 | else ret = 0; | 234 | else ret = 0; |
231 | } | 235 | } |
232 | else { | 236 | else { |
233 | unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0, | 237 | unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0, |
234 | 0 }; | 238 | 0 }; |
235 | 239 | ||
236 | ret = run_syscall_stub(mm_idp, __NR_munmap, args, 0, | 240 | ret = run_syscall_stub(mm_idp, __NR_munmap, args, 0, |
237 | data, done); | 241 | data, done); |
238 | if(ret < 0) | 242 | } |
239 | printk("munmap stub failed, errno = %d\n", ret); | ||
240 | } | ||
241 | 243 | ||
242 | return ret; | 244 | return ret; |
243 | } | 245 | } |
244 | 246 | ||
245 | int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, | 247 | int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, |
246 | int r, int w, int x, int done, void **data) | 248 | int r, int w, int x, int done, void **data) |
247 | { | 249 | { |
248 | struct proc_mm_op protect; | 250 | struct proc_mm_op protect; |
249 | int prot, ret; | 251 | int prot, ret; |
250 | 252 | ||
251 | prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | | 253 | prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | |
252 | (x ? PROT_EXEC : 0); | 254 | (x ? PROT_EXEC : 0); |
253 | 255 | if(proc_mm){ | |
254 | if(proc_mm){ | 256 | int fd = mm_idp->u.mm_fd; |
255 | int fd = mm_idp->u.mm_fd; | 257 | |
256 | protect = ((struct proc_mm_op) { .op = MM_MPROTECT, | 258 | protect = ((struct proc_mm_op) { .op = MM_MPROTECT, |
257 | .u = | 259 | .u = |
258 | { .mprotect = | 260 | { .mprotect = |
259 | { .addr = | 261 | { .addr = |
260 | (unsigned long) addr, | 262 | (unsigned long) addr, |
261 | .len = len, | 263 | .len = len, |
262 | .prot = prot } } } ); | 264 | .prot = prot } } } ); |
263 | 265 | ||
264 | ret = os_write_file(fd, &protect, sizeof(protect)); | 266 | ret = os_write_file(fd, &protect, sizeof(protect)); |
265 | if(ret != sizeof(protect)) | 267 | if(ret != sizeof(protect)) |
266 | printk("protect failed, err = %d", -ret); | 268 | printk("protect failed, err = %d", -ret); |
267 | else ret = 0; | 269 | else ret = 0; |
268 | } | 270 | } |
269 | else { | 271 | else { |
270 | unsigned long args[] = { addr, len, prot, 0, 0, 0 }; | 272 | unsigned long args[] = { addr, len, prot, 0, 0, 0 }; |
271 | 273 | ||
272 | ret = run_syscall_stub(mm_idp, __NR_mprotect, args, 0, | 274 | ret = run_syscall_stub(mm_idp, __NR_mprotect, args, 0, |
273 | data, done); | 275 | data, done); |
274 | } | 276 | } |
275 | 277 | ||
276 | return ret; | 278 | return ret; |
277 | } | 279 | } |
278 | 280 | ||
279 | void before_mem_skas(unsigned long unused) | 281 | void before_mem_skas(unsigned long unused) |