* [PATCH] [HVM] enable MTF for guest single step debug
@ 2008-12-11 7:09 Zhai, Edwin
2008-12-11 11:45 ` Keir Fraser
0 siblings, 1 reply; 3+ messages in thread
From: Zhai, Edwin @ 2008-12-11 7:09 UTC (permalink / raw)
To: Xen Developers; +Cc: Zhai, Edwin
[-- Attachment #1: Type: text/plain, Size: 372 bytes --]
Monitor Trap Flag (MTF), is a debugging feature that cause vmexit on
certain instruction boundaries, which can be used for HVM single step.
We prefer MTF over TF, as it make TF free for guest use.
This patch try to enable MTF for single step in gdb, and keep backward
compatibility on old processor.
Pls. see MTF details @ SDM 3b 21.7.2
Thanks,
--
best rgds,
edwin
[-- Attachment #2: MTF_enable_r18891_v1.patch --]
[-- Type: text/plain, Size: 12952 bytes --]
Enable MTF for HVM guest single step in gdb
Signed-off-by: Edwin Zhai <edwin.zhai@intel.com>
Index: hv/tools/libxc/xc_ptrace.c
===================================================================
--- hv.orig/tools/libxc/xc_ptrace.c
+++ hv/tools/libxc/xc_ptrace.c
@@ -524,10 +524,18 @@ 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_set_hvm_param(xc_handle, current_domid, HVM_PARAM_MTF,
+ (cpu << 1) | 1))
+ {
+ 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 +546,20 @@ 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_set_hvm_param(xc_handle, current_domid, HVM_PARAM_MTF,
+ (cpu << 1) | 0))
{
- 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;
+ }
}
}
}
Index: hv/xen/arch/x86/hvm/hvm.c
===================================================================
--- hv.orig/xen/arch/x86/hvm/hvm.c
+++ hv/xen/arch/x86/hvm/hvm.c
@@ -2504,6 +2504,24 @@ long do_hvm_op(unsigned long op, XEN_GUE
rc = -EINVAL;
break;
+ case HVM_PARAM_MTF:
+ rc = -EPERM;
+ if ( !IS_PRIV(current->domain) )
+ break;
+
+ rc = -EINVAL;
+ /* format: cpu | function
+ * function: 1-enable; 0-disable
+ */
+ if ( (a.value >> 1) >= MAX_VIRT_CPUS ||
+ (v = d->vcpu[a.value >> 1]) == NULL )
+ break;
+
+ if ( !d->debugger_attached )
+ break;
+
+ rc = hvm_single_step(v, (a.value & 0x1));
+ break;
}
if ( rc == 0 )
Index: hv/xen/arch/x86/hvm/vmx/intr.c
===================================================================
--- hv.orig/xen/arch/x86/hvm/vmx/intr.c
+++ hv/xen/arch/x86/hvm/vmx/intr.c
@@ -117,6 +117,17 @@ asmlinkage void vmx_intr_assist(void)
unsigned int tpr_threshold = 0;
enum hvm_intblk intblk;
+ /* Block event injection when single step with MTF,
+ * or else step into the guest event handler(SDM 3b 21.7.2)
+ */
+ if ( cpu_has_monitor_trap_flag && v->arch.hvm_vmx.activate_mtf )
+ {
+ 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);
Index: hv/xen/arch/x86/hvm/vmx/vmcs.c
===================================================================
--- hv.orig/xen/arch/x86/hvm/vmx/vmcs.c
+++ hv/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,13 @@ 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;
Index: hv/xen/arch/x86/hvm/vmx/vmx.c
===================================================================
--- hv.orig/xen/arch/x86/hvm/vmx/vmx.c
+++ hv/xen/arch/x86/hvm/vmx/vmx.c
@@ -1258,6 +1258,11 @@ void vmx_inject_hw_exception(int trap, i
switch ( trap )
{
case TRAP_debug:
+ /* If has MTF, TF is free for guest use */
+ if ( cpu_has_monitor_trap_flag )
+ {
+ break;
+ }
if ( guest_cpu_user_regs()->eflags & X86_EFLAGS_TF )
{
__restore_debug_registers(curr);
@@ -1336,6 +1341,15 @@ static void vmx_set_info_guest(struct vc
vmx_vmcs_exit(v);
}
+static int vmx_single_step(struct vcpu *v, int enable)
+{
+ if ( !cpu_has_monitor_trap_flag )
+ return -1;
+
+ v->arch.hvm_vmx.activate_mtf = enable;
+ return 0;
+}
+
static struct hvm_function_table vmx_function_table = {
.name = "VMX",
.domain_initialise = vmx_domain_initialise,
@@ -1367,7 +1381,8 @@ static struct hvm_function_table vmx_fun
.msr_write_intercept = vmx_msr_write_intercept,
.invlpg_intercept = vmx_invlpg_intercept,
.set_uc_mode = vmx_set_uc_mode,
- .set_info_guest = vmx_set_info_guest
+ .set_info_guest = vmx_set_info_guest,
+ .single_step = vmx_single_step
};
static unsigned long *vpid_bitmap;
@@ -2342,6 +2357,13 @@ asmlinkage void vmx_vmexit_handler(struc
switch ( vector )
{
case TRAP_debug:
+ /* If has MTF, use it for single step rather than TF*/
+ if ( cpu_has_monitor_trap_flag )
+ {
+ gdprintk(XENLOG_ERR, "Unexpected TRAP_debug vmexit!");
+ goto exit_and_crash;
+ }
+
/*
* Updates DR6 where debugger can peek (See 3B 23.2.1,
* Table 23-1, "Exit Qualification for Debug Exceptions").
@@ -2538,6 +2560,19 @@ asmlinkage void vmx_vmexit_handler(struc
break;
}
+ case EXIT_REASON_MONITOR_TRAP_FLAG:
+ {
+ if ( !v->domain->debugger_attached )
+ goto exit_and_crash;
+
+ v->arch.hvm_vmx.exec_control &= ~CPU_BASED_MONITOR_TRAP_FLAG;
+ __vmwrite(CPU_BASED_VM_EXEC_CONTROL,
+ v->arch.hvm_vmx.exec_control);
+
+ domain_pause_for_debugger();
+ break;
+ }
+
default:
exit_and_crash:
gdprintk(XENLOG_ERR, "Bad vmexit (reason %x)\n", exit_reason);
Index: hv/xen/include/asm-x86/hvm/vmx/vmcs.h
===================================================================
--- hv.orig/xen/include/asm-x86/hvm/vmx/vmcs.h
+++ hv/xen/include/asm-x86/hvm/vmx/vmcs.h
@@ -119,6 +119,9 @@ struct arch_vmx_struct {
struct segment_register vm86_saved_seg[x86_seg_tr + 1];
/* Remember EFLAGS while in virtual 8086 mode */
uint32_t vm86_saved_eflags;
+
+ /* If need activate MTF for guest single step deubg ?*/
+ uint8_t activate_mtf;
};
int vmx_create_vmcs(struct vcpu *v);
@@ -142,6 +145,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 +190,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
Index: hv/xen/include/asm-x86/hvm/vmx/vmx.h
===================================================================
--- hv.orig/xen/include/asm-x86/hvm/vmx/vmx.h
+++ hv/xen/include/asm-x86/hvm/vmx/vmx.h
@@ -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
Index: hv/xen/include/public/hvm/params.h
===================================================================
--- hv.orig/xen/include/public/hvm/params.h
+++ hv/xen/include/public/hvm/params.h
@@ -103,6 +103,9 @@
/* TSS used on Intel when CR0.PE=0. */
#define HVM_PARAM_VM86_TSS 15
-#define HVM_NR_PARAMS 16
+/* HVM MTF(Monitor Trap Flag) Enabling for debug */
+#define HVM_PARAM_MTF 16
+
+#define HVM_NR_PARAMS 17
#endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
Index: hv/xen/include/asm-x86/hvm/hvm.h
===================================================================
--- hv.orig/xen/include/asm-x86/hvm/hvm.h
+++ hv/xen/include/asm-x86/hvm/hvm.h
@@ -129,6 +129,7 @@ struct hvm_function_table {
void (*invlpg_intercept)(unsigned long vaddr);
void (*set_uc_mode)(struct vcpu *v);
void (*set_info_guest)(struct vcpu *v);
+ int (*single_step)(struct vcpu *v, int enable);
};
extern struct hvm_function_table hvm_funcs;
@@ -277,6 +278,7 @@ static inline int hvm_do_pmu_interrupt(s
#define X86_EVENTTYPE_HW_EXCEPTION 3 /* hardware exception */
#define X86_EVENTTYPE_SW_INTERRUPT 4 /* software interrupt */
#define X86_EVENTTYPE_SW_EXCEPTION 6 /* software exception */
+#define X86_EVENTTYPE_OTHER 7 /* other event */
int hvm_event_needs_reinjection(uint8_t type, uint8_t vector);
@@ -321,4 +323,13 @@ static inline void hvm_set_info_guest(st
return hvm_funcs.set_info_guest(v);
}
+static inline int hvm_single_step(struct vcpu *v, int enable)
+{
+ if ( hvm_funcs.single_step )
+ return hvm_funcs.single_step(v, enable);
+
+ /* return -1, ask gdb to handle */
+ return -1;
+}
+
#endif /* __ASM_X86_HVM_HVM_H__ */
Index: hv/xen/arch/x86/hvm/svm/svm.c
===================================================================
--- hv.orig/xen/arch/x86/hvm/svm/svm.c
+++ hv/xen/arch/x86/hvm/svm/svm.c
@@ -795,6 +795,11 @@ static int svm_do_pmu_interrupt(struct c
return 0;
}
+static int svm_single_step(struct vcpu *v, int enable)
+{
+ return -1;
+}
+
static struct hvm_function_table svm_function_table = {
.name = "SVM",
.cpu_down = svm_cpu_down,
@@ -823,7 +828,8 @@ static struct hvm_function_table svm_fun
.fpu_dirty_intercept = svm_fpu_dirty_intercept,
.msr_read_intercept = svm_msr_read_intercept,
.msr_write_intercept = svm_msr_write_intercept,
- .invlpg_intercept = svm_invlpg_intercept
+ .invlpg_intercept = svm_invlpg_intercept,
+ .single_step = svm_single_step
};
int start_svm(struct cpuinfo_x86 *c)
[-- Attachment #3: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH] [HVM] enable MTF for guest single step debug
2008-12-11 7:09 [PATCH] [HVM] enable MTF for guest single step debug Zhai, Edwin
@ 2008-12-11 11:45 ` Keir Fraser
2008-12-12 7:03 ` Zhai, Edwin
0 siblings, 1 reply; 3+ messages in thread
From: Keir Fraser @ 2008-12-11 11:45 UTC (permalink / raw)
To: Zhai, Edwin, Xen Developers
On 11/12/2008 07:09, "Zhai, Edwin" <edwin.zhai@intel.com> wrote:
> Monitor Trap Flag (MTF), is a debugging feature that cause vmexit on
> certain instruction boundaries, which can be used for HVM single step.
> We prefer MTF over TF, as it make TF free for guest use.
>
> This patch try to enable MTF for single step in gdb, and keep backward
> compatibility on old processor.
>
> Pls. see MTF details @ SDM 3b 21.7.2
Don't need EVENTTYPE_OTHER. Don't need to modify svm.c at all. The hvm_param
is gross since there is no obvious symmetric get() to go with your set() --
please just hack in a domctl, that'd be neater in this case imo even though
specific right now to x86 hvm.
That'll do for comments on patch v1... :-)
-- Keir
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] [HVM] enable MTF for guest single step debug
2008-12-11 11:45 ` Keir Fraser
@ 2008-12-12 7:03 ` Zhai, Edwin
0 siblings, 0 replies; 3+ messages in thread
From: Zhai, Edwin @ 2008-12-12 7:03 UTC (permalink / raw)
To: Keir Fraser; +Cc: Xen Developers, Zhai, Edwin
[-- Attachment #1: Type: text/plain, Size: 1010 bytes --]
Thanks for comments.
v2 comes :)
Keir Fraser wrote:
> On 11/12/2008 07:09, "Zhai, Edwin" <edwin.zhai@intel.com> wrote:
>
>
>> Monitor Trap Flag (MTF), is a debugging feature that cause vmexit on
>> certain instruction boundaries, which can be used for HVM single step.
>> We prefer MTF over TF, as it make TF free for guest use.
>>
>> This patch try to enable MTF for single step in gdb, and keep backward
>> compatibility on old processor.
>>
>> Pls. see MTF details @ SDM 3b 21.7.2
>>
>
> Don't need EVENTTYPE_OTHER. Don't need to modify svm.c at all. The hvm_param
> is gross since there is no obvious symmetric get() to go with your set() --
> please just hack in a domctl, that'd be neater in this case imo even though
> specific right now to x86 hvm.
>
> That'll do for comments on patch v1... :-)
>
> -- Keir
>
>
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xensource.com
> http://lists.xensource.com/xen-devel
>
>
--
best rgds,
edwin
[-- Attachment #2: MTF_enable_r18891_v2.patch --]
[-- Type: text/plain, Size: 13331 bytes --]
Index: hv/tools/libxc/xc_ptrace.c
===================================================================
--- hv.orig/tools/libxc/xc_ptrace.c
+++ hv/tools/libxc/xc_ptrace.c
@@ -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;
+ }
}
}
}
Index: hv/xen/arch/x86/hvm/vmx/intr.c
===================================================================
--- hv.orig/xen/arch/x86/hvm/vmx/intr.c
+++ hv/xen/arch/x86/hvm/vmx/intr.c
@@ -117,6 +117,17 @@ asmlinkage void vmx_intr_assist(void)
unsigned int tpr_threshold = 0;
enum hvm_intblk intblk;
+ /* Block event injection when single step with MTF,
+ * or else step into the guest event handler(SDM 3b 21.7.2)
+ */
+ if ( cpu_has_monitor_trap_flag && 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);
Index: hv/xen/arch/x86/hvm/vmx/vmcs.c
===================================================================
--- hv.orig/xen/arch/x86/hvm/vmx/vmcs.c
+++ hv/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,13 @@ 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;
Index: hv/xen/arch/x86/hvm/vmx/vmx.c
===================================================================
--- hv.orig/xen/arch/x86/hvm/vmx/vmx.c
+++ hv/xen/arch/x86/hvm/vmx/vmx.c
@@ -1258,6 +1258,11 @@ void vmx_inject_hw_exception(int trap, i
switch ( trap )
{
case TRAP_debug:
+ /* If has MTF, TF is free for guest use */
+ if ( cpu_has_monitor_trap_flag )
+ {
+ break;
+ }
if ( guest_cpu_user_regs()->eflags & X86_EFLAGS_TF )
{
__restore_debug_registers(curr);
@@ -2342,6 +2347,13 @@ asmlinkage void vmx_vmexit_handler(struc
switch ( vector )
{
case TRAP_debug:
+ /* If has MTF, use it for single step rather than TF*/
+ if ( cpu_has_monitor_trap_flag )
+ {
+ gdprintk(XENLOG_ERR, "Unexpected TRAP_debug vmexit!");
+ goto exit_and_crash;
+ }
+
/*
* Updates DR6 where debugger can peek (See 3B 23.2.1,
* Table 23-1, "Exit Qualification for Debug Exceptions").
@@ -2538,6 +2550,19 @@ asmlinkage void vmx_vmexit_handler(struc
break;
}
+ case EXIT_REASON_MONITOR_TRAP_FLAG:
+ {
+ if ( !v->domain->debugger_attached )
+ goto exit_and_crash;
+
+ v->arch.hvm_vmx.exec_control &= ~CPU_BASED_MONITOR_TRAP_FLAG;
+ __vmwrite(CPU_BASED_VM_EXEC_CONTROL,
+ v->arch.hvm_vmx.exec_control);
+
+ domain_pause_for_debugger();
+ break;
+ }
+
default:
exit_and_crash:
gdprintk(XENLOG_ERR, "Bad vmexit (reason %x)\n", exit_reason);
Index: hv/xen/include/asm-x86/hvm/vmx/vmcs.h
===================================================================
--- hv.orig/xen/include/asm-x86/hvm/vmx/vmcs.h
+++ hv/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
(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
Index: hv/xen/include/asm-x86/hvm/vmx/vmx.h
===================================================================
--- hv.orig/xen/include/asm-x86/hvm/vmx/vmx.h
+++ hv/xen/include/asm-x86/hvm/vmx/vmx.h
@@ -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
Index: hv/tools/libxc/xc_domain.c
===================================================================
--- hv.orig/tools/libxc/xc_domain.c
+++ hv/tools/libxc/xc_domain.c
@@ -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
Index: hv/xen/arch/x86/domctl.c
===================================================================
--- hv.orig/xen/arch/x86/domctl.c
+++ hv/xen/arch/x86/domctl.c
@@ -1037,6 +1037,34 @@ 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;
+
+ if ( (domctl->u.debug_op.vcpu >= MAX_VIRT_CPUS) ||
+ ((v = d->vcpu[domctl->u.debug_op.vcpu]) == NULL) )
+ goto debug_op_out;
+
+ /* Only HVM domain likely to debug with HV's help,
+ * PV handle debug in xc_ptrace
+ */
+ 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;
Index: hv/xen/arch/x86/hvm/hvm.c
===================================================================
--- hv.orig/xen/arch/x86/hvm/hvm.c
+++ hv/xen/arch/x86/hvm/hvm.c
@@ -2700,6 +2700,28 @@ long do_hvm_op(unsigned long op, XEN_GUE
return rc;
}
+int hvm_debug_op(struct vcpu *v, int32_t op)
+{
+ int rc = -ENOSYS;
+
+ switch ( op )
+ {
+ case XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_ON:
+ case XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_OFF:
+ if ( !cpu_has_monitor_trap_flag )
+ break;
+ rc = 0;
+ v->arch.hvm_vcpu.single_step =
+ ( op == XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_OFF ) ? 0 : 1;
+ break;
+ default:
+ rc = -ENOSYS;
+ }
+
+ return rc;
+}
+
+
/*
* Local variables:
* mode: C
Index: hv/xen/include/asm-x86/hvm/hvm.h
===================================================================
--- hv.orig/xen/include/asm-x86/hvm/hvm.h
+++ hv/xen/include/asm-x86/hvm/hvm.h
@@ -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__ */
Index: hv/xen/include/asm-x86/hvm/vcpu.h
===================================================================
--- hv.orig/xen/include/asm-x86/hvm/vcpu.h
+++ hv/xen/include/asm-x86/hvm/vcpu.h
@@ -96,6 +96,7 @@ struct hvm_vcpu {
/* We may write up to m128 as a number of device-model transactions. */
paddr_t mmio_large_write_pa;
unsigned int mmio_large_write_bytes;
+ unsigned int single_step;
};
#endif /* __ASM_X86_HVM_VCPU_H__ */
Index: hv/xen/include/public/domctl.h
===================================================================
--- hv.orig/xen/include/public/domctl.h
+++ hv/xen/include/public/domctl.h
@@ -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
Index: hv/tools/libxc/xenctrl.h
===================================================================
--- hv.orig/tools/libxc/xenctrl.h
+++ hv/tools/libxc/xenctrl.h
@@ -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,
[-- Attachment #3: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2008-12-12 7:03 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-12-11 7:09 [PATCH] [HVM] enable MTF for guest single step debug Zhai, Edwin
2008-12-11 11:45 ` Keir Fraser
2008-12-12 7:03 ` Zhai, Edwin
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.