Skip to contentSkip to conversation

x86 entry stuff, maybe for 4.4

PATCH Superseded Andy Lutomirski 6 participants 18 messages Nov 6, 2015 – Nov 9, 2015

Subsystems (4)

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore

Andy Lutomirski

author maintainer
#0 lore raw

cover x86 entry stuff, maybe for 4.4

The first patch is a bit ugly, but it fixes a bug that could affect lockdep. That bug is very minor and may not be observable at all, but I don't really want to bet on it.

The other three are intended to fix a performance regression in the entry rework that Frédéric objected to. They're much later than I'd like to have sent them for 4.4, but they're kind-of sort-of regression fixes, so maybe they're still okay. They would certainly need careful review, though.

I don't have a great benchmark for them. The biggest impact is likely to be to user page fault latency on CONFIG_CONTEXT_TRACKING=y kernels (i.e. distro kernels) that don't use context tracking (i.e. most users).

Andy Lutomirski (4):
x86/entry/64: Fix irqflag tracing wrt context tracking
context_tracking: Switch to new static_branch API x86/asm: Add asm macros for static keys/jump labels x86/entry/64: Bypass enter_from_user_mode on non-context-tracking
boots

 arch/x86/entry/calling.h               | 15 ++++++++++
 arch/x86/entry/entry_64.S              | 19 ++++++++-----
 arch/x86/include/asm/jump_label.h      | 52 ++++++++++++++++++++++++++++------
 include/linux/context_tracking_state.h |  4 +--
 kernel/context_tracking.c              |  4 +--
 5 files changed, 75 insertions(+), 19 deletions(-)
Signature · 1 line
2.4.3
author maintainer
#1 lore raw

PATCH 1/4 x86/entry/64: Fix irqflag tracing wrt context tracking

Paolo pointed out that enter_from_user_mode could be called while irqflags were traced as though IRQs were on.

In principle, this could confuse lockdep. It doesn't cause any problems that I've seen in any configuration, but if I build with CONFIG_DEBUG_LOCKDEP=y, enable a nohz_full CPU, and add code like:

	if (irqs_disabled()) {
		spin_lock(&something);
		spin_unlock(&something);
	}

to the top of enter_from_user_mode, then lockdep will complain without this fix. It seems that lockdep's irqflags sanity checks are too weak to detect this bug without forcing the issue.

This patch adds one byte to normal kernels, and it's IMO a bit ugly. I haven't spotted a better way to do this yet, though. The issue is that we can't do TRACE_IRQS_OFF until after SWAPGS (if needed), but we're also supposed to do it before calling C code.

An alternative approach would be to call trace_hardirqs_off in enter_from_user_mode. That would be less code and would not bloat normal kernels at all, but it would be harder to see how the code worked.

---
 arch/x86/entry/entry_64.S | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)
arch/x86/entry/entry_64.S +10 -1
index 53616ca03244..f585df24ab3d 100644
@@ -509,6 +509,14 @@ END(irq_entries_start)
 	 * tracking that we're in kernel mode.
 	 */
 	SWAPGS
+
+	/*
+	 * IRQs are off.  NB: this trace call is duplicated.  That's
+	 * okay -- it's idempotent and it's irrelevant for performance as
+	 * it's a no-op unless CONFIG_DEBUG_LOCKDEP=y.
+	 */
+	TRACE_IRQS_OFF
+
 #ifdef CONFIG_CONTEXT_TRACKING
 	call enter_from_user_mode
 #endif
@@ -1049,12 +1057,13 @@ ENTRY(error_entry)
 	SWAPGS
 
 .Lerror_entry_from_usermode_after_swapgs:
+	TRACE_IRQS_OFF
 #ifdef CONFIG_CONTEXT_TRACKING
 	call enter_from_user_mode
 #endif
+	ret
 
 .Lerror_entry_done:
-
 	TRACE_IRQS_OFF
 	ret
 
Signature · 1 line
2.4.3
Reviewed-by on v1 1/4
#2 lore raw

Re: [PATCH 1/4] x86/entry/64: Fix irqflag tracing wrt context tracking

Quoted 21 lines · Andy Lutomirski

