Commit bf3e8bf11e78b271cde3ddadf9e4521585e42867

Authored by bellard
1 parent 9acbed06

experimental code copy support - CPU_INTERRUPT_EXITTB support


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@618 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 134 additions and 18 deletions
cpu-exec.c
... ... @@ -212,6 +212,16 @@ int cpu_exec(CPUState *env1)
212 212 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
213 213 }
214 214 #endif
  215 + if (interrupt_request & CPU_INTERRUPT_EXITTB) {
  216 + env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
  217 + /* ensure that no TB jump will be modified as
  218 + the program flow was changed */
  219 +#ifdef __sparc__
  220 + tmp_T0 = 0;
  221 +#else
  222 + T0 = 0;
  223 +#endif
  224 + }
215 225 if (interrupt_request & CPU_INTERRUPT_EXIT) {
216 226 env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
217 227 env->exception_index = EXCP_INTERRUPT;
... ... @@ -362,7 +372,12 @@ int cpu_exec(CPUState *env1)
362 372 T0 = tmp_T0;
363 373 #endif
364 374 /* see if we can patch the calling TB. */
365   - if (T0 != 0) {
  375 + if (T0 != 0
  376 +#if defined(TARGET_I386) && defined(USE_CODE_COPY)
  377 + && (tb->cflags & CF_CODE_COPY) ==
  378 + (((TranslationBlock *)(T0 & ~3))->cflags & CF_CODE_COPY)
  379 +#endif
  380 + ) {
366 381 spin_lock(&tb_lock);
367 382 tb_add_jump((TranslationBlock *)(T0 & ~3), T0 & 3, tb);
368 383 spin_unlock(&tb_lock);
... ... @@ -384,6 +399,74 @@ int cpu_exec(CPUState *env1)
384 399 : /* no outputs */
385 400 : "r" (gen_func)
386 401 : "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14");
  402 +#elif defined(TARGET_I386) && defined(USE_CODE_COPY)
  403 +{
  404 + if (!(tb->cflags & CF_CODE_COPY)) {
  405 + gen_func();
  406 + } else {
  407 + /* we work with native eflags */
  408 + CC_SRC = cc_table[CC_OP].compute_all();
  409 + CC_OP = CC_OP_EFLAGS;
  410 + asm(".globl exec_loop\n"
  411 + "\n"
  412 + "debug1:\n"
  413 + " pushl %%ebp\n"
  414 + " fs movl %10, %9\n"
  415 + " fs movl %11, %%eax\n"
  416 + " andl $0x400, %%eax\n"
  417 + " fs orl %8, %%eax\n"
  418 + " pushl %%eax\n"
  419 + " popf\n"
  420 + " fs movl %%esp, %12\n"
  421 + " fs movl %0, %%eax\n"
  422 + " fs movl %1, %%ecx\n"
  423 + " fs movl %2, %%edx\n"
  424 + " fs movl %3, %%ebx\n"
  425 + " fs movl %4, %%esp\n"
  426 + " fs movl %5, %%ebp\n"
  427 + " fs movl %6, %%esi\n"
  428 + " fs movl %7, %%edi\n"
  429 + " fs jmp *%9\n"
  430 + "exec_loop:\n"
  431 + " fs movl %%esp, %4\n"
  432 + " fs movl %12, %%esp\n"
  433 + " fs movl %%eax, %0\n"
  434 + " fs movl %%ecx, %1\n"
  435 + " fs movl %%edx, %2\n"
  436 + " fs movl %%ebx, %3\n"
  437 + " fs movl %%ebp, %5\n"
  438 + " fs movl %%esi, %6\n"
  439 + " fs movl %%edi, %7\n"
  440 + " pushf\n"
  441 + " popl %%eax\n"
  442 + " movl %%eax, %%ecx\n"
  443 + " andl $0x400, %%ecx\n"
  444 + " shrl $9, %%ecx\n"
  445 + " andl $0x8d5, %%eax\n"
  446 + " fs movl %%eax, %8\n"
  447 + " movl $1, %%eax\n"
  448 + " subl %%ecx, %%eax\n"
  449 + " fs movl %%eax, %11\n"
  450 + " fs movl %9, %%ebx\n" /* get T0 value */
  451 + " popl %%ebp\n"
  452 + :
  453 + : "m" (*(uint8_t *)offsetof(CPUState, regs[0])),
  454 + "m" (*(uint8_t *)offsetof(CPUState, regs[1])),
  455 + "m" (*(uint8_t *)offsetof(CPUState, regs[2])),
  456 + "m" (*(uint8_t *)offsetof(CPUState, regs[3])),
  457 + "m" (*(uint8_t *)offsetof(CPUState, regs[4])),
  458 + "m" (*(uint8_t *)offsetof(CPUState, regs[5])),
  459 + "m" (*(uint8_t *)offsetof(CPUState, regs[6])),
  460 + "m" (*(uint8_t *)offsetof(CPUState, regs[7])),
  461 + "m" (*(uint8_t *)offsetof(CPUState, cc_src)),
  462 + "m" (*(uint8_t *)offsetof(CPUState, tmp0)),
  463 + "a" (gen_func),
  464 + "m" (*(uint8_t *)offsetof(CPUState, df)),
  465 + "m" (*(uint8_t *)offsetof(CPUState, saved_esp))
  466 + : "%ecx", "%edx"
  467 + );
  468 + }
  469 +}
387 470 #else
388 471 gen_func();
389 472 #endif
... ... @@ -512,7 +595,8 @@ void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32)
512 595 write caused the exception and otherwise 0'. 'old_set' is the
513 596 signal set which should be restored */
514 597 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
515   - int is_write, sigset_t *old_set)
  598 + int is_write, sigset_t *old_set,
  599 + void *puc)
