Commit fbf9eeb34dfd9f9eb805410d90ffbb9ca2c0fbd1
1 parent
046d6672
added cpu_resume_from_signal() - irq fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@755 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
52 additions
and
20 deletions
cpu-exec.c
... | ... | @@ -21,6 +21,20 @@ |
21 | 21 | #include "exec.h" |
22 | 22 | #include "disas.h" |
23 | 23 | |
24 | +#if !defined(CONFIG_SOFTMMU) | |
25 | +#undef EAX | |
26 | +#undef ECX | |
27 | +#undef EDX | |
28 | +#undef EBX | |
29 | +#undef ESP | |
30 | +#undef EBP | |
31 | +#undef ESI | |
32 | +#undef EDI | |
33 | +#undef EIP | |
34 | +#include <signal.h> | |
35 | +#include <sys/ucontext.h> | |
36 | +#endif | |
37 | + | |
24 | 38 | int tb_invalidated_flag; |
25 | 39 | |
26 | 40 | //#define DEBUG_EXEC |
... | ... | @@ -34,6 +48,28 @@ void cpu_loop_exit(void) |
34 | 48 | } |
35 | 49 | #endif |
36 | 50 | |
51 | +/* exit the current TB from a signal handler. The host registers are | |
52 | + restored in a state compatible with the CPU emulator | |
53 | + */ | |
54 | +void cpu_resume_from_signal(CPUState *env1, void *puc) | |
55 | +{ | |
56 | +#if !defined(CONFIG_SOFTMMU) | |
57 | + struct ucontext *uc = puc; | |
58 | +#endif | |
59 | + | |
60 | + env = env1; | |
61 | + | |
62 | + /* XXX: restore cpu registers saved in host registers */ | |
63 | + | |
64 | +#if !defined(CONFIG_SOFTMMU) | |
65 | + if (puc) { | |
66 | + /* XXX: use siglongjmp ? */ | |
67 | + sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL); | |
68 | + } | |
69 | +#endif | |
70 | + longjmp(env->jmp_env, 1); | |
71 | +} | |
72 | + | |
37 | 73 | /* main execution loop */ |
38 | 74 | |
39 | 75 | int cpu_exec(CPUState *env1) |
... | ... | @@ -190,12 +226,12 @@ int cpu_exec(CPUState *env1) |
190 | 226 | (env->eflags & IF_MASK) && |
191 | 227 | !(env->hflags & HF_INHIBIT_IRQ_MASK)) { |
192 | 228 | int intno; |
229 | + env->interrupt_request &= ~CPU_INTERRUPT_HARD; | |
193 | 230 | intno = cpu_get_pic_interrupt(env); |
194 | 231 | if (loglevel & CPU_LOG_TB_IN_ASM) { |
195 | 232 | fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno); |
196 | 233 | } |
197 | 234 | do_interrupt(intno, 0, 0, 0, 1); |
198 | - env->interrupt_request &= ~CPU_INTERRUPT_HARD; | |
199 | 235 | /* ensure that no TB jump will be modified as |
200 | 236 | the program flow was changed */ |
201 | 237 | #ifdef __sparc__ |
... | ... | @@ -548,6 +584,15 @@ int cpu_exec(CPUState *env1) |
548 | 584 | return ret; |
549 | 585 | } |
550 | 586 | |
587 | +/* must only be called from the generated code as an exception can be | |
588 | + generated */ | |
589 | +void tb_invalidate_page_range(target_ulong start, target_ulong end) | |
590 | +{ | |
591 | + target_ulong phys_addr; | |
592 | + phys_addr = get_phys_addr_code(env, start); | |
593 | + tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0); | |
594 | +} | |
595 | + | |
551 | 596 | #if defined(TARGET_I386) && defined(CONFIG_USER_ONLY) |
552 | 597 | |
553 | 598 | void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector) |
... | ... | @@ -594,18 +639,6 @@ void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32) |
594 | 639 | |
595 | 640 | #if !defined(CONFIG_SOFTMMU) |
596 | 641 | |
597 | -#undef EAX | |
598 | -#undef ECX | |
599 | -#undef EDX | |
600 | -#undef EBX | |
601 | -#undef ESP | |
602 | -#undef EBP | |
603 | -#undef ESI | |
604 | -#undef EDI | |
605 | -#undef EIP | |
606 | -#include <signal.h> | |
607 | -#include <sys/ucontext.h> | |
608 | - | |
609 | 642 | #if defined(TARGET_I386) |
610 | 643 | |
611 | 644 | /* 'pc' is the host PC at which the exception was raised. 'address' is |
... | ... | @@ -626,9 +659,10 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, |
626 | 659 | pc, address, is_write, *(unsigned long *)old_set); |
627 | 660 | #endif |
628 | 661 | /* XXX: locking issue */ |
629 | - if (is_write && page_unprotect(address)) { | |
662 | + if (is_write && page_unprotect(address, pc, puc)) { | |
630 | 663 | return 1; |
631 | 664 | } |
665 | + | |
632 | 666 | /* see if it is an MMU fault */ |
633 | 667 | ret = cpu_x86_handle_mmu_fault(env, address, is_write, |
634 | 668 | ((env->hflags & HF_CPL_MASK) == 3), 0); |
... | ... | @@ -655,8 +689,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, |
655 | 689 | } else { |
656 | 690 | /* activate soft MMU for this block */ |
657 | 691 | env->hflags |= HF_SOFTMMU_MASK; |
658 | - sigprocmask(SIG_SETMASK, old_set, NULL); | |
659 | - cpu_loop_exit(); | |
692 | + cpu_resume_from_signal(env, puc); | |
660 | 693 | } |
661 | 694 | /* never comes here */ |
662 | 695 | return 1; |
... | ... | @@ -676,7 +709,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, |
676 | 709 | void *puc) |
677 | 710 | { |
678 | 711 | /* XXX: locking issue */ |
679 | - if (is_write && page_unprotect(address)) { | |
712 | + if (is_write && page_unprotect(address, pc, puc)) { | |
680 | 713 | return 1; |
681 | 714 | } |
682 | 715 | return 0; |
... | ... | @@ -698,7 +731,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, |
698 | 731 | pc, address, is_write, *(unsigned long *)old_set); |
699 | 732 | #endif |
700 | 733 | /* XXX: locking issue */ |
701 | - if (is_write && page_unprotect(address)) { | |
734 | + if (is_write && page_unprotect(address, pc, puc)) { | |
702 | 735 | return 1; |
703 | 736 | } |
704 | 737 | |
... | ... | @@ -727,8 +760,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, |
727 | 760 | do_queue_exception_err(env->exception_index, env->error_code); |
728 | 761 | } else { |
729 | 762 | /* activate soft MMU for this block */ |
730 | - sigprocmask(SIG_SETMASK, old_set, NULL); | |
731 | - cpu_loop_exit(); | |
763 | + cpu_resume_from_signal(env, puc); | |
732 | 764 | } |
733 | 765 | /* never comes here */ |
734 | 766 | return 1; | ... | ... |