Commit 25eb44841e4125da67338320d8af0b4859c672de

Authored by bellard
1 parent b333af06

better locking - added PowerPC signal handler (add it for the other archs too be…

…cause it needed for full exception support)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@168 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 30 additions and 88 deletions
exec-i386.c
... ... @@ -27,95 +27,16 @@
27 27  
28 28 /* thread support */
29 29  
30   -#ifdef __powerpc__
31   -static inline int testandset (int *p)
32   -{
33   - int ret;
34   - __asm__ __volatile__ (
35   - "0: lwarx %0,0,%1 ;"
36   - " xor. %0,%3,%0;"
37   - " bne 1f;"
38   - " stwcx. %2,0,%1;"
39   - " bne- 0b;"
40   - "1: "
41   - : "=&r" (ret)
42   - : "r" (p), "r" (1), "r" (0)
43   - : "cr0", "memory");
44   - return ret;
45   -}
46   -#endif
47   -
48   -#ifdef __i386__
49   -static inline int testandset (int *p)
50   -{
51   - char ret;
52   - long int readval;
53   -
54   - __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
55   - : "=q" (ret), "=m" (*p), "=a" (readval)
56   - : "r" (1), "m" (*p), "a" (0)
57   - : "memory");
58   - return ret;
59   -}
60   -#endif
61   -
62   -#ifdef __s390__
63   -static inline int testandset (int *p)
64   -{
65   - int ret;
66   -
67   - __asm__ __volatile__ ("0: cs %0,%1,0(%2)\n"
68   - " jl 0b"
69   - : "=&d" (ret)
70   - : "r" (1), "a" (p), "0" (*p)
71   - : "cc", "memory" );
72   - return ret;
73   -}
74   -#endif
75   -
76   -#ifdef __alpha__
77   -int testandset (int *p)
78   -{
79   - int ret;
80   - unsigned long one;
81   -
82   - __asm__ __volatile__ ("0: mov 1,%2\n"
83   - " ldl_l %0,%1\n"
84   - " stl_c %2,%1\n"
85   - " beq %2,1f\n"
86   - ".subsection 2\n"
87   - "1: br 0b\n"
88   - ".previous"
89   - : "=r" (ret), "=m" (*p), "=r" (one)
90   - : "m" (*p));
91   - return ret;
92   -}
93   -#endif
94   -
95   -#ifdef __sparc__
96   -static inline int testandset (int *p)
97   -{
98   - int ret;
99   -
100   - __asm__ __volatile__("ldstub [%1], %0"
101   - : "=r" (ret)
102   - : "r" (p)
103   - : "memory");
104   -
105   - return (ret ? 1 : 0);
106   -}
107   -#endif
108   -
109   -int global_cpu_lock = 0;
  30 +spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
110 31  
111 32 void cpu_lock(void)
112 33 {
113   - while (testandset(&global_cpu_lock));
  34 + spin_lock(&global_cpu_lock);
114 35 }
115 36  
116 37 void cpu_unlock(void)
117 38 {
118   - global_cpu_lock = 0;
  39 + spin_unlock(&global_cpu_lock);
119 40 }
120 41  
121 42 /* exception support */
... ... @@ -292,16 +213,16 @@ int cpu_x86_exec(CPUX86State *env1)
292 213 flags);
293 214 if (!tb) {
294 215 /* if no translated code available, then translate it now */
295   - /* XXX: very inefficient: we lock all the cpus when
296   - generating code */
297   - cpu_lock();
  216 + /* very inefficient but safe: we lock all the cpus
  217 + when generating code */
  218 + spin_lock(&tb_lock);
298 219 tc_ptr = code_gen_ptr;
299 220 ret = cpu_x86_gen_code(code_gen_ptr, CODE_GEN_MAX_SIZE,
300 221 &code_gen_size, pc, cs_base, flags,
301 222 &code_size);
302 223 /* if invalid instruction, signal it */
303 224 if (ret != 0) {
304   - cpu_unlock();
  225 + spin_unlock(&tb_lock);
305 226 raise_exception(EXCP06_ILLOP);
306 227 }
307 228 tb = tb_alloc((unsigned long)pc, code_size);
... ... @@ -311,7 +232,7 @@ int cpu_x86_exec(CPUX86State *env1)
311 232 tb->tc_ptr = tc_ptr;
312 233 tb->hash_next = NULL;
313 234 code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
314   - cpu_unlock();
  235 + spin_unlock(&tb_lock);
315 236 }
316 237 #ifdef DEBUG_EXEC
317 238 if (loglevel) {
... ... @@ -412,6 +333,7 @@ static inline int handle_cpu_signal(unsigned long pc,
412 333 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx wr=%d oldset=0x%08lx\n",
413 334 pc, address, is_write, *(unsigned long *)old_set);
414 335 #endif
  336 + /* XXX: locking issue */
415 337 if (is_write && page_unprotect(address)) {
416 338 sigprocmask(SIG_SETMASK, old_set, NULL);
417 339 return 1;
... ... @@ -454,8 +376,28 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
454 376 uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ?
455 377 (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
456 378 pold_set);
  379 +#elif defined(__powerpc)
  380 + struct ucontext *uc = puc;
  381 + struct pt_regs *regs = uc->uc_mcontext.regs;
  382 + unsigned long pc;
  383 + sigset_t *pold_set;
  384 + int is_write;
  385 +
  386 + pc = regs->nip;
  387 + pold_set = &uc->uc_sigmask;
  388 + is_write = 0;
  389 +#if 0
  390 + /* ppc 4xx case */
  391 + if (regs->dsisr & 0x00800000)
  392 + is_write = 1;
  393 +#else
  394 + if (regs->trap != 0x400 && (regs->dsisr & 0x02000000))
  395 + is_write = 1;
  396 +#endif
  397 + return handle_cpu_signal(pc, (unsigned long)info->si_addr,
  398 + is_write, pold_set);
457 399 #else
458   -#warning No CPU specific signal handler: cannot handle target SIGSEGV events
  400 +#error CPU specific signal handler needed
459 401 return 0;
460 402 #endif
461 403 }
... ...