2 ===================================================================
3 --- qemu.orig/configure 2006-08-26 16:31:53.000000000 +0100
4 +++ qemu/configure 2006-08-26 16:31:53.000000000 +0100
15 --enable-iasl) build_acpi_tables="yes"
17 + --disable-nptl) nptl="no"
37 +if $cc -c -o $TMPO $TMPC 2> /dev/null ; then
43 ##########################################
48 echo "FMOD support $fmod $fmod_support"
49 echo "kqemu support $kqemu"
50 +echo "NPTL support $nptl"
51 echo "Documentation $build_docs"
52 [ ! -z "$uname_release" ] && \
53 echo "uname -r $uname_release"
55 echo "SDL_CFLAGS=`$sdl_config --cflags`" >> $config_mak
59 + if test "$nptl" = "yes" ; then
60 + case "$target_cpu" in
62 + echo "#define USE_NPTL 1" >> $config_h
68 if test "$cocoa" = "yes" ; then
69 Index: qemu/exec-all.h
70 ===================================================================
71 --- qemu.orig/exec-all.h 2006-08-26 16:28:32.000000000 +0100
72 +++ qemu/exec-all.h 2006-08-26 16:31:53.000000000 +0100
74 extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
75 extern void *io_mem_opaque[IO_MEM_NB_ENTRIES];
78 -static inline int testandset (int *p)
81 - __asm__ __volatile__ (
82 - "0: lwarx %0,0,%1\n"
89 - : "r" (p), "r" (1), "r" (0)
96 -static inline int testandset (int *p)
98 - long int readval = 0;
100 - __asm__ __volatile__ ("lock; cmpxchgl %2, %0"
101 - : "+m" (*p), "+a" (readval)
109 -static inline int testandset (int *p)
111 - long int readval = 0;
113 - __asm__ __volatile__ ("lock; cmpxchgl %2, %0"
114 - : "+m" (*p), "+a" (readval)
122 -static inline int testandset (int *p)
126 - __asm__ __volatile__ ("0: cs %0,%1,0(%2)\n"
129 - : "r" (1), "a" (p), "0" (*p)
130 - : "cc", "memory" );
136 -static inline int testandset (int *p)
141 - __asm__ __volatile__ ("0: mov 1,%2\n"
148 - : "=r" (ret), "=m" (*p), "=r" (one)
155 -static inline int testandset (int *p)
159 - __asm__ __volatile__("ldstub [%1], %0"
164 - return (ret ? 1 : 0);
169 -static inline int testandset (int *spinlock)
171 - register unsigned int ret;
172 - __asm__ __volatile__("swp %0, %1, [%2]"
174 - : "0"(1), "r"(spinlock));
181 -static inline int testandset (int *p)
184 - __asm__ __volatile__("tas %1; sne %0"
193 -#include <ia64intrin.h>
195 -static inline int testandset (int *p)
197 - return __sync_lock_test_and_set (p, 1);
201 -typedef int spinlock_t;
203 -#define SPIN_LOCK_UNLOCKED 0
205 -#if defined(CONFIG_USER_ONLY)
206 -static inline void spin_lock(spinlock_t *lock)
208 - while (testandset(lock));
211 -static inline void spin_unlock(spinlock_t *lock)
216 -static inline int spin_trylock(spinlock_t *lock)
218 - return !testandset(lock);
221 -static inline void spin_lock(spinlock_t *lock)
225 -static inline void spin_unlock(spinlock_t *lock)
229 -static inline int spin_trylock(spinlock_t *lock)
234 +#include "qemu_spinlock.h"
236 extern spinlock_t tb_lock;
238 Index: qemu/linux-user/arm/syscall.h
239 ===================================================================
240 --- qemu.orig/linux-user/arm/syscall.h 2006-03-09 19:18:11.000000000 +0000
241 +++ qemu/linux-user/arm/syscall.h 2006-08-26 16:31:53.000000000 +0100
243 #define ARM_SYSCALL_BASE 0x900000
244 #define ARM_THUMB_SYSCALL 0
246 -#define ARM_NR_cacheflush (ARM_SYSCALL_BASE + 0xf0000 + 2)
247 +#define ARM_NR_BASE 0xf0000
248 +#define ARM_NR_cacheflush (ARM_NR_BASE + 2)
249 +#define ARM_NR_set_tls (ARM_NR_BASE + 5)
251 #define ARM_NR_semihosting 0x123456
252 #define ARM_NR_thumb_semihosting 0xAB
253 Index: qemu/linux-user/main.c
254 ===================================================================
255 --- qemu.orig/linux-user/main.c 2006-08-26 16:28:40.000000000 +0100
256 +++ qemu/linux-user/main.c 2006-08-26 16:31:53.000000000 +0100
261 +/* Handle a jump to the kernel code page. */
263 +do_kernel_trap(CPUARMState *env)
269 + switch (env->regs[15]) {
270 + case 0xffff0fc0: /* __kernel_cmpxchg */
271 + /* XXX: This only works between threads, not between processes.
272 + Use native atomic operations. */
273 + /* ??? This probably breaks horribly if the access segfaults. */
275 + ptr = (uint32_t *)env->regs[2];
276 + cpsr = cpsr_read(env);
277 + if (*ptr == env->regs[0]) {
278 + *ptr = env->regs[1];
285 + cpsr_write(env, cpsr, CPSR_C);
288 + case 0xffff0fe0: /* __kernel_get_tls */
289 + env->regs[0] = env->cp15.c13_tls;
294 + /* Jump back to the caller. */
295 + addr = env->regs[14];
300 + env->regs[15] = addr;
305 void cpu_loop(CPUARMState *env)
312 - if (n == ARM_NR_cacheflush) {
313 - arm_cache_flush(env->regs[0], env->regs[1]);
314 - } else if (n == ARM_NR_semihosting
315 - || n == ARM_NR_thumb_semihosting) {
316 + if (n == ARM_NR_semihosting
317 + || n == ARM_NR_thumb_semihosting) {
318 env->regs[0] = do_arm_semihosting (env);
319 } else if (n == 0 || n >= ARM_SYSCALL_BASE
320 || (env->thumb && n == ARM_THUMB_SYSCALL)) {
321 @@ -379,14 +421,34 @@
322 n -= ARM_SYSCALL_BASE;
325 - env->regs[0] = do_syscall(env,
333 + if ( n > ARM_NR_BASE) {
336 + case ARM_NR_cacheflush:
337 + arm_cache_flush(env->regs[0], env->regs[1]);
340 + case ARM_NR_set_tls:
341 + cpu_set_tls(env, env->regs[0]);
346 + printf ("Error: Bad syscall: %x\n", n);
352 + env->regs[0] = do_syscall(env,
368 + case EXCP_KERNEL_TRAP:
369 + if (do_kernel_trap(env))
374 fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
375 @@ -1639,6 +1705,10 @@
376 ts->heap_base = info->brk;
377 /* This will be filled in on the first SYS_HEAPINFO call. */
379 + /* Register the magic kernel code page. The cpu will generate a
380 + special exception when it tries to execute code here. We can't
381 + put real code here because it may be in use by the host kernel. */
382 + page_set_flags(0xffff0000, 0xffff0fff, 0);
384 #elif defined(TARGET_SPARC)
386 Index: qemu/linux-user/qemu.h
387 ===================================================================
388 --- qemu.orig/linux-user/qemu.h 2006-08-26 16:28:40.000000000 +0100
389 +++ qemu/linux-user/qemu.h 2006-08-26 16:33:50.000000000 +0100
393 int used; /* non zero if used */
395 + uint32_t *child_tidptr;
397 struct image_info *info;
399 } __attribute__((aligned(16))) TaskState;
400 Index: qemu/linux-user/syscall.c
401 ===================================================================
402 --- qemu.orig/linux-user/syscall.c 2006-08-26 16:28:40.000000000 +0100
403 +++ qemu/linux-user/syscall.c 2006-08-26 16:31:53.000000000 +0100
405 #include <linux/kd.h>
408 +#include "qemu_spinlock.h"
413 +#define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \
414 + CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)
416 +/* XXX: Hardcode the above values. */
417 +#define CLONE_NPTL_FLAGS2 0
420 #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC)
421 /* 16 bit uid wrappers emulation */
423 @@ -1602,20 +1611,38 @@
425 #define NEW_STACK_SIZE 8192
428 +static spinlock_t nptl_lock = SPIN_LOCK_UNLOCKED;
431 static int clone_func(void *arg)
435 + /* Wait until the parent has finshed initializing the tls state. */
436 + while (!spin_trylock(&nptl_lock))
438 + spin_unlock(&nptl_lock);
445 -int do_fork(CPUState *env, unsigned int flags, unsigned long newsp)
446 +int do_fork(CPUState *env, unsigned int flags, unsigned long newsp,
447 + uint32_t *parent_tidptr, void *newtls,
448 + uint32_t *child_tidptr)
455 + unsigned int nptl_flags;
457 + if (flags & CLONE_PARENT_SETTID)
458 + *parent_tidptr = gettid();
461 if (flags & CLONE_VM) {
462 ts = malloc(sizeof(TaskState) + NEW_STACK_SIZE);
463 @@ -1665,16 +1692,60 @@
464 #error unsupported target CPU
466 new_env->opaque = ts;
468 + nptl_flags = flags;
469 + flags &= ~CLONE_NPTL_FLAGS2;
470 + if (nptl_flags & CLONE_CHILD_CLEARTID) {
471 + ts->child_tidptr = child_tidptr;
473 + if (nptl_flags & CLONE_SETTLS)
474 + cpu_set_tls (new_env, newtls);
475 + /* Grab the global cpu lock so that the thread setup appears
477 + if (nptl_flags & CLONE_CHILD_SETTID)
478 + spin_lock(&nptl_lock);
480 + if (flags & CLONE_NPTL_FLAGS2)
485 ret = __clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
487 ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
491 + if (nptl_flags & CLONE_CHILD_SETTID)
492 + *child_tidptr = ret;
494 + /* Allow the child to continue. */
495 + if (nptl_flags & CLONE_CHILD_SETTID)
496 + spin_unlock(&nptl_lock);
499 - /* if no CLONE_VM, we consider it is a fork */
500 - if ((flags & ~CSIGNAL) != 0)
503 + /* if no CLONE_VM, we consider it is a fork */
504 + if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0)
508 + /* There is a race condition here. The parent process could
509 + theoretically read the TID in the child process before the child
510 + tid is set. This would require using either ptrace
511 + (not implemented) or having *_tidptr to point at a shared memory
512 + mapping. We can't repeat the spinlock hack used above because
513 + the child process gets its own copy of the lock. */
515 + /* Child Process. */
516 + if (flags & CLONE_CHILD_SETTID)
517 + *child_tidptr = gettid();
518 + ts = (TaskState *)env->opaque;
519 + if (flags & CLONE_CHILD_CLEARTID)
520 + ts->child_tidptr = child_tidptr;
521 + if (flags & CLONE_SETTLS)
522 + cpu_set_tls (env, newtls);
528 @@ -1918,7 +1989,7 @@
532 - ret = get_errno(do_fork(cpu_env, SIGCHLD, 0));
533 + ret = get_errno(do_fork(cpu_env, SIGCHLD, 0, NULL, NULL, NULL));
535 case TARGET_NR_waitpid:
537 @@ -2989,7 +3060,8 @@
538 ret = get_errno(fsync(arg1));
540 case TARGET_NR_clone:
541 - ret = get_errno(do_fork(cpu_env, arg1, arg2));
542 + ret = get_errno(do_fork(cpu_env, arg1, arg2, (uint32_t *)arg3,
543 + (void *)arg4, (uint32_t *)arg5));
545 #ifdef __NR_exit_group
546 /* new thread calls */
547 @@ -3339,7 +3411,8 @@
549 #ifdef TARGET_NR_vfork
550 case TARGET_NR_vfork:
551 - ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD, 0));
552 + ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD, 0,
553 + NULL, NULL, NULL));
556 #ifdef TARGET_NR_ugetrlimit
557 @@ -3838,4 +3911,3 @@
562 Index: qemu/target-arm/cpu.h
563 ===================================================================
564 --- qemu.orig/target-arm/cpu.h 2006-03-09 19:18:27.000000000 +0000
565 +++ qemu/target-arm/cpu.h 2006-08-26 16:31:53.000000000 +0100
570 +#define EXCP_KERNEL_TRAP 8 /* Jumped to kernel code page. */
574 /* We currently assume float and double are IEEE single and double
575 precision respectively.
578 uint32_t c13_fcse; /* FCSE PID. */
579 uint32_t c13_context; /* Context ID. */
580 + uint32_t c13_tls; /* Paul Brook told me to just add this ;) */
583 /* Internal CPU feature flags. */
585 int cpu_arm_signal_handler(int host_signum, struct siginfo *info,
588 +void cpu_lock(void);
589 +void cpu_unlock(void);
590 +#if defined(USE_NPTL)
591 +static inline void cpu_set_tls(CPUARMState *env, void *newtls)
593 + env->cp15.c13_tls = (uint32_t)newtls;
597 #define CPSR_M (0x1f)
598 #define CPSR_T (1 << 5)
599 #define CPSR_F (1 << 6)
601 #define CPSR_J (1 << 24)
602 #define CPSR_IT_0_1 (3 << 25)
603 #define CPSR_Q (1 << 27)
604 -#define CPSR_NZCV (0xf << 28)
605 +#define CPSR_V (1 << 28)
606 +#define CPSR_C (1 << 29)
607 +#define CPSR_Z (1 << 30)
608 +#define CPSR_N (1 << 31)
609 +#define CPSR_NZCV (CPSR_N | CPSR_Z | CPSR_C | CPSR_V)
611 #define CACHED_CPSR_BITS (CPSR_T | CPSR_Q | CPSR_NZCV)
612 /* Return the current CPSR value. */
613 Index: qemu/target-arm/exec.h
614 ===================================================================
615 --- qemu.orig/target-arm/exec.h 2006-03-09 19:18:27.000000000 +0000
616 +++ qemu/target-arm/exec.h 2006-08-26 16:31:53.000000000 +0100
621 -void cpu_lock(void);
622 -void cpu_unlock(void);
623 void helper_set_cp15(CPUState *, uint32_t, uint32_t);
624 uint32_t helper_get_cp15(CPUState *, uint32_t);
626 Index: qemu/target-arm/op.c
627 ===================================================================
628 --- qemu.orig/target-arm/op.c 2006-08-26 16:28:48.000000000 +0100
629 +++ qemu/target-arm/op.c 2006-08-26 16:31:53.000000000 +0100
634 +void OPPROTO op_kernel_trap(void)
636 + env->exception_index = EXCP_KERNEL_TRAP;
640 /* VFP support. We follow the convention used for VFP instrunctions:
641 Single precition routines have a "s" suffix, double precision a
643 Index: qemu/target-arm/translate.c
644 ===================================================================
645 --- qemu.orig/target-arm/translate.c 2006-08-26 16:28:48.000000000 +0100
646 +++ qemu/target-arm/translate.c 2006-08-26 16:31:53.000000000 +0100
647 @@ -2382,6 +2382,7 @@
648 s->is_jmp = DISAS_JUMP;
652 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
653 basic block 'tb'. If search_pc is TRUE, also generate PC
654 information for each intermediate instruction. */
655 @@ -2416,6 +2417,15 @@
659 +#ifdef CONFIG_USER_ONLY
660 + /* Intercept jump to the magic kernel page. */
661 + if (dc->pc > 0xffff0000) {
662 + gen_op_kernel_trap();
663 + dc->is_jmp = DISAS_UPDATE;
668 if (env->nb_breakpoints > 0) {
669 for(j = 0; j < env->nb_breakpoints; j++) {
670 if (env->breakpoints[j] == dc->pc) {
671 Index: qemu/qemu_spinlock.h
672 ===================================================================
673 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
674 +++ qemu/qemu_spinlock.h 2006-08-26 16:31:53.000000000 +0100
677 + * internal execution defines for qemu
679 + * Copyright (c) 2003 Fabrice Bellard
681 + * This library is free software; you can redistribute it and/or
682 + * modify it under the terms of the GNU Lesser General Public
683 + * License as published by the Free Software Foundation; either
684 + * version 2 of the License, or (at your option) any later version.
686 + * This library is distributed in the hope that it will be useful,
687 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
688 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
689 + * Lesser General Public License for more details.
691 + * You should have received a copy of the GNU Lesser General Public
692 + * License along with this library; if not, write to the Free Software
693 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
696 +#ifndef _QEMU_SPINLOCK_H
697 +#define _QEMU_SPINLOCK_H
700 +static inline int testandset (int *p)
703 + __asm__ __volatile__ (
704 + "0: lwarx %0,0,%1\n"
707 + " stwcx. %2,0,%1\n"
711 + : "r" (p), "r" (1), "r" (0)
712 + : "cr0", "memory");
718 +static inline int testandset (int *p)
720 + long int readval = 0;
722 + __asm__ __volatile__ ("lock; cmpxchgl %2, %0"
723 + : "+m" (*p), "+a" (readval)
731 +static inline int testandset (int *p)
733 + long int readval = 0;
735 + __asm__ __volatile__ ("lock; cmpxchgl %2, %0"
736 + : "+m" (*p), "+a" (readval)
744 +static inline int testandset (int *p)
748 + __asm__ __volatile__ ("0: cs %0,%1,0(%2)\n"
751 + : "r" (1), "a" (p), "0" (*p)
752 + : "cc", "memory" );
758 +static inline int testandset (int *p)
763 + __asm__ __volatile__ ("0: mov 1,%2\n"
770 + : "=r" (ret), "=m" (*p), "=r" (one)
777 +static inline int testandset (int *p)
781 + __asm__ __volatile__("ldstub [%1], %0"
786 + return (ret ? 1 : 0);
791 +static inline int testandset (int *spinlock)
793 + register unsigned int ret;
794 + __asm__ __volatile__("swp %0, %1, [%2]"
796 + : "0"(1), "r"(spinlock));
803 +static inline int testandset (int *p)
806 + __asm__ __volatile__("tas %1; sne %0"
815 +#include <ia64intrin.h>
817 +static inline int testandset (int *p)
819 + return __sync_lock_test_and_set (p, 1);
823 +typedef int spinlock_t;
825 +#define SPIN_LOCK_UNLOCKED 0
827 +#if defined(CONFIG_USER_ONLY)
828 +static inline void spin_lock(spinlock_t *lock)
830 + while (testandset(lock));
833 +static inline void spin_unlock(spinlock_t *lock)
838 +static inline int spin_trylock(spinlock_t *lock)
840 + return !testandset(lock);
843 +static inline void spin_lock(spinlock_t *lock)
847 +static inline void spin_unlock(spinlock_t *lock)
851 +static inline int spin_trylock(spinlock_t *lock)
857 +#endif /* ! _QEMU_SPINLOCK_H */