Paolo pointed out that enter_from_user_mode could be called while irqflags were traced as though IRQs were on.

In principle, this could confuse lockdep. It doesn't cause any problems that I've seen in any configuration, but if I build with CONFIG_DEBUG_LOCKDEP=y, enable a nohz_full CPU, and add code like:

	if (irqs_disabled()) {
		spin_lock(&something);
		spin_unlock(&something);
	}

to the top of enter_from_user_mode, then lockdep will complain without this fix. It seems that lockdep's irqflags sanity checks are too weak to detect this bug without forcing the issue.

This patch adds one byte to normal kernels, and it's IMO a bit ugly. I haven't spotted a better way to do this yet, though. The issue is that we can't do TRACE_IRQS_OFF until after SWAPGS (if needed), but we're also supposed to do it before calling C code.

Quoted 6 lines

An alternative approach would be to call trace_hardirqs_off in enter_from_user_mode. That would be less code and would not bloat normal kernels at all, but it would be harder to see how the code worked.

maintainer
#3 lore raw

Re: [PATCH 1/4] x86/entry/64: Fix irqflag tracing wrt context tracking

In reply to Andy Lutomirski
Quoted 12 lines · Andy Lutomirski

Paolo pointed out that enter_from_user_mode could be called while irqflags were traced as though IRQs were on.

In principle, this could confuse lockdep. It doesn't cause any problems that I've seen in any configuration, but if I build with CONFIG_DEBUG_LOCKDEP=y, enable a nohz_full CPU, and add code like:

	if (irqs_disabled()) {
		spin_lock(&something);
		spin_unlock(&something);
	}
Quoted 8 lines

to the top of enter_from_user_mode, then lockdep will complain without this fix. It seems that lockdep's irqflags sanity checks are too weak to detect this bug without forcing the issue.

This patch adds one byte to normal kernels, and it's IMO a bit ugly. I haven't spotted a better way to do this yet, though. The issue is that we can't do TRACE_IRQS_OFF until after SWAPGS (if needed), but we're also supposed to do it before calling C code.

I would not mind to have that explanation in the code itself so that people don't scratch heads why the duplicated TRACE_IRQS_OFF call.

Signature · 4 lines
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
#4 lore raw

Re: [PATCH 1/4] x86/entry/64: Fix irqflag tracing wrt context tracking

Quoted 17 lines · Borislav Petkov
Quoted 16 lines · Andy Lutomirski

Paolo pointed out that enter_from_user_mode could be called while irqflags were traced as though IRQs were on.

In principle, this could confuse lockdep. It doesn't cause any problems that I've seen in any configuration, but if I build with CONFIG_DEBUG_LOCKDEP=y, enable a nohz_full CPU, and add code like:

      if (irqs_disabled()) {
              spin_lock(&something);
              spin_unlock(&something);
      }

to the top of enter_from_user_mode, then lockdep will complain without this fix. It seems that lockdep's irqflags sanity checks are too weak to detect this bug without forcing the issue.

Quoted 8 lines
Quoted 4 lines

This patch adds one byte to normal kernels, and it's IMO a bit ugly. I haven't spotted a better way to do this yet, though. The issue is that we can't do TRACE_IRQS_OFF until after SWAPGS (if needed), but we're also supposed to do it before calling C code.

I would not mind to have that explanation in the code itself so that people don't scratch heads why the duplicated TRACE_IRQS_OFF call.

Done for v2.

--Andy

author maintainer
#5 lore raw

PATCH 2/4 context_tracking: Switch to new static_branch API

In reply to Andy Lutomirski

This is much less error-prone than the old code.

---
 include/linux/context_tracking_state.h | 4 ++--
 kernel/context_tracking.c              | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)
include/linux/context_tracking_state.h +2 -2
index ee956c528fab..1d34fe68f48a 100644
@@ -22,12 +22,12 @@ struct context_tracking {
 };
 
 #ifdef CONFIG_CONTEXT_TRACKING
