ia64/xen-unstable

changeset 18931: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>
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