Commit 68a7931591fca65ac5dc2e1b23688e08d1c328a6
1 parent
c9159e53
reduced irq latency
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@296 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
6 changed files
with
35 additions
and
29 deletions
cpu-all.h
... | ... | @@ -309,6 +309,10 @@ void page_unprotect_range(uint8_t *data, unsigned long data_size); |
309 | 309 | void cpu_abort(CPUState *env, const char *fmt, ...); |
310 | 310 | extern CPUState *cpu_single_env; |
311 | 311 | |
312 | +#define CPU_INTERRUPT_EXIT 0x01 /* wants exit from main loop */ | |
313 | +#define CPU_INTERRUPT_HARD 0x02 /* hardware interrupt pending */ | |
314 | +void cpu_interrupt(CPUX86State *s, int mask); | |
315 | + | |
312 | 316 | /* gdb stub API */ |
313 | 317 | extern int gdbstub_fd; |
314 | 318 | CPUState *cpu_gdbstub_get_env(void *opaque); | ... | ... |
cpu-exec.c
... | ... | @@ -71,7 +71,7 @@ int cpu_exec(CPUState *env1) |
71 | 71 | #ifdef __sparc__ |
72 | 72 | int saved_i7, tmp_T0; |
73 | 73 | #endif |
74 | - int code_gen_size, ret; | |
74 | + int code_gen_size, ret, interrupt_request; | |
75 | 75 | void (*gen_func)(void); |
76 | 76 | TranslationBlock *tb, **ptb; |
77 | 77 | uint8_t *tc_ptr, *cs_base, *pc; |
... | ... | @@ -139,7 +139,6 @@ int cpu_exec(CPUState *env1) |
139 | 139 | #else |
140 | 140 | #error unsupported target CPU |
141 | 141 | #endif |
142 | - env->interrupt_request = 0; | |
143 | 142 | env->exception_index = -1; |
144 | 143 | |
145 | 144 | /* prepare setjmp context for exception handling */ |
... | ... | @@ -176,28 +175,32 @@ int cpu_exec(CPUState *env1) |
176 | 175 | } |
177 | 176 | env->exception_index = -1; |
178 | 177 | } |
179 | -#if defined(TARGET_I386) | |
180 | - /* if hardware interrupt pending, we execute it */ | |
181 | - if (env->hard_interrupt_request && | |
182 | - (env->eflags & IF_MASK)) { | |
183 | - int intno; | |
184 | - intno = cpu_x86_get_pic_interrupt(env); | |
185 | - if (loglevel) { | |
186 | - fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno); | |
187 | - } | |
188 | - do_interrupt(intno, 0, 0, 0); | |
189 | - env->hard_interrupt_request = 0; | |
190 | - } | |
191 | -#endif | |
192 | 178 | T0 = 0; /* force lookup of first TB */ |
193 | 179 | for(;;) { |
194 | 180 | #ifdef __sparc__ |
195 | 181 | /* g1 can be modified by some libc? functions */ |
196 | 182 | tmp_T0 = T0; |
197 | 183 | #endif |
198 | - if (env->interrupt_request) { | |
199 | - env->exception_index = EXCP_INTERRUPT; | |
200 | - cpu_loop_exit(); | |
184 | + interrupt_request = env->interrupt_request; | |
185 | + if (interrupt_request) { | |
186 | +#if defined(TARGET_I386) | |
187 | + /* if hardware interrupt pending, we execute it */ | |
188 | + if ((interrupt_request & CPU_INTERRUPT_HARD) && | |
189 | + (env->eflags & IF_MASK)) { | |
190 | + int intno; | |
191 | + intno = cpu_x86_get_pic_interrupt(env); | |
192 | + if (loglevel) { | |
193 | + fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno); | |
194 | + } | |
195 | + do_interrupt(intno, 0, 0, 0); | |
196 | + env->interrupt_request &= ~CPU_INTERRUPT_HARD; | |
197 | + } | |
198 | +#endif | |
199 | + if (interrupt_request & CPU_INTERRUPT_EXIT) { | |
200 | + env->interrupt_request &= ~CPU_INTERRUPT_EXIT; | |
201 | + env->exception_index = EXCP_INTERRUPT; | |
202 | + cpu_loop_exit(); | |
203 | + } | |
201 | 204 | } |
202 | 205 | #ifdef DEBUG_EXEC |
203 | 206 | if (loglevel) { |
... | ... | @@ -212,7 +215,7 @@ int cpu_exec(CPUState *env1) |
212 | 215 | env->regs[R_EBP] = EBP; |
213 | 216 | env->regs[R_ESP] = ESP; |
214 | 217 | env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK); |
215 | - cpu_x86_dump_state(env, logfile, 0); | |
218 | + cpu_x86_dump_state(env, logfile, X86_DUMP_CCOP); | |
216 | 219 | env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); |
217 | 220 | #elif defined(TARGET_ARM) |
218 | 221 | cpu_arm_dump_state(env, logfile, 0); |
... | ... | @@ -454,7 +457,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, |
454 | 457 | { |
455 | 458 | TranslationBlock *tb; |
456 | 459 | int ret; |
457 | - | |
460 | + | |
458 | 461 | if (cpu_single_env) |
459 | 462 | env = cpu_single_env; /* XXX: find a correct solution for multithread */ |
460 | 463 | #if defined(DEBUG_SIGNAL) | ... | ... |
cpu-i386.h
... | ... | @@ -254,10 +254,7 @@ typedef struct CPUX86State { |
254 | 254 | struct TranslationBlock *current_tb; /* currently executing TB */ |
255 | 255 | uint32_t cr[5]; /* NOTE: cr1 is unused */ |
256 | 256 | uint32_t dr[8]; /* debug registers */ |
257 | - int interrupt_request; /* if true, will exit from cpu_exec() ASAP */ | |
258 | - /* if true, will call cpu_x86_get_pic_interrupt() ASAP to get the | |
259 | - request interrupt number */ | |
260 | - int hard_interrupt_request; | |
257 | + int interrupt_request; | |
261 | 258 | int user_mode_only; /* user mode only simulation */ |
262 | 259 | |
263 | 260 | /* user data */ |
... | ... | @@ -275,7 +272,6 @@ int cpu_x86_inl(CPUX86State *env, int addr); |
275 | 272 | |
276 | 273 | CPUX86State *cpu_x86_init(void); |
277 | 274 | int cpu_x86_exec(CPUX86State *s); |
278 | -void cpu_x86_interrupt(CPUX86State *s); | |
279 | 275 | void cpu_x86_close(CPUX86State *s); |
280 | 276 | int cpu_x86_get_pic_interrupt(CPUX86State *s); |
281 | 277 | ... | ... |
exec.c
... | ... | @@ -617,11 +617,12 @@ static void tb_reset_jump_recursive(TranslationBlock *tb) |
617 | 617 | tb_reset_jump_recursive2(tb, 1); |
618 | 618 | } |
619 | 619 | |
620 | -void cpu_interrupt(CPUState *env) | |
620 | +/* mask must never be zero */ | |
621 | +void cpu_interrupt(CPUState *env, int mask) | |
621 | 622 | { |
622 | 623 | TranslationBlock *tb; |
623 | - | |
624 | - env->interrupt_request = 1; | |
624 | + | |
625 | + env->interrupt_request |= mask; | |
625 | 626 | /* if the cpu is currently executing code, we must unlink it and |
626 | 627 | all the potentially executing TB */ |
627 | 628 | tb = env->current_tb; | ... | ... |
linux-user/signal.c
... | ... | @@ -333,7 +333,7 @@ static void host_signal_handler(int host_signum, siginfo_t *info, |
333 | 333 | host_to_target_siginfo_noswap(&tinfo, info); |
334 | 334 | if (queue_signal(sig, &tinfo) == 1) { |
335 | 335 | /* interrupt the virtual CPU as soon as possible */ |
336 | - cpu_interrupt(global_env); | |
336 | + cpu_interrupt(global_env, CPU_INTERRUPT_EXIT); | |
337 | 337 | } |
338 | 338 | } |
339 | 339 | ... | ... |
translate-i386.c
... | ... | @@ -3331,12 +3331,14 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
3331 | 3331 | if (!s->vm86) { |
3332 | 3332 | if (s->cpl <= s->iopl) { |
3333 | 3333 | gen_op_sti(); |
3334 | + s->is_jmp = 2; /* give a chance to handle pending irqs */ | |
3334 | 3335 | } else { |
3335 | 3336 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3336 | 3337 | } |
3337 | 3338 | } else { |
3338 | 3339 | if (s->iopl == 3) { |
3339 | 3340 | gen_op_sti(); |
3341 | + s->is_jmp = 2; /* give a chance to handle pending irqs */ | |
3340 | 3342 | } else { |
3341 | 3343 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3342 | 3344 | } | ... | ... |