-extern struct static_key context_tracking_enabled;
+extern struct static_key_false context_tracking_enabled;
 DECLARE_PER_CPU(struct context_tracking, context_tracking);
 
 static inline bool context_tracking_is_enabled(void)
 {
-	return static_key_false(&context_tracking_enabled);
+	return static_branch_unlikely(&context_tracking_enabled);
 }
 
 static inline bool context_tracking_cpu_is_enabled(void)
kernel/context_tracking.c +2 -2
index 0a495ab35bc7..d0fb09e40784 100644
@@ -24,7 +24,7 @@
 #define CREATE_TRACE_POINTS
 #include <trace/events/context_tracking.h>
 
-struct static_key context_tracking_enabled = STATIC_KEY_INIT_FALSE;
+DEFINE_STATIC_KEY_FALSE(context_tracking_enabled);
 EXPORT_SYMBOL_GPL(context_tracking_enabled);
 
 DEFINE_PER_CPU(struct context_tracking, context_tracking);
@@ -191,7 +191,7 @@ void __init context_tracking_cpu_set(int cpu)
 
 	if (!per_cpu(context_tracking.active, cpu)) {
 		per_cpu(context_tracking.active, cpu) = true;
-		static_key_slow_inc(&context_tracking_enabled);
+		static_branch_inc(&context_tracking_enabled);
 	}
 
 	if (initialized)
Signature · 1 line
2.4.3
author maintainer
#7 lore raw

PATCH 3/4 x86/asm: Add asm macros for static keys/jump labels

In reply to Andy Lutomirski

Unfortunately, these only work if HAVE_JUMP_LABEL. In principle, we could do some serious surgery on the core jump label infrastructure to keep the patch infrastructure available on x86 on all builds, but that's probably not worth it.

---
 arch/x86/include/asm/jump_label.h | 52 +++++++++++++++++++++++++++++++++------
 1 file changed, 44 insertions(+), 8 deletions(-)
arch/x86/include/asm/jump_label.h +44 -8
index 5daeca3d0f9e..da275c1825f5 100644
@@ -1,13 +1,6 @@
 #ifndef _ASM_X86_JUMP_LABEL_H
 #define _ASM_X86_JUMP_LABEL_H
 
-#ifndef __ASSEMBLY__
-
-#include <linux/stringify.h>
-#include <linux/types.h>
-#include <asm/nops.h>
-#include <asm/asm.h>
-
 #define JUMP_LABEL_NOP_SIZE 5
 
 #ifdef CONFIG_X86_64
@@ -16,6 +9,14 @@
 # define STATIC_KEY_INIT_NOP GENERIC_NOP5_ATOMIC
 #endif
 
