linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/3] x86 msr: msr goto extension support
@ 2014-07-31  9:41 kan.liang
  2014-07-31  9:41 ` [PATCH 2/3] x86 perf: Protect LBR msrs accessing against potential #GP kan.liang
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: kan.liang @ 2014-07-31  9:41 UTC (permalink / raw)
  To: peterz; +Cc: andi, alexander.shishkin, linux-kernel, Kan Liang

From: Kan Liang <kan.liang@intel.com>

Currently, {rd,wr}msrl_safe can handle the exception which caused by accessing
specific MSR.
However, it will introduce extra conditional branch for testing errors. That
will impact the "fast" path's performance.
The newly implemented {rd,wr}msrl_goto function can not only handle the
exception which caused by accessing specific MSR,
but also takes advantage of the asm goto extension to eliminate the impact of
performance.

The asm goto extension is supported by GCC 4.5 and later versions. If the
compiler doesn't support goto extension, _safe will be used to replace _goto.

Signed-off-by: Kan Liang <kan.liang@intel.com>
---
 arch/x86/include/asm/msr.h      | 60 +++++++++++++++++++++++++++++++++++++++++
 arch/x86/include/asm/paravirt.h | 18 +++++++++++++
 2 files changed, 78 insertions(+)

diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h
index de36f22..55438da 100644
--- a/arch/x86/include/asm/msr.h
+++ b/arch/x86/include/asm/msr.h
@@ -203,6 +203,66 @@ do {                                                            \
 
 #define rdtscpll(val, aux) (val) = native_read_tscp(&(aux))
 
+#ifdef CC_HAVE_ASM_GOTO
+
+/*
+ * The _goto version is rdmsrl/wrmsrl with exception handling
+ * The advantage (than _safe) is that it can directly jump in the
+ * exception handling code, and never test in the "fast" path.
+ *
+ * Since _goto doesn't support output, try to protect the output
+ * registers by clobbers, and process the registers immediately.
+ */
+#define rdmsrl_goto(msr, result, fail_label)			\
+do {								\
+	DECLARE_ARGS(val, low, high);				\
+	asm_volatile_goto("2: rdmsr\n"				\
+			"1:\n\t"				\
+			_ASM_EXTABLE(2b, %l[fail_label])	\
+			: /* No outputs. */			\
+			: "c" (msr)				\
+			: "%rax", "%rdx"			\
+			: fail_label);				\
+	asm volatile (""					\
+			: EAX_EDX_RET(val, low, high)		\
+			: );					\
+	result = EAX_EDX_VAL(val, low, high);			\
+} while (0)
+
+#define wrmsrl_goto(msr, val, fail_label)			\
+do {								\
+	unsigned low, high;					\
+	low = (u32)val;						\
+	high = (u32)(val >> 32);				\
+	asm_volatile_goto("2: wrmsr\n"				\
+			"1:\n\t"				\
+			_ASM_EXTABLE(2b, %l[fail_label])	\
+			: /* No outputs. */			\
+			: "c" (msr), "a" (low), "d" (high)	\
+			: "memory"				\
+			: fail_label);				\
+} while (0)
+
+#else /* CC_HAVE_ASM_GOTO */
+
+/*
+ * If compiler doesn't support asm goto, use _safe to replace
+ */
+#define rdmsrl_goto(msr, result, fail_label)			\
+do {								\
+	if (rdmsrl_safe(msr, &result))				\
+		goto fail_label;				\
+} while (0)
+
+#define wrmsrl_goto(msr, result, fail_label)			\
+do {								\
+	if (wrmsr_safe((msr), (u32)(result),			\
+				(u32)((result) >> 32)))		\
+		goto fail_label;				\
+} while (0)
+
+#endif  /* CC_HAVE_ASM_GOTO */
+
 #endif	/* !CONFIG_PARAVIRT */
 
 #define wrmsrl_safe(msr, val) wrmsr_safe((msr), (u32)(val),		\
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
index cd6e161..1fa18a1 100644
--- a/arch/x86/include/asm/paravirt.h
+++ b/arch/x86/include/asm/paravirt.h
@@ -174,6 +174,24 @@ static inline int rdmsrl_safe(unsigned msr, unsigned long long *p)
 	return err;
 }
 
+/*
+ * TODO: paravirt _goto doesn't support yet.
+ * But the implementation as below doesn't impact the current performance,
+ * since rdmsrl/wrmsrl eventually call _safe version in paravirt now.
+ */
+#define rdmsrl_goto(msr, result, fail_label)			\
+do {								\
+	if (rdmsrl_safe(msr, &result))				\
+		goto fail_label;				\
+} while (0)
+
+#define wrmsrl_goto(msr, result, fail_label)			\
+do {								\
+	if (wrmsr_safe((msr), (u32)(result),			\
+				(u32)((result) >> 32)))		\
+		goto fail_label;				\
+} while (0)
+
 static inline u64 paravirt_read_tsc(void)
 {
 	return PVOP_CALL0(u64, pv_cpu_ops.read_tsc);
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2014-08-02  5:27 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-07-31  9:41 [PATCH 1/3] x86 msr: msr goto extension support kan.liang
2014-07-31  9:41 ` [PATCH 2/3] x86 perf: Protect LBR msrs accessing against potential #GP kan.liang
2014-08-01  7:38   ` Peter Zijlstra
2014-08-01  7:44     ` Peter Zijlstra
2014-08-01 13:21       ` Andi Kleen
2014-08-01 18:50         ` Peter Zijlstra
2014-08-02  5:27           ` Ingo Molnar
2014-07-31  9:41 ` [PATCH 3/3] x86 perf: Protect LBR and BTS enabling kan.liang
2014-07-31 21:05 ` [PATCH 1/3] x86 msr: msr goto extension support Andy Lutomirski
2014-08-01  8:05   ` Peter Zijlstra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).