debuggers.hg
changeset 18959:5b73fa1b9562
x86: Enable MTF for HVM guest single step in gdb
Signed-off-by: Edwin Zhai <edwin.zhai@intel.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
Signed-off-by: Edwin Zhai <edwin.zhai@intel.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author | Keir Fraser <keir.fraser@citrix.com> |
---|---|
date | Tue Dec 16 11:49:20 2008 +0000 (2008-12-16) |
parents | f827181eadd4 |
children | c3df4b8ea2fc |
files | tools/libxc/xc_domain.c tools/libxc/xc_ptrace.c tools/libxc/xenctrl.h xen/arch/x86/domctl.c xen/arch/x86/hvm/hvm.c xen/arch/x86/hvm/vmx/intr.c xen/arch/x86/hvm/vmx/vmcs.c xen/arch/x86/hvm/vmx/vmx.c xen/include/asm-x86/hvm/hvm.h xen/include/asm-x86/hvm/vcpu.h xen/include/asm-x86/hvm/vmx/vmcs.h xen/include/asm-x86/hvm/vmx/vmx.h xen/include/public/domctl.h |
line diff
1.1 --- a/tools/libxc/xc_domain.c Mon Dec 15 11:37:14 2008 +0000 1.2 +++ b/tools/libxc/xc_domain.c Tue Dec 16 11:49:20 2008 +0000 1.3 @@ -1061,6 +1061,20 @@ int xc_domain_suppress_spurious_page_fau 1.4 1.5 } 1.6 1.7 +int xc_domain_debug_control(int xc, uint32_t domid, uint32_t sop, uint32_t vcpu) 1.8 +{ 1.9 + DECLARE_DOMCTL; 1.10 + 1.11 + memset(&domctl, 0, sizeof(domctl)); 1.12 + domctl.domain = (domid_t)domid; 1.13 + domctl.cmd = XEN_DOMCTL_debug_op; 1.14 + domctl.u.debug_op.op = sop; 1.15 + domctl.u.debug_op.vcpu = vcpu; 1.16 + 1.17 + return do_domctl(xc, &domctl); 1.18 +} 1.19 + 1.20 + 1.21 /* 1.22 * Local variables: 1.23 * mode: C
2.1 --- a/tools/libxc/xc_ptrace.c Mon Dec 15 11:37:14 2008 +0000 2.2 +++ b/tools/libxc/xc_ptrace.c Tue Dec 16 11:49:20 2008 +0000 2.3 @@ -524,10 +524,20 @@ xc_ptrace( 2.4 /* XXX we can still have problems if the user switches threads 2.5 * during single-stepping - but that just seems retarded 2.6 */ 2.7 - ctxt[cpu].c.user_regs.eflags |= PSL_T; 2.8 - if ((retval = xc_vcpu_setcontext(xc_handle, current_domid, cpu, 2.9 - &ctxt[cpu]))) 2.10 - goto out_error_domctl; 2.11 + /* Try to enalbe Monitor Trap Flag for HVM, and fall back to TF 2.12 + * if no MTF support 2.13 + */ 2.14 + if ( !current_is_hvm || 2.15 + xc_domain_debug_control(xc_handle, 2.16 + current_domid, 2.17 + XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_ON, 2.18 + cpu) ) 2.19 + { 2.20 + ctxt[cpu].c.user_regs.eflags |= PSL_T; 2.21 + if ((retval = xc_vcpu_setcontext(xc_handle, current_domid, cpu, 2.22 + &ctxt[cpu]))) 2.23 + goto out_error_domctl; 2.24 + } 2.25 /* FALLTHROUGH */ 2.26 2.27 case PTRACE_CONT: 2.28 @@ -538,15 +548,22 @@ xc_ptrace( 2.29 { 2.30 FOREACH_CPU(cpumap, index) { 2.31 cpu = index - 1; 2.32 - if (fetch_regs(xc_handle, cpu, NULL)) 2.33 - goto out_error; 2.34 - /* Clear trace flag */ 2.35 - if ( ctxt[cpu].c.user_regs.eflags & PSL_T ) 2.36 + if ( !current_is_hvm || 2.37 + xc_domain_debug_control(xc_handle, 2.38 + current_domid, 2.39 + XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_OFF, 2.40 + cpu) ) 2.41 { 2.42 - ctxt[cpu].c.user_regs.eflags &= ~PSL_T; 2.43 - if ((retval = xc_vcpu_setcontext(xc_handle, current_domid, 2.44 - cpu, &ctxt[cpu]))) 2.45 - goto out_error_domctl; 2.46 + if (fetch_regs(xc_handle, cpu, NULL)) 2.47 + goto out_error; 2.48 + /* Clear trace flag */ 2.49 + if ( ctxt[cpu].c.user_regs.eflags & PSL_T ) 2.50 + { 2.51 + ctxt[cpu].c.user_regs.eflags &= ~PSL_T; 2.52 + if ((retval = xc_vcpu_setcontext(xc_handle, current_domid, 2.53 + cpu, &ctxt[cpu]))) 2.54 + goto out_error_domctl; 2.55 + } 2.56 } 2.57 } 2.58 }
3.1 --- a/tools/libxc/xenctrl.h Mon Dec 15 11:37:14 2008 +0000 3.2 +++ b/tools/libxc/xenctrl.h Tue Dec 16 11:49:20 2008 +0000 3.3 @@ -1111,6 +1111,12 @@ int xc_domain_set_target(int xc_handle, 3.4 uint32_t domid, 3.5 uint32_t target); 3.6 3.7 +/* Control the domain for debug */ 3.8 +int xc_domain_debug_control(int xc_handle, 3.9 + uint32_t domid, 3.10 + uint32_t sop, 3.11 + uint32_t vcpu); 3.12 + 3.13 #if defined(__i386__) || defined(__x86_64__) 3.14 int xc_cpuid_check(int xc, 3.15 const unsigned int *input,
4.1 --- a/xen/arch/x86/domctl.c Mon Dec 15 11:37:14 2008 +0000 4.2 +++ b/xen/arch/x86/domctl.c Tue Dec 16 11:49:20 2008 +0000 4.3 @@ -1022,6 +1022,32 @@ long arch_do_domctl( 4.4 } 4.5 break; 4.6 4.7 + case XEN_DOMCTL_debug_op: 4.8 + { 4.9 + struct domain *d; 4.10 + struct vcpu *v; 4.11 + 4.12 + ret = -ESRCH; 4.13 + d = rcu_lock_domain_by_id(domctl->domain); 4.14 + if ( d == NULL ) 4.15 + break; 4.16 + 4.17 + ret = -EINVAL; 4.18 + if ( (domctl->u.debug_op.vcpu >= MAX_VIRT_CPUS) || 4.19 + ((v = d->vcpu[domctl->u.debug_op.vcpu]) == NULL) ) 4.20 + goto debug_op_out; 4.21 + 4.22 + ret = -EINVAL; 4.23 + if ( !is_hvm_domain(d)) 4.24 + goto debug_op_out; 4.25 + 4.26 + ret = hvm_debug_op(v, domctl->u.debug_op.op); 4.27 + 4.28 + debug_op_out: 4.29 + rcu_unlock_domain(d); 4.30 + } 4.31 + break; 4.32 + 4.33 default: 4.34 ret = -ENOSYS; 4.35 break;
5.1 --- a/xen/arch/x86/hvm/hvm.c Mon Dec 15 11:37:14 2008 +0000 5.2 +++ b/xen/arch/x86/hvm/hvm.c Tue Dec 16 11:49:20 2008 +0000 5.3 @@ -2700,6 +2700,32 @@ long do_hvm_op(unsigned long op, XEN_GUE 5.4 return rc; 5.5 } 5.6 5.7 +int hvm_debug_op(struct vcpu *v, int32_t op) 5.8 +{ 5.9 + int rc; 5.10 + 5.11 + switch ( op ) 5.12 + { 5.13 + case XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_ON: 5.14 + case XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_OFF: 5.15 + rc = -ENOSYS; 5.16 + if ( !cpu_has_monitor_trap_flag ) 5.17 + break; 5.18 + rc = 0; 5.19 + vcpu_pause(v); 5.20 + v->arch.hvm_vcpu.single_step = 5.21 + (op == XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_ON); 5.22 + vcpu_unpause(v); /* guest will latch new state */ 5.23 + break; 5.24 + default: 5.25 + rc = -ENOSYS; 5.26 + break; 5.27 + } 5.28 + 5.29 + return rc; 5.30 +} 5.31 + 5.32 + 5.33 /* 5.34 * Local variables: 5.35 * mode: C
6.1 --- a/xen/arch/x86/hvm/vmx/intr.c Mon Dec 15 11:37:14 2008 +0000 6.2 +++ b/xen/arch/x86/hvm/vmx/intr.c Tue Dec 16 11:49:20 2008 +0000 6.3 @@ -117,6 +117,14 @@ asmlinkage void vmx_intr_assist(void) 6.4 unsigned int tpr_threshold = 0; 6.5 enum hvm_intblk intblk; 6.6 6.7 + /* Block event injection when single step with MTF. */ 6.8 + if ( unlikely(v->arch.hvm_vcpu.single_step) ) 6.9 + { 6.10 + v->arch.hvm_vmx.exec_control |= CPU_BASED_MONITOR_TRAP_FLAG; 6.11 + __vmwrite(CPU_BASED_VM_EXEC_CONTROL, v->arch.hvm_vmx.exec_control); 6.12 + return; 6.13 + } 6.14 + 6.15 /* Crank the handle on interrupt state. */ 6.16 pt_update_irq(v); 6.17 hvm_dirq_assist(v);
7.1 --- a/xen/arch/x86/hvm/vmx/vmcs.c Mon Dec 15 11:37:14 2008 +0000 7.2 +++ b/xen/arch/x86/hvm/vmx/vmcs.c Tue Dec 16 11:49:20 2008 +0000 7.3 @@ -99,6 +99,7 @@ static void vmx_init_vmcs_config(void) 7.4 (opt_softtsc ? CPU_BASED_RDTSC_EXITING : 0)); 7.5 opt = (CPU_BASED_ACTIVATE_MSR_BITMAP | 7.6 CPU_BASED_TPR_SHADOW | 7.7 + CPU_BASED_MONITOR_TRAP_FLAG | 7.8 CPU_BASED_ACTIVATE_SECONDARY_CONTROLS); 7.9 _vmx_cpu_based_exec_control = adjust_vmx_controls( 7.10 min, opt, MSR_IA32_VMX_PROCBASED_CTLS); 7.11 @@ -515,6 +516,9 @@ static int construct_vmcs(struct vcpu *v 7.12 v->arch.hvm_vmx.secondary_exec_control &= ~SECONDARY_EXEC_ENABLE_EPT; 7.13 } 7.14 7.15 + /* Do not enable Monitor Trap Flag unless start single step debug */ 7.16 + v->arch.hvm_vmx.exec_control &= ~CPU_BASED_MONITOR_TRAP_FLAG; 7.17 + 7.18 __vmwrite(CPU_BASED_VM_EXEC_CONTROL, v->arch.hvm_vmx.exec_control); 7.19 if ( cpu_has_vmx_secondary_exec_control ) 7.20 __vmwrite(SECONDARY_VM_EXEC_CONTROL, 7.21 @@ -867,7 +871,11 @@ void vmx_do_resume(struct vcpu *v) 7.22 if ( unlikely(v->arch.hvm_vcpu.debug_state_latch != debug_state) ) 7.23 { 7.24 unsigned long intercepts = __vmread(EXCEPTION_BITMAP); 7.25 - unsigned long mask = (1U << TRAP_debug) | (1U << TRAP_int3); 7.26 + unsigned long mask = 1u << TRAP_int3; 7.27 + 7.28 + if ( !cpu_has_monitor_trap_flag ) 7.29 + mask |= 1u << TRAP_debug; 7.30 + 7.31 v->arch.hvm_vcpu.debug_state_latch = debug_state; 7.32 if ( debug_state ) 7.33 intercepts |= mask;
8.1 --- a/xen/arch/x86/hvm/vmx/vmx.c Mon Dec 15 11:37:14 2008 +0000 8.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c Tue Dec 16 11:49:20 2008 +0000 8.3 @@ -1263,6 +1263,8 @@ void vmx_inject_hw_exception(int trap, i 8.4 __restore_debug_registers(curr); 8.5 write_debugreg(6, read_debugreg(6) | 0x4000); 8.6 } 8.7 + if ( cpu_has_monitor_trap_flag ) 8.8 + break; 8.9 case TRAP_int3: 8.10 if ( curr->domain->debugger_attached ) 8.11 { 8.12 @@ -2348,7 +2350,7 @@ asmlinkage void vmx_vmexit_handler(struc 8.13 */ 8.14 exit_qualification = __vmread(EXIT_QUALIFICATION); 8.15 write_debugreg(6, exit_qualification | 0xffff0ff0); 8.16 - if ( !v->domain->debugger_attached ) 8.17 + if ( !v->domain->debugger_attached || cpu_has_monitor_trap_flag ) 8.18 goto exit_and_crash; 8.19 domain_pause_for_debugger(); 8.20 break; 8.21 @@ -2538,6 +2540,15 @@ asmlinkage void vmx_vmexit_handler(struc 8.22 break; 8.23 } 8.24 8.25 + case EXIT_REASON_MONITOR_TRAP_FLAG: 8.26 + { 8.27 + v->arch.hvm_vmx.exec_control &= ~CPU_BASED_MONITOR_TRAP_FLAG; 8.28 + __vmwrite(CPU_BASED_VM_EXEC_CONTROL, v->arch.hvm_vmx.exec_control); 8.29 + if ( v->domain->debugger_attached && v->arch.hvm_vcpu.single_step ) 8.30 + domain_pause_for_debugger(); 8.31 + break; 8.32 + } 8.33 + 8.34 default: 8.35 exit_and_crash: 8.36 gdprintk(XENLOG_ERR, "Bad vmexit (reason %x)\n", exit_reason);
9.1 --- a/xen/include/asm-x86/hvm/hvm.h Mon Dec 15 11:37:14 2008 +0000 9.2 +++ b/xen/include/asm-x86/hvm/hvm.h Tue Dec 16 11:49:20 2008 +0000 9.3 @@ -321,4 +321,6 @@ static inline void hvm_set_info_guest(st 9.4 return hvm_funcs.set_info_guest(v); 9.5 } 9.6 9.7 +int hvm_debug_op(struct vcpu *v, int32_t op); 9.8 + 9.9 #endif /* __ASM_X86_HVM_HVM_H__ */
10.1 --- a/xen/include/asm-x86/hvm/vcpu.h Mon Dec 15 11:37:14 2008 +0000 10.2 +++ b/xen/include/asm-x86/hvm/vcpu.h Tue Dec 16 11:49:20 2008 +0000 10.3 @@ -59,6 +59,7 @@ struct hvm_vcpu { 10.4 10.5 bool_t flag_dr_dirty; 10.6 bool_t debug_state_latch; 10.7 + bool_t single_step; 10.8 10.9 union { 10.10 struct arch_vmx_struct vmx;
11.1 --- a/xen/include/asm-x86/hvm/vmx/vmcs.h Mon Dec 15 11:37:14 2008 +0000 11.2 +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h Tue Dec 16 11:49:20 2008 +0000 11.3 @@ -142,6 +142,7 @@ void vmx_vmcs_exit(struct vcpu *v); 11.4 #define CPU_BASED_MOV_DR_EXITING 0x00800000 11.5 #define CPU_BASED_UNCOND_IO_EXITING 0x01000000 11.6 #define CPU_BASED_ACTIVATE_IO_BITMAP 0x02000000 11.7 +#define CPU_BASED_MONITOR_TRAP_FLAG 0x08000000 11.8 #define CPU_BASED_ACTIVATE_MSR_BITMAP 0x10000000 11.9 #define CPU_BASED_MONITOR_EXITING 0x20000000 11.10 #define CPU_BASED_PAUSE_EXITING 0x40000000 11.11 @@ -186,6 +187,8 @@ extern bool_t cpu_has_vmx_ins_outs_instr 11.12 (vmx_secondary_exec_control & SECONDARY_EXEC_ENABLE_EPT) 11.13 #define cpu_has_vmx_vpid \ 11.14 (vmx_secondary_exec_control & SECONDARY_EXEC_ENABLE_VPID) 11.15 +#define cpu_has_monitor_trap_flag \ 11.16 + (vmx_cpu_based_exec_control & CPU_BASED_MONITOR_TRAP_FLAG) 11.17 11.18 /* GUEST_INTERRUPTIBILITY_INFO flags. */ 11.19 #define VMX_INTR_SHADOW_STI 0x00000001
12.1 --- a/xen/include/asm-x86/hvm/vmx/vmx.h Mon Dec 15 11:37:14 2008 +0000 12.2 +++ b/xen/include/asm-x86/hvm/vmx/vmx.h Tue Dec 16 11:49:20 2008 +0000 12.3 @@ -96,6 +96,7 @@ void vmx_realmode(struct cpu_user_regs * 12.4 #define EXIT_REASON_INVALID_GUEST_STATE 33 12.5 #define EXIT_REASON_MSR_LOADING 34 12.6 #define EXIT_REASON_MWAIT_INSTRUCTION 36 12.7 +#define EXIT_REASON_MONITOR_TRAP_FLAG 37 12.8 #define EXIT_REASON_MONITOR_INSTRUCTION 39 12.9 #define EXIT_REASON_PAUSE_INSTRUCTION 40 12.10 #define EXIT_REASON_MACHINE_CHECK 41
13.1 --- a/xen/include/public/domctl.h Mon Dec 15 11:37:14 2008 +0000 13.2 +++ b/xen/include/public/domctl.h Tue Dec 16 11:49:20 2008 +0000 13.3 @@ -619,6 +619,17 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_subsc 13.4 */ 13.5 #define XEN_DOMCTL_suppress_spurious_page_faults 53 13.6 13.7 +#define XEN_DOMCTL_debug_op 54 13.8 +#define XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_OFF 0 13.9 +#define XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_ON 1 13.10 +struct xen_domctl_debug_op { 13.11 + uint32_t op; /* IN */ 13.12 + uint32_t vcpu; /* IN */ 13.13 +}; 13.14 +typedef struct xen_domctl_debug_op xen_domctl_debug_op_t; 13.15 +DEFINE_XEN_GUEST_HANDLE(xen_domctl_debug_op_t); 13.16 + 13.17 + 13.18 struct xen_domctl { 13.19 uint32_t cmd; 13.20 uint32_t interface_version; /* XEN_DOMCTL_INTERFACE_VERSION */ 13.21 @@ -658,6 +669,7 @@ struct xen_domctl { 13.22 struct xen_domctl_set_opt_feature set_opt_feature; 13.23 struct xen_domctl_set_target set_target; 13.24 struct xen_domctl_subscribe subscribe; 13.25 + struct xen_domctl_debug_op debug_op; 13.26 #if defined(__i386__) || defined(__x86_64__) 13.27 struct xen_domctl_cpuid cpuid; 13.28 #endif