+#include <asm/asm.h>
+#include <asm/nops.h>
+
+#ifndef __ASSEMBLY__
+
+#include <linux/stringify.h>
+#include <linux/types.h>
+
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
 	asm_volatile_goto("1:"
@@ -59,5 +60,40 @@ struct jump_entry {
 	jump_label_t key;
 };
 
-#endif  /* __ASSEMBLY__ */
+#else	/* __ASSEMBLY__ */
+
+.macro STATIC_JUMP_IF_TRUE target, key, def
+.Lstatic_jump_\@:
+	.if \def
+	/* Equivalent to "jmp.d32 \target" */
+	.byte		0xe9
+	.long		\target - .Lstatic_jump_after_\@
+.Lstatic_jump_after_\@:
+	.else
+	.byte		STATIC_KEY_INIT_NOP
+	.endif
+	.pushsection __jump_table, "aw"
+	_ASM_ALIGN
+	_ASM_PTR	.Lstatic_jump_\@, \target, \key
+	.popsection
+.endm
+
+.macro STATIC_JUMP_IF_FALSE target, key, def
+.Lstatic_jump_\@:
+	.if \def
+	.byte		STATIC_KEY_INIT_NOP
+	.else
+	/* Equivalent to "jmp.d32 \target" */
+	.byte		0xe9
+	.long		\target - .Lstatic_jump_after_\@
+.Lstatic_jump_after_\@:
+	.endif
+	.pushsection __jump_table, "aw"
+	_ASM_ALIGN
+	_ASM_PTR	.Lstatic_jump_\@, \target, \key + 1
+	.popsection
+.endm
+
+#endif	/* __ASSEMBLY__ */
+
 #endif
Signature · 1 line
2.4.3
#8 lore raw

Re: [PATCH 3/4] x86/asm: Add asm macros for static keys/jump labels

Quoted 4 lines · Andy Lutomirski

Unfortunately, these only work if HAVE_JUMP_LABEL. In principle, we could do some serious surgery on the core jump label infrastructure to keep the patch infrastructure available on x86 on all builds, but that's probably not worth it.

No, but we can be smarter about it. There is nothing which that asm entry code needs from linux/jump_label.h and asm/jump_label.h execpt STATIC_KEY_INIT_NOP. Something like the patch below should do the trick.

Thanks,

tglx

arch/x86/entry/calling.h +19 -0
Index: tip/arch/x86/entry/calling.h
===================================================================
@@ -232,3 +232,22 @@ For 32-bit we have the following convent
 
 #endif /* CONFIG_X86_64 */
 
+/* ASM jump label support */
+#if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL)
+#include <asm/jump_label.h>
+
+	.macro STATIC_CALL_IF_ENABLED fun, key
+	1:
+	jmp.d32		2f
+	call		fun
+	.pushsection __jump_table, "aw"
+	_ASM_ALIGN
+	_ASM_PTR	1b, 2f, \key
+	.popsection
+	2:
+	.endm
+#else
+	.macro STATIC_CALL_IF_ENABLED fun, key
+	call		fun
+	.endm
+#endif
arch/x86/entry/entry_64.S +2 -2
Index: tip/arch/x86/entry/entry_64.S
===================================================================
@@ -510,7 +510,7 @@ END(irq_entries_start)
 	 */
 	SWAPGS
 #ifdef CONFIG_CONTEXT_TRACKING
-	call enter_from_user_mode
+	STATIC_CALL_IF_ENABLED enter_from_user_mode, context_tracking_enabled
 #endif
 
 1:
@@ -1050,7 +1050,7 @@ ENTRY(error_entry)
 
 .Lerror_entry_from_usermode_after_swapgs:
 #ifdef CONFIG_CONTEXT_TRACKING
-	call enter_from_user_mode
+	STATIC_CALL_IF_ENABLED enter_from_user_mode, context_tracking_enabled
 #endif
 
 .Lerror_entry_done:
arch/x86/include/asm/jump_label.h +5 -4
Index: tip/arch/x86/include/asm/jump_label.h
===================================================================
@@ -1,10 +1,6 @@
 #ifndef _ASM_X86_JUMP_LABEL_H
 #define _ASM_X86_JUMP_LABEL_H
 
-#ifndef __ASSEMBLY__
-
-#include <linux/stringify.h>
-#include <linux/types.h>
 #include <asm/nops.h>
 #include <asm/asm.h>
 
@@ -16,6 +12,11 @@
 # define STATIC_KEY_INIT_NOP GENERIC_NOP5_ATOMIC
 #endif
 
+#ifndef __ASSEMBLY__
+
+#include <linux/stringify.h>
+#include <linux/types.h>
+
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
 	asm_volatile_goto("1:"
#9 lore raw

Re: [PATCH 3/4] x86/asm: Add asm macros for static keys/jump labels

Quoted 8 lines · Thomas Gleixner
Quoted 4 lines · Andy Lutomirski

Unfortunately, these only work if HAVE_JUMP_LABEL. In principle, we could do some serious surgery on the core jump label infrastructure to keep the patch infrastructure available on x86 on all builds, but that's probably not worth it.

Quoted 4 lines

No, but we can be smarter about it. There is nothing which that asm entry code needs from linux/jump_label.h and asm/jump_label.h execpt STATIC_KEY_INIT_NOP. Something like the patch below should do the trick.

I like some bits of this. See below.

Quoted 10 lines

Thanks,

tglx

Index: tip/arch/x86/entry/calling.h
===================================================================

arch/x86/entry/calling.h For 32-bit we have the following convent · line 239

Quoted 8 lines
arch/x86/entry/calling.h +5 -0
@@ -232,3 +232,22 @@ For 32-bit we have the following convent
 
 #endif /* CONFIG_X86_64 */
 
+/* ASM jump label support */
+#if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL)
+#include <asm/jump_label.h>
+
+       .macro STATIC_CALL_IF_ENABLED fun, key

I think we still need the "def" parameter. But maybe the "static call" is a good idea. (By giving 'def' a default value or omitting it entirely, it's too easy not to think about it, and that's a huge historical source of breakage and it's a good part of the reason for the new improved C API. At least these days I *think* we'll diagnose the problem on bootup instead of waiting for random breakage later.)

arch/x86/entry/calling.h For 32-bit we have the following convent · line 241

Quoted 2 lines
arch/x86/entry/calling.h +2 -0
+       1:
+       jmp.d32         2f

Old binutils will choke on this. But maybe no one has jump labels and old binutils.

arch/x86/entry/calling.h For 32-bit we have the following convent · line 252

Quoted 11 lines
arch/x86/entry/calling.h +11 -0
+       call            fun
+       .pushsection __jump_table, "aw"
+       _ASM_ALIGN
+       _ASM_PTR        1b, 2f, \key
+       .popsection
+       2:
+       .endm
+#else
+       .macro STATIC_CALL_IF_ENABLED fun, key
+       call            fun
+       .endm

This could result in errors down the road, since this macro is really "static call if enabled or if the kernel is built without jump labels". enter_from_user_mode is special because it's already a no-op if context tracking is off, but I'm not sure that this oddity should leak into more generic code.

arch/x86/entry/entry_64.S END(irq_entries_start) · line 514

Quoted 12 lines
arch/x86/entry/calling.h +1 -0
+#endif

Index: tip/arch/x86/entry/entry_64.S
===================================================================

arch/x86/entry/entry_64.S +1 -1
@@ -510,7 +510,7 @@ END(irq_entries_start)
         */
        SWAPGS
 #ifdef CONFIG_CONTEXT_TRACKING
-       call enter_from_user_mode
+       STATIC_CALL_IF_ENABLED enter_from_user_mode, context_tracking_enabled
 #endif

This doesn't get rid of the ifdeffery, which I thought was a nice feature of my patch.

--Andy

#10 lore raw

Re: [PATCH 3/4] x86/asm: Add asm macros for static keys/jump labels

Quoted 13 lines · Andy Lutomirski

arch/x86/entry/calling.h For 32-bit we have the following convent · line 239

Quoted 5 lines · Thomas Gleixner
arch/x86/entry/calling.h +5 -0
+/* ASM jump label support */
+#if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL)
+#include <asm/jump_label.h>
+
+       .macro STATIC_CALL_IF_ENABLED fun, key

I think we still need the "def" parameter. But maybe the "static call" is a good idea. (By giving 'def' a default value or omitting it entirely, it's too easy not to think about it, and that's a huge historical source of breakage and it's a good part of the reason for the new improved C API. At least these days I *think* we'll diagnose the problem on bootup instead of waiting for random breakage later.)

Ok. That's easy to add :)

Quoted 5 lines

arch/x86/entry/calling.h For 32-bit we have the following convent · line 241

Quoted 2 lines
arch/x86/entry/calling.h +2 -0
+       1:
+       jmp.d32         2f

Old binutils will choke on this. But maybe no one has jump labels and old binutils.

Good question.

Quoted 12 lines

arch/x86/entry/calling.h For 32-bit we have the following convent · line 252

Quoted 11 lines
arch/x86/entry/calling.h +11 -0
+       call            fun
+       .pushsection __jump_table, "aw"
+       _ASM_ALIGN
+       _ASM_PTR        1b, 2f, \key
+       .popsection
+       2:
+       .endm
+#else
+       .macro STATIC_CALL_IF_ENABLED fun, key
+       call            fun
+       .endm
Quoted 5 lines

This could result in errors down the road, since this macro is really "static call if enabled or if the kernel is built without jump labels". enter_from_user_mode is special because it's already a no-op if context tracking is off, but I'm not sure that this oddity should leak into more generic code.

Hmm. Maybe we need a better name for this macro.

Quoted 7 lines
Quoted 7 lines

+#endif
Index: tip/arch/x86/entry/entry_64.S
===================================================================

arch/x86/entry/entry_64.S +0 -0
@@ -510,7 +510,7 @@ END(irq_entries_start)
         */
Quoted 8 lines

arch/x86/entry/entry_64.S END(irq_entries_start) · line 514

Quoted 5 lines
arch/x86/entry/entry_64.S +1 -1
        SWAPGS
 #ifdef CONFIG_CONTEXT_TRACKING
-       call enter_from_user_mode
+       STATIC_CALL_IF_ENABLED enter_from_user_mode, context_tracking_enabled
 #endif

This doesn't get rid of the ifdeffery, which I thought was a nice feature of my patch.

Right. I was just too lazy to add another macro :)

My main point was to avoid the extra stuff for !HAVE_JUMP_LABEL and hide this in a header file.

Thanks,

tglx

#11 lore raw

Re: [PATCH 3/4] x86/asm: Add asm macros for static keys/jump labels

Quoted 61 lines · Thomas Gleixner
Quoted 13 lines · Andy Lutomirski

arch/x86/entry/calling.h For 32-bit we have the following convent · line 239

Quoted 5 lines · Thomas Gleixner
arch/x86/entry/calling.h +5 -0
+/* ASM jump label support */
+#if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL)
+#include <asm/jump_label.h>
+
+       .macro STATIC_CALL_IF_ENABLED fun, key

I think we still need the "def" parameter. But maybe the "static call" is a good idea. (By giving 'def' a default value or omitting it entirely, it's too easy not to think about it, and that's a huge historical source of breakage and it's a good part of the reason for the new improved C API. At least these days I *think* we'll diagnose the problem on bootup instead of waiting for random breakage later.)

Ok. That's easy to add :)

Quoted 5 lines

arch/x86/entry/calling.h For 32-bit we have the following convent · line 241

Quoted 2 lines
arch/x86/entry/calling.h +2 -0
+       1:
+       jmp.d32         2f

Old binutils will choke on this. But maybe no one has jump labels and old binutils.

Good question.

Quoted 12 lines

arch/x86/entry/calling.h For 32-bit we have the following convent · line 252

Quoted 11 lines
arch/x86/entry/calling.h +11 -0
+       call            fun
+       .pushsection __jump_table, "aw"
+       _ASM_ALIGN
+       _ASM_PTR        1b, 2f, \key
+       .popsection
+       2:
+       .endm
+#else
+       .macro STATIC_CALL_IF_ENABLED fun, key
+       call            fun
+       .endm
Quoted 5 lines

This could result in errors down the road, since this macro is really "static call if enabled or if the kernel is built without jump labels". enter_from_user_mode is special because it's already a no-op if context tracking is off, but I'm not sure that this oddity should leak into more generic code.

Hmm. Maybe we need a better name for this macro.

Quoted 7 lines
Quoted 7 lines

+#endif
Index: tip/arch/x86/entry/entry_64.S
===================================================================

arch/x86/entry/entry_64.S +0 -0
@@ -510,7 +510,7 @@ END(irq_entries_start)
         */
Quoted 8 lines

arch/x86/entry/entry_64.S END(irq_entries_start) · line 514

Quoted 5 lines
arch/x86/entry/entry_64.S +1 -1
        SWAPGS
 #ifdef CONFIG_CONTEXT_TRACKING
-       call enter_from_user_mode
+       STATIC_CALL_IF_ENABLED enter_from_user_mode, context_tracking_enabled
 #endif

This doesn't get rid of the ifdeffery, which I thought was a nice feature of my patch.

Quoted 5 lines

Right. I was just too lazy to add another macro :)

