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,6 +212,16 @@ int cpu_exec(CPUState *env1)
212 env->interrupt_request &= ~CPU_INTERRUPT_HARD; 212 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
213 } 213 }
214 #endif 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 if (interrupt_request & CPU_INTERRUPT_EXIT) { 225 if (interrupt_request & CPU_INTERRUPT_EXIT) {
216 env->interrupt_request &= ~CPU_INTERRUPT_EXIT; 226 env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
217 env->exception_index = EXCP_INTERRUPT; 227 env->exception_index = EXCP_INTERRUPT;
@@ -362,7 +372,12 @@ int cpu_exec(CPUState *env1) @@ -362,7 +372,12 @@ int cpu_exec(CPUState *env1)
362 T0 = tmp_T0; 372 T0 = tmp_T0;
363 #endif 373 #endif
364 /* see if we can patch the calling TB. */ 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 spin_lock(&tb_lock); 381 spin_lock(&tb_lock);
367 tb_add_jump((TranslationBlock *)(T0 & ~3), T0 & 3, tb); 382 tb_add_jump((TranslationBlock *)(T0 & ~3), T0 & 3, tb);
368 spin_unlock(&tb_lock); 383 spin_unlock(&tb_lock);
@@ -384,6 +399,74 @@ int cpu_exec(CPUState *env1) @@ -384,6 +399,74 @@ int cpu_exec(CPUState *env1)
384 : /* no outputs */ 399 : /* no outputs */
385 : "r" (gen_func) 400 : "r" (gen_func)
386 : "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14"); 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 #else 470 #else
388 gen_func(); 471 gen_func();
389 #endif 472 #endif
@@ -512,7 +595,8 @@ void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32) @@ -512,7 +595,8 @@ void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32)
512 write caused the exception and otherwise 0'. 'old_set' is the 595 write caused the exception and otherwise 0'. 'old_set' is the
513 signal set which should be restored */ 596 signal set which should be restored */
514 static inline int handle_cpu_signal(unsigned long pc, unsigned long address, 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 TranslationBlock *tb; 601 TranslationBlock *tb;
518 int ret; 602 int ret;
@@ -520,8 +604,8 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, @@ -520,8 +604,8 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
520 if (cpu_single_env) 604 if (cpu_single_env)
521 env = cpu_single_env; /* XXX: find a correct solution for multithread */ 605 env = cpu_single_env; /* XXX: find a correct solution for multithread */
522 #if defined(DEBUG_SIGNAL) 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 #endif 609 #endif
526 /* XXX: locking issue */ 610 /* XXX: locking issue */
527 if (is_write && page_unprotect(address)) { 611 if (is_write && page_unprotect(address)) {
@@ -539,7 +623,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, @@ -539,7 +623,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
539 if (tb) { 623 if (tb) {
540 /* the PC is inside the translated code. It means that we have 624 /* the PC is inside the translated code. It means that we have
541 a virtual CPU fault */ 625 a virtual CPU fault */
542 - cpu_restore_state(tb, env, pc); 626 + cpu_restore_state(tb, env, pc, puc);
543 } 627 }
544 if (ret == 1) { 628 if (ret == 1) {
545 #if 0 629 #if 0
@@ -562,14 +646,16 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, @@ -562,14 +646,16 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
562 646
563 #elif defined(TARGET_ARM) 647 #elif defined(TARGET_ARM)
564 static inline int handle_cpu_signal(unsigned long pc, unsigned long address, 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 /* XXX: do more */ 652 /* XXX: do more */
568 return 0; 653 return 0;
569 } 654 }
570 #elif defined(TARGET_SPARC) 655 #elif defined(TARGET_SPARC)
571 static inline int handle_cpu_signal(unsigned long pc, unsigned long address, 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 /* XXX: locking issue */ 660 /* XXX: locking issue */
575 if (is_write && page_unprotect(address)) { 661 if (is_write && page_unprotect(address)) {
@@ -579,7 +665,8 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, @@ -579,7 +665,8 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
579 } 665 }
580 #elif defined (TARGET_PPC) 666 #elif defined (TARGET_PPC)
581 static inline int handle_cpu_signal(unsigned long pc, unsigned long address, 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 TranslationBlock *tb; 671 TranslationBlock *tb;
585 int ret; 672 int ret;
@@ -609,7 +696,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, @@ -609,7 +696,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
609 if (tb) { 696 if (tb) {
610 /* the PC is inside the translated code. It means that we have 697 /* the PC is inside the translated code. It means that we have
611 a virtual CPU fault */ 698 a virtual CPU fault */
612 - cpu_restore_state(tb, env, pc); 699 + cpu_restore_state(tb, env, pc, puc);
613 } 700 }
614 if (ret == 1) { 701 if (ret == 1) {
615 #if 0 702 #if 0
@@ -618,7 +705,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, @@ -618,7 +705,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
618 #endif 705 #endif
619 /* we restore the process signal mask as the sigreturn should 706 /* we restore the process signal mask as the sigreturn should
620 do it (XXX: use sigsetjmp) */ 707 do it (XXX: use sigsetjmp) */
621 - sigprocmask(SIG_SETMASK, old_set, NULL); 708 + sigprocmask(SIG_SETMASK, old_set, NULL);
622 do_queue_exception_err(env->exception_index, env->error_code); 709 do_queue_exception_err(env->exception_index, env->error_code);
623 } else { 710 } else {
624 /* activate soft MMU for this block */ 711 /* activate soft MMU for this block */
@@ -634,11 +721,32 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, @@ -634,11 +721,32 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
634 721
635 #if defined(__i386__) 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 int cpu_signal_handler(int host_signum, struct siginfo *info, 744 int cpu_signal_handler(int host_signum, struct siginfo *info,
638 void *puc) 745 void *puc)
639 { 746 {
640 struct ucontext *uc = puc; 747 struct ucontext *uc = puc;
641 unsigned long pc; 748 unsigned long pc;
  749 + int trapno;
642 750
643 #ifndef REG_EIP 751 #ifndef REG_EIP
644 /* for glibc 2.1 */ 752 /* for glibc 2.1 */
@@ -647,10 +755,18 @@ int cpu_signal_handler(int host_signum, struct siginfo *info, @@ -647,10 +755,18 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
647 #define REG_TRAPNO TRAPNO 755 #define REG_TRAPNO TRAPNO
648 #endif 756 #endif
649 pc = uc->uc_mcontext.gregs[REG_EIP]; 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 #elif defined(__powerpc) 772 #elif defined(__powerpc)
@@ -674,7 +790,7 @@ int cpu_signal_handler(int host_signum, struct siginfo *info, @@ -674,7 +790,7 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
674 is_write = 1; 790 is_write = 1;
675 #endif 791 #endif
676 return handle_cpu_signal(pc, (unsigned long)info->si_addr, 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 #elif defined(__alpha__) 796 #elif defined(__alpha__)
@@ -704,7 +820,7 @@ int cpu_signal_handler(int host_signum, struct siginfo *info, @@ -704,7 +820,7 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
704 } 820 }
705 821
706 return handle_cpu_signal(pc, (unsigned long)info->si_addr, 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 #elif defined(__sparc__) 825 #elif defined(__sparc__)
710 826
@@ -736,7 +852,7 @@ int cpu_signal_handler(int host_signum, struct siginfo *info, @@ -736,7 +852,7 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
736 } 852 }
737 } 853 }
738 return handle_cpu_signal(pc, (unsigned long)info->si_addr, 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 #elif defined(__arm__) 858 #elif defined(__arm__)
@@ -770,7 +886,7 @@ int cpu_signal_handler(int host_signum, struct siginfo *info, @@ -770,7 +886,7 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
770 is_write = 0; 886 is_write = 0;
771 return handle_cpu_signal(pc, (unsigned long)info->si_addr, 887 return handle_cpu_signal(pc, (unsigned long)info->si_addr,
772 is_write, 888 is_write,
773 - &uc->uc_sigmask); 889 + &uc->uc_sigmask, puc);
774 } 890 }
775 891
776 #else 892 #else