# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1229428160 0
# Node ID 5b73fa1b9562d18ecdde2b3c8556989bdb2117e0
# Parent f827181eadd4f3f8f6afb37b493e9c9e1d511204
x86: Enable MTF for HVM guest single step in gdb
Signed-off-by: Edwin Zhai <edwin.zhai@xxxxxxxxx>
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
tools/libxc/xc_domain.c | 14 ++++++++++++
tools/libxc/xc_ptrace.c | 41 ++++++++++++++++++++++++++-----------
tools/libxc/xenctrl.h | 6 +++++
xen/arch/x86/domctl.c | 26 +++++++++++++++++++++++
xen/arch/x86/hvm/hvm.c | 26 +++++++++++++++++++++++
xen/arch/x86/hvm/vmx/intr.c | 8 +++++++
xen/arch/x86/hvm/vmx/vmcs.c | 10 ++++++++-
xen/arch/x86/hvm/vmx/vmx.c | 13 ++++++++++-
xen/include/asm-x86/hvm/hvm.h | 2 +
xen/include/asm-x86/hvm/vcpu.h | 1
xen/include/asm-x86/hvm/vmx/vmcs.h | 3 ++
xen/include/asm-x86/hvm/vmx/vmx.h | 1
xen/include/public/domctl.h | 12 ++++++++++
13 files changed, 149 insertions(+), 14 deletions(-)
diff -r f827181eadd4 -r 5b73fa1b9562 tools/libxc/xc_domain.c
--- a/tools/libxc/xc_domain.c Mon Dec 15 11:37:14 2008 +0000
+++ b/tools/libxc/xc_domain.c Tue Dec 16 11:49:20 2008 +0000
@@ -1061,6 +1061,20 @@ int xc_domain_suppress_spurious_page_fau
}
+int xc_domain_debug_control(int xc, uint32_t domid, uint32_t sop, uint32_t
vcpu)
+{
+ DECLARE_DOMCTL;
+
+ memset(&domctl, 0, sizeof(domctl));
+ domctl.domain = (domid_t)domid;
+ domctl.cmd = XEN_DOMCTL_debug_op;
+ domctl.u.debug_op.op = sop;
+ domctl.u.debug_op.vcpu = vcpu;
+
+ return do_domctl(xc, &domctl);
+}
+
+
/*
* Local variables:
* mode: C
diff -r f827181eadd4 -r 5b73fa1b9562 tools/libxc/xc_ptrace.c
--- a/tools/libxc/xc_ptrace.c Mon Dec 15 11:37:14 2008 +0000
+++ b/tools/libxc/xc_ptrace.c Tue Dec 16 11:49:20 2008 +0000
@@ -524,10 +524,20 @@ xc_ptrace(
/* XXX we can still have problems if the user switches threads
* during single-stepping - but that just seems retarded
*/
- ctxt[cpu].c.user_regs.eflags |= PSL_T;
- if ((retval = xc_vcpu_setcontext(xc_handle, current_domid, cpu,
- &ctxt[cpu])))
- goto out_error_domctl;
+ /* Try to enalbe Monitor Trap Flag for HVM, and fall back to TF
+ * if no MTF support
+ */
+ if ( !current_is_hvm ||
+ xc_domain_debug_control(xc_handle,
+ current_domid,
+ XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_ON,
+ cpu) )
+ {
+ ctxt[cpu].c.user_regs.eflags |= PSL_T;
+ if ((retval = xc_vcpu_setcontext(xc_handle, current_domid, cpu,
+ &ctxt[cpu])))
+ goto out_error_domctl;
+ }
/* FALLTHROUGH */
case PTRACE_CONT:
@@ -538,15 +548,22 @@ xc_ptrace(
{
FOREACH_CPU(cpumap, index) {
cpu = index - 1;
- if (fetch_regs(xc_handle, cpu, NULL))
- goto out_error;
- /* Clear trace flag */
- if ( ctxt[cpu].c.user_regs.eflags & PSL_T )
+ if ( !current_is_hvm ||
+ xc_domain_debug_control(xc_handle,
+ current_domid,
+
XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_OFF,
+ cpu) )
{
- ctxt[cpu].c.user_regs.eflags &= ~PSL_T;
- if ((retval = xc_vcpu_setcontext(xc_handle, current_domid,
- cpu, &ctxt[cpu])))
- goto out_error_domctl;
+ if (fetch_regs(xc_handle, cpu, NULL))
+ goto out_error;
+ /* Clear trace flag */
+ if ( ctxt[cpu].c.user_regs.eflags & PSL_T )
+ {
+ ctxt[cpu].c.user_regs.eflags &= ~PSL_T;
+ if ((retval = xc_vcpu_setcontext(xc_handle,
current_domid,
+ cpu, &ctxt[cpu])))
+ goto out_error_domctl;
+ }
}
}
}
diff -r f827181eadd4 -r 5b73fa1b9562 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h Mon Dec 15 11:37:14 2008 +0000
+++ b/tools/libxc/xenctrl.h Tue Dec 16 11:49:20 2008 +0000
@@ -1111,6 +1111,12 @@ int xc_domain_set_target(int xc_handle,
uint32_t domid,
uint32_t target);
+/* Control the domain for debug */
+int xc_domain_debug_control(int xc_handle,
+ uint32_t domid,
+ uint32_t sop,
+ uint32_t vcpu);
+
#if defined(__i386__) || defined(__x86_64__)
int xc_cpuid_check(int xc,
const unsigned int *input,
diff -r f827181eadd4 -r 5b73fa1b9562 xen/arch/x86/domctl.c
--- a/xen/arch/x86/domctl.c Mon Dec 15 11:37:14 2008 +0000
+++ b/xen/arch/x86/domctl.c Tue Dec 16 11:49:20 2008 +0000
@@ -1022,6 +1022,32 @@ long arch_do_domctl(
}
break;
+ case XEN_DOMCTL_debug_op:
+ {
+ struct domain *d;
+ struct vcpu *v;
+
+ ret = -ESRCH;
+ d = rcu_lock_domain_by_id(domctl->domain);
+ if ( d == NULL )
+ break;
+
+ ret = -EINVAL;
+ if ( (domctl->u.debug_op.vcpu >= MAX_VIRT_CPUS) ||
+ ((v = d->vcpu[domctl->u.debug_op.vcpu]) == NULL) )
+ goto debug_op_out;
+
+ ret = -EINVAL;
+ if ( !is_hvm_domain(d))
+ goto debug_op_out;
+
+ ret = hvm_debug_op(v, domctl->u.debug_op.op);
+
+ debug_op_out:
+ rcu_unlock_domain(d);
+ }
+ break;
+
default:
ret = -ENOSYS;
break;
diff -r f827181eadd4 -r 5b73fa1b9562 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c Mon Dec 15 11:37:14 2008 +0000
+++ b/xen/arch/x86/hvm/hvm.c Tue Dec 16 11:49:20 2008 +0000
@@ -2700,6 +2700,32 @@ long do_hvm_op(unsigned long op, XEN_GUE
return rc;
}
+int hvm_debug_op(struct vcpu *v, int32_t op)
+{
+ int rc;
+
+ switch ( op )
+ {
+ case XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_ON:
+ case XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_OFF:
+ rc = -ENOSYS;
+ if ( !cpu_has_monitor_trap_flag )
+ break;
+ rc = 0;
+ vcpu_pause(v);
+ v->arch.hvm_vcpu.single_step =
+ (op == XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_ON);
+ vcpu_unpause(v); /* guest will latch new state */
+ break;
+ default:
+ rc = -ENOSYS;
+ break;
+ }
+
+ return rc;
+}
+
+
/*
* Local variables:
* mode: C
diff -r f827181eadd4 -r 5b73fa1b9562 xen/arch/x86/hvm/vmx/intr.c
--- a/xen/arch/x86/hvm/vmx/intr.c Mon Dec 15 11:37:14 2008 +0000
+++ b/xen/arch/x86/hvm/vmx/intr.c Tue Dec 16 11:49:20 2008 +0000
@@ -117,6 +117,14 @@ asmlinkage void vmx_intr_assist(void)
unsigned int tpr_threshold = 0;
enum hvm_intblk intblk;
+ /* Block event injection when single step with MTF. */
+ if ( unlikely(v->arch.hvm_vcpu.single_step) )
+ {
+ v->arch.hvm_vmx.exec_control |= CPU_BASED_MONITOR_TRAP_FLAG;
+ __vmwrite(CPU_BASED_VM_EXEC_CONTROL, v->arch.hvm_vmx.exec_control);
+ return;
+ }
+
/* Crank the handle on interrupt state. */
pt_update_irq(v);
hvm_dirq_assist(v);
diff -r f827181eadd4 -r 5b73fa1b9562 xen/arch/x86/hvm/vmx/vmcs.c
--- a/xen/arch/x86/hvm/vmx/vmcs.c Mon Dec 15 11:37:14 2008 +0000
+++ b/xen/arch/x86/hvm/vmx/vmcs.c Tue Dec 16 11:49:20 2008 +0000
@@ -99,6 +99,7 @@ static void vmx_init_vmcs_config(void)
(opt_softtsc ? CPU_BASED_RDTSC_EXITING : 0));
opt = (CPU_BASED_ACTIVATE_MSR_BITMAP |
CPU_BASED_TPR_SHADOW |
+ CPU_BASED_MONITOR_TRAP_FLAG |
CPU_BASED_ACTIVATE_SECONDARY_CONTROLS);
_vmx_cpu_based_exec_control = adjust_vmx_controls(
min, opt, MSR_IA32_VMX_PROCBASED_CTLS);
@@ -515,6 +516,9 @@ static int construct_vmcs(struct vcpu *v
v->arch.hvm_vmx.secondary_exec_control &= ~SECONDARY_EXEC_ENABLE_EPT;
}
+ /* Do not enable Monitor Trap Flag unless start single step debug */
+ v->arch.hvm_vmx.exec_control &= ~CPU_BASED_MONITOR_TRAP_FLAG;
+
__vmwrite(CPU_BASED_VM_EXEC_CONTROL, v->arch.hvm_vmx.exec_control);
if ( cpu_has_vmx_secondary_exec_control )
__vmwrite(SECONDARY_VM_EXEC_CONTROL,
@@ -867,7 +871,11 @@ void vmx_do_resume(struct vcpu *v)
if ( unlikely(v->arch.hvm_vcpu.debug_state_latch != debug_state) )
{
unsigned long intercepts = __vmread(EXCEPTION_BITMAP);
- unsigned long mask = (1U << TRAP_debug) | (1U << TRAP_int3);
+ unsigned long mask = 1u << TRAP_int3;
+
+ if ( !cpu_has_monitor_trap_flag )
+ mask |= 1u << TRAP_debug;
+
v->arch.hvm_vcpu.debug_state_latch = debug_state;
if ( debug_state )
intercepts |= mask;
diff -r f827181eadd4 -r 5b73fa1b9562 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c Mon Dec 15 11:37:14 2008 +0000
+++ b/xen/arch/x86/hvm/vmx/vmx.c Tue Dec 16 11:49:20 2008 +0000
@@ -1263,6 +1263,8 @@ void vmx_inject_hw_exception(int trap, i
__restore_debug_registers(curr);
write_debugreg(6, read_debugreg(6) | 0x4000);
}
+ if ( cpu_has_monitor_trap_flag )
+ break;
case TRAP_int3:
if ( curr->domain->debugger_attached )
{
@@ -2348,7 +2350,7 @@ asmlinkage void vmx_vmexit_handler(struc
*/
exit_qualification = __vmread(EXIT_QUALIFICATION);
write_debugreg(6, exit_qualification | 0xffff0ff0);
- if ( !v->domain->debugger_attached )
+ if ( !v->domain->debugger_attached || cpu_has_monitor_trap_flag )
goto exit_and_crash;
domain_pause_for_debugger();
break;
@@ -2538,6 +2540,15 @@ asmlinkage void vmx_vmexit_handler(struc
break;
}
+ case EXIT_REASON_MONITOR_TRAP_FLAG:
+ {
+ v->arch.hvm_vmx.exec_control &= ~CPU_BASED_MONITOR_TRAP_FLAG;
+ __vmwrite(CPU_BASED_VM_EXEC_CONTROL, v->arch.hvm_vmx.exec_control);
+ if ( v->domain->debugger_attached && v->arch.hvm_vcpu.single_step )
+ domain_pause_for_debugger();
+ break;
+ }
+
default:
exit_and_crash:
gdprintk(XENLOG_ERR, "Bad vmexit (reason %x)\n", exit_reason);
diff -r f827181eadd4 -r 5b73fa1b9562 xen/include/asm-x86/hvm/hvm.h
--- a/xen/include/asm-x86/hvm/hvm.h Mon Dec 15 11:37:14 2008 +0000
+++ b/xen/include/asm-x86/hvm/hvm.h Tue Dec 16 11:49:20 2008 +0000
@@ -321,4 +321,6 @@ static inline void hvm_set_info_guest(st
return hvm_funcs.set_info_guest(v);
}
+int hvm_debug_op(struct vcpu *v, int32_t op);
+
#endif /* __ASM_X86_HVM_HVM_H__ */
diff -r f827181eadd4 -r 5b73fa1b9562 xen/include/asm-x86/hvm/vcpu.h
--- a/xen/include/asm-x86/hvm/vcpu.h Mon Dec 15 11:37:14 2008 +0000
+++ b/xen/include/asm-x86/hvm/vcpu.h Tue Dec 16 11:49:20 2008 +0000
@@ -59,6 +59,7 @@ struct hvm_vcpu {
bool_t flag_dr_dirty;
bool_t debug_state_latch;
+ bool_t single_step;
union {
struct arch_vmx_struct vmx;
diff -r f827181eadd4 -r 5b73fa1b9562 xen/include/asm-x86/hvm/vmx/vmcs.h
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h Mon Dec 15 11:37:14 2008 +0000
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h Tue Dec 16 11:49:20 2008 +0000
@@ -142,6 +142,7 @@ void vmx_vmcs_exit(struct vcpu *v);
#define CPU_BASED_MOV_DR_EXITING 0x00800000
#define CPU_BASED_UNCOND_IO_EXITING 0x01000000
#define CPU_BASED_ACTIVATE_IO_BITMAP 0x02000000
+#define CPU_BASED_MONITOR_TRAP_FLAG 0x08000000
#define CPU_BASED_ACTIVATE_MSR_BITMAP 0x10000000
#define CPU_BASED_MONITOR_EXITING 0x20000000
#define CPU_BASED_PAUSE_EXITING 0x40000000
@@ -186,6 +187,8 @@ extern bool_t cpu_has_vmx_ins_outs_instr
(vmx_secondary_exec_control & SECONDARY_EXEC_ENABLE_EPT)
#define cpu_has_vmx_vpid \
(vmx_secondary_exec_control & SECONDARY_EXEC_ENABLE_VPID)
+#define cpu_has_monitor_trap_flag \
+ (vmx_cpu_based_exec_control & CPU_BASED_MONITOR_TRAP_FLAG)
/* GUEST_INTERRUPTIBILITY_INFO flags. */
#define VMX_INTR_SHADOW_STI 0x00000001
diff -r f827181eadd4 -r 5b73fa1b9562 xen/include/asm-x86/hvm/vmx/vmx.h
--- a/xen/include/asm-x86/hvm/vmx/vmx.h Mon Dec 15 11:37:14 2008 +0000
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h Tue Dec 16 11:49:20 2008 +0000
@@ -96,6 +96,7 @@ void vmx_realmode(struct cpu_user_regs *
#define EXIT_REASON_INVALID_GUEST_STATE 33
#define EXIT_REASON_MSR_LOADING 34
#define EXIT_REASON_MWAIT_INSTRUCTION 36
+#define EXIT_REASON_MONITOR_TRAP_FLAG 37
#define EXIT_REASON_MONITOR_INSTRUCTION 39
#define EXIT_REASON_PAUSE_INSTRUCTION 40
#define EXIT_REASON_MACHINE_CHECK 41
diff -r f827181eadd4 -r 5b73fa1b9562 xen/include/public/domctl.h
--- a/xen/include/public/domctl.h Mon Dec 15 11:37:14 2008 +0000
+++ b/xen/include/public/domctl.h Tue Dec 16 11:49:20 2008 +0000
@@ -619,6 +619,17 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_subsc
*/
#define XEN_DOMCTL_suppress_spurious_page_faults 53
+#define XEN_DOMCTL_debug_op 54
+#define XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_OFF 0
+#define XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_ON 1
+struct xen_domctl_debug_op {
+ uint32_t op; /* IN */
+ uint32_t vcpu; /* IN */
+};
+typedef struct xen_domctl_debug_op xen_domctl_debug_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_debug_op_t);
+
+
struct xen_domctl {
uint32_t cmd;
uint32_t interface_version; /* XEN_DOMCTL_INTERFACE_VERSION */
@@ -658,6 +669,7 @@ struct xen_domctl {
struct xen_domctl_set_opt_feature set_opt_feature;
struct xen_domctl_set_target set_target;
struct xen_domctl_subscribe subscribe;
+ struct xen_domctl_debug_op debug_op;
#if defined(__i386__) || defined(__x86_64__)
struct xen_domctl_cpuid cpuid;
#endif
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|