My main point was to avoid the extra stuff for !HAVE_JUMP_LABEL and hide this in a header file.

True. But I hid it in a header file, too, but it was just a different header file -- I had it all hidden away as CALL_ENTER_FROM_USER_MODE.

--Andy

#12 lore raw

Re: [PATCH 3/4] x86/asm: Add asm macros for static keys/jump labels

Quoted 3 lines · Andy Lutomirski

On Sat, Nov 7, 2015 at 8:58 AM, Thomas Gleixner <[email protected]> wrote:
True. But I hid it in a header file, too, but it was just a different header file -- I had it all hidden away as CALL_ENTER_FROM_USER_MODE.

It probably does not really make a difference :)

I just got triggered by you saying:

Quoted 1 line

Unfortunately, these only work if HAVE_JUMP_LABEL ....

Thanks,

tglx

#13 lore raw

Re: [PATCH 3/4] x86/asm: Add asm macros for static keys/jump labels

Quoted 10 lines · Thomas Gleixner
Quoted 3 lines · Andy Lutomirski

On Sat, Nov 7, 2015 at 8:58 AM, Thomas Gleixner <[email protected]> wrote:
True. But I hid it in a header file, too, but it was just a different header file -- I had it all hidden away as CALL_ENTER_FROM_USER_MODE.

