# HG changeset patch # User root@xen-trw1.amd.com # Node ID 00b7e98338c4d020de76b65b3162a1c4f9da219c # Parent fd3a436e142580cbd7ccb9a90c3a5d0600b903ab Add xenoprofile support for VT in the same fashion as the AMD-V patch. The VT vmx_oprofile_get_eip() function needs some additional work and verification of the logic, although testing indicates that the basic functionality works. diff -r fd3a436e1425 -r 00b7e98338c4 xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Fri Sep 15 14:33:01 2006 +++ b/xen/arch/x86/hvm/vmx/vmx.c Fri Sep 15 15:01:04 2006 @@ -729,6 +729,29 @@ *(u16 *)(hypercall_page + (__HYPERVISOR_iret * 32)) = 0x0b0f; /* ud2 */ } +static int +vmx_oprofile_get_eip( + struct vcpu *v, struct cpu_user_regs *r, unsigned long *eip) +{ + int mode; + /* test for guest's NMI */ + if( v->arch.guest_context.flags & VGCF_hvm_guest_nmi ) + { + v->arch.guest_context.flags &= ~VGCF_hvm_guest_nmi; + /* SVM guest was running */ + __vmread(GUEST_RIP, &eip); //TODO: valid here? + //TODO: add access to CPL of guest for mode of 0 or 1. + mode = 0; + } + else + { + /* some NMI while the HV was running */ + *eip = r->eip; + mode = 2; + } + return mode; +} + /* Setup HVM interfaces */ static void vmx_setup_hvm_funcs(void) { @@ -758,6 +781,8 @@ hvm_funcs.init_ap_context = vmx_init_ap_context; hvm_funcs.init_hypercall_page = vmx_init_hypercall_page; + + hvm_funcs.oprofile_get_eip = vmx_oprofile_get_eip; } int start_vmx(void) @@ -2211,6 +2236,10 @@ break; } case TRAP_nmi: + /* + * set the guest NMI context flag + */ + v->arch.guest_context.flags |= VGCF_hvm_guest_nmi; do_nmi(®s); break; default: diff -r fd3a436e1425 -r 00b7e98338c4 xen/arch/x86/oprofile/op_model_p4.c --- a/xen/arch/x86/oprofile/op_model_p4.c Fri Sep 15 14:33:01 2006 +++ b/xen/arch/x86/oprofile/op_model_p4.c Fri Sep 15 15:01:04 2006 @@ -16,6 +16,7 @@ #include #include #include +#include #include "op_x86_model.h" #include "op_counter.h" @@ -633,11 +634,19 @@ int ovf = 0; unsigned long eip = regs->eip; int mode = 0; - - if (guest_kernel_mode(current, regs)) - mode = 1; - else if (ring_0(regs)) - mode = 2; + struct vcpu *v = current; + + if ( hvm_guest(v) ) + { + mode = hvm_oprofile_get_eip( v, regs, &eip ); + } + else + { + if (guest_kernel_mode(v, regs)) + mode = 1; + else if (ring_0(regs)) + mode = 2; + } stag = get_stagger(); diff -r fd3a436e1425 -r 00b7e98338c4 xen/arch/x86/oprofile/op_model_ppro.c --- a/xen/arch/x86/oprofile/op_model_ppro.c Fri Sep 15 14:33:01 2006 +++ b/xen/arch/x86/oprofile/op_model_ppro.c Fri Sep 15 15:01:04 2006 @@ -18,6 +18,7 @@ #include #include #include +#include #include "op_x86_model.h" #include "op_counter.h" @@ -101,16 +102,24 @@ int ovf = 0; unsigned long eip = regs->eip; int mode = 0; + struct vcpu *v = current; - if ( guest_kernel_mode(current, regs) ) - mode = 1; - else if ( ring_0(regs) ) - mode = 2; + if ( hvm_guest(v) ) + { + mode = hvm_oprofile_get_eip( v, regs, &eip ); + } + else + { + if (guest_kernel_mode(v, regs)) + mode = 1; + else if (ring_0(regs)) + mode = 2; + } for (i = 0 ; i < NUM_COUNTERS; ++i) { CTR_READ(low, high, msrs, i); if (CTR_OVERFLOWED(low)) { - xenoprof_log_event(current, eip, mode, i); + xenoprof_log_event(v, eip, mode, i); CTR_WRITE(reset_value[i], msrs, i); ovf = 1; }