ia64/xen-unstable

changeset 15955:305a8dbc264c

[xen][hvm][tracing] Refine hvm tracing

This patch does two things:
* Allows hvm traces to take advantage of the variable-size traces
* Adds some hvm functionality

This includes tracing actions like clts and lmsw, values of {p,mm}io reads
and writes, and making different trace records for hvm domains running in
64-bit mode if the trace record includes a virtual address.
author George Dunlap <gdunlap@xensource.com>
date Fri Sep 21 15:33:37 2007 +0100 (2007-09-21)
parents 7ed576909132
children a956ef58b012
files xen/arch/x86/hvm/io.c xen/arch/x86/hvm/svm/svm.c xen/arch/x86/hvm/vmx/vmx.c xen/include/asm-x86/hvm/trace.h xen/include/public/trace.h
line diff
     1.1 --- a/xen/arch/x86/hvm/io.c	Fri Sep 21 15:26:07 2007 +0100
     1.2 +++ b/xen/arch/x86/hvm/io.c	Fri Sep 21 15:33:37 2007 +0100
     1.3 @@ -40,6 +40,7 @@
     1.4  #include <asm/hvm/vpt.h>
     1.5  #include <asm/hvm/vpic.h>
     1.6  #include <asm/hvm/vlapic.h>
     1.7 +#include <asm/hvm/trace.h>
     1.8  
     1.9  #include <public/sched.h>
    1.10  #include <xen/iocap.h>
    1.11 @@ -476,6 +477,7 @@ static void hvm_pio_assist(struct cpu_us
    1.12              printk("Error: %s unknown port size\n", __FUNCTION__);
    1.13              domain_crash_synchronous();
    1.14          }
    1.15 +        HVMTRACE_1D(IO_ASSIST, current, p->data);
    1.16      }
    1.17  }
    1.18  
    1.19 @@ -491,6 +493,8 @@ static void hvm_mmio_assist(struct cpu_u
    1.20      dst = mmio_opp->operand[1];
    1.21      size = operand_size(src);
    1.22  
    1.23 +    HVMTRACE_1D(MMIO_ASSIST, current, p->data);
    1.24 +        
    1.25      switch (mmio_opp->instr) {
    1.26      case INSTR_MOV:
    1.27          if (dst & REGISTER) {
     2.1 --- a/xen/arch/x86/hvm/svm/svm.c	Fri Sep 21 15:26:07 2007 +0100
     2.2 +++ b/xen/arch/x86/hvm/svm/svm.c	Fri Sep 21 15:33:37 2007 +0100
     2.3 @@ -1482,7 +1482,7 @@ static void svm_io_instruction(struct vc
     2.4      if (dir==IOREQ_READ)
     2.5          HVMTRACE_2D(IO_READ,  v, port, size);
     2.6      else
     2.7 -        HVMTRACE_2D(IO_WRITE, v, port, size);
     2.8 +        HVMTRACE_3D(IO_WRITE, v, port, size, regs->eax);
     2.9  
    2.10      HVM_DBG_LOG(DBG_LEVEL_IO, 
    2.11                  "svm_io_instruction: port 0x%x eip=%x:%"PRIx64", "
    2.12 @@ -1759,6 +1759,7 @@ static void svm_cr_access(
    2.13          vmcb->exception_intercepts &= ~(1U << TRAP_no_device);
    2.14          vmcb->cr0 &= ~X86_CR0_TS; /* clear TS */
    2.15          v->arch.hvm_vcpu.guest_cr[0] &= ~X86_CR0_TS; /* clear TS */
    2.16 +        HVMTRACE_0D(CLTS, current);
    2.17          break;
    2.18  
    2.19      case INSTR_LMSW:
    2.20 @@ -1766,6 +1767,7 @@ static void svm_cr_access(
    2.21          value = get_reg(gpreg, regs, vmcb) & 0xF;
    2.22          value = (v->arch.hvm_vcpu.guest_cr[0] & ~0xF) | value;
    2.23          result = svm_set_cr0(value);
    2.24 +        HVMTRACE_1D(LMSW, current, value);
    2.25          break;
    2.26  
    2.27      case INSTR_SMSW:
    2.28 @@ -1912,7 +1914,7 @@ static void svm_do_msr_access(
    2.29          regs->edx = msr_content >> 32;
    2.30  
    2.31   done:
    2.32 -        HVMTRACE_2D(MSR_READ, v, ecx, msr_content);
    2.33 +        hvmtrace_msr_read(v, ecx, msr_content);
    2.34          HVM_DBG_LOG(DBG_LEVEL_1, "returns: ecx=%x, eax=%lx, edx=%lx",
    2.35                      ecx, (unsigned long)regs->eax, (unsigned long)regs->edx);
    2.36  
    2.37 @@ -1922,7 +1924,7 @@ static void svm_do_msr_access(
    2.38      {
    2.39          msr_content = (u32)regs->eax | ((u64)regs->edx << 32);
    2.40  
    2.41 -        HVMTRACE_2D(MSR_WRITE, v, ecx, msr_content);
    2.42 +        hvmtrace_msr_write(v, ecx, msr_content);
    2.43  
    2.44          switch (ecx)
    2.45          {
    2.46 @@ -2158,7 +2160,7 @@ asmlinkage void svm_vmexit_handler(struc
    2.47  
    2.48      exit_reason = vmcb->exitcode;
    2.49  
    2.50 -    HVMTRACE_2D(VMEXIT, v, regs->eip, exit_reason);
    2.51 +    hvmtrace_vmexit(v, regs->eip, exit_reason);
    2.52  
    2.53      if ( unlikely(exit_reason == VMEXIT_INVALID) )
    2.54      {
    2.55 @@ -2378,7 +2380,7 @@ asmlinkage void svm_trace_vmentry(void)
    2.56      struct vcpu *v = current;
    2.57  
    2.58      /* This is the last C code before the VMRUN instruction. */
    2.59 -    HVMTRACE_0D(VMENTRY, v);
    2.60 +    hvmtrace_vmentry(v);
    2.61  }
    2.62    
    2.63  /*
     3.1 --- a/xen/arch/x86/hvm/vmx/vmx.c	Fri Sep 21 15:26:07 2007 +0100
     3.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c	Fri Sep 21 15:33:37 2007 +0100
     3.3 @@ -1825,7 +1825,7 @@ static void vmx_io_instruction(unsigned 
     3.4          if ( dir == IOREQ_READ )
     3.5              HVMTRACE_2D(IO_READ,  current, port, size);
     3.6          else
     3.7 -            HVMTRACE_2D(IO_WRITE, current, port, size);
     3.8 +            HVMTRACE_3D(IO_WRITE, current, port, size, regs->eax);
     3.9  
    3.10          if ( port == 0xe9 && dir == IOREQ_WRITE && size == 1 )
    3.11              hvm_print_line(current, regs->eax); /* guest debug output */
    3.12 @@ -2249,11 +2249,13 @@ static int vmx_cr_access(unsigned long e
    3.13  
    3.14          v->arch.hvm_vcpu.guest_cr[0] &= ~X86_CR0_TS; /* clear TS */
    3.15          __vmwrite(CR0_READ_SHADOW, v->arch.hvm_vcpu.guest_cr[0]);
    3.16 +        HVMTRACE_0D(CLTS, current);
    3.17          break;
    3.18      case TYPE_LMSW:
    3.19          value = v->arch.hvm_vcpu.guest_cr[0];
    3.20          value = (value & ~0xF) |
    3.21              (((exit_qualification & LMSW_SOURCE_DATA) >> 16) & 0xF);
    3.22 +        HVMTRACE_1D(LMSW, current, value);
    3.23          return vmx_set_cr0(value);
    3.24      default:
    3.25          BUG();
    3.26 @@ -2326,7 +2328,7 @@ static int vmx_do_msr_read(struct cpu_us
    3.27      regs->edx = msr_content >> 32;
    3.28  
    3.29  done:
    3.30 -    HVMTRACE_2D(MSR_READ, v, ecx, msr_content);
    3.31 +    hvmtrace_msr_read(v, ecx, msr_content);
    3.32      HVM_DBG_LOG(DBG_LEVEL_1, "returns: ecx=%x, eax=%lx, edx=%lx",
    3.33                  ecx, (unsigned long)regs->eax,
    3.34                  (unsigned long)regs->edx);
    3.35 @@ -2407,7 +2409,8 @@ static int vmx_do_msr_write(struct cpu_u
    3.36                  ecx, (u32)regs->eax, (u32)regs->edx);
    3.37  
    3.38      msr_content = (u32)regs->eax | ((u64)regs->edx << 32);
    3.39 -    HVMTRACE_2D(MSR_WRITE, v, ecx, msr_content);
    3.40 +
    3.41 +    hvmtrace_msr_write(v, ecx, msr_content);
    3.42  
    3.43      switch ( ecx )
    3.44      {
    3.45 @@ -2550,7 +2553,7 @@ asmlinkage void vmx_vmexit_handler(struc
    3.46  
    3.47      exit_reason = __vmread(VM_EXIT_REASON);
    3.48  
    3.49 -    HVMTRACE_2D(VMEXIT, v, regs->eip, exit_reason);
    3.50 +    hvmtrace_vmexit(VMEXIT, v, regs->eip, exit_reason);
    3.51  
    3.52      perfc_incra(vmexits, exit_reason);
    3.53  
    3.54 @@ -2637,7 +2640,7 @@ asmlinkage void vmx_vmexit_handler(struc
    3.55  
    3.56              if ( paging_fault(exit_qualification, regs) )
    3.57              {
    3.58 -                HVMTRACE_2D(PF_XEN, v, exit_qualification, regs->error_code);
    3.59 +                hvmtrace_pf_xen(v, exit_qualification, regs->error_code);
    3.60                  break;
    3.61              }
    3.62  
    3.63 @@ -2791,7 +2794,8 @@ asmlinkage void vmx_vmexit_handler(struc
    3.64  asmlinkage void vmx_trace_vmentry(void)
    3.65  {
    3.66      struct vcpu *v = current;
    3.67 -    HVMTRACE_0D(VMENTRY, v);
    3.68 +    
    3.69 +    hvmtrace_vmentry(v);
    3.70  }
    3.71  
    3.72  /*
     4.1 --- a/xen/include/asm-x86/hvm/trace.h	Fri Sep 21 15:26:07 2007 +0100
     4.2 +++ b/xen/include/asm-x86/hvm/trace.h	Fri Sep 21 15:33:37 2007 +0100
     4.3 @@ -26,20 +26,154 @@
     4.4  #define DO_TRC_HVM_VMMCALL     1
     4.5  #define DO_TRC_HVM_HLT         1
     4.6  #define DO_TRC_HVM_INVLPG      1
     4.7 +#define DO_TRC_HVM_IO_ASSIST   1
     4.8 +#define DO_TRC_HVM_MMIO_ASSIST 1
     4.9 +#define DO_TRC_HVM_CLTS        1
    4.10 +#define DO_TRC_HVM_LMSW        1
    4.11  
    4.12 -#define HVMTRACE_4D(evt, vcpu, d1, d2, d3, d4)                      \
    4.13 -    do {                                                            \
    4.14 -        if (DO_TRC_HVM_ ## evt)                                     \
    4.15 -            TRACE_5D(                                               \
    4.16 -                TRC_HVM_ ## evt,                                    \
    4.17 -                ((vcpu)->domain->domain_id<<16) + (vcpu)->vcpu_id,  \
    4.18 -                d1, d2, d3, d4                                      \
    4.19 -            );                                                      \
    4.20 +
    4.21 +
    4.22 +static inline void hvmtrace_vmexit(struct vcpu *v,
    4.23 +                                   unsigned long rip,
    4.24 +                                   unsigned long exit_reason)
    4.25 +{
    4.26 +#ifdef __x86_64__
    4.27 +    if(hvm_long_mode_enabled(v))
    4.28 +    {
    4.29 +        struct {
    4.30 +            unsigned did:16, vid:16;
    4.31 +            unsigned exit_reason:32;
    4.32 +            u64 rip;
    4.33 +        } d;
    4.34 +
    4.35 +        d.did = v->domain->domain_id;
    4.36 +        d.vid = v->vcpu_id;
    4.37 +        d.exit_reason = exit_reason;
    4.38 +        d.rip = rip;
    4.39 +        trace_var(TRC_HVM_VMEXIT64, 1/*cycles*/, sizeof(d), (unsigned char *)&d);
    4.40 +    } else {
    4.41 +#endif
    4.42 +        struct {
    4.43 +            unsigned did:16, vid:16;
    4.44 +            unsigned exit_reason:32;
    4.45 +            u32 eip;
    4.46 +        } d;
    4.47 +
    4.48 +        d.did = v->domain->domain_id;
    4.49 +        d.vid = v->vcpu_id;
    4.50 +        d.exit_reason = exit_reason;
    4.51 +        d.eip = rip;
    4.52 +        trace_var(TRC_HVM_VMEXIT, 1/*cycles*/, sizeof(d), (unsigned char *)&d);
    4.53 +#ifdef __x86_64__
    4.54 +    }
    4.55 +#endif
    4.56 +}
    4.57 +
    4.58 +
    4.59 +static inline void hvmtrace_vmentry(struct vcpu *v)
    4.60 +{
    4.61 +    struct {
    4.62 +        unsigned did:16, vid:16;
    4.63 +    } d;
    4.64 +    d.did = v->domain->domain_id;
    4.65 +    d.vid = v->vcpu_id;
    4.66 +    trace_var(TRC_HVM_VMENTRY, 1/*cycles*/, sizeof(d), (unsigned char *)&d);
    4.67 +}
    4.68 +
    4.69 +static inline void hvmtrace_msr_read(struct vcpu *v, u32 ecx, u64 msr_content)
    4.70 +{
    4.71 +    struct {
    4.72 +        unsigned did:16, vid:16;
    4.73 +        u32 ecx;
    4.74 +        u64 msr_content;
    4.75 +    } d;
    4.76 +    d.did = v->domain->domain_id;
    4.77 +    d.vid = v->vcpu_id;
    4.78 +    d.ecx = ecx;
    4.79 +    d.msr_content = msr_content;
    4.80 +    trace_var(TRC_HVM_MSR_READ, 0/*!cycles*/, sizeof(d), (unsigned char *)&d);
    4.81 +}
    4.82 +
    4.83 +static inline void hvmtrace_msr_write(struct vcpu *v, u32 ecx, u64 msr_content)
    4.84 +{
    4.85 +    struct {
    4.86 +        unsigned did:16, vid:16;
    4.87 +        u32 ecx;
    4.88 +        u64 msr_content;
    4.89 +    } d;
    4.90 +    d.did = v->domain->domain_id;
    4.91 +    d.vid = v->vcpu_id;
    4.92 +    d.ecx = ecx;
    4.93 +    d.msr_content = msr_content;
    4.94 +    trace_var(TRC_HVM_MSR_WRITE, 0/*!cycles*/,sizeof(d), (unsigned char *)&d);
    4.95 +}
    4.96 +
    4.97 +static inline void hvmtrace_pf_xen(struct vcpu *v, unsigned long va,
    4.98 +                                   u32 error_code)
    4.99 +{
   4.100 +#ifdef __x86_64__
   4.101 +    if(hvm_long_mode_enabled(v))
   4.102 +    {
   4.103 +        struct {
   4.104 +            unsigned did:16, vid:16;
   4.105 +            u32 error_code;
   4.106 +            u64 va;
   4.107 +        } d;
   4.108 +        d.did = v->domain->domain_id;
   4.109 +        d.vid = v->vcpu_id;
   4.110 +        d.error_code = error_code;
   4.111 +        d.va = va;
   4.112 +        trace_var(TRC_HVM_PF_XEN64, 0/*!cycles*/,sizeof(d),
   4.113 +                  (unsigned char *)&d);
   4.114 +    } else {
   4.115 +#endif
   4.116 +        struct {
   4.117 +            unsigned did:16, vid:16;
   4.118 +            u32 error_code;
   4.119 +            u32 va;
   4.120 +        } d;
   4.121 +        d.did = v->domain->domain_id;
   4.122 +        d.vid = v->vcpu_id;
   4.123 +        d.error_code = error_code;
   4.124 +        d.va = va;
   4.125 +        trace_var(TRC_HVM_PF_XEN, 0/*!cycles*/,sizeof(d), (unsigned char *)&d);
   4.126 +#ifdef __x86_64__
   4.127 +    }
   4.128 +#endif
   4.129 +}
   4.130 +
   4.131 +#define HVMTRACE_ND(evt, vcpu, count, d1, d2, d3, d4)                   \
   4.132 +    do {                                                                \
   4.133 +        if (DO_TRC_HVM_ ## evt)                                         \
   4.134 +        {                                                               \
   4.135 +            struct {                                                    \
   4.136 +                unsigned did:16, vid:16;                                \
   4.137 +                u32 d[4];                                               \
   4.138 +            } _d;                                                       \
   4.139 +            _d.did=(vcpu)->domain->domain_id;                           \
   4.140 +            _d.vid=(vcpu)->vcpu_id;                                     \
   4.141 +            _d.d[0]=(d1);                                               \
   4.142 +            _d.d[1]=(d2);                                               \
   4.143 +            _d.d[2]=(d3);                                               \
   4.144 +            _d.d[3]=(d4);                                               \
   4.145 +            trace_var(TRC_HVM_ ## evt, 0/*!cycles*/,                    \
   4.146 +                      sizeof(u32)*count+1, (unsigned char *)&_d);       \
   4.147 +        }                                                               \
   4.148      } while(0)
   4.149  
   4.150 -#define HVMTRACE_3D(evt, vcpu, d1, d2, d3)       HVMTRACE_4D(evt, vcpu, d1, d2, d3,  0)
   4.151 -#define HVMTRACE_2D(evt, vcpu, d1, d2)           HVMTRACE_4D(evt, vcpu, d1, d2,  0,  0)
   4.152 -#define HVMTRACE_1D(evt, vcpu, d1)               HVMTRACE_4D(evt, vcpu, d1,  0,  0,  0)
   4.153 -#define HVMTRACE_0D(evt, vcpu)                   HVMTRACE_4D(evt, vcpu,  0,  0,  0,  0)
   4.154 +#define HVMTRACE_4D(evt, vcpu, d1, d2, d3, d4)   HVMTRACE_ND(evt, vcpu, 4, d1, d2, d3,  d4)
   4.155 +#define HVMTRACE_3D(evt, vcpu, d1, d2, d3)       HVMTRACE_ND(evt, vcpu, 3, d1, d2, d3,  0)
   4.156 +#define HVMTRACE_2D(evt, vcpu, d1, d2)           HVMTRACE_ND(evt, vcpu, 2, d1, d2,  0,  0)
   4.157 +#define HVMTRACE_1D(evt, vcpu, d1)               HVMTRACE_ND(evt, vcpu, 1, d1,  0,  0,  0)
   4.158 +#define HVMTRACE_0D(evt, vcpu)                   HVMTRACE_ND(evt, vcpu, 0, 0,  0,  0,  0)
   4.159  
   4.160  #endif //__ASM_X86_HVM_TRACE_H__
   4.161 +/*
   4.162 + * Local variables:
   4.163 + * mode: C
   4.164 + * c-set-style: "BSD"
   4.165 + * c-basic-offset: 4
   4.166 + * tab-width: 4
   4.167 + * indent-tabs-mode: nil
   4.168 + * End:
   4.169 + */
     5.1 --- a/xen/include/public/trace.h	Fri Sep 21 15:26:07 2007 +0100
     5.2 +++ b/xen/include/public/trace.h	Fri Sep 21 15:33:37 2007 +0100
     5.3 @@ -77,6 +77,7 @@
     5.4  /* trace events per subclass */
     5.5  #define TRC_HVM_VMENTRY         (TRC_HVM_ENTRYEXIT + 0x01)
     5.6  #define TRC_HVM_VMEXIT          (TRC_HVM_ENTRYEXIT + 0x02)
     5.7 +#define TRC_HVM_VMEXIT64        (TRC_HVM_ENTRYEXIT + 0x03)
     5.8  #define TRC_HVM_PF_XEN          (TRC_HVM_HANDLER + 0x01)
     5.9  #define TRC_HVM_PF_INJECT       (TRC_HVM_HANDLER + 0x02)
    5.10  #define TRC_HVM_INJ_EXC         (TRC_HVM_HANDLER + 0x03)
    5.11 @@ -98,6 +99,11 @@
    5.12  #define TRC_HVM_HLT             (TRC_HVM_HANDLER + 0x13)
    5.13  #define TRC_HVM_INVLPG          (TRC_HVM_HANDLER + 0x14)
    5.14  #define TRC_HVM_MCE             (TRC_HVM_HANDLER + 0x15)
    5.15 +#define TRC_HVM_IO_ASSIST       (TRC_HVM_HANDLER + 0x16)
    5.16 +#define TRC_HVM_MMIO_ASSIST     (TRC_HVM_HANDLER + 0x17)
    5.17 +#define TRC_HVM_CLTS            (TRC_HVM_HANDLER + 0x18)
    5.18 +#define TRC_HVM_LMSW            (TRC_HVM_HANDLER + 0x19)
    5.19 +#define TRC_HVM_PF_XEN64       (TRC_HVM_HANDLER + 0x20)
    5.20  
    5.21  /* This structure represents a single trace buffer record. */
    5.22  struct t_rec {