It probably does not really make a difference :)

I just got triggered by you saying:

Quoted 1 line

Unfortunately, these only work if HAVE_JUMP_LABEL ....

Yeah, I don't really like that either. I think that the real fix would be to compile in the runtime jump label bits unconditionally. Admittedly it would bloat the kernel image a little bit for !CONFIG_JUMP_LABEL or if build with an older gcc, and that's even less appropriate for 4.4 at this point. Peter?

--Andy

maintainer
#14 lore raw

Re: [PATCH 3/4] x86/asm: Add asm macros for static keys/jump labels

Quoted 7 lines · Andy Lutomirski
Quoted 1 line
Quoted 1 line

Unfortunately, these only work if HAVE_JUMP_LABEL ....

Yeah, I don't really like that either. I think that the real fix would be to compile in the runtime jump label bits unconditionally. Admittedly it would bloat the kernel image a little bit for !CONFIG_JUMP_LABEL or if build with an older gcc, and that's even less appropriate for 4.4 at this point. Peter?

That is a _lot_ of code for just one user. I'll bet the tiny people won't be happy about that.

#15 lore raw

Re: [PATCH 3/4] x86/asm: Add asm macros for static keys/jump labels

In reply to Thomas Gleixner
Quoted 11 lines · Thomas Gleixner
Quoted 3 lines · Andy Lutomirski

