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-devel

[Xen-devel] [PATCH] x86: single step after instruction emulation

To: <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-devel] [PATCH] x86: single step after instruction emulation
From: "Jan Beulich" <jbeulich@xxxxxxxxxx>
Date: Thu, 22 Nov 2007 16:58:50 +0000
Delivery-date: Thu, 22 Nov 2007 08:58:13 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
Inject single step trap after emulating instructions if guest's EFLAGS.TF is
set.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>

Index: 2007-11-13/xen/arch/x86/hvm/io.c
===================================================================
--- 2007-11-13.orig/xen/arch/x86/hvm/io.c       2007-11-21 08:47:45.000000000 
+0100
+++ 2007-11-13/xen/arch/x86/hvm/io.c    2007-11-20 16:27:57.000000000 +0100
@@ -863,6 +863,8 @@ void hvm_io_assist(void)
     /* Copy register changes back into current guest state. */
     regs->eflags &= ~X86_EFLAGS_RF;
     memcpy(guest_cpu_user_regs(), regs, HVM_CONTEXT_STACK_BYTES);
+    if ( regs->eflags & X86_EFLAGS_TF )
+        hvm_inject_exception(TRAP_debug, HVM_DELIVER_NO_ERROR_CODE, 0);
 
  out:
     vcpu_end_shutdown_deferral(v);
Index: 2007-11-13/xen/arch/x86/hvm/platform.c
===================================================================
--- 2007-11-13.orig/xen/arch/x86/hvm/platform.c 2007-11-21 08:47:45.000000000 
+0100
+++ 2007-11-13/xen/arch/x86/hvm/platform.c      2007-11-20 16:37:27.000000000 
+0100
@@ -1061,7 +1061,6 @@ void handle_mmio(unsigned long gpa)
     }
 
     regs->eip += inst_len; /* advance %eip */
-    regs->eflags &= ~X86_EFLAGS_RF;
 
     switch ( mmio_op->instr ) {
     case INSTR_MOV:
@@ -1121,7 +1120,6 @@ void handle_mmio(unsigned long gpa)
             /* The guest does not have the non-mmio address mapped. 
              * Need to send in a page fault */
             regs->eip -= inst_len; /* do not advance %eip */
-            regs->eflags |= X86_EFLAGS_RF; /* RF was set by original #PF */
             hvm_inject_exception(TRAP_page_fault, pfec, addr);
             return;
         }
@@ -1150,7 +1148,6 @@ void handle_mmio(unsigned long gpa)
                         /* Failed on the page-spanning copy.  Inject PF into
                          * the guest for the address where we failed */
                         regs->eip -= inst_len; /* do not advance %eip */
-                        regs->eflags |= X86_EFLAGS_RF; /* RF was set by #PF */
                         /* Must set CR2 at the failing address */ 
                         addr += size - rv;
                         gdprintk(XENLOG_DEBUG, "Pagefault on non-io side of a "
Index: 2007-11-13/xen/arch/x86/hvm/svm/svm.c
===================================================================
--- 2007-11-13.orig/xen/arch/x86/hvm/svm/svm.c  2007-11-21 08:47:45.000000000 
+0100
+++ 2007-11-13/xen/arch/x86/hvm/svm/svm.c       2007-11-20 16:46:55.000000000 
+0100
@@ -78,14 +78,6 @@ static void *root_vmcb[NR_CPUS] __read_m
 
 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);
