summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-06-30 13:12:32 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-06-30 13:12:32 +0000
commit68a7931591fca65ac5dc2e1b23688e08d1c328a6 (patch)
treed7b9f908c23ad553d88eef3ab594ec9c700d31a1
parentc9159e5321628a29bcc26216f0166e9cdd7e4b26 (diff)
downloadqemu-68a7931591fca65ac5dc2e1b23688e08d1c328a6.tar.gz
qemu-68a7931591fca65ac5dc2e1b23688e08d1c328a6.tar.bz2
qemu-68a7931591fca65ac5dc2e1b23688e08d1c328a6.zip
reduced irq latency
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@296 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r--cpu-all.h4
-rw-r--r--cpu-exec.c43
-rw-r--r--cpu-i386.h6
-rw-r--r--exec.c7
-rw-r--r--linux-user/signal.c2
-rw-r--r--translate-i386.c2
6 files changed, 35 insertions, 29 deletions
diff --git a/cpu-all.h b/cpu-all.h
index cc0a4ea33f..5c414e805f 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -309,6 +309,10 @@ void page_unprotect_range(uint8_t *data, unsigned long data_size);
void cpu_abort(CPUState *env, const char *fmt, ...);
extern CPUState *cpu_single_env;
+#define CPU_INTERRUPT_EXIT 0x01 /* wants exit from main loop */
+#define CPU_INTERRUPT_HARD 0x02 /* hardware interrupt pending */
+void cpu_interrupt(CPUX86State *s, int mask);
+
/* gdb stub API */
extern int gdbstub_fd;
CPUState *cpu_gdbstub_get_env(void *opaque);
diff --git a/cpu-exec.c b/cpu-exec.c
index aa2ee3a9e3..4da3641e6f 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -71,7 +71,7 @@ int cpu_exec(CPUState *env1)
#ifdef __sparc__
int saved_i7, tmp_T0;
#endif
- int code_gen_size, ret;
+ int code_gen_size, ret, interrupt_request;
void (*gen_func)(void);
TranslationBlock *tb, **ptb;
uint8_t *tc_ptr, *cs_base, *pc;
@@ -139,7 +139,6 @@ int cpu_exec(CPUState *env1)
#else
#error unsupported target CPU
#endif
- env->interrupt_request = 0;
env->exception_index = -1;
/* prepare setjmp context for exception handling */
@@ -176,28 +175,32 @@ int cpu_exec(CPUState *env1)
}
env->exception_index = -1;
}
-#if defined(TARGET_I386)
- /* if hardware interrupt pending, we execute it */
- if (env->hard_interrupt_request &&
- (env->eflags & IF_MASK)) {
- int intno;
- intno = cpu_x86_get_pic_interrupt(env);
- if (loglevel) {
- fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
- }
- do_interrupt(intno, 0, 0, 0);
- env->hard_interrupt_request = 0;
- }
-#endif
T0 = 0; /* force lookup of first TB */
for(;;) {
#ifdef __sparc__
/* g1 can be modified by some libc? functions */
tmp_T0 = T0;
#endif
- if (env->interrupt_request) {
- env->exception_index = EXCP_INTERRUPT;
- cpu_loop_exit();
+ interrupt_request = env->interrupt_request;
+ if (interrupt_request) {
+#if defined(TARGET_I386)
+ /* if hardware interrupt pending, we execute it */
+ if ((interrupt_request & CPU_INTERRUPT_HARD) &&
+ (env->eflags & IF_MASK)) {
+ int intno;
+ intno = cpu_x86_get_pic_interrupt(env);
+ if (loglevel) {
+ fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
+ }
+ do_interrupt(intno, 0, 0, 0);
+ env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+ }
+#endif
+ if (interrupt_request & CPU_INTERRUPT_EXIT) {
+ env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
+ env->exception_index = EXCP_INTERRUPT;
+ cpu_loop_exit();
+ }
}
#ifdef DEBUG_EXEC
if (loglevel) {
@@ -212,7 +215,7 @@ int cpu_exec(CPUState *env1)
env->regs[R_EBP] = EBP;
env->regs[R_ESP] = ESP;
env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
- cpu_x86_dump_state(env, logfile, 0);
+ cpu_x86_dump_state(env, logfile, X86_DUMP_CCOP);
env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
#elif defined(TARGET_ARM)
cpu_arm_dump_state(env, logfile, 0);
@@ -454,7 +457,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
{
TranslationBlock *tb;
int ret;
-
+
if (cpu_single_env)
env = cpu_single_env; /* XXX: find a correct solution for multithread */
#if defined(DEBUG_SIGNAL)
diff --git a/cpu-i386.h b/cpu-i386.h
index 6c7afbf6e2..4029746c80 100644
--- a/cpu-i386.h
+++ b/cpu-i386.h
@@ -254,10 +254,7 @@ typedef struct CPUX86State {
struct TranslationBlock *current_tb; /* currently executing TB */
uint32_t cr[5]; /* NOTE: cr1 is unused */
uint32_t dr[8]; /* debug registers */
- int interrupt_request; /* if true, will exit from cpu_exec() ASAP */
- /* if true, will call cpu_x86_get_pic_interrupt() ASAP to get the
- request interrupt number */
- int hard_interrupt_request;
+ int interrupt_request;
int user_mode_only; /* user mode only simulation */
/* user data */
@@ -275,7 +272,6 @@ int cpu_x86_inl(CPUX86State *env, int addr);
CPUX86State *cpu_x86_init(void);
int cpu_x86_exec(CPUX86State *s);
-void cpu_x86_interrupt(CPUX86State *s);
void cpu_x86_close(CPUX86State *s);
int cpu_x86_get_pic_interrupt(CPUX86State *s);
diff --git a/exec.c b/exec.c
index 4de0c60f1a..e7f5081d0b 100644
--- a/exec.c
+++ b/exec.c
@@ -617,11 +617,12 @@ static void tb_reset_jump_recursive(TranslationBlock *tb)
tb_reset_jump_recursive2(tb, 1);
}
-void cpu_interrupt(CPUState *env)
+/* mask must never be zero */
+void cpu_interrupt(CPUState *env, int mask)
{
TranslationBlock *tb;
-
- env->interrupt_request = 1;
+
+ env->interrupt_request |= mask;
/* if the cpu is currently executing code, we must unlink it and
all the potentially executing TB */
tb = env->current_tb;
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 8c757dd4a1..74aaeea681 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -333,7 +333,7 @@ static void host_signal_handler(int host_signum, siginfo_t *info,
host_to_target_siginfo_noswap(&tinfo, info);
if (queue_signal(sig, &tinfo) == 1) {
/* interrupt the virtual CPU as soon as possible */
- cpu_interrupt(global_env);
+ cpu_interrupt(global_env, CPU_INTERRUPT_EXIT);
}
}
diff --git a/translate-i386.c b/translate-i386.c
index b477ac4adb..8a7147c556 100644
--- a/translate-i386.c
+++ b/translate-i386.c
@@ -3331,12 +3331,14 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
if (!s->vm86) {
if (s->cpl <= s->iopl) {
gen_op_sti();
+ s->is_jmp = 2; /* give a chance to handle pending irqs */
} else {
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
}
} else {
if (s->iopl == 3) {
gen_op_sti();
+ s->is_jmp = 2; /* give a chance to handle pending irqs */
} else {
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
}