Skip to contentSkip to conversation

fix tracing for 64bit guests

PATCH In review Andre Przywara 2 participants 3 messages Jun 6, 2008 – Jun 10, 2008

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 fix tracing for 64bit guests

Hi,

Xen tracing some times ago used to put values of type 'long' into the trace buffer. This has changed to uint32_t. Some trace points log virtual addresses, which get cropped to 32bit in this case. There were some inline functions to handle at least PF_XEN and VMEXIT, which caused a lot of code duplication. The attached patch fixes several issues:
1. fix and extend tools/xentrace/formats
2. Fix xentrace_format to handle up to 7 parameters
3. create convenience macros to properly log long values
4. remove the inline functions in hvm/trace.h and replace them by macros
5. Change the CPUID trace to work correctly
6. group HVM trace points enable mechanism

I used a similar approach as in PV tracing with bit 8 indicating 64bit pointers.

Discussion welcome!

BTW: Why is xentrace_format so awfully slow? I have rewritten the tool in C and reached a speedup of more than 20 times. If someone bugs me I will share the code...

Regards,
Andre.

Signature · 9 lines
Andre Przywara
AMD-Operating System Research Center (OSRC), Dresden, Germany
Tel: +49 351 277-84917
----to satisfy European Law for business letters:
AMD Saxony Limited Liability Company & Co. KG,
Wilschdorfer Landstr. 101, 01109 Dresden, Germany
Register Court Dresden: HRA 4896, General Partner authorized
to represent: AMD Saxony LLC (Wilmington, Delaware, US)
General Manager of AMD Saxony LLC: Dr. Hans-R. Deppe, Thomas McCoy
tools/xentrace/formats +38 -19
diff -r b320cfe1f10f tools/xentrace/formats
@@ -1,48 +1,67 @@ 0x00000000  CPU%(cpu)d  %(tsc)d (+%(relt
 0x00000000  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  unknown (0x%(event)016x)  [ 0x%(1)08x 0x%(2)08x 0x%(3)08x 0x%(4)08x 0x%(5)08x ]
 
-0x0001f001  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  lost_records        0x%(1)08x
-0x0001f002  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  wrap_buffer         0x%(1)08x
-0x0001f003  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  cpu_change          0x%(1)08x
+0x0001f001  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  lost_records      0x%(1)08x
+0x0001f002  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  wrap_buffer       0x%(1)08x
+0x0001f003  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  cpu_change        0x%(1)08x
 
-0x0002f001  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  sched_add_domain	[ domid = 0x%(1)08x, edomid = 0x%(2)08x ]
-0x0002f002  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  sched_rem_domain	[ domid = 0x%(1)08x, edomid = 0x%(2)08x ]
-0x0002f003  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  domain_sleep		[ domid = 0x%(1)08x, edomid = 0x%(2)08x ]
-0x0002f004  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  domain_wake		[ domid = 0x%(1)08x, edomid = 0x%(2)08x ]
-0x0002f005  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  do_yield		[ domid = 0x%(1)08x, edomid = 0x%(2)08x ]
-0x0002f006  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  do_block		[ domid = 0x%(1)08x, edomid = 0x%(2)08x ]
-0x0002f007  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  domain_shutdown		[ domid = 0x%(1)08x, edomid = 0x%(2)08x, reason = 0x%(3)08x ]
+0x0002f001  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  sched_add_domain  [ domid = 0x%(1)08x, edomid = 0x%(2)08x ]
+0x0002f002  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  sched_rem_domain  [ domid = 0x%(1)08x, edomid = 0x%(2)08x ]
+0x0002f003  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  domain_sleep      [ domid = 0x%(1)08x, edomid = 0x%(2)08x ]
+0x0002f004  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  domain_wake       [ domid = 0x%(1)08x, edomid = 0x%(2)08x ]
+0x0002f005  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  do_yield          [ domid = 0x%(1)08x, edomid = 0x%(2)08x ]
+0x0002f006  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  do_block          [ domid = 0x%(1)08x, edomid = 0x%(2)08x ]
+0x0002f007  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  domain_shutdown	  [ domid = 0x%(1)08x, edomid = 0x%(2)08x, reason = 0x%(3)08x ]
 0x0002f008  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  sched_ctl
-0x0002f009  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  sched_adjdom		[ domid = 0x%(1)08x ]
-0x0002f00a  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  __enter_scheduler	[ prev<domid:edomid> = 0x%(1)08x : 0x%(2)08x, next<domid:edomid> = 0x%(3)08x : 0x%(4)08x ]
+0x0002f009  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  sched_adjdom      [ domid = 0x%(1)08x ]
+0x0002f00a  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  __enter_scheduler [ prev<domid:edomid> = 0x%(1)08x : 0x%(2)08x, next<domid:edomid> = 0x%(3)08x : 0x%(4)08x ]
 0x0002f00B  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  s_timer_fn
 0x0002f00c  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  t_timer_fn
 0x0002f00d  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  dom_timer_fn
+0x0002f00e  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  switch_infprev    [ old_domid = 0x%(1)08x, runtime = %(2)d ]
+0x0002f00f  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  switch_infnext    [ new_domid = 0x%(1)08x, time = %(2)d, r_time = %(3)d ]
 
 0x00081001  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  VMENTRY     [ dom:vcpu = 0x%(1)08x ]
 0x00081002  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  VMEXIT      [ dom:vcpu = 0x%(1)08x, exitcode = 0x%(2)08x, rIP  = 0x%(3)08x ]
-0x00082001  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  PF_XEN      [ dom:vcpu = 0x%(1)08x, errorcode = 0x%(2)02x, virt = 0x%(3)08x ]
-0x00082002  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  PF_INJECT   [ dom:vcpu = 0x%(1)08x, virt = 0x%(2)08x, errorcode = 0x%(3)02x ]
+0x00081102  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  VMEXIT      [ dom:vcpu = 0x%(1)08x, exitcode = 0x%(2)08x, rIP  = 0x%(3)016x ]
+0x00082001  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  PF_XEN      [ dom:vcpu = 0x%(1)08x, errorcode = 0x%(3)02x, virt = 0x%(2)08x ]
+0x00082101  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  PF_XEN      [ dom:vcpu = 0x%(1)08x, errorcode = 0x%(3)02x, virt = 0x%(2)016x ]
+0x00082002  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  PF_INJECT   [ dom:vcpu = 0x%(1)08x, errorcode = 0x%(2)02x, virt = 0x%(3)08x ]
+0x00082102  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  PF_INJECT   [ dom:vcpu = 0x%(1)08x,  errorcode = 0x%(2)02x, virt = 0x%(3)016x ]
 0x00082003  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  INJ_EXC     [ dom:vcpu = 0x%(1)08x, vector = 0x%(2)02x, errorcode = 0x%(3)04x ]
 0x00082004  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  INJ_VIRQ    [ dom:vcpu = 0x%(1)08x, vector = 0x%(2)02x, fake = %(3)d ]
 0x00082005  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  REINJ_VIRQ  [ dom:vcpu = 0x%(1)08x, vector = 0x%(2)02x ]
 0x00082006  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  IO_READ     [ dom:vcpu = 0x%(1)08x, port = 0x%(2)04x, size = %(3)d ]
 0x00082007  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  IO_WRITE    [ dom:vcpu = 0x%(1)08x, port = 0x%(2)04x, size = %(3)d ]
 0x00082008  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  CR_READ     [ dom:vcpu = 0x%(1)08x, CR# = %(2)d, value = 0x%(3)08x ]
+0x00082108  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  CR_READ     [ dom:vcpu = 0x%(1)08x, CR# = %(2)d, value = 0x%(3)016x ]
 0x00082009  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  CR_WRITE    [ dom:vcpu = 0x%(1)08x, CR# = %(2)d, value = 0x%(3)08x ]
+0x00082109  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  CR_WRITE    [ dom:vcpu = 0x%(1)08x, CR# = %(2)d, value = 0x%(3)016x ]
 0x0008200A  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  DR_READ     [ dom:vcpu = 0x%(1)08x ]
 0x0008200B  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  DR_WRITE    [ dom:vcpu = 0x%(1)08x ]
-0x0008200C  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  MSR_READ    [ dom:vcpu = 0x%(1)08x, MSR# = 0x%(2)08x, value = 0x%(3)08x ]
-0x0008200D  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  MSR_WRITE   [ dom:vcpu = 0x%(1)08x, MSR# = 0x%(2)08x, value = 0x%(3)08x ]
-0x0008200E  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  CPUID       [ dom:vcpu = 0x%(1)08x, func = 0x%(2)08x, eax:ebx = 0x%(3)016x, ecx:edx = 0x%(4)016x ]
+0x0008200C  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  MSR_READ    [ dom:vcpu = 0x%(1)08x, MSR# = 0x%(2)08x, value = 0x%(3)016x ]
+0x0008200D  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  MSR_WRITE   [ dom:vcpu = 0x%(1)08x, MSR# = 0x%(2)08x, value = 0x%(3)016x ]
+0x0008200E  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  CPUID       [ dom:vcpu = 0x%(1)08x, func = 0x%(2)08x, eax = 0x%(3)08x, ebx = 0x%(4)08x, ecx=0x%(5)08x, edx = 0x%(6)08x ]
 0x0008200F  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  INTR        [ dom:vcpu = 0x%(1)08x, vector = 0x%(2)02x ]
 0x00082010  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  NMI         [ dom:vcpu = 0x%(1)08x ]
 0x00082011  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  SMI         [ dom:vcpu = 0x%(1)08x ]
 0x00082012  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  VMMCALL     [ dom:vcpu = 0x%(1)08x, func = 0x%(2)08x ]
 0x00082013  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  HLT         [ dom:vcpu = 0x%(1)08x, intpending = %(2)d ]
-0x00082014  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  INVLPG      [ dom:vcpu = 0x%(1)08x, virt = 0x%(2)08x, invlpga = %(3)d, asid = 0x%(4)02x ]
+0x00082014  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  INVLPG      [ dom:vcpu = 0x%(1)08x, is invlpga? = %(2)d, virt = 0x%(3)08x ]
+0x00082114  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  INVLPG      [ dom:vcpu = 0x%(1)08x, is invlpga? = %(2)d, virt = 0x%(3)016x ]
 0x00082015  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  MCE         [ dom:vcpu = 0x%(1)08x ]
 0x00082016  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  IO_ASSIST   [ dom:vcpu = 0x%(1)08x, data = 0x%(2)04x ]
 0x00082017  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  MMIO_ASSIST [ dom:vcpu = 0x%(1)08x, data = 0x%(2)04x ]
 0x00082018  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  CLTS        [ dom:vcpu = 0x%(1)08x ]
 0x00082019  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  LMSW        [ dom:vcpu = 0x%(1)08x, value = 0x%(2)08x ]
-0x00082020  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  PF_XEN64    [ dom:vcpu = 0x%(1)08x, errorcode = 0x%(2)02x, virt = 0x%(3)08x ]
+0x00082119  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  LMSW        [ dom:vcpu = 0x%(1)08x, value = 0x%(2)016x ]
+
+0x0010f001  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  page_grant_map      [ domid = %(1)d ]
+0x0010f002  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  page_grant_unmap    [ domid = %(1)d ]
+0x0010f003  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  page_grant_transfer [ domid = %(1)d ]
+
+0x0020f001  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  hypercall  [ eip = 0x%(1)08x, eax = 0x%(2)08x ]
+0x0020f101  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  hypercall  [ rip = 0x%(1)016x, eax = 0x%(2)08x ]
+0x0020f003  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  trap       [ eip = 0x%(1)08x, trapnr:error = 0x%(2)08x ]
+0x0020f103  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  trap       [ rip = 0x%(1)016x, trapnr:error = 0x%(2)08x ]
+0x0020f004  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  page_fault [ eip = 0x%(1)08x, addr = 0x%(2)08x, error = 0x%(3)08x ]
+0x0020f104  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  page_fault [ rip = 0x%(1)16x, addr = 0x%(3)16x, error = 0x%(5)08x ]
tools/xentrace/xentrace_format +20 -4
diff -r b320cfe1f10f tools/xentrace/xentrace_format
@@ -17,12 +17,12 @@ def usage():
           {event_id}{whitespace}{text format string}
 
           The textual format string may include format specifiers, such as:
-            %(cpu)d, %(tsc)d, %(event)d, %(1)d, %(2)d, %(3)d, %(4)d, %(5)d
+            %(cpu)d, %(tsc)d, %(event)d, %(1)d, %(2)d, %(3)d, %(4)d, ... 
           [ the 'd' format specifier outputs in decimal, alternatively 'x'
             will output in hexadecimal and 'o' will output in octal ]
 
           Which correspond to the CPU number, event ID, timestamp counter and
-          the 5 data fields from the trace record.  There should be one such
+          the 7 data fields from the trace record.  There should be one such
           rule for each type of event.
           
           Depending on your system and the volume of trace buffer data,
@@ -84,7 +84,7 @@ defs = read_defs(arg[0])
 defs = read_defs(arg[0])
 
 # structure of trace record (as output by xentrace):
-# HDR(I) {TSC(Q)} D1(I) D2(I) D3(I) D4(I) D5(I)
+# HDR(I) {TSC(Q)} D1(I) D2(I) D3(I) D4(I) D5(I) D6(I) D7(I)
 #
 # HDR consists of EVENT:28:, n_data:3:, tsc_in:1:
 # EVENT means Event ID
@@ -101,6 +101,8 @@ D3REC  = "III"
 D3REC  = "III"
 D4REC  = "IIII"
 D5REC  = "IIIII"
+D6REC  = "IIIIII"
+D7REC  = "IIIIIII"
 
 last_tsc = [0]
 
@@ -121,6 +123,8 @@ while not interrupted:
         d3 = 0
         d4 = 0
         d5 = 0
+        d6 = 0
+        d7 = 0
 
         tsc = 0
 
@@ -155,6 +159,16 @@ while not interrupted:
             if not line:
                 break
             (d1, d2, d3, d4, d5) = struct.unpack(D5REC, line)
+        if n_data == 6:
+            line = sys.stdin.read(struct.calcsize(D6REC))
+            if not line:
+                break
+            (d1, d2, d3, d4, d5, d6) = struct.unpack(D6REC, line)
+        if n_data == 7:
+            line = sys.stdin.read(struct.calcsize(D7REC))
+            if not line:
+                break
+            (d1, d2, d3, d4, d5, d6, d7) = struct.unpack(D7REC, line)
 
         # Event field is 28bit of 'uint32_t' in header, not 'long'.
         event &= 0x0fffffff
@@ -191,7 +205,9 @@ while not interrupted:
                 '2'     : d2,
                 '3'     : d3,
                 '4'     : d4,
-                '5'     : d5    }
+                '5'     : d5,
+                '6'     : d6,
+                '7'     : d7    }
 
         try:
 
xen/arch/x86/hvm/svm/svm.c +16 -9
diff -r b320cfe1f10f xen/arch/x86/hvm/svm/svm.c
@@ -757,7 +757,7 @@ static void svm_inject_exception(
     if ( trapnr == TRAP_page_fault )
     {
         vmcb->cr2 = curr->arch.hvm_vcpu.guest_cr[2] = cr2;
-        HVMTRACE_2D(PF_INJECT, curr, curr->arch.hvm_vcpu.guest_cr[2], errcode);
+        HVMTRACE_LONG_2D(PF_INJECT, curr, errcode, TRC_PAR_LONG(cr2));
     }
     else
     {
@@ -914,8 +914,7 @@ static void svm_cpuid_intercept(
             __clear_bit(X86_FEATURE_APIC & 31, edx);
     }
 
-    HVMTRACE_3D(CPUID, v, input,
-                ((uint64_t)*eax << 32) | *ebx, ((uint64_t)*ecx << 32) | *edx);
+    HVMTRACE_5D (CPUID, v, input, *eax, *ebx, *ecx, *edx);
 }
 
 static void svm_vmexit_do_cpuid(struct cpu_user_regs *regs)
@@ -1014,7 +1013,7 @@ static int svm_msr_read_intercept(struct
     regs->edx = msr_content >> 32;
 
  done:
-    hvmtrace_msr_read(v, ecx, msr_content);
+    HVMTRACE_3D (MSR_READ, v, ecx, regs->eax, regs->edx);
     HVM_DBG_LOG(DBG_LEVEL_1, "returns: ecx=%x, eax=%lx, edx=%lx",
                 ecx, (unsigned long)regs->eax, (unsigned long)regs->edx);
     return X86EMUL_OKAY;
@@ -1033,7 +1032,7 @@ static int svm_msr_write_intercept(struc
 
     msr_content = (u32)regs->eax | ((u64)regs->edx << 32);
 
-    hvmtrace_msr_write(v, ecx, msr_content);
+    HVMTRACE_3D (MSR_WRITE, v, ecx, regs->eax, regs->edx);
 
     switch ( ecx )
     {
@@ -1153,7 +1152,7 @@ static void svm_invlpg_intercept(unsigne
 static void svm_invlpg_intercept(unsigned long vaddr)
 {
     struct vcpu *curr = current;
-    HVMTRACE_2D(INVLPG, curr, 0, vaddr);
+    HVMTRACE_LONG_2D(INVLPG, curr, 0, TRC_PAR_LONG(vaddr));
     paging_invlpg(curr, vaddr);
     svm_asid_g_invlpg(curr, vaddr);
 }
@@ -1176,7 +1175,12 @@ asmlinkage void svm_vmexit_handler(struc
 
     exit_reason = vmcb->exitcode;
 
-    hvmtrace_vmexit(v, regs->eip, exit_reason);
+    if ( hvm_long_mode_enabled(v) )
+        HVMTRACE_ND (VMEXIT64, 1/*cycles*/, v, 3, exit_reason,
+            regs->eip & 0xFFFFFFFF, regs->eip >> 32, 0, 0, 0);
+    else
+        HVMTRACE_ND (VMEXIT, 1/*cycles*/, v, 2, exit_reason,
+            regs->eip, 0, 0, 0, 0);
 
     if ( unlikely(exit_reason == VMEXIT_INVALID) )
     {
@@ -1244,7 +1248,10 @@ asmlinkage void svm_vmexit_handler(struc
 
         if ( paging_fault(va, regs) )
         {
-            HVMTRACE_2D(PF_XEN, v, va, regs->error_code);
+            if (hvm_long_mode_enabled(v))
+                HVMTRACE_LONG_2D(PF_XEN, v, regs->error_code, TRC_PAR_LONG(va));
+            else
+                HVMTRACE_2D(PF_XEN, v, regs->error_code, va);
             break;
         }
 
@@ -1382,7 +1389,7 @@ asmlinkage void svm_vmexit_handler(struc
 
 asmlinkage void svm_trace_vmentry(void)
 {
-    hvmtrace_vmentry(current);
+    HVMTRACE_ND (VMENTRY, 1/*cycles*/, current, 0, 0, 0, 0, 0, 0, 0);
 }
   
 /*
xen/arch/x86/hvm/vmx/vmx.c +22 -12
diff -r b320cfe1f10f xen/arch/x86/hvm/vmx/vmx.c
@@ -1107,7 +1107,8 @@ static void __vmx_inject_exception(
     __vmwrite(VM_ENTRY_INTR_INFO, intr_fields);
 
     if ( trap == TRAP_page_fault )
-        HVMTRACE_2D(PF_INJECT, v, v->arch.hvm_vcpu.guest_cr[2], error_code);
+        HVMTRACE_LONG_2D(PF_INJECT, v, error_code,
+            TRC_PAR_LONG(v->arch.hvm_vcpu.guest_cr[2]));
     else
         HVMTRACE_2D(INJ_EXC, v, trap, error_code);
 }
@@ -1328,8 +1329,7 @@ static void vmx_cpuid_intercept(
             break;
     }
 
-    HVMTRACE_3D(CPUID, current, input,
-                ((uint64_t)*eax << 32) | *ebx, ((uint64_t)*ecx << 32) | *edx);
+    HVMTRACE_5D (CPUID, current, input, *eax, *ebx, *ecx, *edx);
 }
 
 static void vmx_do_cpuid(struct cpu_user_regs *regs)
@@ -1367,7 +1367,7 @@ static void vmx_invlpg_intercept(unsigne
 static void vmx_invlpg_intercept(unsigned long vaddr)
 {
     struct vcpu *curr = current;
-    HVMTRACE_2D(INVLPG, curr, /*invlpga=*/ 0, vaddr);
+    HVMTRACE_LONG_2D(INVLPG, curr, /*invlpga=*/ 0, TRC_PAR_LONG(vaddr));
     if ( paging_invlpg(curr, vaddr) )
         vpid_sync_vcpu_gva(curr, vaddr);
 }
@@ -1418,7 +1418,7 @@ static int mov_to_cr(int gp, int cr, str
         goto exit_and_crash;
     }
 
-    HVMTRACE_2D(CR_WRITE, v, cr, value);
+    HVMTRACE_LONG_2D(CR_WRITE, v, cr, TRC_PAR_LONG(value));
 
     HVM_DBG_LOG(DBG_LEVEL_1, "CR%d, value = %lx", cr, value);
 
@@ -1489,7 +1489,7 @@ static void mov_from_cr(int cr, int gp, 
         break;
     }
 
-    HVMTRACE_2D(CR_READ, v, cr, value);
+    HVMTRACE_LONG_2D(CR_READ, v, cr, TRC_PAR_LONG(value));
 
     HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR%d, value = %lx", cr, value);
 }
@@ -1520,7 +1520,7 @@ static int vmx_cr_access(unsigned long e
     case VMX_CONTROL_REG_ACCESS_TYPE_LMSW:
         value = v->arch.hvm_vcpu.guest_cr[0];
         value = (value & ~0xFFFF) | ((exit_qualification >> 16) & 0xFFFF);
-        HVMTRACE_1D(LMSW, current, value);
+        HVMTRACE_LONG_1D(LMSW, current, value);
         return !hvm_set_cr0(value);
     default:
         BUG();
@@ -1675,7 +1675,7 @@ static int vmx_msr_read_intercept(struct
     regs->edx = (uint32_t)(msr_content >> 32);
 
 done:
-    hvmtrace_msr_read(v, ecx, msr_content);
+    HVMTRACE_3D (MSR_READ, v, ecx, regs->eax, regs->edx);
     HVM_DBG_LOG(DBG_LEVEL_1, "returns: ecx=%x, eax=%lx, edx=%lx",
                 ecx, (unsigned long)regs->eax,
                 (unsigned long)regs->edx);
@@ -1786,7 +1786,7 @@ static int vmx_msr_write_intercept(struc
 
     msr_content = (u32)regs->eax | ((u64)regs->edx << 32);
 
-    hvmtrace_msr_write(v, ecx, msr_content);
+    HVMTRACE_3D (MSR_WRITE, v, ecx, regs->eax, regs->edx);
 
     switch ( ecx )
     {
@@ -2020,7 +2020,12 @@ asmlinkage void vmx_vmexit_handler(struc
 
     exit_reason = __vmread(VM_EXIT_REASON);
 
-    hvmtrace_vmexit(v, regs->eip, exit_reason);
+    if ( hvm_long_mode_enabled(v) )
+        HVMTRACE_ND (VMEXIT64, 1/*cycles*/, v, 3, exit_reason,
+            regs->eip & 0xFFFFFFFF, regs->eip >> 32, 0, 0, 0);
+    else
+        HVMTRACE_ND (VMEXIT, 1/*cycles*/, v, 2, exit_reason,
+            regs->eip, 0, 0, 0, 0);
 
     perfc_incra(vmexits, exit_reason);
 
@@ -2109,7 +2114,12 @@ asmlinkage void vmx_vmexit_handler(struc
 
             if ( paging_fault(exit_qualification, regs) )
             {
-                hvmtrace_pf_xen(v, exit_qualification, regs->error_code);
+                if ( hvm_long_mode_enabled(v) )
+                    HVMTRACE_LONG_2D (PF_XEN, v, regs->error_code,
+                        TRC_PAR_LONG(exit_qualification) );
+                else
+                    HVMTRACE_2D (PF_XEN, v,
+                        regs->error_code, exit_qualification );
                 break;
             }
 
@@ -2271,7 +2281,7 @@ asmlinkage void vmx_vmexit_handler(struc
 
 asmlinkage void vmx_trace_vmentry(void)
 {
-    hvmtrace_vmentry(current);
+    HVMTRACE_ND (VMENTRY, 1/*cycles*/, current, 0, 0, 0, 0, 0, 0, 0);
 }
 
 /*
xen/arch/x86/trace.c +8 -8
diff -r b320cfe1f10f xen/arch/x86/trace.c
@@ -7,8 +7,8 @@
 #include <xen/trace.h>
 
 #ifndef __x86_64__
-#undef TRC_PV_64_FLAG
-#define TRC_PV_64_FLAG 0
+#undef TRC_64_FLAG
+#define TRC_64_FLAG 0
 #endif
 
 asmlinkage void trace_hypercall(void)
@@ -38,7 +38,7 @@ asmlinkage void trace_hypercall(void)
         u32 event;
 
         event = TRC_PV_HYPERCALL;
-        event |= TRC_PV_64_FLAG;
+        event |= TRC_64_FLAG;
         d.eip = regs->eip;
         d.eax = regs->eax;
 
@@ -84,7 +84,7 @@ void __trace_pv_trap(int trapnr, unsigne
         d.use_error_code=!!use_error_code;
                 
         event = TRC_PV_TRAP;
-        event |= TRC_PV_64_FLAG;
+        event |= TRC_64_FLAG;
         __trace_var(event, 1, sizeof(d), (unsigned char *)&d);
     }
 }
@@ -119,7 +119,7 @@ void __trace_pv_page_fault(unsigned long
         d.addr = addr;
         d.error_code = error_code;
         event = TRC_PV_PAGE_FAULT;
-        event |= TRC_PV_64_FLAG;
+        event |= TRC_64_FLAG;
         __trace_var(event, 1, sizeof(d), (unsigned char *)&d);
     }
 }
@@ -135,7 +135,7 @@ void __trace_trap_one_addr(unsigned even
     else
 #endif        
     {
-        event |= TRC_PV_64_FLAG;
+        event |= TRC_64_FLAG;
         __trace_var(event, 1, sizeof(va), (unsigned char *)&va);
     }
 }
@@ -161,7 +161,7 @@ void __trace_trap_two_addr(unsigned even
         } __attribute__((packed)) d;
         d.va1=va1;
         d.va2=va2;
-        event |= TRC_PV_64_FLAG;
+        event |= TRC_64_FLAG;
         __trace_var(event, 1, sizeof(d), (unsigned char *)&d);
     }
 }
@@ -207,7 +207,7 @@ void __trace_ptwr_emulation(unsigned lon
 
         event = ((CONFIG_PAGING_LEVELS == 3) ?
                  TRC_PV_PTWR_EMULATION_PAE : TRC_PV_PTWR_EMULATION);
-        event |= TRC_PV_64_FLAG;
+        event |= TRC_64_FLAG;
         __trace_var(event, 1/*tsc*/, sizeof(d), (unsigned char *)&d);
     }
 }
xen/include/asm-x86/hvm/trace.h +87 -165

276 lines not on this page · raw message

xen/include/public/trace.h +8 -3
diff -r b320cfe1f10f xen/include/public/trace.h
@@ -87,21 +87,25 @@
 #define TRC_PV_PTWR_EMULATION        (TRC_PV + 11)
 #define TRC_PV_PTWR_EMULATION_PAE    (TRC_PV + 12)
   /* Indicates that addresses in trace record are 64 bits */
-#define TRC_PV_64_FLAG               (0x100) 
+#define TRC_64_FLAG               (0x100) 
 
 /* trace events per subclass */
 #define TRC_HVM_VMENTRY         (TRC_HVM_ENTRYEXIT + 0x01)
 #define TRC_HVM_VMEXIT          (TRC_HVM_ENTRYEXIT + 0x02)
-#define TRC_HVM_VMEXIT64        (TRC_HVM_ENTRYEXIT + 0x03)
+#define TRC_HVM_VMEXIT64        (TRC_HVM_ENTRYEXIT + TRC_64_FLAG + 0x02)
 #define TRC_HVM_PF_XEN          (TRC_HVM_HANDLER + 0x01)
+#define TRC_HVM_PF_XEN64        (TRC_HVM_HANDLER + TRC_64_FLAG + 0x01)
 #define TRC_HVM_PF_INJECT       (TRC_HVM_HANDLER + 0x02)
+#define TRC_HVM_PF_INJECT64     (TRC_HVM_HANDLER + TRC_64_FLAG + 0x02)
 #define TRC_HVM_INJ_EXC         (TRC_HVM_HANDLER + 0x03)
 #define TRC_HVM_INJ_VIRQ        (TRC_HVM_HANDLER + 0x04)
 #define TRC_HVM_REINJ_VIRQ      (TRC_HVM_HANDLER + 0x05)
 #define TRC_HVM_IO_READ         (TRC_HVM_HANDLER + 0x06)
 #define TRC_HVM_IO_WRITE        (TRC_HVM_HANDLER + 0x07)
 #define TRC_HVM_CR_READ         (TRC_HVM_HANDLER + 0x08)
+#define TRC_HVM_CR_READ64       (TRC_HVM_HANDLER + TRC_64_FLAG + 0x08)
 #define TRC_HVM_CR_WRITE        (TRC_HVM_HANDLER + 0x09)
+#define TRC_HVM_CR_WRITE64      (TRC_HVM_HANDLER + TRC_64_FLAG + 0x09)
 #define TRC_HVM_DR_READ         (TRC_HVM_HANDLER + 0x0A)
 #define TRC_HVM_DR_WRITE        (TRC_HVM_HANDLER + 0x0B)
 #define TRC_HVM_MSR_READ        (TRC_HVM_HANDLER + 0x0C)
@@ -113,12 +117,13 @@
 #define TRC_HVM_VMMCALL         (TRC_HVM_HANDLER + 0x12)
 #define TRC_HVM_HLT             (TRC_HVM_HANDLER + 0x13)
 #define TRC_HVM_INVLPG          (TRC_HVM_HANDLER + 0x14)
+#define TRC_HVM_INVLPG64        (TRC_HVM_HANDLER + TRC_64_FLAG + 0x14)
 #define TRC_HVM_MCE             (TRC_HVM_HANDLER + 0x15)
 #define TRC_HVM_IO_ASSIST       (TRC_HVM_HANDLER + 0x16)
 #define TRC_HVM_MMIO_ASSIST     (TRC_HVM_HANDLER + 0x17)
 #define TRC_HVM_CLTS            (TRC_HVM_HANDLER + 0x18)
 #define TRC_HVM_LMSW            (TRC_HVM_HANDLER + 0x19)
-#define TRC_HVM_PF_XEN64        (TRC_HVM_HANDLER + 0x20)
+#define TRC_HVM_LMSW64          (TRC_HVM_HANDLER + TRC_64_FLAG + 0x19)
 
 /* This structure represents a single trace buffer record. */
 struct t_rec {

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel

#1 lore raw

Hi Keir,

I saw you were committing some changes to my patch:

- if ( hvm_long_mode_enabled(v) )
- HVMTRACE_ND (VMEXIT64, 1/*cycles*/, v, 3, exit_reason,
- regs->eip & 0xFFFFFFFF, regs->eip >> 32, 0, 0, 0);
- else
- HVMTRACE_ND (VMEXIT, 1/*cycles*/, v, 2, exit_reason,
- regs->eip, 0, 0, 0, 0);
+ HVMTRACE_ND(VMEXIT64, 1/*cycles*/, v, 3, exit_reason,
+ (uint32_t)regs->eip, (uint32_t)((uint64_t)regs->eip >> 32),
+ 0, 0, 0);

This basically will always log 64bit values for the instruction pointer. I thought about this approach, too, but didn't do it because I got the impression that trace files are large enough and with the recently introduced 'variable number of parameters' saving disk space is a concern. Do you want to promote other pointers to always 64bit, too? Shall I prepare a patch for this?
I also had the idea to include gzipping in the xentrace tool, this should save about 80% of disk space at the cost of a slightly higher Dom0 load (or use lzo?). Is this something I should implement?

Regards,
Andre

Quoted 21 lines · Andre Przywara

Hi,

Xen tracing some times ago used to put values of type 'long' into the trace buffer. This has changed to uint32_t. Some trace points log virtual addresses, which get cropped to 32bit in this case. There were some inline functions to handle at least PF_XEN and VMEXIT, which caused a lot of code duplication. The attached patch fixes several issues:
1. fix and extend tools/xentrace/formats
2. Fix xentrace_format to handle up to 7 parameters
3. create convenience macros to properly log long values
4. remove the inline functions in hvm/trace.h and replace them by macros
5. Change the CPUID trace to work correctly
6. group HVM trace points enable mechanism

I used a similar approach as in PV tracing with bit 8 indicating 64bit pointers.

Discussion welcome!

BTW: Why is xentrace_format so awfully slow? I have rewritten the tool in C and reached a speedup of more than 20 times. If someone bugs me I will share the code...

Regards,
Andre.

Signature · 9 lines
Andre Przywara
AMD-Operating System Research Center (OSRC), Dresden, Germany
Tel: +49 351 277-84917
----to satisfy European Law for business letters:
AMD Saxony Limited Liability Company & Co. KG,
Wilschdorfer Landstr. 101, 01109 Dresden, Germany
Register Court Dresden: HRA 4896, General Partner authorized
to represent: AMD Saxony LLC (Wilmington, Delaware, US)
General Manager of AMD Saxony LLC: Dr. Hans-R. Deppe, Thomas McCoy
#2 lore raw
Quoted 6 lines · Andre Przywara

This basically will always log 64bit values for the instruction pointer. I thought about this approach, too, but didn't do it because I got the impression that trace files are large enough and with the recently introduced 'variable number of parameters' saving disk space is a concern. Do you want to promote other pointers to always 64bit, too? Shall I prepare a patch for this?

My opinion is if it's efficient enough for 64-bit guests then it must be good enough for 32-bit guests too. Further, I don't want extra usually unnecessary checks on the common vmentry/vmexit paths, and always using the 64-bit version reduces code clutter.

-- Keir