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
|