lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Thu,  6 Feb 2014 12:50:32 +0200
From:	Alexander Shishkin <alexander.shishkin@...ux.intel.com>
To:	Peter Zijlstra <a.p.zijlstra@...llo.nl>
Cc:	Ingo Molnar <mingo@...hat.com>, linux-kernel@...r.kernel.org,
	Frederic Weisbecker <fweisbec@...il.com>,
	Mike Galbraith <efault@....de>,
	Paul Mackerras <paulus@...ba.org>,
	Stephane Eranian <eranian@...gle.com>,
	Andi Kleen <ak@...ux.intel.com>,
	Adrian Hunter <adrian.hunter@...el.com>,
	Matt Fleming <matt.fleming@...el.com>,
	Alexander Shishkin <alexander.shishkin@...ux.intel.com>
Subject: [PATCH v1 09/11] x86: perf: intel_pt: Add core dump functionality

Intel Processor Trace (PT) data can be used in process core dumps. This
is done by implementing itrace code dump related hooks that configure and
output trace data to a core file. The driver will also include the list
of PT capabilities in itrace core dump notes so that the decoder can make
assumptions about the binary stream.

Signed-off-by: Alexander Shishkin <alexander.shishkin@...ux.intel.com>
---
 arch/x86/kernel/cpu/intel_pt.h            |  2 +
 arch/x86/kernel/cpu/perf_event_intel_pt.c | 74 +++++++++++++++++++++++++++++++
 2 files changed, 76 insertions(+)

diff --git a/arch/x86/kernel/cpu/intel_pt.h b/arch/x86/kernel/cpu/intel_pt.h
index dd69092..befde1f 100644
--- a/arch/x86/kernel/cpu/intel_pt.h
+++ b/arch/x86/kernel/cpu/intel_pt.h
@@ -84,6 +84,8 @@ enum pt_capabilities {
 struct pt_pmu {
 	struct itrace_pmu	itrace;
 	u32			caps[4 * PT_CPUID_LEAVES];
+	char			*capstr;
+	unsigned int		caplen;
 };
 
 /**
diff --git a/arch/x86/kernel/cpu/perf_event_intel_pt.c b/arch/x86/kernel/cpu/perf_event_intel_pt.c
index af1482d..cb03594 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_pt.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_pt.c
@@ -24,6 +24,7 @@
 #include <linux/slab.h>
 #include <linux/debugfs.h>
 #include <linux/device.h>
+#include <linux/coredump.h>
 
 #include <asm-generic/sizes.h>
 #include <asm/perf_event.h>
@@ -88,6 +89,34 @@ static void pt_cap_set(enum pt_capabilities cap, u32 val)
 	pt_pmu.caps[idx] = (val << shift) & cd->mask;
 }
 
+/**
+ * pt_cap_string - format PT capabilities into an ascii string
+ *
+ * We need to include PT capabilities in the core dump note so that the
+ * decoder knows what to expect in the binary stream.
+ */
+static void pt_cap_string(void)
+{
+	char *capstr;
+	int pos, i;
+
+	capstr = kzalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!capstr)
+		return;
+
+	for (i = 0, pos = 0; i < ARRAY_SIZE(pt_caps) && pos < PAGE_SIZE; i++) {
+		pos += snprintf(&capstr[pos], PAGE_SIZE - pos, "%s:%x%c",
+				pt_caps[i].name, pt_cap_get(i),
+				i == ARRAY_SIZE(pt_caps) - 1 ? 0 : ',');
+	}
+
+	if (pt_pmu.capstr)
+		kfree(pt_pmu.capstr);
+
+	pt_pmu.capstr = capstr;
+	pt_pmu.caplen = pos;
+}
+
 static ssize_t pt_cap_show(struct device *cdev,
 			   struct device_attribute *attr,
 			   char *buf)
@@ -114,6 +143,7 @@ static ssize_t pt_cap_store(struct device *cdev,
 		return -EINVAL;
 
 	pt_cap_set(cap, new);
+	pt_cap_string();
 	return size;
 }
 
@@ -179,6 +209,7 @@ static int __init pt_pmu_hw_init(void)
 		attrs[i] = &de_attrs[i].attr.attr;
 	}
 
+	pt_cap_string();
 	pt_cap_group.attrs = attrs;
 	return 0;
 
@@ -1070,6 +1101,46 @@ out:
 	pt_event_start(event, 0);
 }
 
+static size_t pt_trace_core_size(struct perf_event *event)
+{
+	return pt_pmu.caplen;
+}
+
+static unsigned int pt_core_copy(void *data, const void *src,
+				 unsigned int len)
+{
+	struct coredump_params *cprm = data;
+
+	if (dump_emit(cprm, src, len))
+		return 0;
+
+	return len;
+}
+
+static void pt_trace_core_output(struct coredump_params *cprm,
+				 struct perf_event *event,
+				 unsigned long len)
+{
+	struct pt_buffer *buf;
+	u64 from, to;
+	int ret;
+
+	buf = itrace_priv(event);
+
+	if (!dump_emit(cprm, pt_pmu.capstr, pt_pmu.caplen))
+		return;
+
+	to = local64_read(&buf->head);
+	if (to < len)
+		from = buf->size + to - len;
+	else
+		from = to - len;
+
+	ret = pt_buffer_output(buf, from, to, pt_core_copy, cprm);
+	if (ret < 0)
+		pr_warn("%s: failed to copy trace data\n", __func__);
+}
+
 static __init int pt_init(void)
 {
 	int ret, cpu;
@@ -1097,6 +1168,9 @@ static __init int pt_init(void)
 	pt_pmu.itrace.free_buffer	= pt_buffer_itrace_free;
 	pt_pmu.itrace.sample_trace	= pt_trace_sampler_trace;
 	pt_pmu.itrace.sample_output	= pt_trace_sampler_output;
+	pt_pmu.itrace.core_size		= pt_trace_core_size;
+	pt_pmu.itrace.core_output	= pt_trace_core_output;
+	pt_pmu.itrace.coredump_config	= RTIT_CTL_TSC_EN | RTIT_CTL_DISRETC;
 	pt_pmu.itrace.name		= "intel_pt";
 	ret = itrace_pmu_register(&pt_pmu.itrace);
 
-- 
1.8.5.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists