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:	Fri, 16 Dec 2011 17:12:19 +0100
From:	Hans Rosenfeld <hans.rosenfeld@....com>
To:	<mingo@...e.hu>
CC:	<hpa@...or.com>, <tglx@...utronix.de>, <suresh.b.siddha@...el.com>,
	<eranian@...gle.com>, <brgerst@...il.com>,
	<robert.richter@....com>, <Andreas.Herrmann3@....com>,
	<x86@...nel.org>, <linux-kernel@...r.kernel.org>,
	<bebl@...eta.org>, Benjamin Block <benjamin.block@....com>,
	Hans Rosenfeld <hans.rosenfeld@....com>
Subject: [RFC 1/5] x86, perf: Implement software-activation of lwp

From: Benjamin Block <benjamin.block@....com>

Adds activation of lwp for ring3-software. With this patch and
scheduler-support (xsave-patches done by Hans Rosenfeld) a
userspace-application can use the lwp-instructions (llwpcb,
slwpcb, ..) to activate lwp.

Support for the threshold-interrupt is not given and thus the
corresponding bits are not set. It is therefore unavailable for
userspace-applications.

Signed-off-by: Benjamin Block <benjamin.block@....com>
Signed-off-by: Hans Rosenfeld <hans.rosenfeld@....com>
---
 arch/x86/include/asm/msr-index.h         |    1 +
 arch/x86/kernel/cpu/Makefile             |    2 +-
 arch/x86/kernel/cpu/perf_event_amd_lwp.c |  138 ++++++++++++++++++++++++++++++
 3 files changed, 140 insertions(+), 1 deletions(-)
 create mode 100644 arch/x86/kernel/cpu/perf_event_amd_lwp.c

diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 2d9cf3c..557a6fd 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -136,6 +136,7 @@
 #define MSR_AMD64_IBSDCPHYSAD		0xc0011039
 #define MSR_AMD64_IBSCTL		0xc001103a
 #define MSR_AMD64_IBSBRTARGET		0xc001103b
+#define MSR_AMD64_LWP_CFG		0xc0000105
 #define MSR_AMD64_LWP_CBADDR		0xc0000106
 
 /* Fam 15h MSRs */
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
index 6042981..9973465 100644
--- a/arch/x86/kernel/cpu/Makefile
+++ b/arch/x86/kernel/cpu/Makefile
@@ -20,7 +20,7 @@ obj-$(CONFIG_X86_32)	+= bugs.o
 obj-$(CONFIG_X86_64)	+= bugs_64.o
 
 obj-$(CONFIG_CPU_SUP_INTEL)		+= intel.o
-obj-$(CONFIG_CPU_SUP_AMD)		+= amd.o
+obj-$(CONFIG_CPU_SUP_AMD)		+= amd.o perf_event_amd_lwp.o
 obj-$(CONFIG_CPU_SUP_CYRIX_32)		+= cyrix.o
 obj-$(CONFIG_CPU_SUP_CENTAUR)		+= centaur.o
 obj-$(CONFIG_CPU_SUP_TRANSMETA_32)	+= transmeta.o
diff --git a/arch/x86/kernel/cpu/perf_event_amd_lwp.c b/arch/x86/kernel/cpu/perf_event_amd_lwp.c
new file mode 100644
index 0000000..9aa9a91
--- /dev/null
+++ b/arch/x86/kernel/cpu/perf_event_amd_lwp.c
@@ -0,0 +1,138 @@
+#include <linux/perf_event.h>
+#include <linux/module.h>
+
+#include <asm/cpufeature.h>
+#include <asm/processor.h>
+
+/* masks only the events as of spec r3.08 (lwp v1) */
+#define LWP_EVENT_MASK		0x7E
+
+struct lwp_capabilities {
+#define LWP_CAPS_LWP			0
+#define LWP_CAPS_THRESHOLD		31
+	unsigned long supported_events;
+	unsigned long available_events;
+
+	u8 size_lwpcb;
+	u8 size_event;
+	u8 size_max_event_id;
+	u8 size_event_offset;
+
+#define LWP_CAPS_FILTER_BRANCH		28
+#define LWP_CAPS_FILTER_IP		29
+#define LWP_CAPS_FILTER_CACHE_LVL	30
+#define LWP_CAPS_FILTER_CACHE_LAT	31
+	unsigned long features;
+};
+
+union lwp_cfg_msr {
+	struct {
+		u32 allowed_events;
+		u8 core_id;
+		u8 interrupt_vector;
+		u16 reserved;
+	} cfg;
+	u64 msr_value;
+};
+
+static struct lwp_capabilities	lwp_caps;
+
+static void get_lwp_caps(struct lwp_capabilities *caps)
+{
+	u32 sizes;
+
+	memset(caps, 0, sizeof(*caps));
+	cpuid(0x8000001C, (u32 *) &caps->available_events, &sizes,
+			(u32 *) &caps->features,
+			(u32 *) &caps->supported_events);
+
+	caps->size_lwpcb = (u8) sizes;
+	caps->size_event = (u8) (sizes >> 0x8);
+	caps->size_max_event_id = (u8) (sizes >> 0x10);
+	caps->size_event_offset = (u8) (sizes >> 0x18);
+}
+
+static void lwp_start_cpu(void *c)
+{
+	struct lwp_capabilities *caps = (struct lwp_capabilities *) c;
+	union lwp_cfg_msr msr;
+
+	msr.msr_value = 0;
+	/* allow supported events of lwpv1 [1..6] */
+	msr.cfg.allowed_events |= ((u32) caps->supported_events) &
+					LWP_EVENT_MASK;
+	/*
+	 * The value showing up in the core-id field of a event-record.
+	 * I currently only 8 bits wide.
+	 */
+	msr.cfg.core_id = (u8) smp_processor_id();
+
+	/*
+	 * We currently do not support the threshold-interrupt so
+	 * bit 31 and [40..47] of msr.msr_value keep 0
+	 *
+	 * msr.cfg.allowed_events |= (1U << 31);
+	 * msr.cfg.interrupt_vector = xxx;
+	 */
+
+	wrmsrl(MSR_AMD64_LWP_CFG, msr.msr_value);
+}
+
+static int __cpuinit
+lwp_cpu_notifier(struct notifier_block *self, unsigned long action,
+		void *hcpu)
+{
+	switch (action & ~CPU_TASKS_FROZEN) {
+	case CPU_STARTING:
+		lwp_start_cpu(&lwp_caps);
+		break;
+	default:
+		return NOTIFY_DONE;
+	}
+
+	return NOTIFY_OK;
+}
+
+static __init int amd_lwp_init(void)
+{
+	if (!static_cpu_has(X86_FEATURE_LWP))
+		return -ENODEV;
+
+	/* read the _supported_ events */
+	get_lwp_caps(&lwp_caps);
+
+	/* we currently only support lwp v1; spec r3.08 */
+	if (!test_bit(LWP_CAPS_LWP, &lwp_caps.supported_events) ||
+			(((lwp_caps.features >> 9) & 0x7F) != 1))
+		return -ENODEV;
+
+	if (!test_bit(LWP_CAPS_THRESHOLD, &lwp_caps.supported_events))
+		return -ENODEV;
+
+	get_online_cpus();
+
+	barrier();
+
+	perf_cpu_notifier(lwp_cpu_notifier);
+	smp_call_function(lwp_start_cpu, &lwp_caps, 1);
+
+	put_online_cpus();
+
+	/*
+	 * The values returned by cpuid are corresponding to the values in
+	 * MSR_AMD64_LWP_CFG and determine what events are available. As we
+	 * have just changed MSR_AMD64_LWP_CFG, we have to re-read the lwp_caps.
+	 */
+	get_lwp_caps(&lwp_caps);
+
+	printk(KERN_INFO "perf: AMD LWP caps: "
+			"[%#lx],[%#hhx|%#hhx|%#hhx|%#hhx],[%#lx],[%#lx]",
+			lwp_caps.available_events, lwp_caps.size_lwpcb,
+			lwp_caps.size_event, lwp_caps.size_max_event_id,
+			lwp_caps.size_event_offset, lwp_caps.features,
+			lwp_caps.supported_events);
+
+	return 0;
+}
+
+device_initcall(amd_lwp_init);
-- 
1.7.7


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

Powered by Openwall GNU/*/Linux Powered by OpenVZ