mirror of
https://git.proxmox.com/git/qemu
synced 2025-08-05 03:34:59 +00:00
Fix crash due to invalid env->current_tb (Adam Lackorzynski, Paul Brook, me)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4317 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
c75a823c80
commit
b5fc09ae52
68
cpu-exec.c
68
cpu-exec.c
@ -36,6 +36,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
int tb_invalidated_flag;
|
int tb_invalidated_flag;
|
||||||
|
static unsigned long next_tb;
|
||||||
|
|
||||||
//#define DEBUG_EXEC
|
//#define DEBUG_EXEC
|
||||||
//#define DEBUG_SIGNAL
|
//#define DEBUG_SIGNAL
|
||||||
@ -273,14 +274,12 @@ static inline TranslationBlock *tb_find_fast(void)
|
|||||||
/* as some TB could have been invalidated because
|
/* as some TB could have been invalidated because
|
||||||
of memory exceptions while generating the code, we
|
of memory exceptions while generating the code, we
|
||||||
must recompute the hash index here */
|
must recompute the hash index here */
|
||||||
T0 = 0;
|
next_tb = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return tb;
|
return tb;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define BREAK_CHAIN T0 = 0
|
|
||||||
|
|
||||||
/* main execution loop */
|
/* main execution loop */
|
||||||
|
|
||||||
int cpu_exec(CPUState *env1)
|
int cpu_exec(CPUState *env1)
|
||||||
@ -293,7 +292,7 @@ int cpu_exec(CPUState *env1)
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
int ret, interrupt_request;
|
int ret, interrupt_request;
|
||||||
long (*gen_func)(void);
|
unsigned long (*gen_func)(void);
|
||||||
TranslationBlock *tb;
|
TranslationBlock *tb;
|
||||||
uint8_t *tc_ptr;
|
uint8_t *tc_ptr;
|
||||||
|
|
||||||
@ -414,7 +413,7 @@ int cpu_exec(CPUState *env1)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
T0 = 0; /* force lookup of first TB */
|
next_tb = 0; /* force lookup of first TB */
|
||||||
for(;;) {
|
for(;;) {
|
||||||
SAVE_GLOBALS();
|
SAVE_GLOBALS();
|
||||||
interrupt_request = env->interrupt_request;
|
interrupt_request = env->interrupt_request;
|
||||||
@ -443,13 +442,13 @@ int cpu_exec(CPUState *env1)
|
|||||||
svm_check_intercept(SVM_EXIT_SMI);
|
svm_check_intercept(SVM_EXIT_SMI);
|
||||||
env->interrupt_request &= ~CPU_INTERRUPT_SMI;
|
env->interrupt_request &= ~CPU_INTERRUPT_SMI;
|
||||||
do_smm_enter();
|
do_smm_enter();
|
||||||
BREAK_CHAIN;
|
next_tb = 0;
|
||||||
} else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
|
} else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
|
||||||
!(env->hflags & HF_NMI_MASK)) {
|
!(env->hflags & HF_NMI_MASK)) {
|
||||||
env->interrupt_request &= ~CPU_INTERRUPT_NMI;
|
env->interrupt_request &= ~CPU_INTERRUPT_NMI;
|
||||||
env->hflags |= HF_NMI_MASK;
|
env->hflags |= HF_NMI_MASK;
|
||||||
do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
|
do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
|
||||||
BREAK_CHAIN;
|
next_tb = 0;
|
||||||
} else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
|
} else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
|
||||||
(env->eflags & IF_MASK || env->hflags & HF_HIF_MASK) &&
|
(env->eflags & IF_MASK || env->hflags & HF_HIF_MASK) &&
|
||||||
!(env->hflags & HF_INHIBIT_IRQ_MASK)) {
|
!(env->hflags & HF_INHIBIT_IRQ_MASK)) {
|
||||||
@ -463,7 +462,7 @@ int cpu_exec(CPUState *env1)
|
|||||||
do_interrupt(intno, 0, 0, 0, 1);
|
do_interrupt(intno, 0, 0, 0, 1);
|
||||||
/* ensure that no TB jump will be modified as
|
/* ensure that no TB jump will be modified as
|
||||||
the program flow was changed */
|
the program flow was changed */
|
||||||
BREAK_CHAIN;
|
next_tb = 0;
|
||||||
#if !defined(CONFIG_USER_ONLY)
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
} else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
|
} else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
|
||||||
(env->eflags & IF_MASK) && !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
|
(env->eflags & IF_MASK) && !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
|
||||||
@ -477,7 +476,7 @@ int cpu_exec(CPUState *env1)
|
|||||||
do_interrupt(intno, 0, 0, -1, 1);
|
do_interrupt(intno, 0, 0, -1, 1);
|
||||||
stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl),
|
stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl),
|
||||||
ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl)) & ~V_IRQ_MASK);
|
ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl)) & ~V_IRQ_MASK);
|
||||||
BREAK_CHAIN;
|
next_tb = 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#elif defined(TARGET_PPC)
|
#elif defined(TARGET_PPC)
|
||||||
@ -490,7 +489,7 @@ int cpu_exec(CPUState *env1)
|
|||||||
ppc_hw_interrupt(env);
|
ppc_hw_interrupt(env);
|
||||||
if (env->pending_interrupts == 0)
|
if (env->pending_interrupts == 0)
|
||||||
env->interrupt_request &= ~CPU_INTERRUPT_HARD;
|
env->interrupt_request &= ~CPU_INTERRUPT_HARD;
|
||||||
BREAK_CHAIN;
|
next_tb = 0;
|
||||||
}
|
}
|
||||||
#elif defined(TARGET_MIPS)
|
#elif defined(TARGET_MIPS)
|
||||||
if ((interrupt_request & CPU_INTERRUPT_HARD) &&
|
if ((interrupt_request & CPU_INTERRUPT_HARD) &&
|
||||||
@ -503,7 +502,7 @@ int cpu_exec(CPUState *env1)
|
|||||||
env->exception_index = EXCP_EXT_INTERRUPT;
|
env->exception_index = EXCP_EXT_INTERRUPT;
|
||||||
env->error_code = 0;
|
env->error_code = 0;
|
||||||
do_interrupt(env);
|
do_interrupt(env);
|
||||||
BREAK_CHAIN;
|
next_tb = 0;
|
||||||
}
|
}
|
||||||
#elif defined(TARGET_SPARC)
|
#elif defined(TARGET_SPARC)
|
||||||
if ((interrupt_request & CPU_INTERRUPT_HARD) &&
|
if ((interrupt_request & CPU_INTERRUPT_HARD) &&
|
||||||
@ -520,7 +519,7 @@ int cpu_exec(CPUState *env1)
|
|||||||
#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
|
#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
|
||||||
cpu_check_irqs(env);
|
cpu_check_irqs(env);
|
||||||
#endif
|
#endif
|
||||||
BREAK_CHAIN;
|
next_tb = 0;
|
||||||
}
|
}
|
||||||
} else if (interrupt_request & CPU_INTERRUPT_TIMER) {
|
} else if (interrupt_request & CPU_INTERRUPT_TIMER) {
|
||||||
//do_interrupt(0, 0, 0, 0, 0);
|
//do_interrupt(0, 0, 0, 0, 0);
|
||||||
@ -531,7 +530,7 @@ int cpu_exec(CPUState *env1)
|
|||||||
&& !(env->uncached_cpsr & CPSR_F)) {
|
&& !(env->uncached_cpsr & CPSR_F)) {
|
||||||
env->exception_index = EXCP_FIQ;
|
env->exception_index = EXCP_FIQ;
|
||||||
do_interrupt(env);
|
do_interrupt(env);
|
||||||
BREAK_CHAIN;
|
next_tb = 0;
|
||||||
}
|
}
|
||||||
/* ARMv7-M interrupt return works by loading a magic value
|
/* ARMv7-M interrupt return works by loading a magic value
|
||||||
into the PC. On real hardware the load causes the
|
into the PC. On real hardware the load causes the
|
||||||
@ -547,22 +546,22 @@ int cpu_exec(CPUState *env1)
|
|||||||
|| !(env->uncached_cpsr & CPSR_I))) {
|
|| !(env->uncached_cpsr & CPSR_I))) {
|
||||||
env->exception_index = EXCP_IRQ;
|
env->exception_index = EXCP_IRQ;
|
||||||
do_interrupt(env);
|
do_interrupt(env);
|
||||||
BREAK_CHAIN;
|
next_tb = 0;
|
||||||
}
|
}
|
||||||
#elif defined(TARGET_SH4)
|
#elif defined(TARGET_SH4)
|
||||||
if (interrupt_request & CPU_INTERRUPT_HARD) {
|
if (interrupt_request & CPU_INTERRUPT_HARD) {
|
||||||
do_interrupt(env);
|
do_interrupt(env);
|
||||||
BREAK_CHAIN;
|
next_tb = 0;
|
||||||
}
|
}
|
||||||
#elif defined(TARGET_ALPHA)
|
#elif defined(TARGET_ALPHA)
|
||||||
if (interrupt_request & CPU_INTERRUPT_HARD) {
|
if (interrupt_request & CPU_INTERRUPT_HARD) {
|
||||||
do_interrupt(env);
|
do_interrupt(env);
|
||||||
BREAK_CHAIN;
|
next_tb = 0;
|
||||||
}
|
}
|
||||||
#elif defined(TARGET_CRIS)
|
#elif defined(TARGET_CRIS)
|
||||||
if (interrupt_request & CPU_INTERRUPT_HARD) {
|
if (interrupt_request & CPU_INTERRUPT_HARD) {
|
||||||
do_interrupt(env);
|
do_interrupt(env);
|
||||||
BREAK_CHAIN;
|
next_tb = 0;
|
||||||
}
|
}
|
||||||
#elif defined(TARGET_M68K)
|
#elif defined(TARGET_M68K)
|
||||||
if (interrupt_request & CPU_INTERRUPT_HARD
|
if (interrupt_request & CPU_INTERRUPT_HARD
|
||||||
@ -575,7 +574,7 @@ int cpu_exec(CPUState *env1)
|
|||||||
first signalled. */
|
first signalled. */
|
||||||
env->exception_index = env->pending_vector;
|
env->exception_index = env->pending_vector;
|
||||||
do_interrupt(1);
|
do_interrupt(1);
|
||||||
BREAK_CHAIN;
|
next_tb = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* Don't use the cached interupt_request value,
|
/* Don't use the cached interupt_request value,
|
||||||
@ -584,7 +583,7 @@ int cpu_exec(CPUState *env1)
|
|||||||
env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
|
env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
|
||||||
/* ensure that no TB jump will be modified as
|
/* ensure that no TB jump will be modified as
|
||||||
the program flow was changed */
|
the program flow was changed */
|
||||||
BREAK_CHAIN;
|
next_tb = 0;
|
||||||
}
|
}
|
||||||
if (interrupt_request & CPU_INTERRUPT_EXIT) {
|
if (interrupt_request & CPU_INTERRUPT_EXIT) {
|
||||||
env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
|
env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
|
||||||
@ -640,13 +639,13 @@ int cpu_exec(CPUState *env1)
|
|||||||
spans two pages, we cannot safely do a direct
|
spans two pages, we cannot safely do a direct
|
||||||
jump. */
|
jump. */
|
||||||
{
|
{
|
||||||
if (T0 != 0 &&
|
if (next_tb != 0 &&
|
||||||
#if USE_KQEMU
|
#if USE_KQEMU
|
||||||
(env->kqemu_enabled != 2) &&
|
(env->kqemu_enabled != 2) &&
|
||||||
#endif
|
#endif
|
||||||
tb->page_addr[1] == -1) {
|
tb->page_addr[1] == -1) {
|
||||||
spin_lock(&tb_lock);
|
spin_lock(&tb_lock);
|
||||||
tb_add_jump((TranslationBlock *)(long)(T0 & ~3), T0 & 3, tb);
|
tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
|
||||||
spin_unlock(&tb_lock);
|
spin_unlock(&tb_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -667,7 +666,7 @@ int cpu_exec(CPUState *env1)
|
|||||||
asm volatile ("ble 0(%%sr4,%1)\n"
|
asm volatile ("ble 0(%%sr4,%1)\n"
|
||||||
"copy %%r31,%%r18\n"
|
"copy %%r31,%%r18\n"
|
||||||
"copy %%r28,%0\n"
|
"copy %%r28,%0\n"
|
||||||
: "=r" (T0)
|
: "=r" (next_tb)
|
||||||
: "r" (gen_func)
|
: "r" (gen_func)
|
||||||
: "r1", "r2", "r3", "r4", "r5", "r6", "r7",
|
: "r1", "r2", "r3", "r4", "r5", "r6", "r7",
|
||||||
"r8", "r9", "r10", "r11", "r12", "r13",
|
"r8", "r9", "r10", "r11", "r12", "r13",
|
||||||
@ -690,8 +689,29 @@ int cpu_exec(CPUState *env1)
|
|||||||
fp.ip = tc_ptr;
|
fp.ip = tc_ptr;
|
||||||
fp.gp = code_gen_buffer + 2 * (1 << 20);
|
fp.gp = code_gen_buffer + 2 * (1 << 20);
|
||||||
(*(void (*)(void)) &fp)();
|
(*(void (*)(void)) &fp)();
|
||||||
|
#elif defined(__i386)
|
||||||
|
asm volatile ("sub $12, %%esp\n\t"
|
||||||
|
"push %%ebp\n\t"
|
||||||
|
"call *%1\n\t"
|
||||||
|
"pop %%ebp\n\t"
|
||||||
|
"add $12, %%esp\n\t"
|
||||||
|
: "=a" (next_tb)
|
||||||
|
: "a" (gen_func)
|
||||||
|
: "ebx", "ecx", "edx", "esi", "edi", "cc",
|
||||||
|
"memory");
|
||||||
|
#elif defined(__x86_64__)
|
||||||
|
asm volatile ("sub $8, %%rsp\n\t"
|
||||||
|
"push %%rbp\n\t"
|
||||||
|
"call *%1\n\t"
|
||||||
|
"pop %%rbp\n\t"
|
||||||
|
"add $8, %%rsp\n\t"
|
||||||
|
: "=a" (next_tb)
|
||||||
|
: "a" (gen_func)
|
||||||
|
: "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9",
|
||||||
|
"r10", "r11", "r12", "r13", "r14", "r15", "cc",
|
||||||
|
"memory");
|
||||||
#else
|
#else
|
||||||
T0 = gen_func();
|
next_tb = gen_func();
|
||||||
#endif
|
#endif
|
||||||
env->current_tb = NULL;
|
env->current_tb = NULL;
|
||||||
/* reset soft MMU for next block (it can currently
|
/* reset soft MMU for next block (it can currently
|
||||||
@ -700,7 +720,7 @@ int cpu_exec(CPUState *env1)
|
|||||||
if (env->hflags & HF_SOFTMMU_MASK) {
|
if (env->hflags & HF_SOFTMMU_MASK) {
|
||||||
env->hflags &= ~HF_SOFTMMU_MASK;
|
env->hflags &= ~HF_SOFTMMU_MASK;
|
||||||
/* do not allow linking to another block */
|
/* do not allow linking to another block */
|
||||||
T0 = 0;
|
next_tb = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(USE_KQEMU)
|
#if defined(USE_KQEMU)
|
||||||
|
Loading…
Reference in New Issue
Block a user