On Sat, Nov 7, 2015 at 8:58 AM, Thomas Gleixner <[email protected]> wrote:
True. But I hid it in a header file, too, but it was just a different header file -- I had it all hidden away as CALL_ENTER_FROM_USER_MODE.

It probably does not really make a difference :)

I just got triggered by you saying:

Quoted 1 line

Unfortunately, these only work if HAVE_JUMP_LABEL ....

Looking again, my patch is crappy is one obvious respect: on non-HAVE_JUMP_LABEL kernels, I'm still generating a macro that will compile but do the wrong thing. I'll add better comments and the correct ifdef in v2. That will make it much harder to screw up without causing a compiler error.

--Andy

author maintainer
#16 lore raw

PATCH 4/4 x86/entry/64: Bypass enter_from_user_mode on non-context-tracking boots

In reply to Andy Lutomirski

On CONFIG_CONTEXT_TRACKING kernels that have context tracking disabled at runtime (which includes most distro kernels), we still have the overhead of a call to enter_from_user_mode in interrupt and exception entries.

If jump labels are available, this uses the jump label infrastructure to skip the call.

---
 arch/x86/entry/calling.h  | 15 +++++++++++++++
 arch/x86/entry/entry_64.S |  8 ++------
 2 files changed, 17 insertions(+), 6 deletions(-)
arch/x86/entry/calling.h +15 -0
index 3c71dd947c7b..271e30c585bc 100644
@@ -1,3 +1,5 @@
+#include <linux/jump_label.h>
+
 /*
 
  x86 function call convention, 64-bit:
@@ -232,3 +234,16 @@ For 32-bit we have the following conventions - kernel is built with
 
 #endif /* CONFIG_X86_64 */
 
