From: "stephane eranian" <eranian@googlemail.com>
To: "Metzger, Markus T" <markus.t.metzger@intel.com>
Cc: "Markus Metzger" <markus.t.metzger@googlemail.com>,
"Ingo Molnar" <mingo@elte.hu>, "Andi Kleen" <andi@firstfloor.org>,
"Andrew Morton" <akpm@linux-foundation.org>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: Re: debugctl msr
Date: Wed, 19 Nov 2008 18:13:11 +0100 [thread overview]
Message-ID: <7c86c4470811190913u743706abgafff3b0f0e3559ec@mail.gmail.com> (raw)
In-Reply-To: <928CFBE8E7CB0040959E56B4EA41A77E08F10CB1@irsmsx504.ger.corp.intel.com>
[-- Attachment #1: Type: text/plain, Size: 4430 bytes --]
Markus,
Speaking of locking, I also ran into another issue with ds_lock.
Perfmon sessions each have a spinlock for access serialization, but to
prevent from PMU and timers interrupts, interrupts are masked. Thus,
when perfmon
calls ds.c, interrupts are masked. That means that we lock/unlock ds_lock
with interrupts disabled. The lock checker triggered when I ran a simple perfmon
session and warned of possible lock inversion. Suppose you are coming from the
ptrace code into ds. You grab ds_lock, but the same process is also running
a perfmon session with PEBS and a counter overflows, you get into
the PMU interrupt handler which may call into ds.c and try to grab the ds_lock.
For that reason, I think you should use a
spin_lock_irqsave/spin_unlock_irqrestore
pairs to protect your ds context.
I found another issue with ds_release(). You need to skip freeing the
buffer when it
is NULL, i.e., was already allocated by caller of ds_request_pebs().
I have attached a diff for the ds.c interface. It disables
ds_validate_access(), export
the PEBS functions to modules, fixes ds_release().
As for handling the interrupt is ds.c, not clear how this could work
with current perfmon.
I don't know how this work on the BTS side. On the PMU side, that is not because
I am using PEBS, that I don't also use other counters as well. Longer
term, I think, there
needs to be a lower-level PMU interrupt service where you would
register a callback
on PMU interrupts. It would be used by NMI watchdog, perfmon,
Oprofile, ds.c. Callbacks
would be chained, just like what happens with the NMI interrupt
handler. Such service would
go hand in hand with a centralized PMU MSR allocator which would
provide safe sharing of
the PMU registers between different subsystems (there is a primitive
version of this already
today in perfctr-watchdog.c).
On Wed, Nov 19, 2008 at 4:47 PM, Metzger, Markus T
<markus.t.metzger@intel.com> wrote:
>>-----Original Message-----
>>From: stephane eranian [mailto:eranian@googlemail.com]
>>Sent: Mittwoch, 19. November 2008 14:00
>>To: Metzger, Markus T
>>Cc: Markus Metzger; Ingo Molnar; Andi Kleen; Andrew Morton;
>>linux-kernel@vger.kernel.org
>>Subject: Re: debugctl msr
>>
>
>>I had to hack ds.c some more to make forward progress with PEBS. First
>>of all my PEBS code is
>>in a kernel module, so all PEBS functions have to be exported.
>>Furhtermore, I need a
>>ds_get_pebs_thres() and ds_set_pebs_thres() calls.
>
> I'm having a deja vu. We had this discussion before. You reported those
> issues and I fixed them. Same for the PEBS size; and Andi Kleen asked
> to exclude ds.c from the build instead of guarding the .c file and to
> use the mm semaphore in ds_allocate_buffer().
>
> That thread ended in the multiplexing discussion and my fixes never got in.
> I'll send a patch covering those problems next week.
>
>
> Regarding access to the interrupt threshold, we never completed
> our discussion.
> If we look towards multiplexing, ds.c has to handle interrupts and
> copy the trace to the various users - at least for BTS.
> I will pull some of the BTS handling from ptrace into ds.c - ds.c needs
> to be able to disable BTS recording for overflow handling and we would
> not want this knowledge in two different places.
>
> I would add those functions now to proceed with the perfmon2 adaptation
> and later remove them again and put overflow handling into ds.c
>
> I'll send a separate patch for those.
>
>
>>But the one key problem is ds_validate_access(). I had to disable this
>>function.
>
> I agree that this is too ptrace centric.
>
> It works fine for the ptrace bts extenstion since ptrace has similar
> restrictions, already.
>
> A better choice would be to return an opaque handle.
>
>
> regards,
> markus.
> ---------------------------------------------------------------------
> Intel GmbH
> Dornacher Strasse 1
> 85622 Feldkirchen/Muenchen Germany
> Sitz der Gesellschaft: Feldkirchen bei Muenchen
> Geschaeftsfuehrer: Douglas Lusk, Peter Gleissner, Hannes Schwaderer
> Registergericht: Muenchen HRB 47456 Ust.-IdNr.
> VAT Registration No.: DE129385895
> Citibank Frankfurt (BLZ 502 109 00) 600119052
>
> This e-mail and any attachments may contain confidential material for
> the sole use of the intended recipient(s). Any review or distribution
> by others is strictly prohibited. If you are not the intended
> recipient, please contact the sender and delete all copies.
>
>
[-- Attachment #2: ds.diff --]
[-- Type: application/octet-stream, Size: 4067 bytes --]
diff --git a/arch/x86/include/asm/ds.h b/arch/x86/include/asm/ds.h
index 72c5a19..fed664a 100644
--- a/arch/x86/include/asm/ds.h
+++ b/arch/x86/include/asm/ds.h
@@ -78,6 +78,7 @@ extern int ds_release_pebs(struct task_struct *task);
*/
extern int ds_get_bts_index(struct task_struct *task, size_t *pos);
extern int ds_get_pebs_index(struct task_struct *task, size_t *pos);
+extern int ds_get_pebs_thres(struct task_struct *task, size_t *pos);
/*
* Return the (array) index one record beyond the end of the array.
diff --git a/arch/x86/kernel/ds.c b/arch/x86/kernel/ds.c
index 2b69994..5882014 100644
--- a/arch/x86/kernel/ds.c
+++ b/arch/x86/kernel/ds.c
@@ -30,7 +30,7 @@
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/mm.h>
-
+#include <linux/module.h>
/*
* The configuration for a particular DS hardware implementation.
@@ -131,7 +131,7 @@ static inline int ds_validate_access(struct ds_context *context,
{
if (!context)
return -EPERM;
-
+return 0;
if (context->owner[qual] == current)
return 0;
@@ -467,6 +467,7 @@ int ds_request_pebs(struct task_struct *task, void *base, size_t size,
{
return ds_request(task, base, size, ovfl, ds_pebs);
}
+EXPORT_SYMBOL(ds_request_pebs);
static int ds_release(struct task_struct *task, enum ds_qualifier qual)
{
@@ -478,12 +479,14 @@ static int ds_release(struct task_struct *task, enum ds_qualifier qual)
if (error < 0)
goto out;
- kfree(context->buffer[qual]);
- context->buffer[qual] = NULL;
+ if (context->buffer[qual]) {
+ kfree(context->buffer[qual]);
+ context->buffer[qual] = NULL;
- current->mm->total_vm -= context->pages[qual];
- current->mm->locked_vm -= context->pages[qual];
- context->pages[qual] = 0;
+ current->mm->total_vm -= context->pages[qual];
+ current->mm->locked_vm -= context->pages[qual];
+ context->pages[qual] = 0;
+ }
context->owner[qual] = NULL;
/*
@@ -506,6 +509,7 @@ int ds_release_pebs(struct task_struct *task)
{
return ds_release(task, ds_pebs);
}
+EXPORT_SYMBOL(ds_release_pebs);
static int ds_get_index(struct task_struct *task, size_t *pos,
enum ds_qualifier qual)
@@ -539,6 +543,32 @@ int ds_get_pebs_index(struct task_struct *task, size_t *pos)
{
return ds_get_index(task, pos, ds_pebs);
}
+EXPORT_SYMBOL(ds_get_pebs_index);
+
+int ds_get_pebs_thres(struct task_struct *task, size_t *pos)
+{
+ struct ds_context *context;
+ unsigned long base, thr;
+ int error;
+
+ context = ds_get_context(task);
+ error = ds_validate_access(context, ds_pebs);
+ if (error < 0)
+ goto out;
+
+ base = ds_get(context->ds, ds_pebs, ds_buffer_base);
+ thr = ds_get(context->ds, ds_pebs, ds_interrupt_threshold);
+
+ error = ((thr - base) / ds_cfg.sizeof_rec[ds_pebs]);
+ if (pos)
+ *pos = error;
+ return error;
+ out:
+ ds_put_context(context);
+ return error;
+}
+EXPORT_SYMBOL(ds_get_pebs_thres);
+
static int ds_get_end(struct task_struct *task, size_t *pos,
enum ds_qualifier qual)
@@ -572,6 +602,7 @@ int ds_get_pebs_end(struct task_struct *task, size_t *pos)
{
return ds_get_end(task, pos, ds_pebs);
}
+EXPORT_SYMBOL(ds_get_pebs_end);
static int ds_access(struct task_struct *task, size_t index,
const void **record, enum ds_qualifier qual)
@@ -747,6 +778,7 @@ int ds_reset_pebs(struct task_struct *task)
{
return ds_reset_or_clear(task, ds_pebs, /* clear = */ 0);
}
+EXPORT_SYMBOL(ds_reset_pebs);
int ds_clear_bts(struct task_struct *task)
{
@@ -796,6 +828,7 @@ int ds_set_pebs_reset(struct task_struct *task, u64 value)
ds_put_context(context);
return error;
}
+EXPORT_SYMBOL(ds_set_pebs_reset);
static const struct ds_configuration ds_cfg_var = {
.sizeof_ds = sizeof(long) * 12,
@@ -804,10 +837,10 @@ static const struct ds_configuration ds_cfg_var = {
.sizeof_rec[ds_pebs] = sizeof(long) * 10
};
static const struct ds_configuration ds_cfg_64 = {
- .sizeof_ds = 8 * 12,
+ .sizeof_ds = 8 * 9,
.sizeof_field = 8,
.sizeof_rec[ds_bts] = 8 * 3,
- .sizeof_rec[ds_pebs] = 8 * 10
+ .sizeof_rec[ds_pebs] = 8 * 18
};
static inline void
next prev parent reply other threads:[~2008-11-19 17:13 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <7c86c4470810300753v7d377092qbcd266178d8e7338@mail.gmail.com>
[not found] ` <029E5BE7F699594398CA44E3DDF5544402AB2C50@swsmsx413.ger.corp.intel.com>
[not found] ` <7c86c4470811040822i6745bee6mbe451284d76549be@mail.gmail.com>
[not found] ` <7c86c4470811050505j678c6929if00cceda2af8cb17@mail.gmail.com>
[not found] ` <7c86c4470811050711w3753232fk1030fb00259a7b8@mail.gmail.com>
[not found] ` <029E5BE7F699594398CA44E3DDF5544402AB350E@swsmsx413.ger.corp.intel.com>
[not found] ` <7c86c4470811060249g62666885nbaa559c1777217a0@mail.gmail.com>
[not found] ` <1226236327.6104.4.camel@raistlin>
[not found] ` <7c86c4470811111411k754887a8ic9b63163928157a6@mail.gmail.com>
[not found] ` <491A812D.9010208@gmail.com>
2008-11-12 10:10 ` stephane eranian
2008-11-12 10:59 ` Metzger, Markus T
2008-11-13 14:50 ` stephane eranian
2008-11-14 14:41 ` Metzger, Markus T
2008-11-14 21:10 ` stephane eranian
2008-11-15 10:01 ` Markus Metzger
2008-11-18 22:00 ` stephane eranian
2008-11-19 12:14 ` Metzger, Markus T
2008-11-19 12:59 ` stephane eranian
2008-11-19 15:47 ` Metzger, Markus T
2008-11-19 17:13 ` stephane eranian [this message]
2008-11-19 18:27 ` Markus Metzger
2008-11-19 19:20 ` stephane eranian
2008-11-19 20:53 ` stephane eranian
2008-11-19 22:26 ` Markus Metzger
2008-11-20 21:19 ` stephane eranian
2008-11-21 8:22 ` Metzger, Markus T
2008-11-21 8:47 ` stephane eranian
2008-11-21 8:58 ` Metzger, Markus T
2008-11-21 13:38 ` stephane eranian
2008-11-21 15:27 ` stephane eranian
2008-11-21 16:10 ` Metzger, Markus T
2008-11-21 16:33 ` stephane eranian
2008-11-21 22:47 ` stephane eranian
2008-11-22 9:51 ` Markus Metzger
2008-11-23 22:31 ` stephane eranian
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=7c86c4470811190913u743706abgafff3b0f0e3559ec@mail.gmail.com \
--to=eranian@googlemail.com \
--cc=akpm@linux-foundation.org \
--cc=andi@firstfloor.org \
--cc=eranian@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=markus.t.metzger@googlemail.com \
--cc=markus.t.metzger@intel.com \
--cc=mingo@elte.hu \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®