diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2008-12-16 11:49:20 +0000 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2008-12-16 11:49:20 +0000 |
commit | 74d59a59e2db922adb45a427df3d77b8ff0f7aea (patch) | |
tree | a0d2e657a8ef20aaa680ea9df187b17511639d18 /xen | |
parent | 53e5cd08efbc58937be16027b35414a3353bfc51 (diff) | |
download | xen-74d59a59e2db922adb45a427df3d77b8ff0f7aea.tar.gz xen-74d59a59e2db922adb45a427df3d77b8ff0f7aea.tar.bz2 xen-74d59a59e2db922adb45a427df3d77b8ff0f7aea.zip |
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>
Diffstat (limited to 'xen')
-rw-r--r-- | xen/arch/x86/domctl.c | 26 | ||||
-rw-r--r-- | xen/arch/x86/hvm/hvm.c | 26 | ||||
-rw-r--r-- | xen/arch/x86/hvm/vmx/intr.c | 8 | ||||
-rw-r--r-- | xen/arch/x86/hvm/vmx/vmcs.c | 10 | ||||
-rw-r--r-- | xen/arch/x86/hvm/vmx/vmx.c | 13 | ||||
-rw-r--r-- | xen/include/asm-x86/hvm/hvm.h | 2 | ||||
-rw-r--r-- | xen/include/asm-x86/hvm/vcpu.h | 1 | ||||
-rw-r--r-- | xen/include/asm-x86/hvm/vmx/vmcs.h | 3 | ||||
-rw-r--r-- | xen/include/asm-x86/hvm/vmx/vmx.h | 1 | ||||
-rw-r--r-- | xen/include/public/domctl.h | 12 |
10 files changed, 100 insertions, 2 deletions
diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index 50967ab71b..8b4c40fea0 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -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 --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 9bda106ec2..fdcea74097 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -2700,6 +2700,32 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) 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 --git a/xen/arch/x86/hvm/vmx/intr.c b/xen/arch/x86/hvm/vmx/intr.c index 2c45e26bfa..afd9d41919 100644 --- a/xen/arch/x86/hvm/vmx/intr.c +++ b/xen/arch/x86/hvm/vmx/intr.c @@ -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 --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c index 051443f7e7..83598c1818 100644 --- a/xen/arch/x86/hvm/vmx/vmcs.c +++ b/xen/arch/x86/hvm/vmx/vmcs.c @@ -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 --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index ff2420f448..1519a78d03 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -1263,6 +1263,8 @@ void vmx_inject_hw_exception(int trap, int error_code) __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(struct cpu_user_regs *regs) */ 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(struct cpu_user_regs *regs) 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 --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h index a9bee16e10..b61c566094 100644 --- a/xen/include/asm-x86/hvm/hvm.h +++ b/xen/include/asm-x86/hvm/hvm.h @@ -321,4 +321,6 @@ static inline void hvm_set_info_guest(struct vcpu *v) return hvm_funcs.set_info_guest(v); } +int hvm_debug_op(struct vcpu *v, int32_t op); + #endif /* __ASM_X86_HVM_HVM_H__ */ diff --git a/xen/include/asm-x86/hvm/vcpu.h b/xen/include/asm-x86/hvm/vcpu.h index 6eb9d67b73..faea392f92 100644 --- a/xen/include/asm-x86/hvm/vcpu.h +++ b/xen/include/asm-x86/hvm/vcpu.h @@ -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 --git a/xen/include/asm-x86/hvm/vmx/vmcs.h b/xen/include/asm-x86/hvm/vmx/vmcs.h index befe36c8c0..5337ec93dd 100644 --- a/xen/include/asm-x86/hvm/vmx/vmcs.h +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h @@ -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_info; (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 --git a/xen/include/asm-x86/hvm/vmx/vmx.h b/xen/include/asm-x86/hvm/vmx/vmx.h index 563e8aea36..21dec48dc4 100644 --- a/xen/include/asm-x86/hvm/vmx/vmx.h +++ b/xen/include/asm-x86/hvm/vmx/vmx.h @@ -96,6 +96,7 @@ void vmx_realmode(struct cpu_user_regs *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 --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h index b7075ac447..4863f48eec 100644 --- a/xen/include/public/domctl.h +++ b/xen/include/public/domctl.h @@ -619,6 +619,17 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_subscribe_t); */ #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 |