diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2004-04-25 21:21:33 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2004-04-25 21:21:33 +0000 |
commit | fbf9eeb34dfd9f9eb805410d90ffbb9ca2c0fbd1 (patch) | |
tree | 43e806f4068a01fcaa4855a631e04f148aae17a9 /cpu-exec.c | |
parent | 046d6672e2238342b1c174e45c41005be78285a7 (diff) | |
download | qemu-fbf9eeb34dfd9f9eb805410d90ffbb9ca2c0fbd1.zip qemu-fbf9eeb34dfd9f9eb805410d90ffbb9ca2c0fbd1.tar.gz qemu-fbf9eeb34dfd9f9eb805410d90ffbb9ca2c0fbd1.tar.bz2 |
added cpu_resume_from_signal() - irq fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@755 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'cpu-exec.c')
-rw-r--r-- | cpu-exec.c | 72 |
1 files changed, 52 insertions, 20 deletions
@@ -21,6 +21,20 @@ #include "exec.h" #include "disas.h" +#if !defined(CONFIG_SOFTMMU) +#undef EAX +#undef ECX +#undef EDX +#undef EBX +#undef ESP +#undef EBP +#undef ESI +#undef EDI +#undef EIP +#include <signal.h> +#include <sys/ucontext.h> +#endif + int tb_invalidated_flag; //#define DEBUG_EXEC @@ -34,6 +48,28 @@ void cpu_loop_exit(void) } #endif +/* exit the current TB from a signal handler. The host registers are + restored in a state compatible with the CPU emulator + */ +void cpu_resume_from_signal(CPUState *env1, void *puc) +{ +#if !defined(CONFIG_SOFTMMU) + struct ucontext *uc = puc; +#endif + + env = env1; + + /* XXX: restore cpu registers saved in host registers */ + +#if !defined(CONFIG_SOFTMMU) + if (puc) { + /* XXX: use siglongjmp ? */ + sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL); + } +#endif + longjmp(env->jmp_env, 1); +} + /* main execution loop */ int cpu_exec(CPUState *env1) @@ -190,12 +226,12 @@ int cpu_exec(CPUState *env1) (env->eflags & IF_MASK) && !(env->hflags & HF_INHIBIT_IRQ_MASK)) { int intno; + env->interrupt_request &= ~CPU_INTERRUPT_HARD; intno = cpu_get_pic_interrupt(env); if (loglevel & CPU_LOG_TB_IN_ASM) { fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno); } do_interrupt(intno, 0, 0, 0, 1); - env->interrupt_request &= ~CPU_INTERRUPT_HARD; /* ensure that no TB jump will be modified as the program flow was changed */ #ifdef __sparc__ @@ -548,6 +584,15 @@ int cpu_exec(CPUState *env1) return ret; } +/* must only be called from the generated code as an exception can be + generated */ +void tb_invalidate_page_range(target_ulong start, target_ulong end) +{ + target_ulong phys_addr; + phys_addr = get_phys_addr_code(env, start); + tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0); +} + #if defined(TARGET_I386) && defined(CONFIG_USER_ONLY) 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) #if !defined(CONFIG_SOFTMMU) -#undef EAX -#undef ECX -#undef EDX -#undef EBX -#undef ESP -#undef EBP -#undef ESI -#undef EDI -#undef EIP -#include <signal.h> -#include <sys/ucontext.h> - #if defined(TARGET_I386) /* '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, pc, address, is_write, *(unsigned long *)old_set); #endif /* XXX: locking issue */ - if (is_write && page_unprotect(address)) { + if (is_write && page_unprotect(address, pc, puc)) { return 1; } + /* see if it is an MMU fault */ ret = cpu_x86_handle_mmu_fault(env, address, is_write, ((env->hflags & HF_CPL_MASK) == 3), 0); @@ -655,8 +689,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, } else { /* activate soft MMU for this block */ env->hflags |= HF_SOFTMMU_MASK; - sigprocmask(SIG_SETMASK, old_set, NULL); - cpu_loop_exit(); + cpu_resume_from_signal(env, puc); } /* never comes here */ return 1; @@ -676,7 +709,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, void *puc) { /* XXX: locking issue */ - if (is_write && page_unprotect(address)) { + if (is_write && page_unprotect(address, pc, puc)) { return 1; } return 0; @@ -698,7 +731,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, pc, address, is_write, *(unsigned long *)old_set); #endif /* XXX: locking issue */ - if (is_write && page_unprotect(address)) { + if (is_write && page_unprotect(address, pc, puc)) { return 1; } @@ -727,8 +760,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, do_queue_exception_err(env->exception_index, env->error_code); } else { /* activate soft MMU for this block */ - sigprocmask(SIG_SETMASK, old_set, NULL); - cpu_loop_exit(); + cpu_resume_from_signal(env, puc); } /* never comes here */ return 1; |