From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
To: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Cc: xen-devel@lists.xen.org, david.vrabel@citrix.com,
JBeulich@suse.com, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v1 3/5] xen/PMU: Initialization code for Xen PMU
Date: Mon, 23 Sep 2013 09:26:18 -0400 [thread overview]
Message-ID: <20130923132618.GD3175@phenom.dumpdata.com> (raw)
In-Reply-To: <1378827110-4192-4-git-send-email-boris.ostrovsky@oracle.com>
On Tue, Sep 10, 2013 at 11:31:48AM -0400, Boris Ostrovsky wrote:
> Map shared data structure that will hold CPU registers, VPMU context,
> VCPU/PCPI IDs of the VCPU interrupted by PMU interrupt. Hypervisor
> fills this information in its handler and passes it to the guest for
> further processing.
>
> Set up PMU VIRQ.
>
> Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
> ---
> arch/x86/xen/Makefile | 2 +-
> arch/x86/xen/pmu.c | 122 +++++++++++++++++++++++++++++++++++++++++
> arch/x86/xen/pmu.h | 12 ++++
> arch/x86/xen/smp.c | 31 ++++++++++-
> include/xen/interface/xen.h | 1 +
> include/xen/interface/xenpmu.h | 77 ++++++++++++++++++++++++++
> 6 files changed, 243 insertions(+), 2 deletions(-)
> create mode 100644 arch/x86/xen/pmu.c
> create mode 100644 arch/x86/xen/pmu.h
>
> diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile
> index 96ab2c0..b187df5 100644
> --- a/arch/x86/xen/Makefile
> +++ b/arch/x86/xen/Makefile
> @@ -13,7 +13,7 @@ CFLAGS_mmu.o := $(nostackp)
> obj-y := enlighten.o setup.o multicalls.o mmu.o irq.o \
> time.o xen-asm.o xen-asm_$(BITS).o \
> grant-table.o suspend.o platform-pci-unplug.o \
> - p2m.o
> + p2m.o pmu.o
Perhaps guard the build of this based on CONFIG_PERF_EVENTS?
That would of course mean you also have to create in xenpmu.h
static inline empy functions for xen_pmu_finish and xen_pmu_init in case
CONFIG_PERF_EVENTS is not set.
>
> obj-$(CONFIG_EVENT_TRACING) += trace.o
>
> diff --git a/arch/x86/xen/pmu.c b/arch/x86/xen/pmu.c
> new file mode 100644
> index 0000000..da061d4
> --- /dev/null
> +++ b/arch/x86/xen/pmu.c
> @@ -0,0 +1,122 @@
> +#include <linux/types.h>
> +#include <linux/interrupt.h>
> +
> +#include <asm/xen/hypercall.h>
> +#include <xen/page.h>
> +#include <xen/interface/xen.h>
> +#include <xen/interface/vcpu.h>
> +#include <xen/interface/xenpmu.h>
> +
> +#include "xen-ops.h"
> +#include "pmu.h"
> +
> +/* x86_pmu.handle_irq definition */
> +#include <../kernel/cpu/perf_event.h>
> +
> +
> +/* Shared page between hypervisor and domain */
> +DEFINE_PER_CPU(struct xenpmu_data *, xenpmu_shared);
> +
> +/* perf callbacks*/
> +int xen_is_in_guest(void)
> +{
> + struct xenpmu_data *xenpmu_data = per_cpu(xenpmu_shared,
> + smp_processor_id());
> +
> + if (!xen_initial_domain() ||
> + xenpmu_data->domain_id > DOMID_SELF || xenpmu_data->domain_id == 0)
> + return 0;
> +
> + return 1;
> +}
> +
> +static int xen_is_user_mode(void)
> +{
> + struct xenpmu_data *xenpmu_data = per_cpu(xenpmu_shared,
> + smp_processor_id());
> + return ((xenpmu_data->regs.cs & 3) == 3);
> +}
> +
> +static unsigned long xen_get_guest_ip(void)
> +{
> + struct xenpmu_data *xenpmu_data = per_cpu(xenpmu_shared,
> + smp_processor_id());
> + return xenpmu_data->regs.eip;
> +}
> +
> +static struct perf_guest_info_callbacks xen_guest_cbs = {
> + .is_in_guest = xen_is_in_guest,
> + .is_user_mode = xen_is_user_mode,
> + .get_guest_ip = xen_get_guest_ip,
> +};
> +
> +/* Convert registers from Xen's format to Linux' */
> +static void xen_convert_regs(struct cpu_user_regs *xen_regs,
> + struct pt_regs *regs)
> +{
> + regs->ip = xen_regs->eip;
> + regs->cs = xen_regs->cs;
> +}
> +
> +irqreturn_t xen_pmu_irq_handler(int irq, void *dev_id)
> +{
> + int ret = IRQ_NONE;
> + struct pt_regs regs;
> + struct xenpmu_data *xenpmu_data = per_cpu(xenpmu_shared,
> + smp_processor_id());
> +
> + xen_convert_regs(&xenpmu_data->regs, ®s);
> + if (x86_pmu.handle_irq(®s))
> + ret = IRQ_HANDLED;
> +
> + return ret;
> +}
> +
> +int xen_pmu_init(int cpu)
> +{
> + int ret = 0;
> + struct xenpmu_params xp;
> + unsigned long pfn;
> + struct xenpmu_data *xenpmu_data;
> +
> + BUILD_BUG_ON(sizeof(struct xenpmu_data) > PAGE_SIZE);
> + xenpmu_data = vmalloc(PAGE_SIZE);
> + if (!xenpmu_data) {
> + ret = -ENOMEM;
> + goto fail;
> + }
> + pfn = vmalloc_to_pfn((char *)xenpmu_data);
> +
> + xp.mfn = pfn_to_mfn(pfn);
> + xp.vcpu = cpu;
> + xp.version.maj = XENPMU_VER_MAJ;
> + xp.version.min = XENPMU_VER_MIN;
> + ret = HYPERVISOR_xenpmu_op(XENPMU_init, &xp);
> + if (ret)
> + goto fail;
> +
> + per_cpu(xenpmu_shared, cpu) = xenpmu_data;
> +
> + if (cpu == 0)
> + perf_register_guest_info_callbacks(&xen_guest_cbs);
> +
> + return ret;
> +
> +fail:
> + vfree(xenpmu_data);
> + return ret;
> +}
> +
> +void xen_pmu_finish(int cpu)
> +{
> + struct xenpmu_params xp;
> +
> + xp.vcpu = cpu;
> + xp.version.maj = XENPMU_VER_MAJ;
> + xp.version.min = XENPMU_VER_MIN;
> +
> + (void)HYPERVISOR_xenpmu_op(XENPMU_finish, &xp);
> +
> + vfree(per_cpu(xenpmu_shared, cpu));
> + per_cpu(xenpmu_shared, cpu) = NULL;
I think you are missing:
perf_unregister_guest_info_callbacks when this is the bootup CPU.
And you should probably move this around to be:
if (cpu == 0 && num_online_cpus() == 1)
perf_unregister_guest_info_callbacks(..)
per_cpu(xenpmu_shared, cpu) = NULL;
vfree(per_cpu(xenpmu_shared, cpu))
?
> +}
> diff --git a/arch/x86/xen/pmu.h b/arch/x86/xen/pmu.h
> new file mode 100644
> index 0000000..51de7d2
> --- /dev/null
> +++ b/arch/x86/xen/pmu.h
> @@ -0,0 +1,12 @@
> +#ifndef __XEN_PMU_H
> +#define __XEN_PMU_H
> +
> +#include <xen/interface/xenpmu.h>
> +
> +irqreturn_t xen_pmu_irq_handler(int irq, void *dev_id);
> +int xen_pmu_init(int cpu);
> +void xen_pmu_finish(int cpu);
> +
> +DECLARE_PER_CPU(struct xenpmu_data *, xenpmu_shared);
> +
> +#endif /* __XEN_PMU_H */
> diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
> index ca92754..17a88d1 100644
> --- a/arch/x86/xen/smp.c
> +++ b/arch/x86/xen/smp.c
> @@ -26,6 +26,7 @@
>
> #include <xen/interface/xen.h>
> #include <xen/interface/vcpu.h>
> +#include <xen/interface/xenpmu.h>
>
> #include <asm/xen/interface.h>
> #include <asm/xen/hypercall.h>
> @@ -37,6 +38,7 @@
> #include <xen/hvc-console.h>
> #include "xen-ops.h"
> #include "mmu.h"
> +#include "pmu.h"
>
> cpumask_var_t xen_cpu_initialized_map;
>
> @@ -49,6 +51,7 @@ static DEFINE_PER_CPU(struct xen_common_irq, xen_callfunc_irq) = { .irq = -1 };
> static DEFINE_PER_CPU(struct xen_common_irq, xen_callfuncsingle_irq) = { .irq = -1 };
> static DEFINE_PER_CPU(struct xen_common_irq, xen_irq_work) = { .irq = -1 };
> static DEFINE_PER_CPU(struct xen_common_irq, xen_debug_irq) = { .irq = -1 };
> +static DEFINE_PER_CPU(struct xen_common_irq, xen_pmu_irq) = { .irq = -1 };
>
> static irqreturn_t xen_call_function_interrupt(int irq, void *dev_id);
> static irqreturn_t xen_call_function_single_interrupt(int irq, void *dev_id);
> @@ -139,11 +142,18 @@ static void xen_smp_intr_free(unsigned int cpu)
> kfree(per_cpu(xen_irq_work, cpu).name);
> per_cpu(xen_irq_work, cpu).name = NULL;
> }
> +
> + if (per_cpu(xen_pmu_irq, cpu).irq >= 0) {
> + unbind_from_irqhandler(per_cpu(xen_pmu_irq, cpu).irq, NULL);
> + per_cpu(xen_pmu_irq, cpu).irq = -1;
> + kfree(per_cpu(xen_pmu_irq, cpu).name);
> + per_cpu(xen_pmu_irq, cpu).name = NULL;
> + }
> };
> static int xen_smp_intr_init(unsigned int cpu)
> {
> int rc;
> - char *resched_name, *callfunc_name, *debug_name;
> + char *resched_name, *callfunc_name, *debug_name, *pmu_name;
>
> resched_name = kasprintf(GFP_KERNEL, "resched%d", cpu);
> rc = bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR,
> @@ -209,6 +219,18 @@ static int xen_smp_intr_init(unsigned int cpu)
> per_cpu(xen_irq_work, cpu).irq = rc;
> per_cpu(xen_irq_work, cpu).name = callfunc_name;
>
> + if (per_cpu(xenpmu_shared, cpu)) {
> + pmu_name = kasprintf(GFP_KERNEL, "pmu%d", cpu);
> + rc = bind_virq_to_irqhandler(VIRQ_XENPMU, cpu,
> + xen_pmu_irq_handler,
> + IRQF_PERCPU|IRQF_NOBALANCING,
> + pmu_name, NULL);
> + if (rc < 0)
> + goto fail;
> + per_cpu(xen_pmu_irq, cpu).irq = rc;
> + per_cpu(xen_pmu_irq, cpu).name = pmu_name;
> + }
> +
> return 0;
>
> fail:
> @@ -307,6 +329,9 @@ static void __init xen_smp_prepare_cpus(unsigned int max_cpus)
> }
> set_cpu_sibling_map(0);
>
> + if (xen_pmu_init(0))
> + pr_err("Could not initialize VPMU for VCPU 0\n");
> +
> if (xen_smp_intr_init(0))
> BUG();
>
> @@ -427,6 +452,9 @@ static int xen_cpu_up(unsigned int cpu, struct task_struct *idle)
> /* Just in case we booted with a single CPU. */
> alternatives_enable_smp();
>
> + if (xen_pmu_init(cpu))
> + pr_err("Could not initialize VPMU for VCPU %u\n", cpu);
> +
> rc = xen_smp_intr_init(cpu);
> if (rc)
> return rc;
> @@ -468,6 +496,7 @@ static void xen_cpu_die(unsigned int cpu)
> xen_smp_intr_free(cpu);
> xen_uninit_lock_cpu(cpu);
> xen_teardown_timer(cpu);
> + xen_pmu_finish(cpu);
> }
>
> static void xen_play_dead(void) /* used only with HOTPLUG_CPU */
That all looks OK
next prev parent reply other threads:[~2013-09-23 13:26 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-09-10 15:31 [PATCH v1 0/5] xen/PMU: PMU support for Xen PV guests Boris Ostrovsky
2013-09-10 15:31 ` Boris Ostrovsky
2013-09-10 15:31 ` [PATCH v1 1/5] xen: xensyms support Boris Ostrovsky
2013-09-10 15:31 ` Boris Ostrovsky
2013-09-11 8:17 ` Jan Beulich
2013-09-11 8:17 ` Jan Beulich
2013-09-10 15:31 ` [PATCH v1 2/5] xen/PMU: Sysfs interface for setting Xen PMU mode Boris Ostrovsky
2013-09-23 13:17 ` Konrad Rzeszutek Wilk
2013-09-23 13:17 ` Konrad Rzeszutek Wilk
2013-09-23 14:05 ` Boris Ostrovsky
2013-09-23 14:05 ` Boris Ostrovsky
2013-09-10 15:31 ` Boris Ostrovsky
2013-09-10 15:31 ` [PATCH v1 3/5] xen/PMU: Initialization code for Xen PMU Boris Ostrovsky
2013-09-10 15:31 ` Boris Ostrovsky
2013-09-23 13:26 ` Konrad Rzeszutek Wilk
2013-09-23 13:26 ` Konrad Rzeszutek Wilk [this message]
2013-09-23 14:18 ` Boris Ostrovsky
2013-09-23 14:18 ` Boris Ostrovsky
2013-09-23 14:25 ` Boris Ostrovsky
2013-09-23 14:25 ` [Xen-devel] " Boris Ostrovsky
2013-09-10 15:31 ` [PATCH v1 4/5] xen/PMU: Add support for PMU registes on PV guests Boris Ostrovsky
2013-09-10 15:31 ` Boris Ostrovsky
2013-09-23 13:28 ` Konrad Rzeszutek Wilk
2013-09-23 13:28 ` Konrad Rzeszutek Wilk
2013-09-10 15:31 ` [PATCH v1 5/5] xen/PMU: Cache MSR accesses during interrupt handling Boris Ostrovsky
2013-09-23 13:29 ` Konrad Rzeszutek Wilk
2013-09-23 13:29 ` Konrad Rzeszutek Wilk
2013-09-10 15:31 ` Boris Ostrovsky
2013-09-11 9:33 ` [PATCH v1 0/5] xen/PMU: PMU support for Xen PV guests David Vrabel
2013-09-11 9:33 ` [Xen-devel] " David Vrabel
2013-09-11 14:26 ` Boris Ostrovsky
2013-09-11 14:26 ` Boris Ostrovsky
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130923132618.GD3175@phenom.dumpdata.com \
--to=konrad.wilk@oracle.com \
--cc=JBeulich@suse.com \
--cc=boris.ostrovsky@oracle.com \
--cc=david.vrabel@citrix.com \
--cc=linux-kernel@vger.kernel.org \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.