better locking - added PowerPC signal handler (add it for the other archs too because it needed for full exception support)

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@168 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
bellard 2003-05-14 21:50:54 +00:00
parent b333af0666
commit 25eb44841e

View File

@ -27,95 +27,16 @@
/* thread support */
#ifdef __powerpc__
static inline int testandset (int *p)
{
int ret;
__asm__ __volatile__ (
"0: lwarx %0,0,%1 ;"
" xor. %0,%3,%0;"
" bne 1f;"
" stwcx. %2,0,%1;"
" bne- 0b;"
"1: "
: "=&r" (ret)
: "r" (p), "r" (1), "r" (0)
: "cr0", "memory");
return ret;
}
#endif
#ifdef __i386__
static inline int testandset (int *p)
{
char ret;
long int readval;
__asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
: "=q" (ret), "=m" (*p), "=a" (readval)
: "r" (1), "m" (*p), "a" (0)
: "memory");
return ret;
}
#endif
#ifdef __s390__
static inline int testandset (int *p)
{
int ret;
__asm__ __volatile__ ("0: cs %0,%1,0(%2)\n"
" jl 0b"
: "=&d" (ret)
: "r" (1), "a" (p), "0" (*p)
: "cc", "memory" );
return ret;
}
#endif
#ifdef __alpha__
int testandset (int *p)
{
int ret;
unsigned long one;
__asm__ __volatile__ ("0: mov 1,%2\n"
" ldl_l %0,%1\n"
" stl_c %2,%1\n"
" beq %2,1f\n"
".subsection 2\n"
"1: br 0b\n"
".previous"
: "=r" (ret), "=m" (*p), "=r" (one)
: "m" (*p));
return ret;
}
#endif
#ifdef __sparc__
static inline int testandset (int *p)
{
int ret;
__asm__ __volatile__("ldstub [%1], %0"
: "=r" (ret)
: "r" (p)
: "memory");
return (ret ? 1 : 0);
}
#endif
int global_cpu_lock = 0;
spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
void cpu_lock(void)
{
while (testandset(&global_cpu_lock));
spin_lock(&global_cpu_lock);
}
void cpu_unlock(void)
{
global_cpu_lock = 0;
spin_unlock(&global_cpu_lock);
}
/* exception support */
@ -292,16 +213,16 @@ int cpu_x86_exec(CPUX86State *env1)
flags);
if (!tb) {
/* if no translated code available, then translate it now */
/* XXX: very inefficient: we lock all the cpus when
generating code */
cpu_lock();
/* very inefficient but safe: we lock all the cpus
when generating code */
spin_lock(&tb_lock);
tc_ptr = code_gen_ptr;
ret = cpu_x86_gen_code(code_gen_ptr, CODE_GEN_MAX_SIZE,
&code_gen_size, pc, cs_base, flags,
&code_size);
/* if invalid instruction, signal it */
if (ret != 0) {
cpu_unlock();
spin_unlock(&tb_lock);
raise_exception(EXCP06_ILLOP);
}
tb = tb_alloc((unsigned long)pc, code_size);
@ -311,7 +232,7 @@ int cpu_x86_exec(CPUX86State *env1)
tb->tc_ptr = tc_ptr;
tb->hash_next = NULL;
code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
cpu_unlock();
spin_unlock(&tb_lock);
}
#ifdef DEBUG_EXEC
if (loglevel) {
@ -412,6 +333,7 @@ static inline int handle_cpu_signal(unsigned long pc,
printf("qemu: SIGSEGV pc=0x%08lx address=%08lx wr=%d oldset=0x%08lx\n",
pc, address, is_write, *(unsigned long *)old_set);
#endif
/* XXX: locking issue */
if (is_write && page_unprotect(address)) {
sigprocmask(SIG_SETMASK, old_set, NULL);
return 1;
@ -454,8 +376,28 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ?
(uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
pold_set);
#elif defined(__powerpc)
struct ucontext *uc = puc;
struct pt_regs *regs = uc->uc_mcontext.regs;
unsigned long pc;
sigset_t *pold_set;
int is_write;
pc = regs->nip;
pold_set = &uc->uc_sigmask;
is_write = 0;
#if 0
/* ppc 4xx case */
if (regs->dsisr & 0x00800000)
is_write = 1;
#else
#warning No CPU specific signal handler: cannot handle target SIGSEGV events
if (regs->trap != 0x400 && (regs->dsisr & 0x02000000))
is_write = 1;
#endif
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
is_write, pold_set);
#else
#error CPU specific signal handler needed
return 0;
#endif
}