[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v1 08/13] x86/PMU: Interface for setting PMU mode and flags
Add runtime interface for setting PMU mode and flags. Three main modes are provided: * PMU off * PMU on: Guests can access PMU MSRs and receive PMU interrupts. dom0 profiles itself and the hypervisor. * dom0-only PMU: dom0 collects samples for both itself and guests. For feature flagso only Intel's BTS is currently supported. Mode and flags are set via new PMU hypercall. Signed-off-by: Boris Ostrovsky <boris.ostrovsky@xxxxxxxxxx> --- xen/arch/x86/hvm/svm/vpmu.c | 2 +- xen/arch/x86/hvm/vmx/vpmu_core2.c | 2 +- xen/arch/x86/hvm/vpmu.c | 77 ++++++++++++++++++++++++++++++++++---- xen/arch/x86/x86_64/compat/entry.S | 4 ++ xen/arch/x86/x86_64/entry.S | 4 ++ xen/include/asm-x86/hvm/vpmu.h | 2 + xen/include/public/xen.h | 1 + xen/include/public/xenpmu.h | 19 ++++++++++ xen/include/xen/hypercall.h | 4 ++ 9 files changed, 105 insertions(+), 10 deletions(-) diff --git a/xen/arch/x86/hvm/svm/vpmu.c b/xen/arch/x86/hvm/svm/vpmu.c index 9f9c9ea..4477f63 100644 --- a/xen/arch/x86/hvm/svm/vpmu.c +++ b/xen/arch/x86/hvm/svm/vpmu.c @@ -458,7 +458,7 @@ int svm_vpmu_initialise(struct vcpu *v, unsigned int vpmu_flags) int ret = 0; /* vpmu enabled? */ - if ( !vpmu_flags ) + if ( vpmu_flags == VPMU_OFF ) return 0; switch ( family ) diff --git a/xen/arch/x86/hvm/vmx/vpmu_core2.c b/xen/arch/x86/hvm/vmx/vpmu_core2.c index f3b6de0..66325d5 100644 --- a/xen/arch/x86/hvm/vmx/vpmu_core2.c +++ b/xen/arch/x86/hvm/vmx/vpmu_core2.c @@ -824,7 +824,7 @@ int vmx_vpmu_initialise(struct vcpu *v, unsigned int vpmu_flags) int ret = 0; vpmu->arch_vpmu_ops = &core2_no_vpmu_ops; - if ( !vpmu_flags ) + if ( vpmu_flags == VPMU_OFF ) return 0; if ( family == 6 ) diff --git a/xen/arch/x86/hvm/vpmu.c b/xen/arch/x86/hvm/vpmu.c index 768f766..820576e 100644 --- a/xen/arch/x86/hvm/vpmu.c +++ b/xen/arch/x86/hvm/vpmu.c @@ -21,6 +21,7 @@ #include <xen/config.h> #include <xen/sched.h> #include <xen/xenoprof.h> +#include <xen/guest_access.h> #include <asm/regs.h> #include <asm/types.h> #include <asm/msr.h> @@ -38,7 +39,7 @@ * "vpmu=off" : vpmu generally disabled * "vpmu=bts" : vpmu enabled and Intel BTS feature switched on. */ -static unsigned int __read_mostly opt_vpmu_enabled; +uint32_t __read_mostly vpmu_mode = VPMU_OFF; static void parse_vpmu_param(char *s); custom_param("vpmu", parse_vpmu_param); @@ -52,7 +53,7 @@ static void __init parse_vpmu_param(char *s) break; default: if ( !strcmp(s, "bts") ) - opt_vpmu_enabled |= VPMU_INTEL_BTS; + vpmu_mode |= VPMU_INTEL_BTS; else if ( *s ) { printk("VPMU: unknown flag: %s - vpmu disabled!\n", s); @@ -60,7 +61,7 @@ static void __init parse_vpmu_param(char *s) } /* fall through */ case 1: - opt_vpmu_enabled |= VPMU_ON; + vpmu_mode |= VPMU_ON; break; } } @@ -226,19 +227,19 @@ void vpmu_initialise(struct vcpu *v) switch ( vendor ) { case X86_VENDOR_AMD: - if ( svm_vpmu_initialise(v, opt_vpmu_enabled) != 0 ) - opt_vpmu_enabled = 0; + if ( svm_vpmu_initialise(v, vpmu_mode) != 0 ) + vpmu_mode = VPMU_OFF; break; case X86_VENDOR_INTEL: - if ( vmx_vpmu_initialise(v, opt_vpmu_enabled) != 0 ) - opt_vpmu_enabled = 0; + if ( vmx_vpmu_initialise(v, vpmu_mode) != 0 ) + vpmu_mode = VPMU_OFF; break; default: printk("VPMU: Initialization failed. " "Unknown CPU vendor %d\n", vendor); - opt_vpmu_enabled = 0; + vpmu_mode = VPMU_OFF; break; } } @@ -260,3 +261,63 @@ void vpmu_dump(struct vcpu *v) vpmu->arch_vpmu_ops->arch_vpmu_dump(v); } +long do_xenpmu_op(int op, XEN_GUEST_HANDLE_PARAM(void) arg) +{ + int ret = -EINVAL; + xenpmu_params_t pmu_params; + uint32_t mode, flags; + + switch ( op ) + { + case XENPMU_mode_set: + if ( !is_control_domain(current->domain) ) + return -EPERM; + + if ( copy_from_guest(&pmu_params, arg, 1) ) + return -EFAULT; + + mode = (uint32_t)pmu_params.control & VPMU_MODE_MASK; + if ( (mode & ~(VPMU_ON | VPMU_PRIV)) || + ((mode & VPMU_ON) && (mode & VPMU_PRIV)) ) + return -EINVAL; + + vpmu_mode &= ~VPMU_MODE_MASK; + vpmu_mode |= mode; + + ret = 0; + break; + + case XENPMU_mode_get: + pmu_params.control = vpmu_mode & VPMU_MODE_MASK; + if ( copy_to_guest(arg, &pmu_params, 1) ) + return -EFAULT; + ret = 0; + break; + + case XENPMU_flags_set: + if ( !is_control_domain(current->domain) ) + return -EPERM; + + if ( copy_from_guest(&pmu_params, arg, 1) ) + return -EFAULT; + + flags = (uint64_t)pmu_params.control & VPMU_FLAGS_MASK; + if ( flags & ~VPMU_INTEL_BTS ) + return -EINVAL; + + vpmu_mode &= ~VPMU_FLAGS_MASK; + vpmu_mode |= flags; + + ret = 0; + break; + + case XENPMU_flags_get: + pmu_params.control = vpmu_mode & VPMU_FLAGS_MASK; + if ( copy_to_guest(arg, &pmu_params, 1) ) + return -EFAULT; + ret = 0; + break; + } + + return ret; +} diff --git a/xen/arch/x86/x86_64/compat/entry.S b/xen/arch/x86/x86_64/compat/entry.S index c0afe2c..bc03ffe 100644 --- a/xen/arch/x86/x86_64/compat/entry.S +++ b/xen/arch/x86/x86_64/compat/entry.S @@ -413,6 +413,8 @@ ENTRY(compat_hypercall_table) .quad do_domctl .quad compat_kexec_op .quad do_tmem_op + .quad do_ni_hypercall /* reserved for XenClient */ + .quad do_xenpmu_op /* 40 */ .rept __HYPERVISOR_arch_0-((.-compat_hypercall_table)/8) .quad compat_ni_hypercall .endr @@ -461,6 +463,8 @@ ENTRY(compat_hypercall_args_table) .byte 1 /* do_domctl */ .byte 2 /* compat_kexec_op */ .byte 1 /* do_tmem_op */ + .byte 0 /* reserved for XenClient */ + .byte 2 /* do_xenpmu_op */ /* 40 */ .rept __HYPERVISOR_arch_0-(.-compat_hypercall_args_table) .byte 0 /* compat_ni_hypercall */ .endr diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S index 5beeccb..2944427 100644 --- a/xen/arch/x86/x86_64/entry.S +++ b/xen/arch/x86/x86_64/entry.S @@ -762,6 +762,8 @@ ENTRY(hypercall_table) .quad do_domctl .quad do_kexec_op .quad do_tmem_op + .quad do_ni_hypercall /* reserved for XenClient */ + .quad do_xenpmu_op /* 40 */ .rept __HYPERVISOR_arch_0-((.-hypercall_table)/8) .quad do_ni_hypercall .endr @@ -810,6 +812,8 @@ ENTRY(hypercall_args_table) .byte 1 /* do_domctl */ .byte 2 /* do_kexec */ .byte 1 /* do_tmem_op */ + .byte 0 /* reserved for XenClient */ + .byte 2 /* do_xenpmu_op */ /* 40 */ .rept __HYPERVISOR_arch_0-(.-hypercall_args_table) .byte 0 /* do_ni_hypercall */ .endr diff --git a/xen/include/asm-x86/hvm/vpmu.h b/xen/include/asm-x86/hvm/vpmu.h index f5f8c9c..cc45c70 100644 --- a/xen/include/asm-x86/hvm/vpmu.h +++ b/xen/include/asm-x86/hvm/vpmu.h @@ -89,5 +89,7 @@ void vpmu_dump(struct vcpu *v); extern int acquire_pmu_ownership(int pmu_ownership); extern void release_pmu_ownership(int pmu_ownership); +extern uint32_t vpmu_mode; + #endif /* __ASM_X86_HVM_VPMU_H_*/ diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h index 3cab74f..7f56560 100644 --- a/xen/include/public/xen.h +++ b/xen/include/public/xen.h @@ -101,6 +101,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_ulong_t); #define __HYPERVISOR_kexec_op 37 #define __HYPERVISOR_tmem_op 38 #define __HYPERVISOR_xc_reserved_op 39 /* reserved for XenClient */ +#define __HYPERVISOR_xenpmu_op 40 /* Architecture-specific hypercall definitions. */ #define __HYPERVISOR_arch_0 48 diff --git a/xen/include/public/xenpmu.h b/xen/include/public/xenpmu.h index 420b674..7240a30 100644 --- a/xen/include/public/xenpmu.h +++ b/xen/include/public/xenpmu.h @@ -8,6 +8,25 @@ #define XENPMU_VER_MAJ 0 #define XENPMU_VER_MIN 0 +/* HYPERVISOR_xenpmu_op commands */ +#define XENPMU_mode_get 0 +#define XENPMU_mode_set 1 +#define XENPMU_flags_get 2 +#define XENPMU_flags_set 3 + +/* Parameters structure for HYPERVISOR_xenpmu_op call */ +typedef struct xenpmu_params { + union { + struct version { + uint8_t maj; + uint8_t min; + } version; + uint64_t pad; + }; + uint64_t control; +} xenpmu_params_t; + + /* VPMU modes */ #define VPMU_MODE_MASK 0xff #define VPMU_OFF 0 diff --git a/xen/include/xen/hypercall.h b/xen/include/xen/hypercall.h index a9e5229..ad3d3de 100644 --- a/xen/include/xen/hypercall.h +++ b/xen/include/xen/hypercall.h @@ -14,6 +14,7 @@ #include <public/event_channel.h> #include <public/tmem.h> #include <public/version.h> +#include <public/xenpmu.h> #include <asm/hypercall.h> #include <xsm/xsm.h> @@ -139,6 +140,9 @@ do_tmem_op( extern long do_xenoprof_op(int op, XEN_GUEST_HANDLE_PARAM(void) arg); +extern long +do_xenpmu_op(int op, XEN_GUEST_HANDLE_PARAM(void) arg); + #ifdef CONFIG_COMPAT extern int -- 1.8.1.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |