X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;ds=sidebyside;f=exec.c;h=e7f5081d0bc7aef38456228adde8e57ab8e6a83f;hb=4690764bba3a489d5180106d08970ced59113e22;hp=2e84f557b4fa0dd98ea5e4ff0b7abee2b0bfd479;hpb=a513fe19ac4896a09c6c338204d76c39e652451f;p=qemu diff --git a/exec.c b/exec.c index 2e84f55..e7f5081 100644 --- a/exec.c +++ b/exec.c @@ -26,11 +26,17 @@ #include #include +#include "config.h" +#ifdef TARGET_I386 #include "cpu-i386.h" +#endif +#ifdef TARGET_ARM +#include "cpu-arm.h" +#endif #include "exec.h" //#define DEBUG_TB_INVALIDATE -#define DEBUG_FLUSH +//#define DEBUG_FLUSH /* make various TB consistency checks */ //#define DEBUG_TB_CHECK @@ -70,7 +76,7 @@ unsigned long host_page_mask; static PageDesc *l1_map[L1_SIZE]; -void page_init(void) +static void page_init(void) { /* NOTE: we can always suppose that host_page_size >= TARGET_PAGE_SIZE */ @@ -190,10 +196,11 @@ void page_set_flags(unsigned long start, unsigned long end, int flags) spin_unlock(&tb_lock); } -void cpu_x86_tblocks_init(void) +void cpu_exec_init(void) { if (!code_gen_ptr) { code_gen_ptr = code_gen_buffer; + page_init(); } } @@ -562,3 +569,121 @@ TranslationBlock *tb_find_pc(unsigned long tc_ptr) } return &tbs[m_max]; } + +static void tb_reset_jump_recursive(TranslationBlock *tb); + +static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n) +{ + TranslationBlock *tb1, *tb_next, **ptb; + unsigned int n1; + + tb1 = tb->jmp_next[n]; + if (tb1 != NULL) { + /* find head of list */ + for(;;) { + n1 = (long)tb1 & 3; + tb1 = (TranslationBlock *)((long)tb1 & ~3); + if (n1 == 2) + break; + tb1 = tb1->jmp_next[n1]; + } + /* we are now sure now that tb jumps to tb1 */ + tb_next = tb1; + + /* remove tb from the jmp_first list */ + ptb = &tb_next->jmp_first; + for(;;) { + tb1 = *ptb; + n1 = (long)tb1 & 3; + tb1 = (TranslationBlock *)((long)tb1 & ~3); + if (n1 == n && tb1 == tb) + break; + ptb = &tb1->jmp_next[n1]; + } + *ptb = tb->jmp_next[n]; + tb->jmp_next[n] = NULL; + + /* suppress the jump to next tb in generated code */ + tb_reset_jump(tb, n); + + /* suppress jumps in the tb on which we could have jump */ + tb_reset_jump_recursive(tb_next); + } +} + +static void tb_reset_jump_recursive(TranslationBlock *tb) +{ + tb_reset_jump_recursive2(tb, 0); + tb_reset_jump_recursive2(tb, 1); +} + +/* mask must never be zero */ +void cpu_interrupt(CPUState *env, int mask) +{ + TranslationBlock *tb; + + env->interrupt_request |= mask; + /* if the cpu is currently executing code, we must unlink it and + all the potentially executing TB */ + tb = env->current_tb; + if (tb) { + tb_reset_jump_recursive(tb); + } +} + + +void cpu_abort(CPUState *env, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + fprintf(stderr, "qemu: fatal: "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); +#ifdef TARGET_I386 + cpu_x86_dump_state(env, stderr, X86_DUMP_FPU | X86_DUMP_CCOP); +#endif + va_end(ap); + abort(); +} + +#ifdef TARGET_I386 +/* unmap all maped pages and flush all associated code */ +void page_unmap(void) +{ + PageDesc *p, *pmap; + unsigned long addr; + int i, j, ret, j1; + + for(i = 0; i < L1_SIZE; i++) { + pmap = l1_map[i]; + if (pmap) { + p = pmap; + for(j = 0;j < L2_SIZE;) { + if (p->flags & PAGE_VALID) { + addr = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS); + /* we try to find a range to make less syscalls */ + j1 = j; + p++; + j++; + while (j < L2_SIZE && (p->flags & PAGE_VALID)) { + p++; + j++; + } + ret = munmap((void *)addr, (j - j1) << TARGET_PAGE_BITS); + if (ret != 0) { + fprintf(stderr, "Could not unmap page 0x%08lx\n", addr); + exit(1); + } + } else { + p++; + j++; + } + } + free(pmap); + l1_map[i] = NULL; + } + } + tb_flush(); +} +#endif