+/*
+ * This does 'call enter_from_user_mode' unless we can avoid it based on
+ * kernel config or using the static jump infrastructure.
+ */
+.macro CALL_ENTER_FROM_USER_MODE
+#ifdef CONFIG_CONTEXT_TRACKING
+#ifdef HAVE_JUMP_LABEL
+	STATIC_JUMP_IF_FALSE .Lafter_call_\@, context_tracking_enabled, def=0
+#endif
+	call enter_from_user_mode
+.Lafter_call_\@:
+#endif
+.endm
arch/x86/entry/entry_64.S +2 -6
index f585df24ab3d..9b49b56efa29 100644
@@ -517,9 +517,7 @@ END(irq_entries_start)
 	 */
 	TRACE_IRQS_OFF
 
-#ifdef CONFIG_CONTEXT_TRACKING
-	call enter_from_user_mode
-#endif
+	CALL_ENTER_FROM_USER_MODE
 
 1:
 	/*
@@ -1058,9 +1056,7 @@ ENTRY(error_entry)
 
 .Lerror_entry_from_usermode_after_swapgs:
 	TRACE_IRQS_OFF
-#ifdef CONFIG_CONTEXT_TRACKING
-	call enter_from_user_mode
-#endif
+	CALL_ENTER_FROM_USER_MODE
 	ret
 
 .Lerror_entry_done:
Signature · 1 line
2.4.3
#17 lore raw

Re: [PATCH 4/4] x86/entry/64: Bypass enter_from_user_mode on non-context-tracking boots

Quoted 57 lines · Andy Lutomirski

On CONFIG_CONTEXT_TRACKING kernels that have context tracking disabled at runtime (which includes most distro kernels), we still have the overhead of a call to enter_from_user_mode in interrupt and exception entries.

If jump labels are available, this uses the jump label infrastructure to skip the call.

---
 arch/x86/entry/calling.h  | 15 +++++++++++++++
 arch/x86/entry/entry_64.S |  8 ++------
 2 files changed, 17 insertions(+), 6 deletions(-)
arch/x86/entry/calling.h +15 -0
index 3c71dd947c7b..271e30c585bc 100644
@@ -1,3 +1,5 @@
+#include <linux/jump_label.h>
+
 /*
 
  x86 function call convention, 64-bit:
@@ -232,3 +234,16 @@ For 32-bit we have the following conventions - kernel is built with
 
 #endif /* CONFIG_X86_64 */
 
+/*
+ * This does 'call enter_from_user_mode' unless we can avoid it based on
+ * kernel config or using the static jump infrastructure.
+ */
+.macro CALL_ENTER_FROM_USER_MODE
+#ifdef CONFIG_CONTEXT_TRACKING
+#ifdef HAVE_JUMP_LABEL
+	STATIC_JUMP_IF_FALSE .Lafter_call_\@, context_tracking_enabled, def=0
+#endif
+	call enter_from_user_mode
+.Lafter_call_\@:
+#endif
+.endm
arch/x86/entry/entry_64.S +1 -3
index f585df24ab3d..9b49b56efa29 100644
@@ -517,9 +517,7 @@ END(irq_entries_start)
 	 */
 	TRACE_IRQS_OFF
 
-#ifdef CONFIG_CONTEXT_TRACKING
-	call enter_from_user_mode
-#endif
+	CALL_ENTER_FROM_USER_MODE
 
 1:
 	/*

arch/x86/entry/entry_64.S ENTRY(error_entry) · line 1060

Quoted 8 lines
arch/x86/entry/entry_64.S +1 -3
@@ -1058,9 +1056,7 @@ ENTRY(error_entry)
 
 .Lerror_entry_from_usermode_after_swapgs:
 	TRACE_IRQS_OFF
-#ifdef CONFIG_CONTEXT_TRACKING
-	call enter_from_user_mode
-#endif
+	CALL_ENTER_FROM_USER_MODE
 	ret

Yeah, so I only have a really minor syntactic nit abou tthis: it's OK to capitalize things when doing macros, but here I don't think capitalizing the called function name is good - I think the following would be more obvious:

CALL_enter_from_user_mode

this makes it really, really obvious (to me!) that this macro is a shortcut for:

call enter_from_user_mode

with some glue around it, and I could grep for 'enter_from_user_mode' immediately
- while grepping for ENTER_FROM_USER_MODE would miss the called function.

Thanks,

Ingo