Patches contributed by Eötvös Lorand University
commit f65cb45cba63f249458b669aa67069eabc37b2f5
Author: Ingo Molnar <mingo@elte.hu>
Date: Tue Dec 16 13:40:44 2008 +0100
perfcounters: flush on setuid exec
Pavel Machek pointed out that performance counters should be flushed
when crossing protection domains on setuid execution.
Reported-by: Pavel Machek <pavel@suse.cz>
Acked-by: Pavel Machek <pavel@suse.cz>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/fs/exec.c b/fs/exec.c
index ec5df9a38313..d5165d899a49 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -33,6 +33,7 @@
#include <linux/string.h>
#include <linux/init.h>
#include <linux/pagemap.h>
+#include <linux/perf_counter.h>
#include <linux/highmem.h>
#include <linux/spinlock.h>
#include <linux/key.h>
@@ -1017,6 +1018,13 @@ int flush_old_exec(struct linux_binprm * bprm)
set_dumpable(current->mm, suid_dumpable);
}
+ /*
+ * Flush performance counters when crossing a
+ * security domain:
+ */
+ if (!get_dumpable(current->mm))
+ perf_counter_exit_task(current);
+
/* An exec changes our domain. We are no longer part of the thread
group */
commit c3895b01e80d120e8d19435f7cb1fa4c60c4e269
Merge: 3c68b4a8071f 968ea6d80e39
Author: Ingo Molnar <mingo@elte.hu>
Date: Tue Dec 16 12:24:38 2008 +0100
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-ingo into cpus4096
commit 3c68b4a8071fb11d905570d9b0e23034adc6c2bb
Merge: 8299608f140a 5279585ff2be
Author: Ingo Molnar <mingo@elte.hu>
Date: Tue Dec 16 12:24:26 2008 +0100
Merge branch 'linus' into cpus4096
commit 9dfc3bc7d21864d47797d64b8d531d4dbbc0b618
Merge: da485e0cb167 cbc34ed1ac36 2bed8446819a ffc2238af843
Author: Ingo Molnar <mingo@elte.hu>
Date: Tue Dec 16 12:03:38 2008 +0100
Merge branches 'tracing/fastboot', 'tracing/ftrace', 'tracing/function-graph-tracer' and 'tracing/hw-branch-tracing' into tracing/core
commit 0cc0c027d4e028632933f1be2dc4cd730358183b
Author: Ingo Molnar <mingo@elte.hu>
Date: Sun Dec 14 23:20:36 2008 +0100
perfcounters: release CPU context when exiting task counters
If counters are exiting via do_exit() not via filp close, then
the CPU context needs to be released - otherwise future percpu
counter creations might fail.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c
index 539fa8283a06..16396e9406fa 100644
--- a/kernel/perf_counter.c
+++ b/kernel/perf_counter.c
@@ -1273,8 +1273,19 @@ __perf_counter_exit_task(struct task_struct *child,
local_irq_disable();
perf_flags = hw_perf_save_disable();
- if (child_counter->state == PERF_COUNTER_STATE_ACTIVE)
+ if (child_counter->state == PERF_COUNTER_STATE_ACTIVE) {
+ struct perf_cpu_context *cpuctx;
+
+ cpuctx = &__get_cpu_var(perf_cpu_context);
+
child_counter->hw_ops->hw_perf_counter_disable(child_counter);
+ child_counter->state = PERF_COUNTER_STATE_INACTIVE;
+ child_counter->oncpu = -1;
+
+ cpuctx->active_oncpu--;
+ child_ctx->nr_active--;
+ }
+
list_del_init(&child_counter->list_entry);
hw_perf_restore(perf_flags);
@@ -1539,4 +1550,3 @@ static int __init perf_counter_sysfs_init(void)
&perfclass_attr_group);
}
device_initcall(perf_counter_sysfs_init);
-
commit 029af8c753bb5a7432aa1ed38bf61fe2c2f66d17
Merge: 75f224cf7700 5279585ff2be
Author: Ingo Molnar <mingo@elte.hu>
Date: Sun Dec 14 21:58:33 2008 +0100
Merge branch 'linus' into perfcounters/core
commit 75f224cf7700ed6006574dc3f2efa29860727570
Author: Ingo Molnar <mingo@elte.hu>
Date: Sun Dec 14 21:58:46 2008 +0100
perfcounters: fix lapic initialization
Fix non-working NMI sampling in certain bootup scenarios.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/arch/x86/kernel/cpu/perf_counter.c b/arch/x86/kernel/cpu/perf_counter.c
index 6d30f603b62c..8a154bd7ba94 100644
--- a/arch/x86/kernel/cpu/perf_counter.c
+++ b/arch/x86/kernel/cpu/perf_counter.c
@@ -557,10 +557,10 @@ void __init init_hw_perf_counters(void)
printk(KERN_INFO "... bit_width: %d\n", eax.split.bit_width);
printk(KERN_INFO "... mask_length: %d\n", eax.split.mask_length);
+ perf_counters_initialized = true;
+
perf_counters_lapic_init(0);
register_die_notifier(&perf_counter_nmi_notifier);
-
- perf_counters_initialized = true;
}
static void x86_perf_counter_read(struct perf_counter *counter)
commit 088e2852c858159d47f71ee8da38e0fb1b21f806
Author: Ingo Molnar <mingo@elte.hu>
Date: Sun Dec 14 20:21:00 2008 +0100
perfcounters, x86: fix sw counters on non-PMC CPUs
Make perf_max_counters default to at least 1 - this allows the sw
counters to be used.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c
index 59c52f9ee431..539fa8283a06 100644
--- a/kernel/perf_counter.c
+++ b/kernel/perf_counter.c
@@ -25,7 +25,7 @@
*/
DEFINE_PER_CPU(struct perf_cpu_context, perf_cpu_context);
-int perf_max_counters __read_mostly;
+int perf_max_counters __read_mostly = 1;
static int perf_reserved_percpu __read_mostly;
static int perf_overcommit __read_mostly = 1;
commit 2b9ff0db19b5e2c77000b7201525f9c3d6e8328d
Author: Ingo Molnar <mingo@elte.hu>
Date: Sun Dec 14 18:36:30 2008 +0100
perfcounters: fix non-intel-perfmon CPUs
Do not write MSR_CORE_PERF_GLOBAL_CTRL on CPUs where it does not exist.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/arch/x86/kernel/cpu/perf_counter.c b/arch/x86/kernel/cpu/perf_counter.c
index 5afae13d8d59..6d30f603b62c 100644
--- a/arch/x86/kernel/cpu/perf_counter.c
+++ b/arch/x86/kernel/cpu/perf_counter.c
@@ -157,6 +157,9 @@ static int __hw_perf_counter_init(struct perf_counter *counter)
void hw_perf_enable_all(void)
{
+ if (unlikely(!perf_counters_initialized))
+ return;
+
wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, perf_counter_mask, 0);
}
@@ -164,14 +167,21 @@ u64 hw_perf_save_disable(void)
{
u64 ctrl;
+ if (unlikely(!perf_counters_initialized))
+ return 0;
+
rdmsrl(MSR_CORE_PERF_GLOBAL_CTRL, ctrl);
wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, 0, 0);
+
return ctrl;
}
EXPORT_SYMBOL_GPL(hw_perf_save_disable);
void hw_perf_restore(u64 ctrl)
{
+ if (unlikely(!perf_counters_initialized))
+ return;
+
wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, ctrl, 0);
}
EXPORT_SYMBOL_GPL(hw_perf_restore);
commit e06c61a879910869aa5bf3f8f634abfee1a7bebc
Author: Ingo Molnar <mingo@elte.hu>
Date: Sun Dec 14 14:44:31 2008 +0100
perfcounters: add nr-of-faults counter
Impact: add new feature, new sw counter
Add a counter that counts the number of pagefaults a task
is experiencing.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c
index fb11e351e44e..59c52f9ee431 100644
--- a/kernel/perf_counter.c
+++ b/kernel/perf_counter.c
@@ -888,6 +888,54 @@ static const struct hw_perf_counter_ops perf_ops_task_clock = {
.hw_perf_counter_read = task_clock_perf_counter_read,
};
+static u64 get_page_faults(void)
+{
+ struct task_struct *curr = current;
+
+ return curr->maj_flt + curr->min_flt;
+}
+
+static void page_faults_perf_counter_update(struct perf_counter *counter)
+{
+ u64 prev, now;
+ s64 delta;
+
+ prev = atomic64_read(&counter->hw.prev_count);
+ now = get_page_faults();
+
+ atomic64_set(&counter->hw.prev_count, now);
+
+ delta = now - prev;
+ if (WARN_ON_ONCE(delta < 0))
+ delta = 0;
+
+ atomic64_add(delta, &counter->count);
+}
+
+static void page_faults_perf_counter_read(struct perf_counter *counter)
+{
+ page_faults_perf_counter_update(counter);
+}
+
+static void page_faults_perf_counter_enable(struct perf_counter *counter)
+{
+ /*
+ * page-faults is a per-task value already,
+ * so we dont have to clear it on switch-in.
+ */
+}
+
+static void page_faults_perf_counter_disable(struct perf_counter *counter)
+{
+ page_faults_perf_counter_update(counter);
+}
+
+static const struct hw_perf_counter_ops perf_ops_page_faults = {
+ .hw_perf_counter_enable = page_faults_perf_counter_enable,
+ .hw_perf_counter_disable = page_faults_perf_counter_disable,
+ .hw_perf_counter_read = page_faults_perf_counter_read,
+};
+
static u64 get_context_switches(void)
{
struct task_struct *curr = current;
@@ -994,6 +1042,9 @@ sw_perf_counter_init(struct perf_counter *counter)
case PERF_COUNT_TASK_CLOCK:
hw_ops = &perf_ops_task_clock;
break;
+ case PERF_COUNT_PAGE_FAULTS:
+ hw_ops = &perf_ops_page_faults;
+ break;
case PERF_COUNT_CONTEXT_SWITCHES:
hw_ops = &perf_ops_context_switches;
break;