diff options
Diffstat (limited to 'meta/packages/qemu/qemu-0.9.1+svnr4027/qemu-0.9.0-nptl.patch')
-rw-r--r-- | meta/packages/qemu/qemu-0.9.1+svnr4027/qemu-0.9.0-nptl.patch | 854 |
1 files changed, 0 insertions, 854 deletions
diff --git a/meta/packages/qemu/qemu-0.9.1+svnr4027/qemu-0.9.0-nptl.patch b/meta/packages/qemu/qemu-0.9.1+svnr4027/qemu-0.9.0-nptl.patch deleted file mode 100644 index 4a87d8d637..0000000000 --- a/meta/packages/qemu/qemu-0.9.1+svnr4027/qemu-0.9.0-nptl.patch +++ /dev/null | |||
@@ -1,854 +0,0 @@ | |||
1 | These are Paul Brook's patches to QEMU-0.8.2 to enable the running of single | ||
2 | ARM binaries under QEMU's user-emulation mode. Without them, QEMU-0.8.1 | ||
3 | immediately dies saying: | ||
4 | Error: f0005 | ||
5 | qemu: uncaught target signal 6 (Aborted) - exiting | ||
6 | while qemu-0.8.2 dies saying: | ||
7 | qemu: Unsupported syscall: 983045 | ||
8 | cannot set up thread-local storage: unknown error | ||
9 | |||
10 | This file is a rediffing of the patches visible at | ||
11 | https://nowt.dyndns.org/patch.qemu_nptl on 27 Sept 2006 | ||
12 | which "patch" fails to apply automatically. | ||
13 | See also http://lists.gnu.org/archive/html/qemu-devel/2006-09/msg00194.html | ||
14 | |||
15 | Martin Guy, 27 Sept 2006 | ||
16 | |||
17 | --- | ||
18 | configure | 25 ++++++ | ||
19 | exec-all.h | 165 ------------------------------------------ | ||
20 | linux-user/arm/syscall.h | 4 - | ||
21 | linux-user/main.c | 94 +++++++++++++++++++++--- | ||
22 | linux-user/qemu.h | 3 | ||
23 | linux-user/syscall.c | 91 ++++++++++++++++++++++- | ||
24 | qemu_spinlock.h | 181 +++++++++++++++++++++++++++++++++++++++++++++++ | ||
25 | target-arm/cpu.h | 10 ++ | ||
26 | target-arm/op.c | 6 + | ||
27 | target-arm/translate.c | 9 ++ | ||
28 | 10 files changed, 405 insertions(+), 183 deletions(-) | ||
29 | |||
30 | Index: qemu/configure | ||
31 | =================================================================== | ||
32 | --- qemu.orig/configure 2008-04-09 23:02:37.000000000 +0100 | ||
33 | +++ qemu/configure 2008-04-09 23:06:36.000000000 +0100 | ||
34 | @@ -109,6 +109,7 @@ | ||
35 | build_docs="no" | ||
36 | uname_release="" | ||
37 | curses="yes" | ||
38 | +nptl="yes" | ||
39 | |||
40 | # OS specific | ||
41 | targetos=`uname -s` | ||
42 | @@ -334,6 +335,8 @@ | ||
43 | ;; | ||
44 | *) echo "ERROR: unknown option $opt"; show_help="yes" | ||
45 | ;; | ||
46 | + --disable-nptl) nptl="no" | ||
47 | + ;; | ||
48 | esac | ||
49 | done | ||
50 | |||
51 | @@ -429,6 +432,7 @@ | ||
52 | echo " --disable-linux-user disable all linux usermode emulation targets" | ||
53 | echo " --enable-darwin-user enable all darwin usermode emulation targets" | ||
54 | echo " --disable-darwin-user disable all darwin usermode emulation targets" | ||
55 | +echo " --disable-nptl disable usermode NPTL guest support" | ||
56 | echo " --fmod-lib path to FMOD library" | ||
57 | echo " --fmod-inc path to FMOD includes" | ||
58 | echo " --enable-uname-release=R Return R for uname -r in usermode emulation" | ||
59 | @@ -595,6 +599,23 @@ | ||
60 | } | ||
61 | EOF | ||
62 | |||
63 | +# check NPTL support | ||
64 | +cat > $TMPC <<EOF | ||
65 | +#include <sched.h> | ||
66 | +void foo() | ||
67 | +{ | ||
68 | +#ifndef CLONE_SETTLS | ||
69 | +#error bork | ||
70 | +#endif | ||
71 | +} | ||
72 | +EOF | ||
73 | + | ||
74 | +if $cc -c -o $TMPO $TMPC 2> /dev/null ; then | ||
75 | + : | ||
76 | +else | ||
77 | + nptl="no" | ||
78 | +fi | ||
79 | + | ||
80 | ########################################## | ||
81 | # SDL probe | ||
82 | |||
83 | @@ -778,6 +799,7 @@ | ||
84 | echo "Documentation $build_docs" | ||
85 | [ ! -z "$uname_release" ] && \ | ||
86 | echo "uname -r $uname_release" | ||
87 | +echo "NPTL support $nptl" | ||
88 | |||
89 | if test $sdl_too_old = "yes"; then | ||
90 | echo "-> Your SDL version is too old - please upgrade to have SDL support" | ||
91 | @@ -1115,6 +1137,9 @@ | ||
92 | echo "TARGET_ARCH=arm" >> $config_mak | ||
93 | echo "#define TARGET_ARCH \"arm\"" >> $config_h | ||
94 | echo "#define TARGET_ARM 1" >> $config_h | ||
95 | + if test "$nptl" = "yes" ; then | ||
96 | + echo "#define USE_NPTL 1" >> $config_h | ||
97 | + fi | ||
98 | bflt="yes" | ||
99 | elif test "$target_cpu" = "sparc" ; then | ||
100 | echo "TARGET_ARCH=sparc" >> $config_mak | ||
101 | Index: qemu/exec-all.h | ||
102 | =================================================================== | ||
103 | --- qemu.orig/exec-all.h 2008-04-09 22:39:38.000000000 +0100 | ||
104 | +++ qemu/exec-all.h 2008-04-09 23:05:55.000000000 +0100 | ||
105 | @@ -297,170 +297,7 @@ | ||
106 | extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4]; | ||
107 | extern void *io_mem_opaque[IO_MEM_NB_ENTRIES]; | ||
108 | |||
109 | -#if defined(__powerpc__) | ||
110 | -static inline int testandset (int *p) | ||
111 | -{ | ||
112 | - int ret; | ||
113 | - __asm__ __volatile__ ( | ||
114 | - "0: lwarx %0,0,%1\n" | ||
115 | - " xor. %0,%3,%0\n" | ||
116 | - " bne 1f\n" | ||
117 | - " stwcx. %2,0,%1\n" | ||
118 | - " bne- 0b\n" | ||
119 | - "1: " | ||
120 | - : "=&r" (ret) | ||
121 | - : "r" (p), "r" (1), "r" (0) | ||
122 | - : "cr0", "memory"); | ||
123 | - return ret; | ||
124 | -} | ||
125 | -#elif defined(__i386__) | ||
126 | -static inline int testandset (int *p) | ||
127 | -{ | ||
128 | - long int readval = 0; | ||
129 | - | ||
130 | - __asm__ __volatile__ ("lock; cmpxchgl %2, %0" | ||
131 | - : "+m" (*p), "+a" (readval) | ||
132 | - : "r" (1) | ||
133 | - : "cc"); | ||
134 | - return readval; | ||
135 | -} | ||
136 | -#elif defined(__x86_64__) | ||
137 | -static inline int testandset (int *p) | ||
138 | -{ | ||
139 | - long int readval = 0; | ||
140 | - | ||
141 | - __asm__ __volatile__ ("lock; cmpxchgl %2, %0" | ||
142 | - : "+m" (*p), "+a" (readval) | ||
143 | - : "r" (1) | ||
144 | - : "cc"); | ||
145 | - return readval; | ||
146 | -} | ||
147 | -#elif defined(__s390__) | ||
148 | -static inline int testandset (int *p) | ||
149 | -{ | ||
150 | - int ret; | ||
151 | - | ||
152 | - __asm__ __volatile__ ("0: cs %0,%1,0(%2)\n" | ||
153 | - " jl 0b" | ||
154 | - : "=&d" (ret) | ||
155 | - : "r" (1), "a" (p), "0" (*p) | ||
156 | - : "cc", "memory" ); | ||
157 | - return ret; | ||
158 | -} | ||
159 | -#elif defined(__alpha__) | ||
160 | -static inline int testandset (int *p) | ||
161 | -{ | ||
162 | - int ret; | ||
163 | - unsigned long one; | ||
164 | - | ||
165 | - __asm__ __volatile__ ("0: mov 1,%2\n" | ||
166 | - " ldl_l %0,%1\n" | ||
167 | - " stl_c %2,%1\n" | ||
168 | - " beq %2,1f\n" | ||
169 | - ".subsection 2\n" | ||
170 | - "1: br 0b\n" | ||
171 | - ".previous" | ||
172 | - : "=r" (ret), "=m" (*p), "=r" (one) | ||
173 | - : "m" (*p)); | ||
174 | - return ret; | ||
175 | -} | ||
176 | -#elif defined(__sparc__) | ||
177 | -static inline int testandset (int *p) | ||
178 | -{ | ||
179 | - int ret; | ||
180 | - | ||
181 | - __asm__ __volatile__("ldstub [%1], %0" | ||
182 | - : "=r" (ret) | ||
183 | - : "r" (p) | ||
184 | - : "memory"); | ||
185 | - | ||
186 | - return (ret ? 1 : 0); | ||
187 | -} | ||
188 | -#elif defined(__arm__) | ||
189 | -static inline int testandset (int *spinlock) | ||
190 | -{ | ||
191 | - register unsigned int ret; | ||
192 | - __asm__ __volatile__("swp %0, %1, [%2]" | ||
193 | - : "=r"(ret) | ||
194 | - : "0"(1), "r"(spinlock)); | ||
195 | - | ||
196 | - return ret; | ||
197 | -} | ||
198 | -#elif defined(__mc68000) | ||
199 | -static inline int testandset (int *p) | ||
200 | -{ | ||
201 | - char ret; | ||
202 | - __asm__ __volatile__("tas %1; sne %0" | ||
203 | - : "=r" (ret) | ||
204 | - : "m" (p) | ||
205 | - : "cc","memory"); | ||
206 | - return ret; | ||
207 | -} | ||
208 | -#elif defined(__ia64) | ||
209 | - | ||
210 | -#include <ia64intrin.h> | ||
211 | - | ||
212 | -static inline int testandset (int *p) | ||
213 | -{ | ||
214 | - return __sync_lock_test_and_set (p, 1); | ||
215 | -} | ||
216 | -#elif defined(__mips__) | ||
217 | -static inline int testandset (int *p) | ||
218 | -{ | ||
219 | - int ret; | ||
220 | - | ||
221 | - __asm__ __volatile__ ( | ||
222 | - " .set push \n" | ||
223 | - " .set noat \n" | ||
224 | - " .set mips2 \n" | ||
225 | - "1: li $1, 1 \n" | ||
226 | - " ll %0, %1 \n" | ||
227 | - " sc $1, %1 \n" | ||
228 | - " beqz $1, 1b \n" | ||
229 | - " .set pop " | ||
230 | - : "=r" (ret), "+R" (*p) | ||
231 | - : | ||
232 | - : "memory"); | ||
233 | - | ||
234 | - return ret; | ||
235 | -} | ||
236 | -#else | ||
237 | -#error unimplemented CPU support | ||
238 | -#endif | ||
239 | - | ||
240 | -typedef int spinlock_t; | ||
241 | - | ||
242 | -#define SPIN_LOCK_UNLOCKED 0 | ||
243 | - | ||
244 | -#if defined(CONFIG_USER_ONLY) | ||
245 | -static inline void spin_lock(spinlock_t *lock) | ||
246 | -{ | ||
247 | - while (testandset(lock)); | ||
248 | -} | ||
249 | - | ||
250 | -static inline void spin_unlock(spinlock_t *lock) | ||
251 | -{ | ||
252 | - *lock = 0; | ||
253 | -} | ||
254 | - | ||
255 | -static inline int spin_trylock(spinlock_t *lock) | ||
256 | -{ | ||
257 | - return !testandset(lock); | ||
258 | -} | ||
259 | -#else | ||
260 | -static inline void spin_lock(spinlock_t *lock) | ||
261 | -{ | ||
262 | -} | ||
263 | - | ||
264 | -static inline void spin_unlock(spinlock_t *lock) | ||
265 | -{ | ||
266 | -} | ||
267 | - | ||
268 | -static inline int spin_trylock(spinlock_t *lock) | ||
269 | -{ | ||
270 | - return 1; | ||
271 | -} | ||
272 | -#endif | ||
273 | +#include "qemu_spinlock.h" | ||
274 | |||
275 | extern spinlock_t tb_lock; | ||
276 | |||
277 | Index: qemu/linux-user/arm/syscall.h | ||
278 | =================================================================== | ||
279 | --- qemu.orig/linux-user/arm/syscall.h 2007-11-27 12:09:33.000000000 +0000 | ||
280 | +++ qemu/linux-user/arm/syscall.h 2008-04-09 23:05:55.000000000 +0100 | ||
281 | @@ -28,7 +28,9 @@ | ||
282 | #define ARM_SYSCALL_BASE 0x900000 | ||
283 | #define ARM_THUMB_SYSCALL 0 | ||
284 | |||
285 | -#define ARM_NR_cacheflush (ARM_SYSCALL_BASE + 0xf0000 + 2) | ||
286 | +#define ARM_NR_BASE 0xf0000 | ||
287 | +#define ARM_NR_cacheflush (ARM_NR_BASE + 2) | ||
288 | +#define ARM_NR_set_tls (ARM_NR_BASE + 5) | ||
289 | |||
290 | #define ARM_NR_semihosting 0x123456 | ||
291 | #define ARM_NR_thumb_semihosting 0xAB | ||
292 | Index: qemu/linux-user/main.c | ||
293 | =================================================================== | ||
294 | --- qemu.orig/linux-user/main.c 2008-04-09 23:02:37.000000000 +0100 | ||
295 | +++ qemu/linux-user/main.c 2008-04-09 23:05:55.000000000 +0100 | ||
296 | @@ -364,6 +364,50 @@ | ||
297 | } | ||
298 | } | ||
299 | |||
300 | +/* Handle a jump to the kernel code page. */ | ||
301 | +static int | ||
302 | +do_kernel_trap(CPUARMState *env) | ||
303 | +{ | ||
304 | + uint32_t addr; | ||
305 | + uint32_t *ptr; | ||
306 | + uint32_t cpsr; | ||
307 | + | ||
308 | + switch (env->regs[15]) { | ||
309 | + case 0xffff0fc0: /* __kernel_cmpxchg */ | ||
310 | + /* XXX: This only works between threads, not between processes. | ||
311 | + Use native atomic operations. */ | ||
312 | + /* ??? This probably breaks horribly if the access segfaults. */ | ||
313 | + cpu_lock(); | ||
314 | + ptr = (uint32_t *)env->regs[2]; | ||
315 | + cpsr = cpsr_read(env); | ||
316 | + if (*ptr == env->regs[0]) { | ||
317 | + *ptr = env->regs[1]; | ||
318 | + env->regs[0] = 0; | ||
319 | + cpsr |= CPSR_C; | ||
320 | + } else { | ||
321 | + env->regs[0] = -1; | ||
322 | + cpsr &= ~CPSR_C; | ||
323 | + } | ||
324 | + cpsr_write(env, cpsr, CPSR_C); | ||
325 | + cpu_unlock(); | ||
326 | + break; | ||
327 | + case 0xffff0fe0: /* __kernel_get_tls */ | ||
328 | + env->regs[0] = env->cp15.c13_tls; | ||
329 | + break; | ||
330 | + default: | ||
331 | + return 1; | ||
332 | + } | ||
333 | + /* Jump back to the caller. */ | ||
334 | + addr = env->regs[14]; | ||
335 | + if (addr & 1) { | ||
336 | + env->thumb = 1; | ||
337 | + addr &= ~1; | ||
338 | + } | ||
339 | + env->regs[15] = addr; | ||
340 | + | ||
341 | + return 0; | ||
342 | +} | ||
343 | + | ||
344 | void cpu_loop(CPUARMState *env) | ||
345 | { | ||
346 | int trapnr; | ||
347 | @@ -474,10 +518,8 @@ | ||
348 | } | ||
349 | } | ||
350 | |||
351 | - if (n == ARM_NR_cacheflush) { | ||
352 | - arm_cache_flush(env->regs[0], env->regs[1]); | ||
353 | - } else if (n == ARM_NR_semihosting | ||
354 | - || n == ARM_NR_thumb_semihosting) { | ||
355 | + if (n == ARM_NR_semihosting | ||
356 | + || n == ARM_NR_thumb_semihosting) { | ||
357 | env->regs[0] = do_arm_semihosting (env); | ||
358 | } else if (n == 0 || n >= ARM_SYSCALL_BASE | ||
359 | || (env->thumb && n == ARM_THUMB_SYSCALL)) { | ||
360 | @@ -488,14 +530,34 @@ | ||
361 | n -= ARM_SYSCALL_BASE; | ||
362 | env->eabi = 0; | ||
363 | } | ||
364 | - env->regs[0] = do_syscall(env, | ||
365 | - n, | ||
366 | - env->regs[0], | ||
367 | - env->regs[1], | ||
368 | - env->regs[2], | ||
369 | - env->regs[3], | ||
370 | - env->regs[4], | ||
371 | - env->regs[5]); | ||
372 | + if ( n > ARM_NR_BASE) { | ||
373 | + switch (n) | ||
374 | + { | ||
375 | + case ARM_NR_cacheflush: | ||
376 | + arm_cache_flush(env->regs[0], env->regs[1]); | ||
377 | + break; | ||
378 | +#ifdef USE_NPTL | ||
379 | + case ARM_NR_set_tls: | ||
380 | + cpu_set_tls(env, env->regs[0]); | ||
381 | + env->regs[0] = 0; | ||
382 | + break; | ||
383 | +#endif | ||
384 | + default: | ||
385 | + printf ("Error: Bad syscall: %x\n", n); | ||
386 | + goto error; | ||
387 | + } | ||
388 | + } | ||
389 | + else | ||
390 | + { | ||
391 | + env->regs[0] = do_syscall(env, | ||
392 | + n, | ||
393 | + env->regs[0], | ||
394 | + env->regs[1], | ||
395 | + env->regs[2], | ||
396 | + env->regs[3], | ||
397 | + env->regs[4], | ||
398 | + env->regs[5]); | ||
399 | + } | ||
400 | } else { | ||
401 | goto error; | ||
402 | } | ||
403 | @@ -534,6 +596,10 @@ | ||
404 | } | ||
405 | } | ||
406 | break; | ||
407 | + case EXCP_KERNEL_TRAP: | ||
408 | + if (do_kernel_trap(env)) | ||
409 | + goto error; | ||
410 | + break; | ||
411 | default: | ||
412 | error: | ||
413 | fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", | ||
414 | @@ -2402,6 +2468,10 @@ | ||
415 | ts->heap_base = info->brk; | ||
416 | /* This will be filled in on the first SYS_HEAPINFO call. */ | ||
417 | ts->heap_limit = 0; | ||
418 | + /* Register the magic kernel code page. The cpu will generate a | ||
419 | + special exception when it tries to execute code here. We can't | ||
420 | + put real code here because it may be in use by the host kernel. */ | ||
421 | + page_set_flags(0xffff0000, 0xffff0fff, 0); | ||
422 | #endif | ||
423 | |||
424 | if (gdbstub_port) { | ||
425 | Index: qemu/linux-user/qemu.h | ||
426 | =================================================================== | ||
427 | --- qemu.orig/linux-user/qemu.h 2008-01-02 15:48:21.000000000 +0000 | ||
428 | +++ qemu/linux-user/qemu.h 2008-04-09 23:05:55.000000000 +0100 | ||
429 | @@ -107,6 +107,9 @@ | ||
430 | uint32_t heap_base; | ||
431 | uint32_t heap_limit; | ||
432 | #endif | ||
433 | +#ifdef USE_NPTL | ||
434 | + uint32_t *child_tidptr; | ||
435 | +#endif | ||
436 | int used; /* non zero if used */ | ||
437 | struct image_info *info; | ||
438 | uint8_t stack[0]; | ||
439 | Index: qemu/linux-user/syscall.c | ||
440 | =================================================================== | ||
441 | --- qemu.orig/linux-user/syscall.c 2008-04-09 23:02:38.000000000 +0100 | ||
442 | +++ qemu/linux-user/syscall.c 2008-04-09 23:05:55.000000000 +0100 | ||
443 | @@ -71,9 +71,18 @@ | ||
444 | #include <linux/kd.h> | ||
445 | |||
446 | #include "qemu.h" | ||
447 | +#include "qemu_spinlock.h" | ||
448 | |||
449 | //#define DEBUG | ||
450 | |||
451 | +#ifdef USE_NPTL | ||
452 | +#define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \ | ||
453 | + CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID) | ||
454 | +#else | ||
455 | +/* XXX: Hardcode the above values. */ | ||
456 | +#define CLONE_NPTL_FLAGS2 0 | ||
457 | +#endif | ||
458 | + | ||
459 | #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \ | ||
460 | || defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS) | ||
461 | /* 16 bit uid wrappers emulation */ | ||
462 | @@ -2702,9 +2711,19 @@ | ||
463 | thread/process */ | ||
464 | #define NEW_STACK_SIZE 8192 | ||
465 | |||
466 | +#ifdef USE_NPTL | ||
467 | +static spinlock_t nptl_lock = SPIN_LOCK_UNLOCKED; | ||
468 | +#endif | ||
469 | + | ||
470 | static int clone_func(void *arg) | ||
471 | { | ||
472 | CPUState *env = arg; | ||
473 | +#ifdef HAVE_NPTL | ||
474 | + /* Wait until the parent has finshed initializing the tls state. */ | ||
475 | + while (!spin_trylock(&nptl_lock)) | ||
476 | + usleep(1); | ||
477 | + spin_unlock(&nptl_lock); | ||
478 | +#endif | ||
479 | cpu_loop(env); | ||
480 | /* never exits */ | ||
481 | return 0; | ||
482 | @@ -2712,13 +2731,22 @@ | ||
483 | |||
484 | /* do_fork() Must return host values and target errnos (unlike most | ||
485 | do_*() functions). */ | ||
486 | -int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp) | ||
487 | +int do_fork(CPUState *env, unsigned int flags, unsigned long newsp, | ||
488 | + uint32_t *parent_tidptr, void *newtls, | ||
489 | + uint32_t *child_tidptr) | ||
490 | { | ||
491 | int ret; | ||
492 | TaskState *ts; | ||
493 | uint8_t *new_stack; | ||
494 | CPUState *new_env; | ||
495 | |||
496 | +#ifdef USE_NPTL | ||
497 | + unsigned int nptl_flags; | ||
498 | + | ||
499 | + if (flags & CLONE_PARENT_SETTID) | ||
500 | + *parent_tidptr = gettid(); | ||
501 | +#endif | ||
502 | + | ||
503 | if (flags & CLONE_VM) { | ||
504 | ts = malloc(sizeof(TaskState) + NEW_STACK_SIZE); | ||
505 | memset(ts, 0, sizeof(TaskState)); | ||
506 | @@ -2784,16 +2812,67 @@ | ||
507 | #error unsupported target CPU | ||
508 | #endif | ||
509 | new_env->opaque = ts; | ||
510 | +#ifdef USE_NPTL | ||
511 | + nptl_flags = flags; | ||
512 | + flags &= ~CLONE_NPTL_FLAGS2; | ||
513 | + | ||
514 | + if (nptl_flags & CLONE_CHILD_CLEARTID) { | ||
515 | + ts->child_tidptr = child_tidptr; | ||
516 | + } | ||
517 | + | ||
518 | + if (nptl_flags & CLONE_SETTLS) | ||
519 | + cpu_set_tls (new_env, newtls); | ||
520 | + | ||
521 | + /* Grab the global cpu lock so that the thread setup appears | ||
522 | + atomic. */ | ||
523 | + if (nptl_flags & CLONE_CHILD_SETTID) | ||
524 | + spin_lock(&nptl_lock); | ||
525 | + | ||
526 | +#else | ||
527 | + if (flags & CLONE_NPTL_FLAGS2) | ||
528 | + return -EINVAL; | ||
529 | +#endif | ||
530 | + | ||
531 | + if (CLONE_VFORK & flags) | ||
532 | + flags ^= CLONE_VM; | ||
533 | #ifdef __ia64__ | ||
534 | ret = __clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env); | ||
535 | #else | ||
536 | ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env); | ||
537 | #endif | ||
538 | +#ifdef USE_NPTL | ||
539 | + if (ret != -1) { | ||
540 | + if (nptl_flags & CLONE_CHILD_SETTID) | ||
541 | + *child_tidptr = ret; | ||
542 | + } | ||
543 | + | ||
544 | + /* Allow the child to continue. */ | ||
545 | + if (nptl_flags & CLONE_CHILD_SETTID) | ||
546 | + spin_unlock(&nptl_lock); | ||
547 | +#endif | ||
548 | } else { | ||
549 | /* if no CLONE_VM, we consider it is a fork */ | ||
550 | - if ((flags & ~CSIGNAL) != 0) | ||
551 | + if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0) | ||
552 | return -EINVAL; | ||
553 | ret = fork(); | ||
554 | +#ifdef USE_NPTL | ||
555 | + /* There is a race condition here. The parent process could | ||
556 | + theoretically read the TID in the child process before the child | ||
557 | + tid is set. This would require using either ptrace | ||
558 | + (not implemented) or having *_tidptr to point at a shared memory | ||
559 | + mapping. We can't repeat the spinlock hack used above because | ||
560 | + the child process gets its own copy of the lock. */ | ||
561 | + if (ret == 0) { | ||
562 | + /* Child Process. */ | ||
563 | + if (flags & CLONE_CHILD_SETTID) | ||
564 | + *child_tidptr = gettid(); | ||
565 | + ts = (TaskState *)env->opaque; | ||
566 | + if (flags & CLONE_CHILD_CLEARTID) | ||
567 | + ts->child_tidptr = child_tidptr; | ||
568 | + if (flags & CLONE_SETTLS) | ||
569 | + cpu_set_tls (env, newtls); | ||
570 | + } | ||
571 | +#endif | ||
572 | } | ||
573 | return ret; | ||
574 | } | ||
575 | @@ -3118,7 +3197,7 @@ | ||
576 | ret = do_brk(arg1); | ||
577 | break; | ||
578 | case TARGET_NR_fork: | ||
579 | - ret = get_errno(do_fork(cpu_env, SIGCHLD, 0)); | ||
580 | + ret = get_errno(do_fork(cpu_env, SIGCHLD, 0, NULL, NULL, NULL)); | ||
581 | break; | ||
582 | #ifdef TARGET_NR_waitpid | ||
583 | case TARGET_NR_waitpid: | ||
584 | @@ -4481,7 +4560,8 @@ | ||
585 | ret = get_errno(fsync(arg1)); | ||
586 | break; | ||
587 | case TARGET_NR_clone: | ||
588 | - ret = get_errno(do_fork(cpu_env, arg1, arg2)); | ||
589 | + ret = get_errno(do_fork(cpu_env, arg1, arg2, (uint32_t *)arg3, | ||
590 | + (void *)arg4, (uint32_t *)arg5)); | ||
591 | break; | ||
592 | #ifdef __NR_exit_group | ||
593 | /* new thread calls */ | ||
594 | @@ -4928,7 +5008,8 @@ | ||
595 | #endif | ||
596 | #ifdef TARGET_NR_vfork | ||
597 | case TARGET_NR_vfork: | ||
598 | - ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD, 0)); | ||
599 | + ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD, 0, | ||
600 | + NULL, NULL, NULL)); | ||
601 | break; | ||
602 | #endif | ||
603 | #ifdef TARGET_NR_ugetrlimit | ||
604 | Index: qemu/qemu_spinlock.h | ||
605 | =================================================================== | ||
606 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | ||
607 | +++ qemu/qemu_spinlock.h 2008-04-09 23:05:55.000000000 +0100 | ||
608 | @@ -0,0 +1,181 @@ | ||
609 | +/* | ||
610 | + * Atomic operation helper include | ||
611 | + * | ||
612 | + * Copyright (c) 2005 Fabrice Bellard | ||
613 | + * | ||
614 | + * This library is free software; you can redistribute it and/or | ||
615 | + * modify it under the terms of the GNU Lesser General Public | ||
616 | + * License as published by the Free Software Foundation; either | ||
617 | + * version 2 of the License, or (at your option) any later version. | ||
618 | + * | ||
619 | + * This library is distributed in the hope that it will be useful, | ||
620 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
621 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
622 | + * Lesser General Public License for more details. | ||
623 | + * | ||
624 | + * You should have received a copy of the GNU Lesser General Public | ||
625 | + * License along with this library; if not, write to the Free Software | ||
626 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
627 | + */ | ||
628 | +#ifndef QEMU_SPINLOCK_H | ||
629 | +#define QEMU_SPINLOCK_H | ||
630 | + | ||
631 | +#ifdef __powerpc__ | ||
632 | +static inline int testandset (int *p) | ||
633 | +{ | ||
634 | + int ret; | ||
635 | + __asm__ __volatile__ ( | ||
636 | + "0: lwarx %0,0,%1\n" | ||
637 | + " xor. %0,%3,%0\n" | ||
638 | + " bne 1f\n" | ||
639 | + " stwcx. %2,0,%1\n" | ||
640 | + " bne- 0b\n" | ||
641 | + "1: " | ||
642 | + : "=&r" (ret) | ||
643 | + : "r" (p), "r" (1), "r" (0) | ||
644 | + : "cr0", "memory"); | ||
645 | + return ret; | ||
646 | +} | ||
647 | +#endif | ||
648 | + | ||
649 | +#ifdef __i386__ | ||
650 | +static inline int testandset (int *p) | ||
651 | +{ | ||
652 | + long int readval = 0; | ||
653 | + | ||
654 | + __asm__ __volatile__ ("lock; cmpxchgl %2, %0" | ||
655 | + : "+m" (*p), "+a" (readval) | ||
656 | + : "r" (1) | ||
657 | + : "cc"); | ||
658 | + return readval; | ||
659 | +} | ||
660 | +#endif | ||
661 | + | ||
662 | +#ifdef __x86_64__ | ||
663 | +static inline int testandset (int *p) | ||
664 | +{ | ||
665 | + long int readval = 0; | ||
666 | + | ||
667 | + __asm__ __volatile__ ("lock; cmpxchgl %2, %0" | ||
668 | + : "+m" (*p), "+a" (readval) | ||
669 | + : "r" (1) | ||
670 | + : "cc"); | ||
671 | + return readval; | ||
672 | +} | ||
673 | +#endif | ||
674 | + | ||
675 | +#ifdef __s390__ | ||
676 | +static inline int testandset (int *p) | ||
677 | +{ | ||
678 | + int ret; | ||
679 | + | ||
680 | + __asm__ __volatile__ ("0: cs %0,%1,0(%2)\n" | ||
681 | + " jl 0b" | ||
682 | + : "=&d" (ret) | ||
683 | + : "r" (1), "a" (p), "0" (*p) | ||
684 | + : "cc", "memory" ); | ||
685 | + return ret; | ||
686 | +} | ||
687 | +#endif | ||
688 | + | ||
689 | +#ifdef __alpha__ | ||
690 | +static inline int testandset (int *p) | ||
691 | +{ | ||
692 | + int ret; | ||
693 | + unsigned long one; | ||
694 | + | ||
695 | + __asm__ __volatile__ ("0: mov 1,%2\n" | ||
696 | + " ldl_l %0,%1\n" | ||
697 | + " stl_c %2,%1\n" | ||
698 | + " beq %2,1f\n" | ||
699 | + ".subsection 2\n" | ||
700 | + "1: br 0b\n" | ||
701 | + ".previous" | ||
702 | + : "=r" (ret), "=m" (*p), "=r" (one) | ||
703 | + : "m" (*p)); | ||
704 | + return ret; | ||
705 | +} | ||
706 | +#endif | ||
707 | + | ||
708 | +#ifdef __sparc__ | ||
709 | +static inline int testandset (int *p) | ||
710 | +{ | ||
711 | + int ret; | ||
712 | + | ||
713 | + __asm__ __volatile__("ldstub [%1], %0" | ||
714 | + : "=r" (ret) | ||
715 | + : "r" (p) | ||
716 | + : "memory"); | ||
717 | + | ||
718 | + return (ret ? 1 : 0); | ||
719 | +} | ||
720 | +#endif | ||
721 | + | ||
722 | +#ifdef __arm__ | ||
723 | +static inline int testandset (int *spinlock) | ||
724 | +{ | ||
725 | + register unsigned int ret; | ||
726 | + __asm__ __volatile__("swp %0, %1, [%2]" | ||
727 | + : "=r"(ret) | ||
728 | + : "0"(1), "r"(spinlock)); | ||
729 | + | ||
730 | + return ret; | ||
731 | +} | ||
732 | +#endif | ||
733 | + | ||
734 | +#ifdef __mc68000 | ||
735 | +static inline int testandset (int *p) | ||
736 | +{ | ||
737 | + char ret; | ||
738 | + __asm__ __volatile__("tas %1; sne %0" | ||
739 | + : "=r" (ret) | ||
740 | + : "m" (p) | ||
741 | + : "cc","memory"); | ||
742 | + return ret; | ||
743 | +} | ||
744 | +#endif | ||
745 | + | ||
746 | +#ifdef __ia64 | ||
747 | +#include <ia64intrin.h> | ||
748 | + | ||
749 | +static inline int testandset (int *p) | ||
750 | +{ | ||
751 | + return __sync_lock_test_and_set (p, 1); | ||
752 | +} | ||
753 | +#endif | ||
754 | + | ||
755 | +typedef int spinlock_t; | ||
756 | + | ||
757 | +#define SPIN_LOCK_UNLOCKED 0 | ||
758 | + | ||
759 | +#if defined(CONFIG_USER_ONLY) | ||
760 | +static inline void spin_lock(spinlock_t *lock) | ||
761 | +{ | ||
762 | + while (testandset(lock)); | ||
763 | +} | ||
764 | + | ||
765 | +static inline void spin_unlock(spinlock_t *lock) | ||
766 | +{ | ||
767 | + *lock = 0; | ||
768 | +} | ||
769 | + | ||
770 | +static inline int spin_trylock(spinlock_t *lock) | ||
771 | +{ | ||
772 | + return !testandset(lock); | ||
773 | +} | ||
774 | +#else | ||
775 | +static inline void spin_lock(spinlock_t *lock) | ||
776 | +{ | ||
777 | +} | ||
778 | + | ||
779 | +static inline void spin_unlock(spinlock_t *lock) | ||
780 | +{ | ||
781 | +} | ||
782 | + | ||
783 | +static inline int spin_trylock(spinlock_t *lock) | ||
784 | +{ | ||
785 | + return 1; | ||
786 | +} | ||
787 | +#endif | ||
788 | + | ||
789 | +#endif | ||
790 | Index: qemu/target-arm/cpu.h | ||
791 | =================================================================== | ||
792 | --- qemu.orig/target-arm/cpu.h 2007-11-27 12:09:57.000000000 +0000 | ||
793 | +++ qemu/target-arm/cpu.h 2008-04-09 23:05:55.000000000 +0100 | ||
794 | @@ -38,6 +38,7 @@ | ||
795 | #define EXCP_FIQ 6 | ||
796 | #define EXCP_BKPT 7 | ||
797 | #define EXCP_EXCEPTION_EXIT 8 /* Return from v7M exception. */ | ||
798 | +#define EXCP_KERNEL_TRAP 9 /* Jumped to kernel code page. */ | ||
799 | |||
800 | #define ARMV7M_EXCP_RESET 1 | ||
801 | #define ARMV7M_EXCP_NMI 2 | ||
802 | @@ -222,6 +223,15 @@ | ||
803 | void cpu_lock(void); | ||
804 | void cpu_unlock(void); | ||
805 | |||
806 | +void cpu_lock(void); | ||
807 | +void cpu_unlock(void); | ||
808 | +#if defined(USE_NPTL) | ||
809 | +static inline void cpu_set_tls(CPUARMState *env, void *newtls) | ||
810 | +{ | ||
811 | + env->cp15.c13_tls2 = (uint32_t)(long)newtls; | ||
812 | +} | ||
813 | +#endif | ||
814 | + | ||
815 | #define CPSR_M (0x1f) | ||
816 | #define CPSR_T (1 << 5) | ||
817 | #define CPSR_F (1 << 6) | ||
818 | Index: qemu/target-arm/op.c | ||
819 | =================================================================== | ||
820 | --- qemu.orig/target-arm/op.c 2008-04-09 22:40:01.000000000 +0100 | ||
821 | +++ qemu/target-arm/op.c 2008-04-09 23:05:55.000000000 +0100 | ||
822 | @@ -994,6 +994,12 @@ | ||
823 | cpu_loop_exit(); | ||
824 | } | ||
825 | |||
826 | +void OPPROTO op_kernel_trap(void) | ||
827 | +{ | ||
828 | + env->exception_index = EXCP_KERNEL_TRAP; | ||
829 | + cpu_loop_exit(); | ||
830 | +} | ||
831 | + | ||
832 | /* VFP support. We follow the convention used for VFP instrunctions: | ||
833 | Single precition routines have a "s" suffix, double precision a | ||
834 | "d" suffix. */ | ||
835 | Index: qemu/target-arm/translate.c | ||
836 | =================================================================== | ||
837 | --- qemu.orig/target-arm/translate.c 2008-04-09 22:40:01.000000000 +0100 | ||
838 | +++ qemu/target-arm/translate.c 2008-04-09 23:05:55.000000000 +0100 | ||
839 | @@ -7496,7 +7496,14 @@ | ||
840 | gen_op_exception_exit(); | ||
841 | } | ||
842 | #endif | ||
843 | - | ||
844 | +#ifdef CONFIG_USER_ONLY | ||
845 | + /* Intercept jump to the magic kernel page. */ | ||
846 | + if (dc->pc > 0xffff0000) { | ||
847 | + gen_op_kernel_trap(); | ||
848 | + dc->is_jmp = DISAS_UPDATE; | ||
849 | + break; | ||
850 | + } | ||
851 | +#endif | ||
852 | if (env->nb_breakpoints > 0) { | ||
853 | for(j = 0; j < env->nb_breakpoints; j++) { | ||
854 | if (env->breakpoints[j] == dc->pc) { | ||