# HG changeset patch # User cegger # Date 1302180533 -7200 Tracing facility for nested virtualization Signed-off-by: Christoph Egger diff -r ee39668a7840 -r aef9e2deb9a7 tools/xentrace/formats --- a/tools/xentrace/formats +++ b/tools/xentrace/formats @@ -5,6 +5,7 @@ 0x0001f002 CPU%(cpu)d %(tsc)d (+%(relt 0x0001f003 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) cpu_change 0x%(1)08x 0x0001f004 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) trace_irq [ vector = %(1)d, count = %(2)d, tot_cycles = 0x%(3)08x, max_cycles = 0x%(4)08x ] +0x00021002 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) continue_running [ dom:vcpu = 0x%(1)08x ] 0x00021011 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) running_to_runnable [ dom:vcpu = 0x%(1)08x ] 0x00021021 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) running_to_blocked [ dom:vcpu = 0x%(1)08x ] 0x00021031 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) running_to_offline [ dom:vcpu = 0x%(1)08x ] @@ -34,7 +35,10 @@ 0x0002800d CPU%(cpu)d %(tsc)d (+%(relt 0x0002800e CPU%(cpu)d %(tsc)d (+%(reltsc)8d) switch_infprev [ old_domid = 0x%(1)08x, runtime = %(2)d ] 0x0002800f 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 +0x00081401 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) nVMENTRY [ rIP = 0x%(1)08x ] +0x00081402 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) nVMEXIT [ exitcode = 0x%(1)08x, rIP = 0x%(2)08x, intercepted = 0x%(5)01x ] +0x00081502 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) nVMEXIT [ exitcode = 0x%(1)08x, rIP = 0x%(3)08x%(2)08x, intercepted = 0x%(6)01x ] +0x00081001 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) VMENTRY [ rIP = 0x%(1)08x ] 0x00081002 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) VMEXIT [ exitcode = 0x%(1)08x, rIP = 0x%(2)08x ] 0x00081102 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) VMEXIT [ exitcode = 0x%(1)08x, rIP = 0x%(3)08x%(2)08x ] 0x00082001 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) PF_XEN [ errorcode = 0x%(2)02x, virt = 0x%(1)08x ] @@ -63,15 +67,19 @@ 0x00082013 CPU%(cpu)d %(tsc)d (+%(relt 0x00082014 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) INVLPG [ is invlpga? = %(1)d, virt = 0x%(2)08x ] 0x00082114 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) INVLPG [ is invlpga? = %(1)d, virt = 0x%(3)08x%(2)08x ] 0x00082015 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) MCE -0x00082016 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) IOPORT_READ [ data = 0x%(1)04x ] -0x00082216 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) IOPORT_WRITE [ data = 0x%(1)04x ] -0x00082017 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) MMIO_READ [ data = 0x%(1)04x ] -0x00082217 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) MMIO_WRITE [ data = 0x%(1)04x ] +0x00082016 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) IOPORT_READ [ data = 0x%(1)04x, value = 0x%(2)08x ] +0x00082216 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) IOPORT_WRITE [ data = 0x%(1)04x, value = 0x%(2)08x ] +0x00082017 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) MMIO_READ [ data = 0x%(1)04x, ip = 0x%(3)08x ] +0x00082217 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) MMIO_WRITE [ data = 0x%(1)04x, ip = 0x%(3)08x, value = 0x%(2)08x ] 0x00082018 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) CLTS 0x00082019 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) LMSW [ value = 0x%(1)08x ] 0x00082119 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) LMSW [ value = 0x%(2)08x%(1)08x ] +0x0008201a CPU%(cpu)d %(tsc)d (+%(reltsc)8d) RDTSC [ value = 0x%(2)08x%(1)08x ] 0x00082020 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) INTR_WINDOW [ value = 0x%(1)08x ] 0x00082021 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) NPF [ gpa = 0x%(2)08x%(1)08x mfn = 0x%(4)08x%(3)08x qual = 0x%(5)04x p2mt = 0x%(6)04x ] +0x00082022 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) VINTR +0x00082023 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) INVD +0x00082024 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) WBINVD 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 ] diff -r ee39668a7840 -r aef9e2deb9a7 xen/arch/x86/hvm/emulate.c --- a/xen/arch/x86/hvm/emulate.c +++ b/xen/arch/x86/hvm/emulate.c @@ -45,6 +45,9 @@ static void hvmtrace_io_assist(int is_mm size += 4; } + *(uint32_t *)&buffer[size] = guest_cpu_user_regs()->eip; + size += 4; + trace_var(event, 0/*!cycles*/, size, buffer); } @@ -153,8 +156,6 @@ static int hvmemul_do_io( p->df = df; p->data = value; - hvmtrace_io_assist(is_mmio, p); - if ( is_mmio ) { rc = hvm_mmio_intercept(p); @@ -166,6 +167,8 @@ static int hvmemul_do_io( rc = hvm_portio_intercept(p); } + hvmtrace_io_assist(is_mmio, p); + switch ( rc ) { case X86EMUL_OKAY: diff -r ee39668a7840 -r aef9e2deb9a7 xen/arch/x86/hvm/hvm.c --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -1108,20 +1108,24 @@ void hvm_hlt(unsigned long rflags) { struct vcpu *curr = current; - if ( hvm_event_pending(curr) ) + if ( hvm_event_pending(curr) ) { + HVMTRACE_2D(HLT, /* pending */ 1, /* shutdown */ 0); return; + } /* * If we halt with interrupts disabled, that's a pretty sure sign that we * want to shut down. In a real processor, NMIs are the only way to break * out of this. */ - if ( unlikely(!(rflags & X86_EFLAGS_IF)) ) + if ( unlikely(!(rflags & X86_EFLAGS_IF)) ) { + HVMTRACE_2D(HLT, /* pending */ 0, /* shutdown */ 1); return hvm_vcpu_down(curr); + } do_sched_op_compat(SCHEDOP_block, 0); - HVMTRACE_1D(HLT, /* pending = */ vcpu_runnable(curr)); + HVMTRACE_2D(HLT, /* pending = */ vcpu_runnable(curr), /* shutdown */ 0); } void hvm_triple_fault(void) diff -r ee39668a7840 -r aef9e2deb9a7 xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -1679,6 +1679,25 @@ asmlinkage void svm_vmexit_handler(struc exit_reason = vmcb->exitcode; + if ( tb_init_done ) { + bool_t intercepted = 0; + if (vcpu_guestmode) + intercepted = nsvm_vmcb_guest_intercepts_exitcode(v, regs, + exit_reason); + + if ( hvm_long_mode_enabled(v) ) { + HVMTRACE_ND(VMEXIT64 | (TRC_HVM_NESTEDFLAG * vcpu_guestmode), + 1/*cycles*/, 6, exit_reason, + (uint32_t)regs->eip, (uint32_t)((uint64_t)regs->eip >> 32), + intercepted, 0, 0); + } else { + HVMTRACE_ND(VMEXIT | (TRC_HVM_NESTEDFLAG * vcpu_guestmode), + 1/*cycles*/, 5, exit_reason, + (uint32_t)regs->eip, + intercepted, 0, 0, 0); + } + } + if ( vcpu_guestmode ) { enum nestedhvm_vmexits nsret; struct nestedvcpu *nv = &vcpu_nestedhvm(v); @@ -1739,15 +1758,6 @@ asmlinkage void svm_vmexit_handler(struc } } - if ( hvm_long_mode_enabled(v) ) - HVMTRACE_ND(VMEXIT64, 1/*cycles*/, 3, exit_reason, - (uint32_t)regs->eip, (uint32_t)((uint64_t)regs->eip >> 32), - 0, 0, 0); - else - HVMTRACE_ND(VMEXIT, 1/*cycles*/, 2, exit_reason, - (uint32_t)regs->eip, - 0, 0, 0, 0); - if ( unlikely(exit_reason == VMEXIT_INVALID) ) { svm_vmcb_dump(__func__, vmcb); @@ -1841,7 +1851,10 @@ asmlinkage void svm_vmexit_handler(struc break; case VMEXIT_VINTR: { - u32 general1_intercepts = vmcb_get_general1_intercepts(vmcb); + uint32_t general1_intercepts; + + HVMTRACE_0D(VINTR); + general1_intercepts = vmcb_get_general1_intercepts(vmcb); intr = vmcb_get_vintr(vmcb); intr.fields.irq = 0; @@ -1853,7 +1866,12 @@ asmlinkage void svm_vmexit_handler(struc } case VMEXIT_INVD: + HVMTRACE_0D(INVD); + svm_vmexit_do_invalidate_cache(regs); + break; + case VMEXIT_WBINVD: + HVMTRACE_0D(WBINVD); svm_vmexit_do_invalidate_cache(regs); break; @@ -2027,7 +2045,10 @@ asmlinkage void svm_vmexit_handler(struc asmlinkage void svm_trace_vmentry(void) { - HVMTRACE_ND (VMENTRY, 1/*cycles*/, 0, 0, 0, 0, 0, 0, 0); + struct vcpu *v = current; + HVMTRACE_ND(VMENTRY | (TRC_HVM_NESTEDFLAG * !!(nestedhvm_vcpu_in_guestmode(v))), + 1/*cycles*/, 1, v->arch.hvm_svm.vmcb->rip, + 0, 0, 0, 0, 0); } /* diff -r ee39668a7840 -r aef9e2deb9a7 xen/include/asm-x86/hvm/trace.h --- a/xen/include/asm-x86/hvm/trace.h +++ b/xen/include/asm-x86/hvm/trace.h @@ -50,7 +50,9 @@ #define DO_TRC_HVM_CLTS DEFAULT_HVM_MISC #define DO_TRC_HVM_LMSW DEFAULT_HVM_MISC #define DO_TRC_HVM_LMSW64 DEFAULT_HVM_MISC - +#define DO_TRC_HVM_VINTR DEFAULT_HVM_MISC +#define DO_TRC_HVM_INVD DEFAULT_HVM_MISC +#define DO_TRC_HVM_WBINVD DEFAULT_HVM_MISC #ifdef __x86_64__ #define TRC_PAR_LONG(par) ((par)&0xFFFFFFFF),((par)>>32) diff -r ee39668a7840 -r aef9e2deb9a7 xen/include/public/trace.h --- a/xen/include/public/trace.h +++ b/xen/include/public/trace.h @@ -123,6 +123,7 @@ #define TRC_SHADOW_RESYNC_ONLY (TRC_SHADOW + 15) /* trace events per subclass */ +#define TRC_HVM_NESTEDFLAG (0x400) #define TRC_HVM_VMENTRY (TRC_HVM_ENTRYEXIT + 0x01) #define TRC_HVM_VMEXIT (TRC_HVM_ENTRYEXIT + 0x02) #define TRC_HVM_VMEXIT64 (TRC_HVM_ENTRYEXIT + TRC_64_FLAG + 0x02) @@ -160,6 +161,9 @@ #define TRC_HVM_RDTSC (TRC_HVM_HANDLER + 0x1a) #define TRC_HVM_INTR_WINDOW (TRC_HVM_HANDLER + 0x20) #define TRC_HVM_NPF (TRC_HVM_HANDLER + 0x21) +#define TRC_HVM_VINTR (TRC_HVM_HANDLER + 0x22) +#define TRC_HVM_INVD (TRC_HVM_HANDLER + 0x23) +#define TRC_HVM_WBINVD (TRC_HVM_HANDLER + 0x24) #define TRC_HVM_IOPORT_WRITE (TRC_HVM_HANDLER + 0x216) #define TRC_HVM_IOMEM_WRITE (TRC_HVM_HANDLER + 0x217)