-    regs->eip += inst_len;
-    regs->eflags &= ~X86_EFLAGS_RF;
-}
-
 static void svm_inject_exception(
     struct vcpu *v, int trap, int ev, int error_code)
 {
@@ -107,6 +99,20 @@ static void svm_inject_exception(
     vmcb->eventinj = event;
 }
 
+static void inline __update_guest_eip(struct vcpu *v,
+    struct cpu_user_regs *regs, int inst_len)
+{
+    ASSERT(inst_len > 0);
+    regs->eip += inst_len;
+    regs->eflags &= ~X86_EFLAGS_RF;
+    if ( v && (regs->eflags & X86_EFLAGS_TF) )
+    {
+        v->arch.guest_context.debugreg[6] =
+            v->arch.hvm_svm.vmcb->dr6 |= 0x4000;
+        svm_inject_exception(v, TRAP_debug, 0, 0);
+    }
+}
+
 static void svm_cpu_down(void)
 {
     write_efer(read_efer() & ~EFER_SVME);
@@ -868,7 +874,12 @@ static void svm_hvm_inject_exception(
     struct vcpu *v = current;
     if ( trapnr == TRAP_page_fault )
         v->arch.hvm_svm.vmcb->cr2 = v->arch.hvm_vcpu.guest_cr[2] = cr2;
-    svm_inject_exception(v, trapnr, (errcode != -1), errcode);
+    if ( trapnr == TRAP_debug &&
+         (guest_cpu_user_regs()->eflags & X86_EFLAGS_TF) )
+        v->arch.guest_context.debugreg[6] =
+            v->arch.hvm_svm.vmcb->dr6 |= 0x4000;
+    svm_inject_exception(v, trapnr,
+                         (errcode != HVM_DELIVER_NO_ERROR_CODE), errcode);
 }
 
 static int svm_event_pending(struct vcpu *v)
@@ -1083,7 +1094,7 @@ static void svm_vmexit_do_cpuid(struct v
 
     inst_len = __get_instruction_length(v, INSTR_CPUID, NULL);
     ASSERT(inst_len > 0);
-    __update_guest_eip(regs, inst_len);
+    __update_guest_eip(v, regs, inst_len);
 }
 
 static unsigned long *get_reg_p(
@@ -1769,7 +1780,7 @@ static void svm_cr_access(
     ASSERT(inst_len);
 
     if ( result )
-        __update_guest_eip(regs, inst_len);
+        __update_guest_eip(v, regs, inst_len);
 }
 
 static void svm_do_msr_access(
@@ -1940,7 +1951,7 @@ static void svm_do_msr_access(
         inst_len = __get_instruction_length(v, INSTR_WRMSR, NULL);
     }
 
-    __update_guest_eip(regs, inst_len);
+    __update_guest_eip(v, regs, inst_len);
 }
 
 static void svm_vmexit_do_hlt(struct vmcb_struct *vmcb,
@@ -1948,7 +1959,7 @@ static void svm_vmexit_do_hlt(struct vmc
 {
     struct hvm_intack intack = hvm_vcpu_has_pending_irq(current);
 
-    __update_guest_eip(regs, 1);
+    __update_guest_eip(NULL, regs, 1);
 
     /* Check for interrupt not handled or new interrupt. */
     if ( vmcb->eventinj.fields.v ||
@@ -1978,7 +1989,7 @@ static void svm_vmexit_do_invalidate_cac
 
     inst_len = __get_instruction_length_from_list(
         curr, list, ARRAY_SIZE(list), NULL, NULL);
-    __update_guest_eip(regs, inst_len);
+    __update_guest_eip(curr, regs, inst_len);
 }
 
 void svm_handle_invlpg(const short invlpga, struct cpu_user_regs *regs)
@@ -2003,7 +2014,7 @@ void svm_handle_invlpg(const short invlp
     {
         inst_len = __get_instruction_length(v, INSTR_INVLPGA, opcode);
         ASSERT(inst_len > 0);
-        __update_guest_eip(regs, inst_len);
+        __update_guest_eip(v, regs, inst_len);
 
         /* 
          * The address is implicit on this instruction. At the moment, we don't
@@ -2030,7 +2041,7 @@ void svm_handle_invlpg(const short invlp
                                              &opcode[inst_len], &length);
 
         inst_len += length;
-        __update_guest_eip(regs, inst_len);
+        __update_guest_eip(v, regs, inst_len);
     }
 
     HVMTRACE_3D(INVLPG, v, (invlpga?1:0), g_vaddr, (invlpga?regs->ecx:0));
@@ -2186,7 +2197,7 @@ asmlinkage void svm_vmexit_handler(struc
             goto exit_and_crash;
         /* AMD Vol2, 15.11: INT3, INTO, BOUND intercepts do not update RIP. */
         inst_len = __get_instruction_length(v, INSTR_INT3, NULL);
-        __update_guest_eip(regs, inst_len);
+        __update_guest_eip(NULL, regs, inst_len);
         domain_pause_for_debugger();
         break;
 
@@ -2268,7 +2279,7 @@ asmlinkage void svm_vmexit_handler(struc
         rc = hvm_do_hypercall(regs);
         if ( rc != HVM_HCALL_preempted )
         {
-            __update_guest_eip(regs, inst_len);
+            __update_guest_eip(v, regs, inst_len);
             if ( rc == HVM_HCALL_invalidate )
                 send_invalidate_req();
         }
Index: 2007-11-13/xen/arch/x86/hvm/vmx/vmx.c
===================================================================
--- 2007-11-13.orig/xen/arch/x86/hvm/vmx/vmx.c  2007-11-21 08:47:45.000000000 
+0100
+++ 2007-11-13/xen/arch/x86/hvm/vmx/vmx.c       2007-11-20 16:32:57.000000000 
+0100
@@ -1093,6 +1093,14 @@ static void vmx_inject_exception(
     vmx_inject_hw_exception(v, trapnr, errcode);
     if ( trapnr == TRAP_page_fault )
         v->arch.hvm_vcpu.guest_cr[2] = cr2;
+    if ( trapnr == TRAP_debug &&
+         (guest_cpu_user_regs()->eflags & X86_EFLAGS_TF) )
+    {
+        unsigned long dr6 = read_debugreg(6);
+
+        v->arch.guest_context.debugreg[6] = dr6 |= 0x4000;
+        write_debugreg(6, dr6);
+    }
 }
 
 static void vmx_update_vtpr(struct vcpu *v, unsigned long value)
@@ -1184,13 +1192,20 @@ static int __get_instruction_length(void
     return len;
 }
 
-static void __update_guest_eip(unsigned long inst_len)
+static void __update_guest_eip(struct vcpu *v, unsigned long inst_len)
 {
     struct cpu_user_regs *regs = guest_cpu_user_regs();
     unsigned long x;
 
     regs->eip += inst_len;
     regs->eflags &= ~X86_EFLAGS_RF;
+    if ( v && (regs->eflags & X86_EFLAGS_TF) )
+    {
+        x = read_debugreg(6);
+        v->arch.guest_context.debugreg[6] = x |= 0x4000;
+        write_debugreg(6, x);
+        vmx_inject_hw_exception(v, TRAP_debug, HVM_DELIVER_NO_ERROR_CODE);
+    }
 
     x = __vmread(GUEST_INTERRUPTIBILITY_INFO);
     if ( x & (VMX_INTR_SHADOW_STI | VMX_INTR_SHADOW_MOV_SS) )
@@ -2824,18 +2839,18 @@ asmlinkage void vmx_vmexit_handler(struc
     }
     case EXIT_REASON_CPUID:
         inst_len = __get_instruction_length(); /* Safe: CPUID */
-        __update_guest_eip(inst_len);
+        __update_guest_eip(v, inst_len);
         vmx_do_cpuid(regs);
         break;
     case EXIT_REASON_HLT:
         inst_len = __get_instruction_length(); /* Safe: HLT */
-        __update_guest_eip(inst_len);
+        __update_guest_eip(NULL, inst_len);
         vmx_do_hlt(regs);
         break;
     case EXIT_REASON_INVLPG:
     {
         inst_len = __get_instruction_length(); /* Safe: INVLPG */
-        __update_guest_eip(inst_len);
+        __update_guest_eip(v, inst_len);
         exit_qualification = __vmread(EXIT_QUALIFICATION);
         vmx_do_invlpg(exit_qualification);
         break;
@@ -2848,7 +2863,7 @@ asmlinkage void vmx_vmexit_handler(struc
         rc = hvm_do_hypercall(regs);
         if ( rc != HVM_HCALL_preempted )
         {
-            __update_guest_eip(inst_len);
+            __update_guest_eip(v, inst_len);
             if ( rc == HVM_HCALL_invalidate )
                 send_invalidate_req();
         }
@@ -2859,7 +2874,7 @@ asmlinkage void vmx_vmexit_handler(struc
         exit_qualification = __vmread(EXIT_QUALIFICATION);
         inst_len = __get_instruction_length(); /* Safe: MOV Cn, LMSW, CLTS */
         if ( vmx_cr_access(exit_qualification, regs) )
-            __update_guest_eip(inst_len);
+            __update_guest_eip(v, inst_len);
         break;
     }
     case EXIT_REASON_DR_ACCESS:
@@ -2874,12 +2889,12 @@ asmlinkage void vmx_vmexit_handler(struc
     case EXIT_REASON_MSR_READ:
         inst_len = __get_instruction_length(); /* Safe: RDMSR */
         if ( vmx_do_msr_read(regs) )
-            __update_guest_eip(inst_len);
+            __update_guest_eip(v, inst_len);
         break;
     case EXIT_REASON_MSR_WRITE:
         inst_len = __get_instruction_length(); /* Safe: WRMSR */
         if ( vmx_do_msr_write(regs) )
-            __update_guest_eip(inst_len);
+            __update_guest_eip(v, inst_len);
         break;
 
     case EXIT_REASON_MWAIT_INSTRUCTION:
@@ -2893,7 +2908,7 @@ asmlinkage void vmx_vmexit_handler(struc
     case EXIT_REASON_VMWRITE:
     case EXIT_REASON_VMXOFF:
     case EXIT_REASON_VMXON:
-        vmx_inject_hw_exception(v, TRAP_invalid_op, VMX_DELIVER_NO_ERROR_CODE);
+        vmx_inject_hw_exception(v, TRAP_invalid_op, HVM_DELIVER_NO_ERROR_CODE);
         break;
 
     case EXIT_REASON_TPR_BELOW_THRESHOLD:
@@ -2911,7 +2926,7 @@ asmlinkage void vmx_vmexit_handler(struc
     case EXIT_REASON_WBINVD:
     {
         inst_len = __get_instruction_length(); /* Safe: INVD, WBINVD */
-        __update_guest_eip(inst_len);
+        __update_guest_eip(v, inst_len);
         if ( !list_empty(&(domain_hvm_iommu(v->domain)->pdev_list)) )
         {
             wbinvd();
Index: 2007-11-13/xen/arch/x86/traps.c
===================================================================
--- 2007-11-13.orig/xen/arch/x86/traps.c        2007-11-21 08:47:45.000000000 
+0100
+++ 2007-11-13/xen/arch/x86/traps.c     2007-11-20 15:46:19.000000000 +0100
@@ -412,6 +412,17 @@ static int do_guest_trap(
     return 0;
 }
 
+static void instruction_done(struct cpu_user_regs *regs, unsigned long eip)
+{
+    regs->eip = eip;
+    regs->eflags &= ~X86_EFLAGS_RF;
+    if ( regs->eflags & X86_EFLAGS_TF )
+    {
+        current->arch.guest_context.debugreg[6] |= 0xffff4ff0;
+        do_guest_trap(TRAP_debug, regs, 0);
+    }
+}
+
 /*
  * Called from asm to set up the NMI trapbounce info.
  * Returns 0 if no callback is set up, else 1.
@@ -657,8 +668,7 @@ static int emulate_forced_invalid_op(str
     regs->ebx = b;
     regs->ecx = c;
     regs->edx = d;
-    regs->eip = eip;
-    regs->eflags &= ~X86_EFLAGS_RF;
+    instruction_done(regs, eip);
 
     trace_trap_one_addr(TRC_PV_FORCED_INVALID_OP, regs->eip);
 
@@ -1950,8 +1960,7 @@ static int emulate_privileged_op(struct 
 #undef rd_ad
 
  done:
-    regs->eip = eip;
-    regs->eflags &= ~X86_EFLAGS_RF;
+    instruction_done(regs, eip);
     return EXCRET_fault_fixed;
 
  fail:
@@ -2280,8 +2289,8 @@ static int emulate_gate_op(struct cpu_u
     else
         sel |= (regs->cs & 3);
 
-    regs->eip = off;
     regs->cs = sel;
+    instruction_done(regs, off);
 #endif
 
     return 0;
Index: 2007-11-13/xen/arch/x86/x86_emulate.c
===================================================================
--- 2007-11-13.orig/xen/arch/x86/x86_emulate.c  2007-11-21 08:47:45.000000000 
+0100
+++ 2007-11-13/xen/arch/x86/x86_emulate.c       2007-11-20 15:38:30.000000000 
+0100
@@ -1615,6 +1615,7 @@ x86_emulate(
     /* Commit shadow register state. */
     _regs.eflags &= ~EFLG_RF;
     *ctxt->regs = _regs;
+    /* FIXME generate_exception_if(_regs.eflags & EFLG_TF, EXC_DB); */
 
  done:
     return rc;
Index: 2007-11-13/xen/include/asm-x86/hvm/support.h
===================================================================
--- 2007-11-13.orig/xen/include/asm-x86/hvm/support.h   2007-11-21 
08:47:45.000000000 +0100
+++ 2007-11-13/xen/include/asm-x86/hvm/support.h        2007-11-20 
15:58:09.000000000 +0100
@@ -50,7 +50,7 @@ static inline vcpu_iodata_t *get_ioreq(s
 #define TYPE_CLTS               (2 << 4)
 #define TYPE_LMSW               (3 << 4)
 
-#define VMX_DELIVER_NO_ERROR_CODE  -1
+#define HVM_DELIVER_NO_ERROR_CODE  -1
 
 #if HVM_DEBUG
 #define DBG_LEVEL_0                 (1 << 0)
Index: 2007-11-13/xen/include/asm-x86/hvm/vmx/vmx.h
===================================================================
--- 2007-11-13.orig/xen/include/asm-x86/hvm/vmx/vmx.h   2007-11-21 
08:47:45.000000000 +0100
+++ 2007-11-13/xen/include/asm-x86/hvm/vmx/vmx.h        2007-11-20 
15:58:49.000000000 +0100
@@ -272,7 +272,7 @@ static inline void __vmx_inject_exceptio
      */
 
     intr_fields = (INTR_INFO_VALID_MASK | (type<<8) | trap);
-    if ( error_code != VMX_DELIVER_NO_ERROR_CODE ) {
+    if ( error_code != HVM_DELIVER_NO_ERROR_CODE ) {
         __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
         intr_fields |= INTR_INFO_DELIVER_CODE_MASK;
     }
@@ -294,13 +294,13 @@ static inline void vmx_inject_hw_excepti
 static inline void vmx_inject_extint(struct vcpu *v, int trap)
 {
     __vmx_inject_exception(v, trap, X86_EVENTTYPE_EXT_INTR,
-                           VMX_DELIVER_NO_ERROR_CODE);
+                           HVM_DELIVER_NO_ERROR_CODE);
 }
 
 static inline void vmx_inject_nmi(struct vcpu *v)
 {
     __vmx_inject_exception(v, 2, X86_EVENTTYPE_NMI,
-                           VMX_DELIVER_NO_ERROR_CODE);
+                           HVM_DELIVER_NO_ERROR_CODE);
 }
 
 #endif /* __ASM_X86_HVM_VMX_VMX_H__ */



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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [PATCH] x86: single step after instruction emulation, Jan Beulich <=