Revision 25eb4484
b/exec-i386.c | ||
---|---|---|
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 | 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 | 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 | 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 | 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 |
} |
Also available in: Unified diff