WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] hvm: Fix EFLAGS setting in MMIO decoder/e

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] hvm: Fix EFLAGS setting in MMIO decoder/emulator.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 05 Apr 2007 06:50:10 -0700
Delivery-date: Thu, 05 Apr 2007 06:49:51 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1175759095 -3600
# Node ID 97453bb714b9d0fb898ef57a20c4ff171e7ebf9e
# Parent  94dfb13cbbed67a60725d7be32e11ebbcffc11fa
hvm: Fix EFLAGS setting in MMIO decoder/emulator.
Signed-off-by: Dexuan Cui <dexuan.cui@xxxxxxxxx>
---
 xen/arch/x86/hvm/io.c |  144 ++++++++++++++++++++++++++++++++++----------------
 1 files changed, 100 insertions(+), 44 deletions(-)

diff -r 94dfb13cbbed -r 97453bb714b9 xen/arch/x86/hvm/io.c
--- a/xen/arch/x86/hvm/io.c     Thu Apr 05 08:43:21 2007 +0100
+++ b/xen/arch/x86/hvm/io.c     Thu Apr 05 08:44:55 2007 +0100
@@ -289,8 +289,12 @@ static void set_reg_value (int size, int
 
 long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs);
 
-static inline void set_eflags_CF(int size, unsigned long v1,
-                                 unsigned long v2, struct cpu_user_regs *regs)
+static inline void set_eflags_CF(int size,
+                                 unsigned int instr,
+                                 unsigned long result,
+                                 unsigned long src,
+                                 unsigned long dst,
+                                 struct cpu_user_regs *regs)
 {
     unsigned long mask;
 
@@ -300,14 +304,28 @@ static inline void set_eflags_CF(int siz
 
     mask = ~0UL >> (8 * (sizeof(mask) - size));
 
-    if ((v1 & mask) > (v2 & mask))
-        regs->eflags |= X86_EFLAGS_CF;
+    if ( instr == INSTR_ADD )
+    {
+        /* CF=1 <==> result is less than the augend and addend) */
+        if ( (result & mask) < (dst & mask) )
+        {
+            ASSERT((result & mask) < (src & mask));
+            regs->eflags |= X86_EFLAGS_CF;
+        }
+    }
     else
-        regs->eflags &= ~X86_EFLAGS_CF;
-}
-
-static inline void set_eflags_OF(int size, unsigned long v1,
-                                 unsigned long v2, unsigned long v3,
+    {
+        ASSERT( instr == INSTR_CMP || instr == INSTR_SUB );
+        if ( (src & mask) > (dst & mask) )
+            regs->eflags |= X86_EFLAGS_CF;
+    }
+}
+
+static inline void set_eflags_OF(int size,
+                                 unsigned int instr,
+                                 unsigned long result,
+                                 unsigned long src,
+                                 unsigned long dst,
                                  struct cpu_user_regs *regs)
 {
     unsigned long mask;
@@ -316,21 +334,32 @@ static inline void set_eflags_OF(int siz
         size = BYTE;
     ASSERT((size <= sizeof(mask)) && (size > 0));
 
-    mask = ~0UL >> (8 * (sizeof(mask) - size));
-
-    if ((v3 ^ v2) & (v3 ^ v1) & mask)
-        regs->eflags |= X86_EFLAGS_OF;
-}
-
-static inline void set_eflags_AF(int size, unsigned long v1,
-                                 unsigned long v2, unsigned long v3,
+    mask =  1UL << ((8*size) - 1);
+
+    if ( instr == INSTR_ADD )
+    {
+        if ((src ^ result) & (dst ^ result) & mask);
+            regs->eflags |= X86_EFLAGS_OF;
+    }
+    else
+    {
+        ASSERT(instr == INSTR_CMP || instr == INSTR_SUB);
+        if ((dst ^ src) & (dst ^ result) & mask)
+            regs->eflags |= X86_EFLAGS_OF;
+    }
+}
+
+static inline void set_eflags_AF(int size,
+                                 unsigned long result,
+                                 unsigned long src,
+                                 unsigned long dst,
                                  struct cpu_user_regs *regs)
 {
-    if ((v1 ^ v2 ^ v3) & 0x10)
+    if ((result ^ src ^ dst) & 0x10)
         regs->eflags |= X86_EFLAGS_AF;
 }
 
-static inline void set_eflags_ZF(int size, unsigned long v1,
+static inline void set_eflags_ZF(int size, unsigned long result,
                                  struct cpu_user_regs *regs)
 {
     unsigned long mask;
@@ -341,11 +370,11 @@ static inline void set_eflags_ZF(int siz
 
     mask = ~0UL >> (8 * (sizeof(mask) - size));
 
-    if ((v1 & mask) == 0)
+    if ((result & mask) == 0)
         regs->eflags |= X86_EFLAGS_ZF;
 }
 
-static inline void set_eflags_SF(int size, unsigned long v1,
+static inline void set_eflags_SF(int size, unsigned long result,
                                  struct cpu_user_regs *regs)
 {
     unsigned long mask;
@@ -354,9 +383,9 @@ static inline void set_eflags_SF(int siz
         size = BYTE;
     ASSERT((size <= sizeof(mask)) && (size > 0));
 
-    mask = ~0UL >> (8 * (sizeof(mask) - size));
-
-    if (v1 & mask)
+    mask = 1UL << ((8*size) - 1);
+
+    if (result & mask)
         regs->eflags |= X86_EFLAGS_SF;
 }
 
@@ -379,10 +408,10 @@ static char parity_table[256] = {
     1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
 };
 
-static inline void set_eflags_PF(int size, unsigned long v1,
+static inline void set_eflags_PF(int size, unsigned long result,
                                  struct cpu_user_regs *regs)
 {
-    if (parity_table[v1 & 0xFF])
+    if (parity_table[result & 0xFF])
         regs->eflags |= X86_EFLAGS_PF;
 }
 
@@ -585,22 +614,6 @@ static void hvm_mmio_assist(struct cpu_u
             diff = (unsigned long) p->data & value;
             set_reg_value(size, index, 0, regs, diff);
         }
-        break;
-
-    case INSTR_ADD:
-        if (src & REGISTER) {
-            index = operand_index(src);
-            value = get_reg_value(size, index, 0, regs);
-            diff = (unsigned long) p->data + value;
-        } else if (src & IMMEDIATE) {
-            value = mmio_opp->immediate;
-            diff = (unsigned long) p->data + value;
-        } else if (src & MEMORY) {
-            index = operand_index(dst);
-            value = get_reg_value(size, index, 0, regs);
-            diff = (unsigned long) p->data + value;
-            set_reg_value(size, index, 0, regs, diff);
-        }
 
         /*
          * The OF and CF flags are cleared; the SF, ZF, and PF
@@ -614,6 +627,37 @@ static void hvm_mmio_assist(struct cpu_u
         set_eflags_PF(size, diff, regs);
         break;
 
+    case INSTR_ADD:
+        if (src & REGISTER) {
+            index = operand_index(src);
+            value = get_reg_value(size, index, 0, regs);
+            diff = (unsigned long) p->data + value;
+        } else if (src & IMMEDIATE) {
+            value = mmio_opp->immediate;
+            diff = (unsigned long) p->data + value;
+        } else if (src & MEMORY) {
+            index = operand_index(dst);
+            value = get_reg_value(size, index, 0, regs);
+            diff = (unsigned long) p->data + value;
+            set_reg_value(size, index, 0, regs, diff);
+        }
+
+        /*
+         * The CF, OF, SF, ZF, AF, and PF flags are set according
+         * to the result
+         */
+        regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|X86_EFLAGS_AF|
+                          X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
+        set_eflags_CF(size, mmio_opp->instr, diff, value,
+                      (unsigned long) p->data, regs);
+        set_eflags_OF(size, mmio_opp->instr, diff, value,
+                      (unsigned long) p->data, regs);
+        set_eflags_AF(size, diff, value, (unsigned long) p->data, regs);
+        set_eflags_ZF(size, diff, regs);
+        set_eflags_SF(size, diff, regs);
+        set_eflags_PF(size, diff, regs);
+        break;
+
     case INSTR_OR:
         if (src & REGISTER) {
             index = operand_index(src);
@@ -691,8 +735,20 @@ static void hvm_mmio_assist(struct cpu_u
          */
         regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|X86_EFLAGS_AF|
                           X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
-        set_eflags_CF(size, value, (unsigned long) p->data, regs);
-        set_eflags_OF(size, diff, value, (unsigned long) p->data, regs);
+        if ( src & (REGISTER | IMMEDIATE) )
+        {
+            set_eflags_CF(size, mmio_opp->instr, diff, value,
+                          (unsigned long) p->data, regs);
+            set_eflags_OF(size, mmio_opp->instr, diff, value,
+                          (unsigned long) p->data, regs);
+        }
+        else
+        {
+            set_eflags_CF(size, mmio_opp->instr, diff,
+                          (unsigned long) p->data, value, regs);
+            set_eflags_OF(size, mmio_opp->instr, diff,
+                          (unsigned long) p->data, value, regs);
+        }
         set_eflags_AF(size, diff, value, (unsigned long) p->data, regs);
         set_eflags_ZF(size, diff, regs);
         set_eflags_SF(size, diff, regs);

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] hvm: Fix EFLAGS setting in MMIO decoder/emulator., Xen patchbot-unstable <=