Loading cpu-defs.h +1 −0 Original line number Diff line number Diff line Loading @@ -166,6 +166,7 @@ typedef struct CPUTLBEntry { \ void *next_cpu; /* next CPU sharing TB cache */ \ int cpu_index; /* CPU index (informative) */ \ int running; /* Nonzero if cpu is currently running(usermode). */ \ /* user data */ \ void *opaque; \ \ Loading cpu-exec.c +11 −14 Original line number Diff line number Diff line Loading @@ -44,7 +44,6 @@ #endif int tb_invalidated_flag; static unsigned long next_tb; //#define DEBUG_EXEC //#define DEBUG_SIGNAL Loading Loading @@ -93,8 +92,6 @@ static TranslationBlock *tb_find_slow(target_ulong pc, target_ulong phys_pc, phys_page1, phys_page2, virt_page2; uint8_t *tc_ptr; spin_lock(&tb_lock); tb_invalidated_flag = 0; regs_to_env(); /* XXX: do it just before cpu_gen_code() */ Loading Loading @@ -155,7 +152,6 @@ static TranslationBlock *tb_find_slow(target_ulong pc, found: /* we add the TB in the virtual pc hash table */ env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb; spin_unlock(&tb_lock); return tb; } Loading Loading @@ -228,14 +224,6 @@ static inline TranslationBlock *tb_find_fast(void) if (__builtin_expect(!tb || tb->pc != pc || tb->cs_base != cs_base || tb->flags != flags, 0)) { tb = tb_find_slow(pc, cs_base, flags); /* Note: we do it here to avoid a gcc bug on Mac OS X when doing it in tb_find_slow */ if (tb_invalidated_flag) { /* as some TB could have been invalidated because of memory exceptions while generating the code, we must recompute the hash index here */ next_tb = 0; } } return tb; } Loading @@ -249,6 +237,7 @@ int cpu_exec(CPUState *env1) int ret, interrupt_request; TranslationBlock *tb; uint8_t *tc_ptr; unsigned long next_tb; if (cpu_halted(env1) == EXCP_HALTED) return EXCP_HALTED; Loading Loading @@ -577,7 +566,16 @@ int cpu_exec(CPUState *env1) #endif } #endif spin_lock(&tb_lock); tb = tb_find_fast(); /* Note: we do it here to avoid a gcc bug on Mac OS X when doing it in tb_find_slow */ if (tb_invalidated_flag) { /* as some TB could have been invalidated because of memory exceptions while generating the code, we must recompute the hash index here */ next_tb = 0; } #ifdef DEBUG_EXEC if ((loglevel & CPU_LOG_EXEC)) { fprintf(logfile, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n", Loading @@ -594,11 +592,10 @@ int cpu_exec(CPUState *env1) (env->kqemu_enabled != 2) && #endif tb->page_addr[1] == -1) { spin_lock(&tb_lock); tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb); spin_unlock(&tb_lock); } } spin_unlock(&tb_lock); tc_ptr = tb->tc_ptr; env->current_tb = tb; /* execute the generated code */ Loading exec-all.h +1 −211 Original line number Diff line number Diff line Loading @@ -302,217 +302,7 @@ extern CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4]; extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4]; extern void *io_mem_opaque[IO_MEM_NB_ENTRIES]; #if defined(__hppa__) typedef int spinlock_t[4]; #define SPIN_LOCK_UNLOCKED { 1, 1, 1, 1 } static inline void resetlock (spinlock_t *p) { (*p)[0] = (*p)[1] = (*p)[2] = (*p)[3] = 1; } #else typedef int spinlock_t; #define SPIN_LOCK_UNLOCKED 0 static inline void resetlock (spinlock_t *p) { *p = SPIN_LOCK_UNLOCKED; } #endif #if defined(__powerpc__) static inline int testandset (int *p) { int ret; __asm__ __volatile__ ( "0: lwarx %0,0,%1\n" " xor. %0,%3,%0\n" " bne 1f\n" " stwcx. %2,0,%1\n" " bne- 0b\n" "1: " : "=&r" (ret) : "r" (p), "r" (1), "r" (0) : "cr0", "memory"); return ret; } #elif defined(__i386__) static inline int testandset (int *p) { long int readval = 0; __asm__ __volatile__ ("lock; cmpxchgl %2, %0" : "+m" (*p), "+a" (readval) : "r" (1) : "cc"); return readval; } #elif defined(__x86_64__) static inline int testandset (int *p) { long int readval = 0; __asm__ __volatile__ ("lock; cmpxchgl %2, %0" : "+m" (*p), "+a" (readval) : "r" (1) : "cc"); return readval; } #elif defined(__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; } #elif defined(__alpha__) static inline 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; } #elif defined(__sparc__) static inline int testandset (int *p) { int ret; __asm__ __volatile__("ldstub [%1], %0" : "=r" (ret) : "r" (p) : "memory"); return (ret ? 1 : 0); } #elif defined(__arm__) static inline int testandset (int *spinlock) { register unsigned int ret; __asm__ __volatile__("swp %0, %1, [%2]" : "=r"(ret) : "0"(1), "r"(spinlock)); return ret; } #elif defined(__mc68000) static inline int testandset (int *p) { char ret; __asm__ __volatile__("tas %1; sne %0" : "=r" (ret) : "m" (p) : "cc","memory"); return ret; } #elif defined(__hppa__) /* Because malloc only guarantees 8-byte alignment for malloc'd data, and GCC only guarantees 8-byte alignment for stack locals, we can't be assured of 16-byte alignment for atomic lock data even if we specify "__attribute ((aligned(16)))" in the type declaration. So, we use a struct containing an array of four ints for the atomic lock type and dynamically select the 16-byte aligned int from the array for the semaphore. */ #define __PA_LDCW_ALIGNMENT 16 static inline void *ldcw_align (void *p) { unsigned long a = (unsigned long)p; a = (a + __PA_LDCW_ALIGNMENT - 1) & ~(__PA_LDCW_ALIGNMENT - 1); return (void *)a; } static inline int testandset (spinlock_t *p) { unsigned int ret; p = ldcw_align(p); __asm__ __volatile__("ldcw 0(%1),%0" : "=r" (ret) : "r" (p) : "memory" ); return !ret; } #elif defined(__ia64) #include <ia64intrin.h> static inline int testandset (int *p) { return __sync_lock_test_and_set (p, 1); } #elif defined(__mips__) static inline int testandset (int *p) { int ret; __asm__ __volatile__ ( " .set push \n" " .set noat \n" " .set mips2 \n" "1: li $1, 1 \n" " ll %0, %1 \n" " sc $1, %1 \n" " beqz $1, 1b \n" " .set pop " : "=r" (ret), "+R" (*p) : : "memory"); return ret; } #else #error unimplemented CPU support #endif #if defined(CONFIG_USER_ONLY) static inline void spin_lock(spinlock_t *lock) { while (testandset(lock)); } static inline void spin_unlock(spinlock_t *lock) { resetlock(lock); } static inline int spin_trylock(spinlock_t *lock) { return !testandset(lock); } #else static inline void spin_lock(spinlock_t *lock) { } static inline void spin_unlock(spinlock_t *lock) { } static inline int spin_trylock(spinlock_t *lock) { return 1; } #endif #include "qemu-lock.h" extern spinlock_t tb_lock; Loading exec.c +11 −2 Original line number Diff line number Diff line Loading @@ -1341,10 +1341,20 @@ void cpu_set_log_filename(const char *filename) /* mask must never be zero, except for A20 change call */ void cpu_interrupt(CPUState *env, int mask) { #if !defined(USE_NPTL) TranslationBlock *tb; static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED; #endif /* FIXME: This is probably not threadsafe. A different thread could be in the mittle of a read-modify-write operation. */ env->interrupt_request |= mask; #if defined(USE_NPTL) /* FIXME: TB unchaining isn't SMP safe. For now just ignore the problem and hope the cpu will stop of its own accord. For userspace emulation this often isn't actually as bad as it sounds. Often signals are used primarily to interrupt blocking syscalls. */ #else /* if the cpu is currently executing code, we must unlink it and all the potentially executing TB */ tb = env->current_tb; Loading @@ -1353,6 +1363,7 @@ void cpu_interrupt(CPUState *env, int mask) tb_reset_jump_recursive(tb); resetlock(&interrupt_lock); } #endif } void cpu_reset_interrupt(CPUState *env, int mask) Loading Loading @@ -2015,7 +2026,6 @@ void page_set_flags(target_ulong start, target_ulong end, int flags) end = TARGET_PAGE_ALIGN(end); if (flags & PAGE_WRITE) flags |= PAGE_WRITE_ORG; spin_lock(&tb_lock); for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) { p = page_find_alloc(addr >> TARGET_PAGE_BITS); /* if the write protection is set, then we invalidate the code Loading @@ -2027,7 +2037,6 @@ void page_set_flags(target_ulong start, target_ulong end, int flags) } p->flags = flags; } spin_unlock(&tb_lock); } int page_check_range(target_ulong start, target_ulong len, int flags) Loading linux-user/elfload.c +2 −2 Original line number Diff line number Diff line Loading @@ -89,7 +89,7 @@ enum { static const char *get_elf_platform(void) { static char elf_platform[] = "i386"; int family = (global_env->cpuid_version >> 8) & 0xff; int family = (thread_env->cpuid_version >> 8) & 0xff; if (family > 6) family = 6; if (family >= 3) Loading @@ -101,7 +101,7 @@ static const char *get_elf_platform(void) static uint32_t get_elf_hwcap(void) { return global_env->cpuid_features; return thread_env->cpuid_features; } #ifdef TARGET_X86_64 Loading Loading
cpu-defs.h +1 −0 Original line number Diff line number Diff line Loading @@ -166,6 +166,7 @@ typedef struct CPUTLBEntry { \ void *next_cpu; /* next CPU sharing TB cache */ \ int cpu_index; /* CPU index (informative) */ \ int running; /* Nonzero if cpu is currently running(usermode). */ \ /* user data */ \ void *opaque; \ \ Loading
cpu-exec.c +11 −14 Original line number Diff line number Diff line Loading @@ -44,7 +44,6 @@ #endif int tb_invalidated_flag; static unsigned long next_tb; //#define DEBUG_EXEC //#define DEBUG_SIGNAL Loading Loading @@ -93,8 +92,6 @@ static TranslationBlock *tb_find_slow(target_ulong pc, target_ulong phys_pc, phys_page1, phys_page2, virt_page2; uint8_t *tc_ptr; spin_lock(&tb_lock); tb_invalidated_flag = 0; regs_to_env(); /* XXX: do it just before cpu_gen_code() */ Loading Loading @@ -155,7 +152,6 @@ static TranslationBlock *tb_find_slow(target_ulong pc, found: /* we add the TB in the virtual pc hash table */ env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb; spin_unlock(&tb_lock); return tb; } Loading Loading @@ -228,14 +224,6 @@ static inline TranslationBlock *tb_find_fast(void) if (__builtin_expect(!tb || tb->pc != pc || tb->cs_base != cs_base || tb->flags != flags, 0)) { tb = tb_find_slow(pc, cs_base, flags); /* Note: we do it here to avoid a gcc bug on Mac OS X when doing it in tb_find_slow */ if (tb_invalidated_flag) { /* as some TB could have been invalidated because of memory exceptions while generating the code, we must recompute the hash index here */ next_tb = 0; } } return tb; } Loading @@ -249,6 +237,7 @@ int cpu_exec(CPUState *env1) int ret, interrupt_request; TranslationBlock *tb; uint8_t *tc_ptr; unsigned long next_tb; if (cpu_halted(env1) == EXCP_HALTED) return EXCP_HALTED; Loading Loading @@ -577,7 +566,16 @@ int cpu_exec(CPUState *env1) #endif } #endif spin_lock(&tb_lock); tb = tb_find_fast(); /* Note: we do it here to avoid a gcc bug on Mac OS X when doing it in tb_find_slow */ if (tb_invalidated_flag) { /* as some TB could have been invalidated because of memory exceptions while generating the code, we must recompute the hash index here */ next_tb = 0; } #ifdef DEBUG_EXEC if ((loglevel & CPU_LOG_EXEC)) { fprintf(logfile, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n", Loading @@ -594,11 +592,10 @@ int cpu_exec(CPUState *env1) (env->kqemu_enabled != 2) && #endif tb->page_addr[1] == -1) { spin_lock(&tb_lock); tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb); spin_unlock(&tb_lock); } } spin_unlock(&tb_lock); tc_ptr = tb->tc_ptr; env->current_tb = tb; /* execute the generated code */ Loading
exec-all.h +1 −211 Original line number Diff line number Diff line Loading @@ -302,217 +302,7 @@ extern CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4]; extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4]; extern void *io_mem_opaque[IO_MEM_NB_ENTRIES]; #if defined(__hppa__) typedef int spinlock_t[4]; #define SPIN_LOCK_UNLOCKED { 1, 1, 1, 1 } static inline void resetlock (spinlock_t *p) { (*p)[0] = (*p)[1] = (*p)[2] = (*p)[3] = 1; } #else typedef int spinlock_t; #define SPIN_LOCK_UNLOCKED 0 static inline void resetlock (spinlock_t *p) { *p = SPIN_LOCK_UNLOCKED; } #endif #if defined(__powerpc__) static inline int testandset (int *p) { int ret; __asm__ __volatile__ ( "0: lwarx %0,0,%1\n" " xor. %0,%3,%0\n" " bne 1f\n" " stwcx. %2,0,%1\n" " bne- 0b\n" "1: " : "=&r" (ret) : "r" (p), "r" (1), "r" (0) : "cr0", "memory"); return ret; } #elif defined(__i386__) static inline int testandset (int *p) { long int readval = 0; __asm__ __volatile__ ("lock; cmpxchgl %2, %0" : "+m" (*p), "+a" (readval) : "r" (1) : "cc"); return readval; } #elif defined(__x86_64__) static inline int testandset (int *p) { long int readval = 0; __asm__ __volatile__ ("lock; cmpxchgl %2, %0" : "+m" (*p), "+a" (readval) : "r" (1) : "cc"); return readval; } #elif defined(__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; } #elif defined(__alpha__) static inline 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; } #elif defined(__sparc__) static inline int testandset (int *p) { int ret; __asm__ __volatile__("ldstub [%1], %0" : "=r" (ret) : "r" (p) : "memory"); return (ret ? 1 : 0); } #elif defined(__arm__) static inline int testandset (int *spinlock) { register unsigned int ret; __asm__ __volatile__("swp %0, %1, [%2]" : "=r"(ret) : "0"(1), "r"(spinlock)); return ret; } #elif defined(__mc68000) static inline int testandset (int *p) { char ret; __asm__ __volatile__("tas %1; sne %0" : "=r" (ret) : "m" (p) : "cc","memory"); return ret; } #elif defined(__hppa__) /* Because malloc only guarantees 8-byte alignment for malloc'd data, and GCC only guarantees 8-byte alignment for stack locals, we can't be assured of 16-byte alignment for atomic lock data even if we specify "__attribute ((aligned(16)))" in the type declaration. So, we use a struct containing an array of four ints for the atomic lock type and dynamically select the 16-byte aligned int from the array for the semaphore. */ #define __PA_LDCW_ALIGNMENT 16 static inline void *ldcw_align (void *p) { unsigned long a = (unsigned long)p; a = (a + __PA_LDCW_ALIGNMENT - 1) & ~(__PA_LDCW_ALIGNMENT - 1); return (void *)a; } static inline int testandset (spinlock_t *p) { unsigned int ret; p = ldcw_align(p); __asm__ __volatile__("ldcw 0(%1),%0" : "=r" (ret) : "r" (p) : "memory" ); return !ret; } #elif defined(__ia64) #include <ia64intrin.h> static inline int testandset (int *p) { return __sync_lock_test_and_set (p, 1); } #elif defined(__mips__) static inline int testandset (int *p) { int ret; __asm__ __volatile__ ( " .set push \n" " .set noat \n" " .set mips2 \n" "1: li $1, 1 \n" " ll %0, %1 \n" " sc $1, %1 \n" " beqz $1, 1b \n" " .set pop " : "=r" (ret), "+R" (*p) : : "memory"); return ret; } #else #error unimplemented CPU support #endif #if defined(CONFIG_USER_ONLY) static inline void spin_lock(spinlock_t *lock) { while (testandset(lock)); } static inline void spin_unlock(spinlock_t *lock) { resetlock(lock); } static inline int spin_trylock(spinlock_t *lock) { return !testandset(lock); } #else static inline void spin_lock(spinlock_t *lock) { } static inline void spin_unlock(spinlock_t *lock) { } static inline int spin_trylock(spinlock_t *lock) { return 1; } #endif #include "qemu-lock.h" extern spinlock_t tb_lock; Loading
exec.c +11 −2 Original line number Diff line number Diff line Loading @@ -1341,10 +1341,20 @@ void cpu_set_log_filename(const char *filename) /* mask must never be zero, except for A20 change call */ void cpu_interrupt(CPUState *env, int mask) { #if !defined(USE_NPTL) TranslationBlock *tb; static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED; #endif /* FIXME: This is probably not threadsafe. A different thread could be in the mittle of a read-modify-write operation. */ env->interrupt_request |= mask; #if defined(USE_NPTL) /* FIXME: TB unchaining isn't SMP safe. For now just ignore the problem and hope the cpu will stop of its own accord. For userspace emulation this often isn't actually as bad as it sounds. Often signals are used primarily to interrupt blocking syscalls. */ #else /* if the cpu is currently executing code, we must unlink it and all the potentially executing TB */ tb = env->current_tb; Loading @@ -1353,6 +1363,7 @@ void cpu_interrupt(CPUState *env, int mask) tb_reset_jump_recursive(tb); resetlock(&interrupt_lock); } #endif } void cpu_reset_interrupt(CPUState *env, int mask) Loading Loading @@ -2015,7 +2026,6 @@ void page_set_flags(target_ulong start, target_ulong end, int flags) end = TARGET_PAGE_ALIGN(end); if (flags & PAGE_WRITE) flags |= PAGE_WRITE_ORG; spin_lock(&tb_lock); for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) { p = page_find_alloc(addr >> TARGET_PAGE_BITS); /* if the write protection is set, then we invalidate the code Loading @@ -2027,7 +2037,6 @@ void page_set_flags(target_ulong start, target_ulong end, int flags) } p->flags = flags; } spin_unlock(&tb_lock); } int page_check_range(target_ulong start, target_ulong len, int flags) Loading
linux-user/elfload.c +2 −2 Original line number Diff line number Diff line Loading @@ -89,7 +89,7 @@ enum { static const char *get_elf_platform(void) { static char elf_platform[] = "i386"; int family = (global_env->cpuid_version >> 8) & 0xff; int family = (thread_env->cpuid_version >> 8) & 0xff; if (family > 6) family = 6; if (family >= 3) Loading @@ -101,7 +101,7 @@ static const char *get_elf_platform(void) static uint32_t get_elf_hwcap(void) { return global_env->cpuid_features; return thread_env->cpuid_features; } #ifdef TARGET_X86_64 Loading