516 600 {
517 601 TranslationBlock *tb;
518 602 int ret;
... ... @@ -520,8 +604,8 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
520 604 if (cpu_single_env)
521 605 env = cpu_single_env; /* XXX: find a correct solution for multithread */
522 606 #if defined(DEBUG_SIGNAL)
523   - printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
524   - pc, address, is_write, *(unsigned long *)old_set);
  607 + qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
  608 + pc, address, is_write, *(unsigned long *)old_set);
525 609 #endif
526 610 /* XXX: locking issue */
527 611 if (is_write && page_unprotect(address)) {
... ... @@ -539,7 +623,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
539 623 if (tb) {
540 624 /* the PC is inside the translated code. It means that we have
541 625 a virtual CPU fault */
542   - cpu_restore_state(tb, env, pc);
  626 + cpu_restore_state(tb, env, pc, puc);
543 627 }
544 628 if (ret == 1) {
545 629 #if 0
... ... @@ -562,14 +646,16 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
562 646  
563 647 #elif defined(TARGET_ARM)
564 648 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
565   - int is_write, sigset_t *old_set)
  649 + int is_write, sigset_t *old_set,
  650 + void *puc)
566 651 {
567 652 /* XXX: do more */
568 653 return 0;
569 654 }
570 655 #elif defined(TARGET_SPARC)
571 656 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
572   - int is_write, sigset_t *old_set)
  657 + int is_write, sigset_t *old_set,
  658 + void *puc)
573 659 {
574 660 /* XXX: locking issue */
575 661 if (is_write && page_unprotect(address)) {
... ... @@ -579,7 +665,8 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
579 665 }
580 666 #elif defined (TARGET_PPC)
581 667 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
582   - int is_write, sigset_t *old_set)
  668 + int is_write, sigset_t *old_set,
  669 + void *puc)
