All of lore.kernel.org
 help / color / mirror / Atom feed
From: Boris Ostrovsky <boris.ostrovsky@oracle.com>
To: Konrad Rzeszutek Wilk <konrad.wilk@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 10:18:37 -0400	[thread overview]
Message-ID: <52404DBD.6010607@oracle.com> (raw)
In-Reply-To: <20130923132618.GD3175@phenom.dumpdata.com>

On 09/23/2013 09:26 AM, Konrad Rzeszutek Wilk wrote:
> 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.

This is interface header, am I allowed to do those sorts of things there?

Also, *theoretically* other performance-measuring tools can use this 
framework, expect for perf-specific things like callbacks and the 
handler call. So maybe I should put CONFIG_PERF_EVENTS in pmu.c?

>>   
>>   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, &regs);
>> +	if (x86_pmu.handle_irq(&regs))
>> +		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.

But there is always at least one CPU running, so I think I should keep 
the callbacks. The only reason I have 'if (cpu == 0)' when I register 
the callbacks is because I only want to do this once and when we are 
coming up cpu 0 is always the boot cpu (right?).

>
> 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))

Then I'd be calling vfree(NULL), wouldn't I?

-boris


  parent reply	other threads:[~2013-09-23 14:16 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-10 15:31 ` 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 ` [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 14:18     ` Boris Ostrovsky
2013-09-23 14:18     ` Boris Ostrovsky [this message]
2013-09-23 14:25       ` [Xen-devel] " Boris Ostrovsky
2013-09-23 14:25       ` Boris Ostrovsky
2013-09-23 13:26   ` Konrad Rzeszutek Wilk
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-10 15:31 ` Boris Ostrovsky
2013-09-23 13:29   ` Konrad Rzeszutek Wilk
2013-09-23 13:29   ` Konrad Rzeszutek Wilk
2013-09-11  9:33 ` [Xen-devel] [PATCH v1 0/5] xen/PMU: PMU support for Xen PV guests David Vrabel
2013-09-11 14:26   ` Boris Ostrovsky
2013-09-11 14:26   ` [Xen-devel] " Boris Ostrovsky
2013-09-11  9:33 ` David Vrabel

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=52404DBD.6010607@oracle.com \
    --to=boris.ostrovsky@oracle.com \
    --cc=JBeulich@suse.com \
    --cc=david.vrabel@citrix.com \
    --cc=konrad.wilk@oracle.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.