From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1HWA4w-0001h7-Hn for qemu-devel@nongnu.org; Tue, 27 Mar 2007 07:43:06 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1HWA4v-0001gu-Ll for qemu-devel@nongnu.org; Tue, 27 Mar 2007 07:43:05 -0400 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1HWA4v-0001gr-GV for qemu-devel@nongnu.org; Tue, 27 Mar 2007 06:43:05 -0500 Received: from os.inf.tu-dresden.de ([141.76.48.99]) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1HWA2Y-000673-R2 for qemu-devel@nongnu.org; Tue, 27 Mar 2007 07:40:39 -0400 Received: from silo.inf.tu-dresden.de ([141.76.48.100]) by os.inf.tu-dresden.de with esmtps (TLSv1:AES256-SHA:256) (Exim 4.66) id 1HWA2W-0004Ri-MF for qemu-devel@nongnu.org; Tue, 27 Mar 2007 13:40:36 +0200 Received: from kauer by silo.inf.tu-dresden.de with local (Exim 4.50) id 1HWA2W-0004Qa-Df for qemu-devel@nongnu.org; Tue, 27 Mar 2007 13:40:36 +0200 Date: Tue, 27 Mar 2007 13:40:36 +0200 Message-ID: <20070327114036.GD32622@silo.inf.tu-dresden.de> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="Pd0ReVV5GZGQvF3a" Content-Disposition: inline From: Bernhard Kauer Subject: [Qemu-devel] Patch: generate a DBF when a GPF could not be delivered on x86 Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org --Pd0ReVV5GZGQvF3a Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Qemu does not generate a double fault (DBF) on x86, if a general protection fault could not be delivered. Instead it hangs in a loop. The patch fix this bug by checking whether we are already in a GPF exception. Bernhard Kauer --Pd0ReVV5GZGQvF3a Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="qemu_dbf.diff" Index: helper.c =================================================================== RCS file: /sources/qemu/qemu/target-i386/helper.c,v retrieving revision 1.74 diff -u -r1.74 helper.c --- helper.c 1 Feb 2007 22:12:19 -0000 1.74 +++ helper.c 27 Mar 2007 11:33:34 -0000 @@ -592,6 +592,16 @@ sp += 4;\ } +void +raise_gpf(int intno, int is_int, int is_hw, int error) +{ + if (!is_int && !is_hw && intno == EXCP0D_GPF) + raise_exception_err(EXCP08_DBLE, 0); + else + raise_exception_err(EXCP0D_GPF, error >= 0 ? error : intno * TARGET_LONG_SIZE + 2); +} + + /* protected mode interrupt */ static void do_interrupt_protected(int intno, int is_int, int error_code, unsigned int next_eip, int is_hw) @@ -624,7 +634,7 @@ dt = &env->idt; if (intno * 8 + 7 > dt->limit) - raise_exception_err(EXCP0D_GPF, intno * 8 + 2); + raise_gpf(intno, is_int, is_hw, -1); ptr = dt->base + intno * 8; e1 = ldl_kernel(ptr); e2 = ldl_kernel(ptr + 4); @@ -661,29 +671,30 @@ case 15: /* 386 trap gate */ break; default: - raise_exception_err(EXCP0D_GPF, intno * 8 + 2); + raise_gpf(intno, is_int, is_hw, -1); break; } dpl = (e2 >> DESC_DPL_SHIFT) & 3; cpl = env->hflags & HF_CPL_MASK; /* check privledge if software int */ if (is_int && dpl < cpl) - raise_exception_err(EXCP0D_GPF, intno * 8 + 2); + raise_gpf(intno, is_int, is_hw, -1); + /* check valid bit */ if (!(e2 & DESC_P_MASK)) raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2); selector = e1 >> 16; offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff); if ((selector & 0xfffc) == 0) - raise_exception_err(EXCP0D_GPF, 0); + raise_gpf(intno, is_int, is_hw, 0); if (load_segment(&e1, &e2, selector) != 0) - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_gpf(intno, is_int, is_hw, selector & 0xfffc); if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK))) - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_gpf(intno, is_int, is_hw, selector & 0xfffc); dpl = (e2 >> DESC_DPL_SHIFT) & 3; if (dpl > cpl) - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_gpf(intno, is_int, is_hw, selector & 0xfffc); if (!(e2 & DESC_P_MASK)) raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); if (!(e2 & DESC_C_MASK) && dpl < cpl) { @@ -710,14 +721,14 @@ } else if ((e2 & DESC_C_MASK) || dpl == cpl) { /* to same priviledge */ if (env->eflags & VM_MASK) - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_gpf(intno, is_int, is_hw, selector & 0xfffc); new_stack = 0; sp_mask = get_sp_mask(env->segs[R_SS].flags); ssp = env->segs[R_SS].base; esp = ESP; dpl = cpl; } else { - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_gpf(intno, is_int, is_hw, selector & 0xfffc); new_stack = 0; /* avoid warning */ sp_mask = 0; /* avoid warning */ ssp = 0; /* avoid warning */ @@ -860,7 +871,7 @@ dt = &env->idt; if (intno * 16 + 15 > dt->limit) - raise_exception_err(EXCP0D_GPF, intno * 16 + 2); + raise_gpf(intno, is_int, is_hw, -1); ptr = dt->base + intno * 16; e1 = ldl_kernel(ptr); e2 = ldl_kernel(ptr + 4); @@ -872,14 +883,13 @@ case 15: /* 386 trap gate */ break; default: - raise_exception_err(EXCP0D_GPF, intno * 16 + 2); - break; + raise_gpf(intno, is_int, is_hw, -1); } dpl = (e2 >> DESC_DPL_SHIFT) & 3; cpl = env->hflags & HF_CPL_MASK; /* check privledge if software int */ if (is_int && dpl < cpl) - raise_exception_err(EXCP0D_GPF, intno * 16 + 2); + raise_gpf(intno, is_int, is_hw, -1); /* check valid bit */ if (!(e2 & DESC_P_MASK)) raise_exception_err(EXCP0B_NOSEG, intno * 16 + 2); @@ -887,19 +897,19 @@ offset = ((target_ulong)e3 << 32) | (e2 & 0xffff0000) | (e1 & 0x0000ffff); ist = e2 & 7; if ((selector & 0xfffc) == 0) - raise_exception_err(EXCP0D_GPF, 0); + raise_gpf(intno, is_int, is_hw, 0); if (load_segment(&e1, &e2, selector) != 0) - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_gpf(intno, is_int, is_hw, selector & 0xfffc); if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK))) - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_gpf(intno, is_int, is_hw, selector & 0xfffc); dpl = (e2 >> DESC_DPL_SHIFT) & 3; if (dpl > cpl) - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_gpf(intno, is_int, is_hw, selector & 0xfffc); if (!(e2 & DESC_P_MASK)) raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); if (!(e2 & DESC_L_MASK) || (e2 & DESC_B_MASK)) - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_gpf(intno, is_int, is_hw, selector & 0xfffc); if ((!(e2 & DESC_C_MASK) && dpl < cpl) || ist != 0) { /* to inner priviledge */ if (ist != 0) @@ -912,7 +922,7 @@ } else if ((e2 & DESC_C_MASK) || dpl == cpl) { /* to same priviledge */ if (env->eflags & VM_MASK) - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_gpf(intno, is_int, is_hw, selector & 0xfffc); new_stack = 0; if (ist != 0) esp = get_rsp_from_tss(ist + 3); @@ -921,7 +931,7 @@ esp &= ~0xfLL; /* align stack */ dpl = cpl; } else { - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); + raise_gpf(intno, is_int, is_hw, selector & 0xfffc); new_stack = 0; /* avoid warning */ esp = 0; /* avoid warning */ } @@ -1089,7 +1099,12 @@ /* real mode (simpler !) */ dt = &env->idt; if (intno * 4 + 3 > dt->limit) - raise_exception_err(EXCP0D_GPF, intno * 8 + 2); + { + if (!is_int && intno == EXCP0D_GPF) + raise_exception_err(EXCP08_DBLE, 0); + else + raise_exception_err(EXCP0D_GPF, intno * 4 + 2); + } ptr = dt->base + intno * 4; offset = lduw_kernel(ptr); selector = lduw_kernel(ptr + 2); --Pd0ReVV5GZGQvF3a--