583 670 {
584 671 TranslationBlock *tb;
585 672 int ret;
... ... @@ -609,7 +696,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
609 696 if (tb) {
610 697 /* the PC is inside the translated code. It means that we have
611 698 a virtual CPU fault */
612   - cpu_restore_state(tb, env, pc);
  699 + cpu_restore_state(tb, env, pc, puc);
613 700 }
614 701 if (ret == 1) {
615 702 #if 0
... ... @@ -618,7 +705,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
618 705 #endif
619 706 /* we restore the process signal mask as the sigreturn should
620 707 do it (XXX: use sigsetjmp) */
621   - sigprocmask(SIG_SETMASK, old_set, NULL);
  708 + sigprocmask(SIG_SETMASK, old_set, NULL);
622 709 do_queue_exception_err(env->exception_index, env->error_code);
623 710 } else {
624 711 /* activate soft MMU for this block */
... ... @@ -634,11 +721,32 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
634 721  
635 722 #if defined(__i386__)
636 723  
  724 +#if defined(USE_CODE_COPY)
  725 +static void cpu_send_trap(unsigned long pc, int trap,
  726 + struct ucontext *uc)
  727 +{
  728 + TranslationBlock *tb;
  729 +
  730 + if (cpu_single_env)
  731 + env = cpu_single_env; /* XXX: find a correct solution for multithread */
  732 + /* now we have a real cpu fault */
  733 + tb = tb_find_pc(pc);
  734 + if (tb) {
  735 + /* the PC is inside the translated code. It means that we have
  736 + a virtual CPU fault */
  737 + cpu_restore_state(tb, env, pc, uc);
  738 + }
  739 + sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
  740 + raise_exception_err(trap, env->error_code);
  741 +}
  742 +#endif
  743 +
637 744 int cpu_signal_handler(int host_signum, struct siginfo *info,
638 745 void *puc)
639 746 {
640 747 struct ucontext *uc = puc;
641 748 unsigned long pc;
  749 + int trapno;
642 750  
643 751 #ifndef REG_EIP
644 752 /* for glibc 2.1 */
... ... @@ -647,10 +755,18 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
647 755 #define REG_TRAPNO TRAPNO
648 756 #endif
649 757 pc = uc->uc_mcontext.gregs[REG_EIP];
650   - return handle_cpu_signal(pc, (unsigned long)info->si_addr,
651   - uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ?
652   - (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
653   - &uc->uc_sigmask);
  758 + trapno = uc->uc_mcontext.gregs[REG_TRAPNO];
  759 +#if defined(TARGET_I386) && defined(USE_CODE_COPY)
  760 + if (trapno == 0x00 || trapno == 0x05) {
  761 + /* send division by zero or bound exception */
  762 + cpu_send_trap(pc, trapno, uc);
  763 + return 1;
  764 + } else
  765 +#endif
  766 + return handle_cpu_signal(pc, (unsigned long)info->si_addr,
  767 + trapno == 0xe ?
  768 + (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
  769 + &uc->uc_sigmask, puc);
654 770 }
655 771  
656 772 #elif defined(__powerpc)
... ... @@ -674,7 +790,7 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
674 790 is_write = 1;
675 791 #endif
676 792 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
677   - is_write, &uc->uc_sigmask);
  793 + is_write, &uc->uc_sigmask, puc);
678 794 }
679 795  
680 796 #elif defined(__alpha__)
... ... @@ -704,7 +820,7 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
704 820 }
705 821  
706 822 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
707   - is_write, &uc->uc_sigmask);
  823 + is_write, &uc->uc_sigmask, puc);
708 824 }
709 825 #elif defined(__sparc__)
710 826  
... ... @@ -736,7 +852,7 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
736 852 }
737 853 }
738 854 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
739   - is_write, sigmask);
  855 + is_write, sigmask, NULL);
740 856 }
741 857  
742 858 #elif defined(__arm__)
... ... @@ -770,7 +886,7 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
770 886 is_write = 0;
771 887 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
772 888 is_write,
773   - &uc->uc_sigmask);
  889 + &uc->uc_sigmask, puc);
774 890 }
775 891  
776 892 #else
... ...