~jderose/ubuntu/raring/qemu/vde-again

« back to all changes in this revision

Viewing changes to debian/patches/42_arm_tls.patch

  • Committer: Bazaar Package Importer
  • Author(s): Aurelien Jarno, Aurelien Jarno
  • Date: 2008-08-25 04:38:35 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20080825043835-8e3tftavy8bujdch
Tags: 0.9.1-6
[ Aurelien Jarno ]
* debian/control: 
  - Update list of supported targets (Closes: bug#488339).
* debian/qemu-make-debian-root:
  - Use mktemp instead of $$ to create temporary directories (Closes: 
    bug#496394).
* debian/links:
  - Add missing links to manpages.

Show diffs side-by-side

added added

removed removed

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