[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] xentrace/x86: PV guest tracing extensions.
# HG changeset patch # User Keir Fraser <keir@xxxxxxxxxxxxx> # Date 1192190762 -3600 # Node ID a330276d8c9095cbf9a39e21d945ab1cc32b7a5c # Parent ef4119637f52648c096e899801f1ca82dbbc04d2 xentrace/x86: PV guest tracing extensions. From: George Dunlap <gdunlap@xxxxxxxxxxxxx> Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> --- xen/arch/x86/Makefile | 1 xen/arch/x86/mm.c | 3 xen/arch/x86/trace.c | 231 +++++++++++++++++++++++++++++++++++++ xen/arch/x86/traps.c | 37 +++++ xen/arch/x86/x86_32/entry.S | 6 xen/arch/x86/x86_64/compat/entry.S | 12 + xen/arch/x86/x86_64/entry.S | 12 + xen/include/asm-ia64/trace.h | 4 xen/include/asm-powerpc/trace.h | 4 xen/include/asm-x86/trace.h | 46 +++++++ xen/include/public/trace.h | 15 ++ xen/include/xen/domain.h | 2 xen/include/xen/trace.h | 5 13 files changed, 373 insertions(+), 5 deletions(-) diff -r ef4119637f52 -r a330276d8c90 xen/arch/x86/Makefile --- a/xen/arch/x86/Makefile Fri Oct 12 11:55:41 2007 +0100 +++ b/xen/arch/x86/Makefile Fri Oct 12 13:06:02 2007 +0100 @@ -40,6 +40,7 @@ obj-y += string.o obj-y += string.o obj-y += sysctl.o obj-y += time.o +obj-y += trace.o obj-y += traps.o obj-y += usercopy.o obj-y += x86_emulate.o diff -r ef4119637f52 -r a330276d8c90 xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Fri Oct 12 11:55:41 2007 +0100 +++ b/xen/arch/x86/mm.c Fri Oct 12 13:06:02 2007 +0100 @@ -111,6 +111,7 @@ #include <asm/shared.h> #include <public/memory.h> #include <xsm/xsm.h> +#include <xen/trace.h> #define MEM_LOG(_f, _a...) gdprintk(XENLOG_WARNING , _f "\n" , ## _a) @@ -3402,6 +3403,8 @@ static int ptwr_emulated_update( BUG(); } + trace_ptwr_emulation(addr, nl1e); + unmap_domain_page(pl1e); /* Finally, drop the old PTE. */ diff -r ef4119637f52 -r a330276d8c90 xen/arch/x86/trace.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/arch/x86/trace.c Fri Oct 12 13:06:02 2007 +0100 @@ -0,0 +1,231 @@ +#include <xen/config.h> +#include <xen/init.h> +#include <xen/kernel.h> +#include <xen/lib.h> +#include <xen/domain.h> +#include <xen/sched.h> +#include <xen/trace.h> + +#ifndef __x86_64__ +#undef TRC_PV_64_FLAG +#define TRC_PV_64_FLAG 0 +#endif + +asmlinkage void trace_hypercall(void) +{ + struct cpu_user_regs *regs = guest_cpu_user_regs(); + + if ( !tb_init_done ) + return; + +#ifdef __x86_64__ + if ( is_pv_32on64_vcpu(current) ) + { + struct { + u32 eip,eax; + } __attribute__((packed)) d; + + d.eip = regs->eip; + d.eax = regs->eax; + + __trace_var(TRC_PV_HYPERCALL, 1, + sizeof(d), (unsigned char *)&d); + } + else +#endif + { + struct { + unsigned long eip; + u32 eax; + } __attribute__((packed)) d; + u32 event; + + event = TRC_PV_HYPERCALL; + event |= TRC_PV_64_FLAG; + d.eip = regs->eip; + d.eax = regs->eax; + + __trace_var(event, 1/*tsc*/, sizeof(d), (unsigned char*)&d); + } +} + +void __trace_pv_trap(int trapnr, unsigned long eip, + int use_error_code, unsigned error_code) +{ + if ( !tb_init_done ) + return; + +#ifdef __x86_64__ + if ( is_pv_32on64_vcpu(current) ) + { + struct { + unsigned eip:32, + trapnr:15, + use_error_code:1, + error_code:16; + } __attribute__((packed)) d; + + d.eip = eip; + d.trapnr = trapnr; + d.error_code = error_code; + d.use_error_code=!!use_error_code; + + __trace_var(TRC_PV_TRAP, 1, + sizeof(d), (unsigned char *)&d); + } + else +#endif + { + struct { + unsigned long eip; + unsigned trapnr:15, + use_error_code:1, + error_code:16; + } __attribute__((packed)) d; + unsigned event; + + d.eip = eip; + d.trapnr = trapnr; + d.error_code = error_code; + d.use_error_code=!!use_error_code; + + event = TRC_PV_TRAP; + event |= TRC_PV_64_FLAG; + __trace_var(event, 1, sizeof(d), (unsigned char *)&d); + } +} + +void __trace_pv_page_fault(unsigned long addr, unsigned error_code) +{ + unsigned long eip = guest_cpu_user_regs()->eip; + + if ( !tb_init_done ) + return; + +#ifdef __x86_64__ + if ( is_pv_32on64_vcpu(current) ) + { + struct { + u32 eip, addr, error_code; + } __attribute__((packed)) d; + + d.eip = eip; + d.addr = addr; + d.error_code = error_code; + + __trace_var(TRC_PV_PAGE_FAULT, 1, sizeof(d), (unsigned char *)&d); + } + else +#endif + { + struct { + unsigned long eip, addr; + u32 error_code; + } __attribute__((packed)) d; + unsigned event; + + d.eip = eip; + d.addr = addr; + d.error_code = error_code; + event = TRC_PV_PAGE_FAULT; + event |= TRC_PV_64_FLAG; + __trace_var(event, 1, sizeof(d), (unsigned char *)&d); + } +} + +void __trace_trap_one_addr(unsigned event, unsigned long va) +{ + if ( !tb_init_done ) + return; + +#ifdef __x86_64__ + if ( is_pv_32on64_vcpu(current) ) + { + u32 d = va; + __trace_var(event, 1, sizeof(d), (unsigned char *)&d); + } + else +#endif + { + event |= TRC_PV_64_FLAG; + __trace_var(event, 1, sizeof(va), (unsigned char *)&va); + } +} + +void __trace_trap_two_addr(unsigned event, unsigned long va1, + unsigned long va2) +{ + if ( !tb_init_done ) + return; + +#ifdef __x86_64__ + if ( is_pv_32on64_vcpu(current) ) + { + struct { + u32 va1, va2; + } __attribute__((packed)) d; + d.va1=va1; + d.va2=va2; + __trace_var(event, 1, sizeof(d), (unsigned char *)&d); + } + else +#endif + { + struct { + unsigned long va1, va2; + } __attribute__((packed)) d; + d.va1=va1; + d.va2=va2; + event |= TRC_PV_64_FLAG; + __trace_var(event, 1, sizeof(d), (unsigned char *)&d); + } +} + +void __trace_ptwr_emulation(unsigned long addr, l1_pgentry_t npte) +{ + unsigned long eip = guest_cpu_user_regs()->eip; + + if ( !tb_init_done ) + return; + + /* We have a couple of different modes to worry about: + * - 32-on-32: 32-bit pte, 32-bit virtual addresses + * - pae-on-pae, pae-on-64: 64-bit pte, 32-bit virtual addresses + * - 64-on-64: 64-bit pte, 64-bit virtual addresses + * pae-on-64 is the only one that requires extra code; in all other + * cases, "unsigned long" is the size of a guest virtual address. + */ + +#ifdef __x86_64__ + if ( is_pv_32on64_vcpu(current) ) + { + struct { + l1_pgentry_t pte; + u32 addr, eip; + } __attribute__((packed)) d; + d.addr = addr; + d.eip = eip; + d.pte = npte; + + __trace_var(TRC_PV_PTWR_EMULATION_PAE, 1, + sizeof(d), (unsigned char *)&d); + } + else +#endif + { + struct { + l1_pgentry_t pte; + unsigned long addr, eip; + } d; + unsigned event; + + d.addr = addr; + d.eip = eip; + d.pte = npte; + + event = ((CONFIG_PAGING_LEVELS == 3) ? + TRC_PV_PTWR_EMULATION_PAE : TRC_PV_PTWR_EMULATION); + event |= TRC_PV_64_FLAG; + __trace_var(event, 1/*tsc*/, sizeof(d), (unsigned char *)&d); + } +} diff -r ef4119637f52 -r a330276d8c90 xen/arch/x86/traps.c --- a/xen/arch/x86/traps.c Fri Oct 12 11:55:41 2007 +0100 +++ b/xen/arch/x86/traps.c Fri Oct 12 13:06:02 2007 +0100 @@ -46,6 +46,7 @@ #include <xen/nmi.h> #include <xen/version.h> #include <xen/kexec.h> +#include <xen/trace.h> #include <asm/paging.h> #include <asm/system.h> #include <asm/io.h> @@ -380,6 +381,8 @@ static int do_guest_trap( struct trap_bounce *tb; const struct trap_info *ti; + trace_pv_trap(trapnr, regs->eip, use_error_code, regs->error_code); + tb = &v->arch.trap_bounce; ti = &v->arch.guest_context.trap_ctxt[trapnr]; @@ -633,6 +636,8 @@ static int emulate_forced_invalid_op(str regs->eip = eip; regs->eflags &= ~X86_EFLAGS_RF; + trace_trap_one_addr(TRC_PV_FORCED_INVALID_OP, regs->eip); + return EXCRET_fault_fixed; } @@ -751,6 +756,8 @@ void propagate_page_fault(unsigned long error_code &= ~PFEC_user_mode; if ( !guest_kernel_mode(v, guest_cpu_user_regs()) ) error_code |= PFEC_user_mode; + + trace_pv_page_fault(addr, error_code); ti = &v->arch.guest_context.trap_ctxt[TRAP_page_fault]; tb->flags = TBF_EXCEPTION | TBF_EXCEPTION_ERRCODE; @@ -783,7 +790,13 @@ static int handle_gdt_ldt_mapping_fault( if ( likely(is_ldt_area) ) { /* LDT fault: Copy a mapping from the guest's LDT, if it is valid. */ - if ( unlikely(map_ldt_shadow_page(offset >> PAGE_SHIFT) == 0) ) + if ( likely(map_ldt_shadow_page(offset >> PAGE_SHIFT)) ) + { + if ( guest_mode(regs) ) + trace_trap_two_addr(TRC_PV_GDT_LDT_MAPPING_FAULT, + regs->eip, offset); + } + else { /* In hypervisor mode? Leave it to the #PF handler to fix up. */ if ( !guest_mode(regs) ) @@ -939,7 +952,12 @@ static int fixup_page_fault(unsigned lon if ( unlikely(IN_HYPERVISOR_RANGE(addr)) ) { if ( paging_mode_external(d) && guest_mode(regs) ) - return paging_fault(addr, regs); + { + int ret = paging_fault(addr, regs); + if ( ret == EXCRET_fault_fixed ) + trace_trap_two_addr(TRC_PV_PAGING_FIXUP, regs->eip, addr); + return ret; + } if ( (addr >= GDT_LDT_VIRT_START) && (addr < GDT_LDT_VIRT_END) ) return handle_gdt_ldt_mapping_fault( addr - GDT_LDT_VIRT_START, regs); @@ -955,7 +973,12 @@ static int fixup_page_fault(unsigned lon return EXCRET_fault_fixed; if ( paging_mode_enabled(d) ) - return paging_fault(addr, regs); + { + int ret = paging_fault(addr, regs); + if ( ret == EXCRET_fault_fixed ) + trace_trap_two_addr(TRC_PV_PAGING_FIXUP, regs->eip, addr); + return ret; + } return 0; } @@ -1872,13 +1895,19 @@ asmlinkage int do_general_protection(str /* Emulate some simple privileged and I/O instructions. */ if ( (regs->error_code == 0) && emulate_privileged_op(regs) ) + { + trace_trap_one_addr(TRC_PV_EMULATE_PRIVOP, regs->eip); return 0; + } #if defined(__i386__) if ( VM_ASSIST(v->domain, VMASST_TYPE_4gb_segments) && (regs->error_code == 0) && gpf_emulate_4gb(regs) ) + { + TRACE_1D(TRC_PV_EMULATE_4GB, regs->eip); return 0; + } #endif /* Pass on GPF as is. */ @@ -2030,6 +2059,8 @@ asmlinkage int do_device_not_available(s do_guest_trap(TRAP_no_device, regs, 0); current->arch.guest_context.ctrlreg[0] &= ~X86_CR0_TS; } + else + TRACE_0D(TRC_PV_MATH_STATE_RESTORE); return EXCRET_fault_fixed; } diff -r ef4119637f52 -r a330276d8c90 xen/arch/x86/x86_32/entry.S --- a/xen/arch/x86/x86_32/entry.S Fri Oct 12 11:55:41 2007 +0100 +++ b/xen/arch/x86/x86_32/entry.S Fri Oct 12 13:06:02 2007 +0100 @@ -194,6 +194,12 @@ 1: sti pushl 20(%esp) # ECX pushl 20(%esp) # EBX #endif + cmpb $0,tb_init_done + je tracing_off + call trace_hypercall + /* Now restore all the registers that trace_hypercall clobbered */ + movl UREGS_eax+24(%esp),%eax /* Hypercall # */ +tracing_off: call *hypercall_table(,%eax,4) addl $24,%esp # Discard the shadow parameters #ifndef NDEBUG diff -r ef4119637f52 -r a330276d8c90 xen/arch/x86/x86_64/compat/entry.S --- a/xen/arch/x86/x86_64/compat/entry.S Fri Oct 12 11:55:41 2007 +0100 +++ b/xen/arch/x86/x86_64/compat/entry.S Fri Oct 12 13:06:02 2007 +0100 @@ -56,6 +56,18 @@ ENTRY(compat_hypercall) movl %ebp,%r9d /* Arg 6 */ movl UREGS_rbx(%rsp),%edi /* Arg 1 */ #endif + cmpb $0,tb_init_done(%rip) + je compat_tracing_off + call trace_hypercall + /* Now restore all the registers that trace_hypercall clobbered */ + movl UREGS_rax(%rsp),%eax /* Hypercall # */ + movl UREGS_rbx(%rsp),%edi /* Arg 1 */ + movl UREGS_rcx(%rsp),%esi /* Arg 2 */ + movl UREGS_rdx(%rsp),%edx /* Arg 3 */ + movl UREGS_rsi(%rsp),%ecx /* Arg 4 */ + movl UREGS_rdi(%rsp),%r8d /* Arg 5 */ + movl UREGS_rbp(%rsp),%r9d /* Arg 6 */ +compat_tracing_off: leaq compat_hypercall_table(%rip),%r10 PERFC_INCR(PERFC_hypercalls, %rax, %rbx) callq *(%r10,%rax,8) diff -r ef4119637f52 -r a330276d8c90 xen/arch/x86/x86_64/entry.S --- a/xen/arch/x86/x86_64/entry.S Fri Oct 12 11:55:41 2007 +0100 +++ b/xen/arch/x86/x86_64/entry.S Fri Oct 12 13:06:02 2007 +0100 @@ -148,6 +148,18 @@ ENTRY(syscall_enter) pushq %rax pushq UREGS_rip+8(%rsp) #endif + cmpb $0,tb_init_done(%rip) + je tracing_off + call trace_hypercall + /* Now restore all the registers that trace_hypercall clobbered */ + movq UREGS_rax(%rsp),%rax /* Hypercall # */ + movq UREGS_rdi(%rsp),%rdi /* Arg 1 */ + movq UREGS_rsi(%rsp),%rsi /* Arg 2 */ + movq UREGS_rdx(%rsp),%rdx /* Arg 3 */ + movq UREGS_r10(%rsp),%rcx /* Arg 4 */ + movq UREGS_rdi(%rsp),%r8 /* Arg 5 */ + movq UREGS_rbp(%rsp),%r9 /* Arg 6 */ +tracing_off: leaq hypercall_table(%rip),%r10 PERFC_INCR(PERFC_hypercalls, %rax, %rbx) callq *(%r10,%rax,8) diff -r ef4119637f52 -r a330276d8c90 xen/include/asm-ia64/trace.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/include/asm-ia64/trace.h Fri Oct 12 13:06:02 2007 +0100 @@ -0,0 +1,4 @@ +#ifndef __ASM_TRACE_H__ +#define __ASM_TRACE_H__ + +#endif /* __ASM_TRACE_H__ */ diff -r ef4119637f52 -r a330276d8c90 xen/include/asm-powerpc/trace.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/include/asm-powerpc/trace.h Fri Oct 12 13:06:02 2007 +0100 @@ -0,0 +1,4 @@ +#ifndef __ASM_TRACE_H__ +#define __ASM_TRACE_H__ + +#endif /* __ASM_TRACE_H__ */ diff -r ef4119637f52 -r a330276d8c90 xen/include/asm-x86/trace.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/include/asm-x86/trace.h Fri Oct 12 13:06:02 2007 +0100 @@ -0,0 +1,46 @@ +#ifndef __ASM_TRACE_H__ +#define __ASM_TRACE_H__ + +#include <asm/page.h> + +void __trace_pv_trap(int trapnr, unsigned long eip, + int use_error_code, unsigned error_code); +static inline void trace_pv_trap(int trapnr, unsigned long eip, + int use_error_code, unsigned error_code) +{ + if ( tb_init_done ) + __trace_pv_trap(trapnr, eip, use_error_code, error_code); +} + +void __trace_pv_page_fault(unsigned long addr, unsigned error_code); +static inline void trace_pv_page_fault(unsigned long addr, + unsigned error_code) +{ + if ( tb_init_done ) + __trace_pv_page_fault(addr, error_code); +} + +void __trace_trap_one_addr(unsigned event, unsigned long va); +static inline void trace_trap_one_addr(unsigned event, unsigned long va) +{ + if ( tb_init_done ) + __trace_trap_one_addr(event, va); +} + +void __trace_trap_two_addr(unsigned event, unsigned long va1, + unsigned long va2); +static inline void trace_trap_two_addr(unsigned event, unsigned long va1, + unsigned long va2) +{ + if ( tb_init_done ) + __trace_trap_two_addr(event, va1, va2); +} + +void __trace_ptwr_emulation(unsigned long addr, l1_pgentry_t npte); +static inline void trace_ptwr_emulation(unsigned long addr, l1_pgentry_t npte) +{ + if ( tb_init_done ) + __trace_ptwr_emulation(addr, npte); +} + +#endif /* __ASM_TRACE_H__ */ diff -r ef4119637f52 -r a330276d8c90 xen/include/public/trace.h --- a/xen/include/public/trace.h Fri Oct 12 11:55:41 2007 +0100 +++ b/xen/include/public/trace.h Fri Oct 12 13:06:02 2007 +0100 @@ -36,6 +36,7 @@ #define TRC_DOM0OP 0x0004f000 /* Xen DOM0 operation trace */ #define TRC_HVM 0x0008f000 /* Xen HVM trace */ #define TRC_MEM 0x0010f000 /* Xen memory trace */ +#define TRC_PV 0x0020f000 /* Xen PV traces */ #define TRC_ALL 0x0ffff000 #define TRC_HD_TO_EVENT(x) ((x)&0x0fffffff) #define TRC_HD_CYCLE_FLAG (1UL<<31) @@ -73,6 +74,20 @@ #define TRC_MEM_PAGE_GRANT_MAP (TRC_MEM + 1) #define TRC_MEM_PAGE_GRANT_UNMAP (TRC_MEM + 2) #define TRC_MEM_PAGE_GRANT_TRANSFER (TRC_MEM + 3) + +#define TRC_PV_HYPERCALL (TRC_PV + 1) +#define TRC_PV_TRAP (TRC_PV + 3) +#define TRC_PV_PAGE_FAULT (TRC_PV + 4) +#define TRC_PV_FORCED_INVALID_OP (TRC_PV + 5) +#define TRC_PV_EMULATE_PRIVOP (TRC_PV + 6) +#define TRC_PV_EMULATE_4GB (TRC_PV + 7) +#define TRC_PV_MATH_STATE_RESTORE (TRC_PV + 8) +#define TRC_PV_PAGING_FIXUP (TRC_PV + 9) +#define TRC_PV_GDT_LDT_MAPPING_FAULT (TRC_PV + 10) +#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) /* trace events per subclass */ #define TRC_HVM_VMENTRY (TRC_HVM_ENTRYEXIT + 0x01) diff -r ef4119637f52 -r a330276d8c90 xen/include/xen/domain.h --- a/xen/include/xen/domain.h Fri Oct 12 11:55:41 2007 +0100 +++ b/xen/include/xen/domain.h Fri Oct 12 13:06:02 2007 +0100 @@ -1,6 +1,8 @@ #ifndef __XEN_DOMAIN_H__ #define __XEN_DOMAIN_H__ + +#include <public/xen.h> typedef union { struct vcpu_guest_context *nat; diff -r ef4119637f52 -r a330276d8c90 xen/include/xen/trace.h --- a/xen/include/xen/trace.h Fri Oct 12 11:55:41 2007 +0100 +++ b/xen/include/xen/trace.h Fri Oct 12 13:06:02 2007 +0100 @@ -21,11 +21,12 @@ #ifndef __XEN_TRACE_H__ #define __XEN_TRACE_H__ +extern int tb_init_done; + #include <xen/config.h> #include <public/sysctl.h> #include <public/trace.h> - -extern int tb_init_done; +#include <asm/trace.h> /* Used to initialise trace buffer functionality */ void init_trace_bufs(void); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |