lkml.org 
[lkml]   [2015]   [Jul]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v5 2/6] xen/PMU: Sysfs interface for setting Xen PMU mode
    Date
    Set Xen's PMU mode via /sys/hypervisor/pmu/pmu_mode. Add XENPMU hypercall.

    Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
    ---
    Documentation/ABI/testing/sysfs-hypervisor-pmu | 23 +++++
    arch/x86/include/asm/xen/hypercall.h | 6 ++
    drivers/xen/sys-hypervisor.c | 127 +++++++++++++++++++++++++
    include/xen/interface/xen.h | 1 +
    include/xen/interface/xenpmu.h | 59 ++++++++++++
    5 files changed, 216 insertions(+)
    create mode 100644 Documentation/ABI/testing/sysfs-hypervisor-pmu
    create mode 100644 include/xen/interface/xenpmu.h

    diff --git a/Documentation/ABI/testing/sysfs-hypervisor-pmu b/Documentation/ABI/testing/sysfs-hypervisor-pmu
    new file mode 100644
    index 0000000..d1ceb77
    --- /dev/null
    +++ b/Documentation/ABI/testing/sysfs-hypervisor-pmu
    @@ -0,0 +1,23 @@
    +What: /sys/hypervisor/pmu/pmu_mode
    +Date: July 2015
    +KernelVersion: 4.2
    +Contact: Boris Ostrovsky <boris.ostrovsky@oracle.com>
    +Description:
    + Describes mode that Xen's performance-monitoring unit (PMU)
    + uses. Accepted values are
    + "off" -- PMU is disabled
    + "self" -- The guest can profile itself
    + "hv" -- The guest can profile itself and, if it is
    + privileged (e.g. dom0), the hypervisor
    + "all" -- The guest can profile itself, the hypervisor
    + and all other guests. Only available to
    + privileged guests.
    +
    +What: /sys/hypervisor/pmu/pmu_features
    +Date: July 2015
    +KernelVersion: 4.2
    +Contact: Boris Ostrovsky <boris.ostrovsky@oracle.com>
    +Description:
    + Describes Xen PMU features (as an integer). A set bit indicates
    + that the corresponding feature is enabled. See
    + include/xen/interface/xenpmu.h for available features
    diff --git a/arch/x86/include/asm/xen/hypercall.h b/arch/x86/include/asm/xen/hypercall.h
    index ca08a27..83aea80 100644
    --- a/arch/x86/include/asm/xen/hypercall.h
    +++ b/arch/x86/include/asm/xen/hypercall.h
    @@ -465,6 +465,12 @@ HYPERVISOR_tmem_op(
    return _hypercall1(int, tmem_op, op);
    }

    +static inline int
    +HYPERVISOR_xenpmu_op(unsigned int op, void *arg)
    +{
    + return _hypercall2(int, xenpmu_op, op, arg);
    +}
    +
    static inline void
    MULTI_fpu_taskswitch(struct multicall_entry *mcl, int set)
    {
    diff --git a/drivers/xen/sys-hypervisor.c b/drivers/xen/sys-hypervisor.c
    index 96453f8..f642085 100644
    --- a/drivers/xen/sys-hypervisor.c
    +++ b/drivers/xen/sys-hypervisor.c
    @@ -20,6 +20,7 @@
    #include <xen/xenbus.h>
    #include <xen/interface/xen.h>
    #include <xen/interface/version.h>
    +#include <xen/interface/xenpmu.h>

    #define HYPERVISOR_ATTR_RO(_name) \
    static struct hyp_sysfs_attr _name##_attr = __ATTR_RO(_name)
    @@ -368,6 +369,124 @@ static void xen_properties_destroy(void)
    sysfs_remove_group(hypervisor_kobj, &xen_properties_group);
    }

    +struct pmu_mode {
    + const char *name;
    + uint32_t mode;
    +};
    +
    +struct pmu_mode pmu_modes[] = {
    + {"off", XENPMU_MODE_OFF},
    + {"self", XENPMU_MODE_SELF},
    + {"hv", XENPMU_MODE_HV},
    + {"all", XENPMU_MODE_ALL}
    +};
    +
    +static ssize_t pmu_mode_store(struct hyp_sysfs_attr *attr,
    + const char *buffer, size_t len)
    +{
    + int ret;
    + struct xen_pmu_params xp;
    + int i;
    +
    + for (i = 0; i < ARRAY_SIZE(pmu_modes); i++) {
    + if (strncmp(buffer, pmu_modes[i].name, len - 1) == 0) {
    + xp.val = pmu_modes[i].mode;
    + break;
    + }
    + }
    +
    + if (i == ARRAY_SIZE(pmu_modes))
    + return -EINVAL;
    +
    + xp.version.maj = XENPMU_VER_MAJ;
    + xp.version.min = XENPMU_VER_MIN;
    + ret = HYPERVISOR_xenpmu_op(XENPMU_mode_set, &xp);
    + if (ret)
    + return ret;
    +
    + return len;
    +}
    +
    +static ssize_t pmu_mode_show(struct hyp_sysfs_attr *attr, char *buffer)
    +{
    + int ret;
    + struct xen_pmu_params xp;
    + int i;
    + uint32_t mode;
    +
    + xp.version.maj = XENPMU_VER_MAJ;
    + xp.version.min = XENPMU_VER_MIN;
    + ret = HYPERVISOR_xenpmu_op(XENPMU_mode_get, &xp);
    + if (ret)
    + return ret;
    +
    + mode = (uint32_t)xp.val;
    + for (i = 0; i < ARRAY_SIZE(pmu_modes); i++) {
    + if (mode == pmu_modes[i].mode)
    + return sprintf(buffer, "%s\n", pmu_modes[i].name);
    + }
    +
    + return -EINVAL;
    +}
    +HYPERVISOR_ATTR_RW(pmu_mode);
    +
    +static ssize_t pmu_features_store(struct hyp_sysfs_attr *attr,
    + const char *buffer, size_t len)
    +{
    + int ret;
    + uint32_t features;
    + struct xen_pmu_params xp;
    +
    + ret = kstrtou32(buffer, 0, &features);
    + if (ret)
    + return ret;
    +
    + xp.val = features;
    + xp.version.maj = XENPMU_VER_MAJ;
    + xp.version.min = XENPMU_VER_MIN;
    + ret = HYPERVISOR_xenpmu_op(XENPMU_feature_set, &xp);
    + if (ret)
    + return ret;
    +
    + return len;
    +}
    +
    +static ssize_t pmu_features_show(struct hyp_sysfs_attr *attr, char *buffer)
    +{
    + int ret;
    + struct xen_pmu_params xp;
    +
    + xp.version.maj = XENPMU_VER_MAJ;
    + xp.version.min = XENPMU_VER_MIN;
    + ret = HYPERVISOR_xenpmu_op(XENPMU_feature_get, &xp);
    + if (ret)
    + return ret;
    +
    + return sprintf(buffer, "0x%x\n", (uint32_t)xp.val);
    +}
    +HYPERVISOR_ATTR_RW(pmu_features);
    +
    +static struct attribute *xen_pmu_attrs[] = {
    + &pmu_mode_attr.attr,
    + &pmu_features_attr.attr,
    + NULL
    +};
    +
    +static const struct attribute_group xen_pmu_group = {
    + .name = "pmu",
    + .attrs = xen_pmu_attrs,
    +};
    +
    +static int __init xen_pmu_init(void)
    +{
    + return sysfs_create_group(hypervisor_kobj, &xen_pmu_group);
    +}
    +
    +static void xen_pmu_destroy(void)
    +{
    + sysfs_remove_group(hypervisor_kobj, &xen_pmu_group);
    +}
    +
    static int __init hyper_sysfs_init(void)
    {
    int ret;
    @@ -390,9 +509,16 @@ static int __init hyper_sysfs_init(void)
    ret = xen_properties_init();
    if (ret)
    goto prop_out;
    + if (xen_initial_domain()) {
    + ret = xen_pmu_init();
    + if (ret)
    + goto pmu_out;
    + }

    goto out;

    +pmu_out:
    + xen_properties_destroy();
    prop_out:
    xen_sysfs_uuid_destroy();
    uuid_out:
    @@ -407,6 +533,7 @@ out:

    static void __exit hyper_sysfs_exit(void)
    {
    + xen_pmu_destroy();
    xen_properties_destroy();
    xen_compilation_destroy();
    xen_sysfs_uuid_destroy();
    diff --git a/include/xen/interface/xen.h b/include/xen/interface/xen.h
    index a483789..c6399a1 100644
    --- a/include/xen/interface/xen.h
    +++ b/include/xen/interface/xen.h
    @@ -80,6 +80,7 @@
    #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/include/xen/interface/xenpmu.h b/include/xen/interface/xenpmu.h
    new file mode 100644
    index 0000000..eac1b49
    --- /dev/null
    +++ b/include/xen/interface/xenpmu.h
    @@ -0,0 +1,59 @@
    +#ifndef __XEN_PUBLIC_XENPMU_H__
    +#define __XEN_PUBLIC_XENPMU_H__
    +
    +#include "xen.h"
    +
    +#define XENPMU_VER_MAJ 0
    +#define XENPMU_VER_MIN 1
    +
    +/*
    + * ` enum neg_errnoval
    + * ` HYPERVISOR_xenpmu_op(enum xenpmu_op cmd, struct xenpmu_params *args);
    + *
    + * @cmd == XENPMU_* (PMU operation)
    + * @args == struct xenpmu_params
    + */
    +/* ` enum xenpmu_op { */
    +#define XENPMU_mode_get 0 /* Also used for getting PMU version */
    +#define XENPMU_mode_set 1
    +#define XENPMU_feature_get 2
    +#define XENPMU_feature_set 3
    +#define XENPMU_init 4
    +#define XENPMU_finish 5
    +
    +/* ` } */
    +
    +/* Parameters structure for HYPERVISOR_xenpmu_op call */
    +struct xen_pmu_params {
    + /* IN/OUT parameters */
    + struct {
    + uint32_t maj;
    + uint32_t min;
    + } version;
    + uint64_t val;
    +
    + /* IN parameters */
    + uint32_t vcpu;
    + uint32_t pad;
    +};
    +
    +/* PMU modes:
    + * - XENPMU_MODE_OFF: No PMU virtualization
    + * - XENPMU_MODE_SELF: Guests can profile themselves
    + * - XENPMU_MODE_HV: Guests can profile themselves, dom0 profiles
    + * itself and Xen
    + * - XENPMU_MODE_ALL: Only dom0 has access to VPMU and it profiles
    + * everyone: itself, the hypervisor and the guests.
    + */
    +#define XENPMU_MODE_OFF 0
    +#define XENPMU_MODE_SELF (1<<0)
    +#define XENPMU_MODE_HV (1<<1)
    +#define XENPMU_MODE_ALL (1<<2)
    +
    +/*
    + * PMU features:
    + * - XENPMU_FEATURE_INTEL_BTS: Intel BTS support (ignored on AMD)
    + */
    +#define XENPMU_FEATURE_INTEL_BTS 1
    +
    +#endif /* __XEN_PUBLIC_XENPMU_H__ */
    --
    1.8.1.4


    \
     
     \ /
      Last update: 2015-07-02 17:21    [W:4.460 / U:0.916 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site