All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] Patch: generate a DBF when a GPF could not be delivered on x86
@ 2007-03-27 11:40 Bernhard Kauer
  2007-03-28  8:13 ` Sebastian Kaliszewski
  0 siblings, 1 reply; 4+ messages in thread
From: Bernhard Kauer @ 2007-03-27 11:40 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 236 bytes --]

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
 

[-- Attachment #2: qemu_dbf.diff --]
[-- Type: text/plain, Size: 6286 bytes --]

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);

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2007-03-31 12:17 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-03-27 11:40 [Qemu-devel] Patch: generate a DBF when a GPF could not be delivered on x86 Bernhard Kauer
2007-03-28  8:13 ` Sebastian Kaliszewski
2007-03-28 12:39   ` Bernhard Kauer
2007-03-31 12:14     ` [Qemu-devel] Patch: generate double and triple faults Bernhard Kauer

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.