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] svm: Fix __update_guest_eip() to clear in

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] svm: Fix __update_guest_eip() to clear interrupt shadow.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 22 Nov 2007 12:00:34 -0800
Delivery-date: Thu, 22 Nov 2007 12:02:16 -0800
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 Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1195571136 0
# Node ID bc6aaa44e296c0d905daf57ebe268b32faa58376
# Parent  64fbef22f86a0fa74a31bf865ebed95aa5179fa6
svm: Fix __update_guest_eip() to clear interrupt shadow.
Get rid of assertions about return value of get_instruction_length()
-- instead test in __update_guest_eip() and crash the domain.
Cache value of 'current' in svm_do_hlt().

The mismanagement of the interrupt shadow was found by Christoph
Egger of AMD.

Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/x86/hvm/svm/svm.c |   61 +++++++++++++++++++++++++++------------------
 1 files changed, 37 insertions(+), 24 deletions(-)

diff -r 64fbef22f86a -r bc6aaa44e296 xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Tue Nov 20 14:35:36 2007 +0000
+++ b/xen/arch/x86/hvm/svm/svm.c        Tue Nov 20 15:05:36 2007 +0000
@@ -74,11 +74,21 @@ static void svm_update_guest_efer(struct
 static void svm_update_guest_efer(struct vcpu *v);
 
 static void inline __update_guest_eip(
-    struct cpu_user_regs *regs, int inst_len) 
-{
-    ASSERT(inst_len > 0);
+    struct cpu_user_regs *regs, unsigned int inst_len)
+{
+    if ( unlikely((inst_len == 0) || (inst_len > 15)) )
+    {
+        gdprintk(XENLOG_ERR, "Bad instruction length %u\n", inst_len);
+        domain_crash(current->domain);
+        return;
+    }
+
+    ASSERT(regs == guest_cpu_user_regs());
+
     regs->eip += inst_len;
     regs->eflags &= ~X86_EFLAGS_RF;
+
+    current->arch.hvm_svm.vmcb->interrupt_shadow = 0;
 }
 
 static void svm_inject_exception(
@@ -1061,7 +1071,6 @@ static void svm_vmexit_do_cpuid(struct v
                 ((uint64_t)eax << 32) | ebx, ((uint64_t)ecx << 32) | edx);
 
     inst_len = __get_instruction_length(v, INSTR_CPUID, NULL);
-    ASSERT(inst_len > 0);
     __update_guest_eip(regs, inst_len);
 }
 
@@ -1642,8 +1651,6 @@ static void svm_cr_access(
         inst_len = __get_instruction_length_from_list(
             v, list_b, ARRAY_SIZE(list_b), &buffer[index], &match);
     }
-
-    ASSERT(inst_len > 0);
 
     inst_len += index;
 
@@ -1745,8 +1752,6 @@ static void svm_cr_access(
         BUG();
     }
 
-    ASSERT(inst_len);
-
     if ( result )
         __update_guest_eip(regs, inst_len);
 }
@@ -1925,20 +1930,23 @@ static void svm_vmexit_do_hlt(struct vmc
 static void svm_vmexit_do_hlt(struct vmcb_struct *vmcb,
                               struct cpu_user_regs *regs)
 {
-    struct hvm_intack intack = hvm_vcpu_has_pending_irq(current);
-
-    __update_guest_eip(regs, 1);
+    struct vcpu *curr = current;
+    struct hvm_intack intack = hvm_vcpu_has_pending_irq(curr);
+    unsigned int inst_len;
+
+    inst_len = __get_instruction_length(curr, INSTR_HLT, NULL);
+    __update_guest_eip(regs, inst_len);
 
     /* Check for interrupt not handled or new interrupt. */
     if ( vmcb->eventinj.fields.v ||
          ((intack.source != hvm_intsrc_none) &&
           !svm_interrupt_blocked(current, intack)) )
     {
-        HVMTRACE_1D(HLT, current, /*int pending=*/ 1);
+        HVMTRACE_1D(HLT, curr, /*int pending=*/ 1);
         return;
     }
 
-    HVMTRACE_1D(HLT, current, /*int pending=*/ 0);
+    HVMTRACE_1D(HLT, curr, /*int pending=*/ 0);
     hvm_hlt(regs->eflags);
 }
 
@@ -1971,17 +1979,15 @@ void svm_handle_invlpg(const short invlp
      * Unknown how many bytes the invlpg instruction will take.  Use the
      * maximum instruction length here
      */
-    if (inst_copy_from_guest(opcode, svm_rip2pointer(v), length) < length)
+    if ( inst_copy_from_guest(opcode, svm_rip2pointer(v), length) < length )
     {
         gdprintk(XENLOG_ERR, "Error reading memory %d bytes\n", length);
-        domain_crash(v->domain);
-        return;
-    }
-
-    if (invlpga)
+        goto crash;
+    }
+
+    if ( invlpga )
     {
         inst_len = __get_instruction_length(v, INSTR_INVLPGA, opcode);
-        ASSERT(inst_len > 0);
         __update_guest_eip(regs, inst_len);
 
         /* 
@@ -1993,9 +1999,13 @@ void svm_handle_invlpg(const short invlp
     else
     {
         /* What about multiple prefix codes? */
-        prefix = (is_prefix(opcode[0])?opcode[0]:0);
+        prefix = (is_prefix(opcode[0]) ? opcode[0] : 0);
         inst_len = __get_instruction_length(v, INSTR_INVLPG, opcode);
-        ASSERT(inst_len > 0);
+        if ( inst_len <= 0 )
+        {
+            gdprintk(XENLOG_ERR, "Error getting invlpg instr len\n");
+            goto crash;
+        }
 
         inst_len--;
         length -= inst_len;
@@ -2012,10 +2022,14 @@ void svm_handle_invlpg(const short invlp
         __update_guest_eip(regs, inst_len);
     }
 
-    HVMTRACE_3D(INVLPG, v, (invlpga?1:0), g_vaddr, (invlpga?regs->ecx:0));
+    HVMTRACE_3D(INVLPG, v, !!invlpga, g_vaddr, (invlpga ? regs->ecx : 0));
 
     paging_invlpg(v, g_vaddr);
     svm_asid_g_invlpg(v, g_vaddr);
+    return;
+
+ crash:
+    domain_crash(v->domain);
 }
 
 
@@ -2242,7 +2256,6 @@ asmlinkage void svm_vmexit_handler(struc
 
     case VMEXIT_VMMCALL:
         inst_len = __get_instruction_length(v, INSTR_VMCALL, NULL);
-        ASSERT(inst_len > 0);
         HVMTRACE_1D(VMMCALL, v, regs->eax);
         rc = hvm_do_hypercall(regs);
         if ( rc != HVM_HCALL_preempted )

_______________________________________________
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] svm: Fix __update_guest_eip() to clear interrupt shadow., Xen patchbot-unstable <=