Skip to contentSkip to conversation

jump label v4

RFC PATCH In review Jason Baron 6 participants 35 messages Jan 12, 2010 – Apr 13, 2010

Subsystems (7)
lore
Share & tools
lore
#0 lore raw

cover jump label v4

hi,

For background, see previous posting: http://marc.info/?l=linux-kernel&m=125858436505941&w=2

Refresh of the jump labeling patches. The largest update revolves around how the jump labels are organized. I've added a hash table, using the name of the tracepoints as the 'key'. (I might want to change this to a pointer, for other users, but the string key works well for tracepoints). I've also pre-sorted the jump tables by name. Thus, when a jump label is enabled/disabled we look up its hash table entry and then walk the list of associated jump labels. The implementation also associates module jump sections with the appropriate keys as they are inserted and removed.

The first 2 patches of the series are a repost of Masami's text_poke_fixup() function, which allows for efficient instruction patching. I believe this is still an ongoing discussion, on the best safest approach here. Masami's text_poke_fixup() has been working well for me. But I could certainly substitute a 'stop_machine()' version or something similar if there is enough interest, until we have a more efficient solution.

patches are against the latest -tip tree.

thanks,

-Jason

Masami Hiramatsu (2):
x86: Introduce generic jump patching without stop_machine kprobes/x86: Cleanup RELATIVEJUMP_INSTRUCTION to RELATIVEJUMP_OPCODE

Mathieu Desnoyers (1):
notifier atomic call chain notrace

Jason Baron(5):
move opcode defs from asm/kprobes.h to asm/alternative.h jump label base
x86: jump label support
jump label tracepoint support
jump label module support

 arch/x86/include/asm/alternative.h |   17 ++
 arch/x86/include/asm/jump_label.h  |   32 ++++
 arch/x86/include/asm/kprobes.h     |    3 -
 arch/x86/kernel/Makefile           |    2 +-
 arch/x86/kernel/alternative.c      |  120 ++++++++++++++
 arch/x86/kernel/jump_label.c       |   52 ++++++
 arch/x86/kernel/kprobes.c          |    2 +-
 arch/x86/kernel/ptrace.c           |    1 +
 include/asm-generic/vmlinux.lds.h  |   10 +-
 include/linux/jump_label.h         |   58 +++++++
 include/linux/module.h             |    5 +-
 include/linux/tracepoint.h         |   34 +++--
 kernel/Makefile                    |    2 +-
 kernel/jump_label.c                |  301 ++++++++++++++++++++++++++++++++++++
 kernel/kprobes.c                   |    2 +-
 kernel/module.c                    |    7 +
 kernel/notifier.c                  |    6 +-
 kernel/tracepoint.c                |    8 +
 18 files changed, 635 insertions(+), 27 deletions(-)
 create mode 100644 arch/x86/include/asm/jump_label.h
 create mode 100644 arch/x86/kernel/jump_label.c
 create mode 100644 include/linux/jump_label.h
 create mode 100644 kernel/jump_label.c
#1 lore raw

RFC PATCH 1/8 jump label v4 - kprobes/x86: Cleanup RELATIVEJUMP_INSTRUCTION to RELATIVEJUMP_OPCODE

Change RELATIVEJUMP_INSTRUCTION macro to RELATIVEJUMP_OPCODE since it represents just the opcode byte.

---
 arch/x86/include/asm/kprobes.h |    2 +-
 arch/x86/kernel/kprobes.c      |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
arch/x86/include/asm/kprobes.h +1 -1
index 4fe681d..eaec8ea 100644
@@ -32,7 +32,7 @@ struct kprobe;
 
 typedef u8 kprobe_opcode_t;
 #define BREAKPOINT_INSTRUCTION	0xcc
-#define RELATIVEJUMP_INSTRUCTION 0xe9
+#define RELATIVEJUMP_OPCODE 0xe9
 #define MAX_INSN_SIZE 16
 #define MAX_STACK_SIZE 64
 #define MIN_STACK_SIZE(ADDR)					       \
arch/x86/kernel/kprobes.c +1 -1
index 5b8c750..7039e6e 100644
@@ -115,7 +115,7 @@ static void __kprobes set_jmp_op(void *from, void *to)
 	} __attribute__((packed)) * jop;
 	jop = (struct __arch_jmp_op *)from;
 	jop->raddr = (s32)((long)(to) - ((long)(from) + 5));
-	jop->op = RELATIVEJUMP_INSTRUCTION;
+	jop->op = RELATIVEJUMP_OPCODE;
 }
 
 /*
Signature · 1 line
1.6.5.1
#2 lore raw

RFC PATCH 2/8 jump label v4 - x86: Introduce generic jump patching without stop_machine

In reply to Jason Baron

Add text_poke_fixup() which takes a fixup address to where a processor jumps if it hits the modifying address while code modifying. text_poke_fixup() does following steps for this purpose.

1. Setup int3 handler for fixup.
2. Put a breakpoint (int3) on the first byte of modifying region, and synchronize code on all CPUs.
3. Modify other bytes of modifying region, and synchronize code on all CPUs.
4. Modify the first byte of modifying region, and synchronize code on all CPUs.
5. Clear int3 handler.

Thus, if some other processor execute modifying address when step2 to step4, it will be jumped to fixup code.

This still has many limitations for modifying multi-instructions at once. However, it is enough for 'a 5 bytes nop replacing with a jump' patching, because;
- Replaced instruction is just one instruction, which is executed atomically.
- Replacing instruction is a jump, so we can set fixup address where the jump goes to.

---
 arch/x86/include/asm/alternative.h |   12 ++++
 arch/x86/include/asm/kprobes.h     |    1 +
 arch/x86/kernel/alternative.c      |  120 ++++++++++++++++++++++++++++++++++++
 kernel/kprobes.c                   |    2 +-
 4 files changed, 134 insertions(+), 1 deletions(-)
arch/x86/include/asm/alternative.h +12 -0
index 3b5b828..9b856b7 100644
@@ -166,4 +166,16 @@ static inline void apply_paravirt(struct paravirt_patch_site *start,
  */
 extern void *text_poke(void *addr, const void *opcode, size_t len);
 
+/*
+ * Setup int3 trap and fixup execution for cross-modifying on SMP case.
+ * If the other cpus execute modifying instruction, it will hit int3
+ * and go to fixup code. This just provides a minimal safety check.
+ * Additional checks/restrictions are required for completely safe
+ * cross-modifying.
+ */
+extern void *text_poke_fixup(void *addr, const void *opcode, size_t len,
+			     void *fixup);
+extern int text_patch_jump(void *addr, void *dest);
+extern void sync_core_all(void);
+
 #endif /* _ASM_X86_ALTERNATIVE_H */
arch/x86/include/asm/kprobes.h +1 -0
index eaec8ea..febab97 100644
@@ -33,6 +33,7 @@ struct kprobe;
 typedef u8 kprobe_opcode_t;
 #define BREAKPOINT_INSTRUCTION	0xcc
 #define RELATIVEJUMP_OPCODE 0xe9
+#define RELATIVEJUMP_SIZE 5
 #define MAX_INSN_SIZE 16
 #define MAX_STACK_SIZE 64
 #define MIN_STACK_SIZE(ADDR)					       \
arch/x86/kernel/alternative.c +120 -0

129 lines not on this page · raw message

kernel/kprobes.c +1 -1
index b7df302..9c4697f 100644
@@ -898,7 +898,7 @@ EXPORT_SYMBOL_GPL(unregister_kprobes);
 
 static struct notifier_block kprobe_exceptions_nb = {
 	.notifier_call = kprobe_exceptions_notify,
-	.priority = 0x7fffffff /* we need to be notified first */
+	.priority = 0x7ffffff0 /* High priority, but not first.  */
 };
 
 unsigned long __weak arch_deref_entry_point(void *entry)
Signature · 1 line
1.6.5.1
#3 lore raw

Re: [RFC PATCH 2/8] jump label v4 - x86: Introduce generic jump patching without stop_machine

Quoted 4 lines · Jason Baron

Add text_poke_fixup() which takes a fixup address to where a processor jumps if it hits the modifying address while code modifying. text_poke_fixup() does following steps for this purpose.

Quoted 8 lines

1. Setup int3 handler for fixup.
2. Put a breakpoint (int3) on the first byte of modifying region, and synchronize code on all CPUs.
3. Modify other bytes of modifying region, and synchronize code on all CPUs.
4. Modify the first byte of modifying region, and synchronize code on all CPUs.
5. Clear int3 handler.

We (Intel OTC) have been able to get an *unofficial* answer as to the validity of this procedure; specifically as it applies to Intel hardware (obviously). We are working on getting an officially approved answer, but as far as we currently know, the procedure as outlined above should work on all Intel hardware. In fact, we believe the synchronization in step 3 is in fact unnecessary (as the synchronization in step 4 provides sufficient guard.)

In fact, if a suitable int3 handler is left permanently in place then step 5 is unnecessary as well. This would slow down other uses of int3 slightly, but might be a worthwhile tradeoff.

Such a permanent int3 handler would need to keep track of two potentially-spurious breakpoints: the current and the previous. The reason for needing two is that one could get a #BP from either the current or the previous modification site between the insertion of int3 and the synchronization in step 2. This, of course, assumes that the actual code poking is forcibly single-threaded (running under a spinlock or other mutex) -- if modifications are allowed to run in parallel you need to consider all possible current or stale #BP sites.

-hpa

#4 lore raw

Re: [RFC PATCH 2/8] jump label v4 - x86: Introduce generic jump patching without stop_machine

Quoted 14 lines · * H. Peter Anvin ([email protected]) wrote:
Quoted 4 lines · Jason Baron

Add text_poke_fixup() which takes a fixup address to where a processor jumps if it hits the modifying address while code modifying. text_poke_fixup() does following steps for this purpose.

Quoted 8 lines

1. Setup int3 handler for fixup.
2. Put a breakpoint (int3) on the first byte of modifying region, and synchronize code on all CPUs.
3. Modify other bytes of modifying region, and synchronize code on all CPUs.
4. Modify the first byte of modifying region, and synchronize code on all CPUs.
5. Clear int3 handler.

Quoted 7 lines

We (Intel OTC) have been able to get an *unofficial* answer as to the validity of this procedure; specifically as it applies to Intel hardware (obviously). We are working on getting an officially approved answer, but as far as we currently know, the procedure as outlined above should work on all Intel hardware. In fact, we believe the synchronization in step 3 is in fact unnecessary (as the synchronization in step 4 provides sufficient guard.)

Hi Peter,

This is great news! Thanks to Intel OTC and yourself for looking into this. In the immediate values patches, I am doing the synchronization at the end of step (3) to ensure that all remote CPUs issue read memory barriers, so the stores to the instruction are done in this order:

spin lock
store int3 to 1st byte
smp_wmb()
sync all cores
store new instruction in all but 1st byte
smp_wmb()
issue smp_rmb() on all cores (a sync all cores has this effect) store new instruction to 1st byte
send IPI to all cores (or call synchronize_sched()) to wait for all
breakpoint handlers to complete.
spin unlock

So the question is: are these wmb/rmb pairs actually needed ? As the instruction fetch is not performed by instructions per se, I doubt a rmb() will have any effect on them. I always prefer to stay on the safe side, but it wouldn't hurt to know.

Quoted 5 lines

In fact, if a suitable int3 handler is left permanently in place then step 5 is unnecessary as well. This would slow down other uses of int3 slightly, but might be a worthwhile tradeoff.

Quoted 8 lines

Such a permanent int3 handler would need to keep track of two potentially-spurious breakpoints: the current and the previous. The reason for needing two is that one could get a #BP from either the current or the previous modification site between the insertion of int3 and the synchronization in step 2. This, of course, assumes that the actual code poking is forcibly single-threaded (running under a spinlock or other mutex) -- if modifications are allowed to run in parallel you need to consider all possible current or stale #BP sites.

Hrm. Assuming we have a spinlock protecting all this, given that we synchronize all cores at step (4) _after_ removing the breakpoint, and given that the breakpoint handler is an interrupt gate (thus executes with interrupts off), I am inclined to think that sending the IPIs at the end of step (4) (and waiting for them to complete) should be enough to ensure that all in-flight breakpoint handlers for this site have completed their execution. This would mean that we only have to keep track of a single site at a time. Or am I missing something ?

Thanks,

Mathieu

Quoted 2 lines

-hpa

Signature · 2 lines
Mathieu Desnoyers
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68
#5 lore raw

Re: [RFC PATCH 2/8] jump label v4 - x86: Introduce generic jump patching without stop_machine

Quoted 42 lines · Mathieu Desnoyers
Quoted 14 lines · * H. Peter Anvin ([email protected]) wrote:
Quoted 4 lines · Jason Baron

Add text_poke_fixup() which takes a fixup address to where a processor jumps if it hits the modifying address while code modifying. text_poke_fixup() does following steps for this purpose.

Quoted 8 lines

1. Setup int3 handler for fixup.
2. Put a breakpoint (int3) on the first byte of modifying region, and synchronize code on all CPUs.
3. Modify other bytes of modifying region, and synchronize code on all CPUs.
4. Modify the first byte of modifying region, and synchronize code on all CPUs.
5. Clear int3 handler.

Quoted 7 lines

We (Intel OTC) have been able to get an *unofficial* answer as to the validity of this procedure; specifically as it applies to Intel hardware (obviously). We are working on getting an officially approved answer, but as far as we currently know, the procedure as outlined above should work on all Intel hardware. In fact, we believe the synchronization in step 3 is in fact unnecessary (as the synchronization in step 4 provides sufficient guard.)

Hi Peter,

This is great news! Thanks to Intel OTC and yourself for looking into this. In the immediate values patches, I am doing the synchronization at the end of step (3) to ensure that all remote CPUs issue read memory barriers, so the stores to the instruction are done in this order:

spin lock
store int3 to 1st byte
smp_wmb()
sync all cores
store new instruction in all but 1st byte
smp_wmb()
issue smp_rmb() on all cores (a sync all cores has this effect) store new instruction to 1st byte
send IPI to all cores (or call synchronize_sched()) to wait for all
breakpoint handlers to complete.
spin unlock

Quoted 5 lines

So the question is: are these wmb/rmb pairs actually needed ? As the instruction fetch is not performed by instructions per se, I doubt a rmb() will have any effect on them. I always prefer to stay on the safe side, but it wouldn't hurt to know.

I don't think the smp_rmb() has any function.

However, you're being quite inconsistent in your terminology here. The assumption above is that the "synchronize code on all CPU" step is sending an IPI to all cores and waiting for it to return, so that each core has executed IPI/IRET before continuation.

It is *not* necessary to wait for the breakpoint handlers to return, as long as they will get to IRET eventually, since IRET is a jump and a serializing instruction.

Quoted 8 lines

Hrm. Assuming we have a spinlock protecting all this, given that we synchronize all cores at step (4) _after_ removing the breakpoint, and given that the breakpoint handler is an interrupt gate (thus executes with interrupts off), I am inclined to think that sending the IPIs at the end of step (4) (and waiting for them to complete) should be enough to ensure that all in-flight breakpoint handlers for this site have completed their execution. This would mean that we only have to keep track of a single site at a time. Or am I missing something ?

Yes: the whole point was that you can omit the synchronization in step 4 if you leave the breakpoint handler in place (I said "omit step 5", but that wasn't really what I meant.)

That means that at the cost of two compares in the standard #BP handler, we can get away with only one IPI per atomic instruction poke.

-hpa

Signature · 2 lines
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel.  I don't speak on their behalf.
#6 lore raw

Re: [RFC PATCH 2/8] jump label v4 - x86: Introduce generic jump patching without stop_machine

Quoted 43 lines · * H. Peter Anvin ([email protected]) wrote:
Quoted 42 lines · Mathieu Desnoyers
Quoted 14 lines · * H. Peter Anvin ([email protected]) wrote:
Quoted 4 lines · Jason Baron

Add text_poke_fixup() which takes a fixup address to where a processor jumps if it hits the modifying address while code modifying. text_poke_fixup() does following steps for this purpose.

Quoted 8 lines

1. Setup int3 handler for fixup.
2. Put a breakpoint (int3) on the first byte of modifying region, and synchronize code on all CPUs.
3. Modify other bytes of modifying region, and synchronize code on all CPUs.
4. Modify the first byte of modifying region, and synchronize code on all CPUs.
5. Clear int3 handler.

Quoted 7 lines

We (Intel OTC) have been able to get an *unofficial* answer as to the validity of this procedure; specifically as it applies to Intel hardware (obviously). We are working on getting an officially approved answer, but as far as we currently know, the procedure as outlined above should work on all Intel hardware. In fact, we believe the synchronization in step 3 is in fact unnecessary (as the synchronization in step 4 provides sufficient guard.)

Hi Peter,

This is great news! Thanks to Intel OTC and yourself for looking into this. In the immediate values patches, I am doing the synchronization at the end of step (3) to ensure that all remote CPUs issue read memory barriers, so the stores to the instruction are done in this order:

spin lock
store int3 to 1st byte
smp_wmb()
sync all cores
store new instruction in all but 1st byte
smp_wmb()
issue smp_rmb() on all cores (a sync all cores has this effect) store new instruction to 1st byte
send IPI to all cores (or call synchronize_sched()) to wait for all
breakpoint handlers to complete.
spin unlock

Quoted 7 lines
Quoted 5 lines

So the question is: are these wmb/rmb pairs actually needed ? As the instruction fetch is not performed by instructions per se, I doubt a rmb() will have any effect on them. I always prefer to stay on the safe side, but it wouldn't hurt to know.

I don't think the smp_rmb() has any function.

OK, that's good to know.

Quoted 5 lines

However, you're being quite inconsistent in your terminology here. The assumption above is that the "synchronize code on all CPU" step is sending an IPI to all cores and waiting for it to return, so that each core has executed IPI/IRET before continuation.

To be strictly correct, we cannot assume that the IPI handler issues IRET before signaling its completion. It's rather the other way around. This is why I add a smp_mb() in the IPI handler for the "synchronize code on all CPUs" step.

Quoted 4 lines

It is *not* necessary to wait for the breakpoint handlers to return, as long as they will get to IRET eventually, since IRET is a jump and a serializing instruction.

Ah, I see. So the added smp_mb() would not be needed then, as long as we know that the other CPUs either are currently running the IPI handler or have executed it. IOW: they will execute IRET very soon or they just executed it since the int3 have been written. I am a bit concerned about NMIs coming in this race window, but as they need to have started after we have put the breakpoint, that should be OK. (note: entry_*.S modifications are needed to support nesting breakpoint handlers in NMIs)

Quoted 10 lines
Quoted 9 lines

Hrm. Assuming we have a spinlock protecting all this, given that we synchronize all cores at step (4) _after_ removing the breakpoint, and given that the breakpoint handler is an interrupt gate (thus executes with interrupts off), I am inclined to think that sending the IPIs at the end of step (4) (and waiting for them to complete) should be enough to ensure that all in-flight breakpoint handlers for this site have completed their execution. This would mean that we only have to keep track of a single site at a time. Or am I missing something ?

Quoted 6 lines

Yes: the whole point was that you can omit the synchronization in step 4 if you leave the breakpoint handler in place (I said "omit step 5", but that wasn't really what I meant.)

That means that at the cost of two compares in the standard #BP handler, we can get away with only one IPI per atomic instruction poke.

OK. That makes sense now.

Thanks,

Mathieu

Quoted 9 lines

-hpa

Signature · 2 lines
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel.  I don't speak on their behalf.
Signature · 2 lines
Mathieu Desnoyers
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68
#7 lore raw

Re: [RFC PATCH 2/8] jump label v4 - x86: Introduce generic jump patching without stop_machine

Quoted 70 lines · Mathieu Desnoyers
Quoted 43 lines · * H. Peter Anvin ([email protected]) wrote:
Quoted 42 lines · Mathieu Desnoyers
Quoted 14 lines · * H. Peter Anvin ([email protected]) wrote:
Quoted 4 lines · Jason Baron

Add text_poke_fixup() which takes a fixup address to where a processor jumps if it hits the modifying address while code modifying. text_poke_fixup() does following steps for this purpose.

Quoted 8 lines

1. Setup int3 handler for fixup.
2. Put a breakpoint (int3) on the first byte of modifying region, and synchronize code on all CPUs.
3. Modify other bytes of modifying region, and synchronize code on all CPUs.
4. Modify the first byte of modifying region, and synchronize code on all CPUs.
5. Clear int3 handler.

Quoted 7 lines

We (Intel OTC) have been able to get an *unofficial* answer as to the validity of this procedure; specifically as it applies to Intel hardware (obviously). We are working on getting an officially approved answer, but as far as we currently know, the procedure as outlined above should work on all Intel hardware. In fact, we believe the synchronization in step 3 is in fact unnecessary (as the synchronization in step 4 provides sufficient guard.)

Hi Peter,

This is great news! Thanks to Intel OTC and yourself for looking into this. In the immediate values patches, I am doing the synchronization at the end of step (3) to ensure that all remote CPUs issue read memory barriers, so the stores to the instruction are done in this order:

spin lock
store int3 to 1st byte
smp_wmb()
sync all cores
store new instruction in all but 1st byte
smp_wmb()
issue smp_rmb() on all cores (a sync all cores has this effect) store new instruction to 1st byte
send IPI to all cores (or call synchronize_sched()) to wait for all
breakpoint handlers to complete.
spin unlock

Quoted 7 lines
Quoted 5 lines

So the question is: are these wmb/rmb pairs actually needed ? As the instruction fetch is not performed by instructions per se, I doubt a rmb() will have any effect on them. I always prefer to stay on the safe side, but it wouldn't hurt to know.

I don't think the smp_rmb() has any function.

OK, that's good to know.

Quoted 5 lines

However, you're being quite inconsistent in your terminology here. The assumption above is that the "synchronize code on all CPU" step is sending an IPI to all cores and waiting for it to return, so that each core has executed IPI/IRET before continuation.

To be strictly correct, we cannot assume that the IPI handler issues IRET before signaling its completion. It's rather the other way around. This is why I add a smp_mb() in the IPI handler for the "synchronize code on all CPUs" step.

Quoted 4 lines

It is *not* necessary to wait for the breakpoint handlers to return, as long as they will get to IRET eventually, since IRET is a jump and a serializing instruction.

Quoted 21 lines

Ah, I see. So the added smp_mb() would not be needed then, as long as we know that the other CPUs either are currently running the IPI handler or have executed it. IOW: they will execute IRET very soon or they just executed it since the int3 have been written. I am a bit concerned about NMIs coming in this race window, but as they need to have started after we have put the breakpoint, that should be OK. (note: entry_*.S modifications are needed to support nesting breakpoint handlers in NMIs)

Quoted 13 lines
Quoted 9 lines

Hrm. Assuming we have a spinlock protecting all this, given that we synchronize all cores at step (4) _after_ removing the breakpoint, and given that the breakpoint handler is an interrupt gate (thus executes with interrupts off), I am inclined to think that sending the IPIs at the end of step (4) (and waiting for them to complete) should be enough to ensure that all in-flight breakpoint handlers for this site have completed their execution. This would mean that we only have to keep track of a single site at a time. Or am I missing something ?

Yes: the whole point was that you can omit the synchronization in step 4 if you leave the breakpoint handler in place (I said "omit step 5", but that wasn't really what I meant.)

Hmm, in that case, how can we reuse the breakpoint handler for another text poke site? Even if we leave the handler, I think we need to clear fixup information for next poking...

Quoted 5 lines
Quoted 3 lines

That means that at the cost of two compares in the standard #BP handler, we can get away with only one IPI per atomic instruction poke.

OK. That makes sense now.

So, let me check the actual replacement steps.

(1) lock text_mutex
(2) setup breakpoint fixup addresses (source and destination)
(3) store int3 to 1st byte, and smp_wmb()
(4) send IPI and issue smp_mb() (or cpuid) with for sync all cores.
(5) store new instruction except 1st byte, and smp_wmb()
(6) store 1st byte of new instruction
(7) send IPI to all cores for waiting for all running breakpoint handlers.
(8) clear fixup addresses
(9) unlock text_mutex

Is this correct?

Thank you,

Signature · 7 lines
Masami Hiramatsu

Software Engineer
Hitachi Computer Products (America), Inc.
Software Solutions Division

e-mail: [email protected]
#8 lore raw

Re: [RFC PATCH 2/8] jump label v4 - x86: Introduce generic jump patching without stop_machine

In reply to Mathieu Desnoyers
Quoted 11 lines · Mathieu Desnoyers
Quoted 3 lines

It is *not* necessary to wait for the breakpoint handlers to return, as long as they will get to IRET eventually, since IRET is a jump and a serializing instruction.

Ah, I see. So the added smp_mb() would not be needed then, as long as we know that the other CPUs either are currently running the IPI handler or have executed it. IOW: they will execute IRET very soon or they just executed it since the int3 have been written. I am a bit concerned about NMIs coming in this race window, but as they need to have started after we have put the breakpoint, that should be OK. (note: entry_*.S modifications are needed to support nesting breakpoint handlers in NMIs)

Hmm, if we support this to modify NMI code, it seems that we need to support not only nesting breakpoint handling but also nesting NMIs, because nesting NMI is unblocked when next IRET (of breakpoint) is issued.

Quoted 1 line

From Intel's Software Developer’s Manual Vol.3A 5.7.1 Handling Multiple NMIs

said below.
---
While an NMI interrupt handler is executing, the processor disables additional calls to the NMI handler until the next IRET instruction is executed. This blocking of subse- quent NMIs prevents stacking up calls to the NMI handler. [...]
---

I assume that your below patch tried to solve this issue, right?
http://lkml.indiana.edu/hypermail/linux/kernel/0804.1/0965.html

Thank you,

Signature · 7 lines
Masami Hiramatsu

Software Engineer
Hitachi Computer Products (America), Inc.
Software Solutions Division

e-mail: [email protected]
#9 lore raw

Re: [RFC PATCH 2/8] jump label v4 - x86: Introduce generic jump patching without stop_machine

Quoted 26 lines · * Masami Hiramatsu ([email protected]) wrote:
Quoted 11 lines · Mathieu Desnoyers
Quoted 3 lines

It is *not* necessary to wait for the breakpoint handlers to return, as long as they will get to IRET eventually, since IRET is a jump and a serializing instruction.

Ah, I see. So the added smp_mb() would not be needed then, as long as we know that the other CPUs either are currently running the IPI handler or have executed it. IOW: they will execute IRET very soon or they just executed it since the int3 have been written. I am a bit concerned about NMIs coming in this race window, but as they need to have started after we have put the breakpoint, that should be OK. (note: entry_*.S modifications are needed to support nesting breakpoint handlers in NMIs)

Hmm, if we support this to modify NMI code, it seems that we need to support not only nesting breakpoint handling but also nesting NMIs, because nesting NMI is unblocked when next IRET (of breakpoint) is issued.

From Intel's Software Developer’s Manual Vol.3A 5.7.1 Handling Multiple NMIs said below.
---
While an NMI interrupt handler is executing, the processor disables additional calls to the NMI handler until the next IRET instruction is executed. This blocking of subse- quent NMIs prevents stacking up calls to the NMI handler. [...]
---

Quoted 3 lines

I assume that your below patch tried to solve this issue, right?
http://lkml.indiana.edu/hypermail/linux/kernel/0804.1/0965.html

Yep. (sorry about late reply).

Mathieu

Quoted 11 lines

Thank you,

Signature · 7 lines
Masami Hiramatsu

Software Engineer
Hitachi Computer Products (America), Inc.
Software Solutions Division

e-mail: [email protected]
Signature · 4 lines
Mathieu Desnoyers
Operating System Efficiency R&D Consultant
EfficiOS Inc.
http://www.efficios.com
#10 lore raw

Re: [RFC PATCH 2/8] jump label v4 - x86: Introduce generic jump patching without stop_machine

In reply to H. Peter Anvin
Quoted 14 lines · H. Peter Anvin
Quoted 4 lines · Jason Baron

Add text_poke_fixup() which takes a fixup address to where a processor jumps if it hits the modifying address while code modifying. text_poke_fixup() does following steps for this purpose.

Quoted 8 lines

1. Setup int3 handler for fixup.
2. Put a breakpoint (int3) on the first byte of modifying region, and synchronize code on all CPUs.
3. Modify other bytes of modifying region, and synchronize code on all CPUs.
4. Modify the first byte of modifying region, and synchronize code on all CPUs.
5. Clear int3 handler.

Quoted 7 lines

We (Intel OTC) have been able to get an *unofficial* answer as to the validity of this procedure; specifically as it applies to Intel hardware (obviously). We are working on getting an officially approved answer, but as far as we currently know, the procedure as outlined above should work on all Intel hardware. In fact, we believe the synchronization in step 3 is in fact unnecessary (as the synchronization in step 4 provides sufficient guard.)

Good news! Thank you very much, Peter!

And actually, this patch is a bit older than I previously posted on LKML.

http://lkml.org/lkml/2009/12/18/312

Oops, I've forgotten update comment on patch... anyway, patch implementation itself is updated and removed second sync_core_all.
I'll post it again with updated comment.

Quoted 3 lines

In fact, if a suitable int3 handler is left permanently in place then step 5 is unnecessary as well. This would slow down other uses of int3 slightly, but might be a worthwhile tradeoff.

OK.

Quoted 8 lines

Such a permanent int3 handler would need to keep track of two potentially-spurious breakpoints: the current and the previous. The reason for needing two is that one could get a #BP from either the current or the previous modification site between the insertion of int3 and the synchronization in step 2. This, of course, assumes that the actual code poking is forcibly single-threaded (running under a spinlock or other mutex) -- if modifications are allowed to run in parallel you need to consider all possible current or stale #BP sites.

Sure, and since we are using fixmap for poking, we need to do this under locking text_mutex.

Thank you!

Signature · 7 lines
Masami Hiramatsu

Software Engineer
Hitachi Computer Products (America), Inc.
Software Solutions Division

e-mail: [email protected]
maintainer
#11 lore raw

Re: [RFC PATCH 2/8] jump label v4 - x86: Introduce generic jump patching without stop_machine

In reply to Jason Baron
Quoted 10 lines · Jason Baron
arch/x86/kernel/alternative.c +10 -0
+/**
+ * text_poke_fixup() -- cross-modifying kernel text with fixup address.
+ * @addr:	Modifying address.
+ * @opcode:	New instruction.
+ * @len:	length of modifying bytes.
+ * @fixup:	Fixup address.
+ *
+ * Note: You must backup replaced instructions before calling this,
+ * if you need to recover it.
+ * Note: Must be called under text_mutex.

arch/x86/kernel/alternative.c void *__kprobes text_poke(void *addr, const void *opcode, size_t len) · line 614

Quoted 10 lines
arch/x86/kernel/alternative.c +10 -0
+ */
+void *__kprobes text_poke_fixup(void *addr, const void *opcode, size_t len,
+				void *fixup)
+{
+	static const unsigned char int3_insn = BREAKPOINT_INSTRUCTION;
+	static const int int3_size = sizeof(int3_insn);
+
+	/* Replacing 1 byte can be done atomically. */
+	if (unlikely(len <= 1))
+		return text_poke(addr, opcode, len);

This part bothers me. The text_poke just writes over the text directly (using a separate mapping). But if that memory is in the pipeline of another CPU, I think this could cause a GPF.

-- Steve

Quoted 25 lines
arch/x86/kernel/alternative.c +25 -0
+
+	/* Preparing */
+	patch_fixup_addr = fixup;
+	wmb();
+	patch_fixup_from = (u8 *)addr + int3_size; /* IP address after int3 */
+
+	/* Cap by an int3 */
+	text_poke(addr, &int3_insn, int3_size);
+	sync_core_all();
+
+	/* Replace tail bytes */
+	text_poke((char *)addr + int3_size, (const char *)opcode + int3_size,
+		  len - int3_size);
+	sync_core_all();
+
+	/* Replace int3 with head byte */
+	text_poke(addr, opcode, int3_size);
+	sync_core_all();
+
+	/* Cleanup */
+	patch_fixup_from = NULL;
+	wmb();
+	return addr;
+}
+
#12 lore raw

Re: [RFC PATCH 2/8] jump label v4 - x86: Introduce generic jump patching without stop_machine

Quoted 18 lines · * Steven Rostedt ([email protected]) wrote:
Quoted 16 lines · Jason Baron
arch/x86/kernel/alternative.c +16 -0
+/**
+ * text_poke_fixup() -- cross-modifying kernel text with fixup address.
+ * @addr:	Modifying address.
+ * @opcode:	New instruction.
+ * @len:	length of modifying bytes.
+ * @fixup:	Fixup address.
+ *
+ * Note: You must backup replaced instructions before calling this,
+ * if you need to recover it.
+ * Note: Must be called under text_mutex.
+ */
+void *__kprobes text_poke_fixup(void *addr, const void *opcode, size_t len,
+				void *fixup)
+{
+	static const unsigned char int3_insn = BREAKPOINT_INSTRUCTION;
+	static const int int3_size = sizeof(int3_insn);
Quoted 8 lines

arch/x86/kernel/alternative.c void *__kprobes text_poke(void *addr, const void *opcode, size_t len) · line 614

Quoted 4 lines
arch/x86/kernel/alternative.c +4 -0
+
+	/* Replacing 1 byte can be done atomically. */
+	if (unlikely(len <= 1))
+		return text_poke(addr, opcode, len);

This part bothers me. The text_poke just writes over the text directly (using a separate mapping). But if that memory is in the pipeline of another CPU, I think this could cause a GPF.

It looks like we are thinking along the same lines.

I'm under the impression that I pointed out this exact same issue in the previous round of review a few weeks ago. Does this submission reflect the up-to-date state of this patch ?

Thanks,

Mathieu

Quoted 29 lines

-- Steve

Quoted 25 lines
arch/x86/kernel/alternative.c +25 -0
+
+	/* Preparing */
+	patch_fixup_addr = fixup;
+	wmb();
+	patch_fixup_from = (u8 *)addr + int3_size; /* IP address after int3 */
+
+	/* Cap by an int3 */
+	text_poke(addr, &int3_insn, int3_size);
+	sync_core_all();
+
+	/* Replace tail bytes */
+	text_poke((char *)addr + int3_size, (const char *)opcode + int3_size,
+		  len - int3_size);
+	sync_core_all();
+
+	/* Replace int3 with head byte */
+	text_poke(addr, opcode, int3_size);
+	sync_core_all();
+
+	/* Cleanup */
+	patch_fixup_from = NULL;
+	wmb();
+	return addr;
+}
+
Signature · 2 lines
Mathieu Desnoyers
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68
#13 lore raw

Re: [RFC PATCH 2/8] jump label v4 - x86: Introduce generic jump patching without stop_machine

Quoted 28 lines · Mathieu Desnoyers
Quoted 18 lines · * Steven Rostedt ([email protected]) wrote:
Quoted 16 lines · Jason Baron
arch/x86/kernel/alternative.c +16 -0
+/**
+ * text_poke_fixup() -- cross-modifying kernel text with fixup address.
+ * @addr:	Modifying address.
+ * @opcode:	New instruction.
+ * @len:	length of modifying bytes.
+ * @fixup:	Fixup address.
+ *
+ * Note: You must backup replaced instructions before calling this,
+ * if you need to recover it.
+ * Note: Must be called under text_mutex.
+ */
+void *__kprobes text_poke_fixup(void *addr, const void *opcode, size_t len,
+				void *fixup)
+{
+	static const unsigned char int3_insn = BREAKPOINT_INSTRUCTION;
+	static const int int3_size = sizeof(int3_insn);
Quoted 8 lines

arch/x86/kernel/alternative.c void *__kprobes text_poke(void *addr, const void *opcode, size_t len) · line 614

Quoted 4 lines
arch/x86/kernel/alternative.c +4 -0
+
+	/* Replacing 1 byte can be done atomically. */
+	if (unlikely(len <= 1))
+		return text_poke(addr, opcode, len);

This part bothers me. The text_poke just writes over the text directly (using a separate mapping). But if that memory is in the pipeline of another CPU, I think this could cause a GPF.

Quoted 5 lines

It looks like we are thinking along the same lines.

I'm under the impression that I pointed out this exact same issue in the previous round of review a few weeks ago. Does this submission reflect the up-to-date state of this patch ?

No, the latest patch just skips step 3 if len == 1. (Jason, could you update your repository?) I thought I sent it the end of the last year ... :)

http://lkml.org/lkml/2009/12/18/312

Thank you,

Signature · 7 lines
Masami Hiramatsu

Software Engineer
Hitachi Computer Products (America), Inc.
Software Solutions Division

e-mail: [email protected]
#14 lore raw

Re: [RFC PATCH 2/8] jump label v4 - x86: Introduce generic jump patching without stop_machine

Quoted 34 lines · Masami Hiramatsu
Quoted 28 lines · * Steven Rostedt ([email protected]) wrote:
Quoted 18 lines · Jason Baron
Quoted 17 lines
arch/x86/kernel/alternative.c +16 -0
+/**
+ * text_poke_fixup() -- cross-modifying kernel text with fixup address.
+ * @addr:	Modifying address.
+ * @opcode:	New instruction.
+ * @len:	length of modifying bytes.
+ * @fixup:	Fixup address.
+ *
+ * Note: You must backup replaced instructions before calling this,
+ * if you need to recover it.
+ * Note: Must be called under text_mutex.
+ */
+void *__kprobes text_poke_fixup(void *addr, const void *opcode, size_t len,
+				void *fixup)
+{
+	static const unsigned char int3_insn = BREAKPOINT_INSTRUCTION;
+	static const int int3_size = sizeof(int3_insn);
Quoted 8 lines

arch/x86/kernel/alternative.c void *__kprobes text_poke(void *addr, const void *opcode, size_t len) · line 614

Quoted 4 lines
arch/x86/kernel/alternative.c +4 -0
+
+	/* Replacing 1 byte can be done atomically. */
+	if (unlikely(len <= 1))
+		return text_poke(addr, opcode, len);

This part bothers me. The text_poke just writes over the text directly (using a separate mapping). But if that memory is in the pipeline of another CPU, I think this could cause a GPF.

Quoted 5 lines

It looks like we are thinking along the same lines.

I'm under the impression that I pointed out this exact same issue in the previous round of review a few weeks ago. Does this submission reflect the up-to-date state of this patch ?

Quoted 8 lines

No, the latest patch just skips step 3 if len == 1. (Jason, could you update your repository?) I thought I sent it the end of the last year ... :)

http://lkml.org/lkml/2009/12/18/312

Thank you,

sorry about that...i've updated to the latest.

thanks,

-Jason

#15 lore raw

Re: [RFC PATCH 2/8] jump label v4 - x86: Introduce generic jump patching without stop_machine

In reply to Steven Rostedt
Quoted 9 lines · Steven Rostedt

arch/x86/kernel/alternative.c void *__kprobes text_poke(void *addr, const void *opcode, size_t len) · line 614

Quoted 4 lines
arch/x86/kernel/alternative.c +4 -0
+
+	/* Replacing 1 byte can be done atomically. */
+	if (unlikely(len <= 1))
+		return text_poke(addr, opcode, len);

This part bothers me. The text_poke just writes over the text directly (using a separate mapping). But if that memory is in the pipeline of another CPU, I think this could cause a GPF.

Could you clarify why you think that?

-hpa

Signature · 2 lines
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel.  I don't speak on their behalf.
#16 lore raw

Re: [RFC PATCH 2/8] jump label v4 - x86: Introduce generic jump patching without stop_machine

Quoted 11 lines · * H. Peter Anvin ([email protected]) wrote:
Quoted 9 lines · Steven Rostedt

arch/x86/kernel/alternative.c void *__kprobes text_poke(void *addr, const void *opcode, size_t len) · line 614

Quoted 4 lines
arch/x86/kernel/alternative.c +4 -0
+
+	/* Replacing 1 byte can be done atomically. */
+	if (unlikely(len <= 1))
+		return text_poke(addr, opcode, len);

This part bothers me. The text_poke just writes over the text directly (using a separate mapping). But if that memory is in the pipeline of another CPU, I think this could cause a GPF.

Quoted 1 line

Could you clarify why you think that?

Basically, what Steven and I were concerned about in this particular patch version is the fact that this code took a "shortcut" for single-byte text modification, thus bypassing the int3-bypass scheme altogether.

As mere atomicity of the modification is not the only concern here (because we also have to deal with instruction trace cache coherency and so forth), then the int3 breakpoint scheme is, I think, also needed for single-byte updates.

Thanks,

Mathieu

Quoted 7 lines

-hpa

Signature · 2 lines
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel.  I don't speak on their behalf.
Signature · 2 lines
Mathieu Desnoyers
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68
#17 lore raw

Re: [RFC PATCH 2/8] jump label v4 - x86: Introduce generic jump patching without stop_machine

Quoted 12 lines · On Sun, 17 Jan 2010 13:55:39 -0500 Mathieu Desnoyers…
Quoted 11 lines · * H. Peter Anvin ([email protected]) wrote:
Quoted 9 lines · Steven Rostedt

arch/x86/kernel/alternative.c void *__kprobes text_poke(void *addr, const void *opcode, size_t len) · line 614

Quoted 4 lines
arch/x86/kernel/alternative.c +4 -0
+
+	/* Replacing 1 byte can be done atomically. */
+	if (unlikely(len <= 1))
+		return text_poke(addr, opcode, len);

This part bothers me. The text_poke just writes over the text directly (using a separate mapping). But if that memory is in the pipeline of another CPU, I think this could cause a GPF.

Quoted 6 lines
Quoted 1 line

Could you clarify why you think that?

Basically, what Steven and I were concerned about in this particular patch version is the fact that this code took a "shortcut" for single-byte text modification, thus bypassing the int3-bypass scheme altogether.

single byte instruction updates are likely 100x safer than any scheme of multi-byte instruction scheme that I have seen, other than a full stop_machine().

That does not mean it is safe, it just means it's an order of complexity less to analyze ;-)

Signature · 3 lines
Arjan van de Ven 	Intel Open Source Technology Centre
For development, discussion and tips for power savings, 
visit http://www.lesswatts.org
#18 lore raw

Re: [RFC PATCH 2/8] jump label v4 - x86: Introduce generic jump patching without stop_machine

Quoted 22 lines · Arjan van de Ven
Quoted 12 lines · On Sun, 17 Jan 2010 13:55:39 -0500 Mathieu Desnoyers…
Quoted 11 lines · * H. Peter Anvin ([email protected]) wrote:
Quoted 9 lines · Steven Rostedt

arch/x86/kernel/alternative.c void *__kprobes text_poke(void *addr, const void *opcode, size_t len) · line 614

Quoted 4 lines
arch/x86/kernel/alternative.c +4 -0
+
+	/* Replacing 1 byte can be done atomically. */
+	if (unlikely(len <= 1))
+		return text_poke(addr, opcode, len);

This part bothers me. The text_poke just writes over the text directly (using a separate mapping). But if that memory is in the pipeline of another CPU, I think this could cause a GPF.

Quoted 6 lines
Quoted 1 line

Could you clarify why you think that?

Basically, what Steven and I were concerned about in this particular patch version is the fact that this code took a "shortcut" for single-byte text modification, thus bypassing the int3-bypass scheme altogether.

Quoted 6 lines

single byte instruction updates are likely 100x safer than any scheme of multi-byte instruction scheme that I have seen, other than a full stop_machine().

That does not mean it is safe, it just means it's an order of complexity less to analyze ;-)

Yeah, so in the latest patch, I updated it to use int3 even if len == 1. :-)

Thank you,

Signature · 7 lines
Masami Hiramatsu

Software Engineer
Hitachi Computer Products (America), Inc.
Software Solutions Division

e-mail: [email protected]
#19 lore raw

Re: [RFC PATCH 2/8] jump label v4 - x86: Introduce generic jump patching without stop_machine

Quoted 17 lines · Masami Hiramatsu
Quoted 17 lines
Quoted 6 lines
Quoted 6 lines
Quoted 5 lines

This part bothers me. The text_poke just writes over the text directly (using a separate mapping). But if that memory is in the pipeline of another CPU, I think this could cause a GPF.

Quoted 6 lines
Quoted 1 line

Could you clarify why you think that?

Basically, what Steven and I were concerned about in this particular patch version is the fact that this code took a "shortcut" for single-byte text modification, thus bypassing the int3-bypass scheme altogether.

single byte instruction updates are likely 100x safer than any scheme of multi-byte instruction scheme that I have seen, other than a full stop_machine().

Quoted 6 lines
Quoted 2 lines

That does not mean it is safe, it just means it's an order of complexity less to analyze ;-)

Yeah, so in the latest patch, I updated it to use int3 even if len == 1. :-)

This really doesn't make much sense to me. The whole basis for the int3 scheme itself is that single-byte updates are atomic, so if single-byte updates can't work -- and as I stated, we at Intel OTC currently believe it safe -- then int3 can't work either.

The one thing to watch out for is that unless you force an IPI/IRET cycle afterwards, you can't know when any particular remote processor will see the update.

-hpa

Signature · 2 lines
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel.  I don't speak on their behalf.
#20 lore raw

Re: [RFC PATCH 2/8] jump label v4 - x86: Introduce generic jump patching without stop_machine

Quoted 21 lines · * H. Peter Anvin ([email protected]) wrote:
Quoted 20 lines · Masami Hiramatsu
Quoted 19 lines
Quoted 6 lines
Quoted 6 lines
Quoted 5 lines

This part bothers me. The text_poke just writes over the text directly (using a separate mapping). But if that memory is in the pipeline of another CPU, I think this could cause a GPF.

Quoted 6 lines
Quoted 1 line

Could you clarify why you think that?

Basically, what Steven and I were concerned about in this particular patch version is the fact that this code took a "shortcut" for single-byte text modification, thus bypassing the int3-bypass scheme altogether.

single byte instruction updates are likely 100x safer than any scheme of multi-byte instruction scheme that I have seen, other than a full stop_machine().

That does not mean it is safe, it just means it's an order of complexity less to analyze ;-)

Quoted 8 lines
Quoted 3 lines

Yeah, so in the latest patch, I updated it to use int3 even if len == 1. :-)

This really doesn't make much sense to me. The whole basis for the int3 scheme itself is that single-byte updates are atomic, so if single-byte updates can't work -- and as I stated, we at Intel OTC currently believe it safe -- then int3 can't work either.

The additional characteristic of the int3 instruction (compared to the general case of a single-byte instruction) is that, when executed, it will trigger a trap, run a trap handler and return to the original code, typically with iret. This therefore implies that a serializing instruction is executed before returning to the instructions following the modification site when the breakpoint is hit.

So I hand out to Intel's expertise the question of whether single-byte instruction modification is safe or not in the general case. I'm just pointing out that I can very well imagine an aggressive superscalar architecture for which pipeline structure would support single-byte int3 patching without any problem due to the implied serialization, but would not support the general-case single-byte modification due to its lack of serialization.

As we might have to port this algorithm to Itanium in a near future, I prefer to stay on the safe side. Intel's "by the book" recommendation is more or less that a serializing instruction must be executed on all CPUs before new code is executed, without mention of single-vs-multi byte instructions. The int3-based bypass follows this requirement, but the single-byte code patching does not.

Unless there is a visible performance gain to special-case the single-byte instruction, I would recommend to stick to the safest solution, which follows Intel "official" guide-lines too.

Thanks,

Mathieu

Quoted 11 lines

The one thing to watch out for is that unless you force an IPI/IRET cycle afterwards, you can't know when any particular remote processor will see the update.

-hpa

Signature · 2 lines
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel.  I don't speak on their behalf.
Signature · 2 lines
Mathieu Desnoyers
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68
#21 lore raw

Re: [RFC PATCH 2/8] jump label v4 - x86: Introduce generic jump patching without stop_machine

Quoted 13 lines · Mathieu Desnoyers
Quoted 5 lines

This really doesn't make much sense to me. The whole basis for the int3 scheme itself is that single-byte updates are atomic, so if single-byte updates can't work -- and as I stated, we at Intel OTC currently believe it safe -- then int3 can't work either.

The additional characteristic of the int3 instruction (compared to the general case of a single-byte instruction) is that, when executed, it will trigger a trap, run a trap handler and return to the original code, typically with iret. This therefore implies that a serializing instruction is executed before returning to the instructions following the modification site when the breakpoint is hit.

Quoted 8 lines

So I hand out to Intel's expertise the question of whether single-byte instruction modification is safe or not in the general case. I'm just pointing out that I can very well imagine an aggressive superscalar architecture for which pipeline structure would support single-byte int3 patching without any problem due to the implied serialization, but would not support the general-case single-byte modification due to its lack of serialization.

This is utter and complete nonsense. You seem to think that everything
is guaranteed to hit the breakpoint, which is obviously false. Furthermore, until you have done the serialization, you're not guaranteed the *breakpoint* is seen, so you have the same condition.

Quoted 10 lines

As we might have to port this algorithm to Itanium in a near future, I prefer to stay on the safe side. Intel's "by the book" recommendation is more or less that a serializing instruction must be executed on all CPUs before new code is executed, without mention of single-vs-multi byte instructions. The int3-based bypass follows this requirement, but the single-byte code patching does not.

Unless there is a visible performance gain to special-case the single-byte instruction, I would recommend to stick to the safest solution, which follows Intel "official" guide-lines too.

No, it doesn't. The only thing that follows the "official" guidelines is stop_machine.

As far as other architectures are concerned, other architectures can have very different and much stricter rules for I/D coherence. Trying to extrapolate from the x86 rules is aggravated insanity.

-hpa

#22 lore raw

Re: [RFC PATCH 2/8] jump label v4 - x86: Introduce generic jump patching without stop_machine

Quoted 23 lines · H. Peter Anvin
Quoted 13 lines · Mathieu Desnoyers
Quoted 5 lines

This really doesn't make much sense to me. The whole basis for the int3 scheme itself is that single-byte updates are atomic, so if single-byte updates can't work -- and as I stated, we at Intel OTC currently believe it safe -- then int3 can't work either.

The additional characteristic of the int3 instruction (compared to the general case of a single-byte instruction) is that, when executed, it will trigger a trap, run a trap handler and return to the original code, typically with iret. This therefore implies that a serializing instruction is executed before returning to the instructions following the modification site when the breakpoint is hit.

Quoted 8 lines

So I hand out to Intel's expertise the question of whether single-byte instruction modification is safe or not in the general case. I'm just pointing out that I can very well imagine an aggressive superscalar architecture for which pipeline structure would support single-byte int3 patching without any problem due to the implied serialization, but would not support the general-case single-byte modification due to its lack of serialization.

Quoted 4 lines

This is utter and complete nonsense. You seem to think that everything
is guaranteed to hit the breakpoint, which is obviously false. Furthermore, until you have done the serialization, you're not guaranteed the *breakpoint* is seen, so you have the same condition.

In that time frame, I guess that the processor sees non-modified instruction and executes it. Since we'll wait until serializing on each processor, I think it is OK for int3-bypass method.

(Of course, this can depend on chip, it is possible that there is a chip
which causes a fault when it has a cache-discarding signal on current- instruction decoding slot. That's also why we are asking this method is OK for x86 processors.)

Thank you,

Signature · 7 lines
Masami Hiramatsu

Software Engineer
Hitachi Computer Products (America), Inc.
Software Solutions Division

e-mail: [email protected]
#23 lore raw

Re: [RFC PATCH 2/8] jump label v4 - x86: Introduce generic jump patching without stop_machine

Quoted 6 lines · Masami Hiramatsu
Quoted 5 lines

This is utter and complete nonsense. You seem to think that everything
is guaranteed to hit the breakpoint, which is obviously false. Furthermore, until you have done the serialization, you're not guaranteed the *breakpoint* is seen, so you have the same condition.

Quoted 9 lines

In that time frame, I guess that the processor sees non-modified instruction and executes it. Since we'll wait until serializing on each processor, I think it is OK for int3-bypass method.

(Of course, this can depend on chip, it is possible that there is a chip
which causes a fault when it has a cache-discarding signal on current- instruction decoding slot. That's also why we are asking this method is OK for x86 processors.)

Yes, it is possible, however, if that was the case, then int3 wouldn't work either. As I said, to the best of our knowledge, at least Intel processors are okay for a single-byte update (I will wait to try to state the full general rule until it has been officially approved or killed.)

-hpa

#24 lore raw

Re: [RFC PATCH 2/8] jump label v4 - x86: Introduce generic jump patching without stop_machine

In reply to H. Peter Anvin
Quoted 23 lines · * H. Peter Anvin ([email protected]) wrote:
Quoted 13 lines · Mathieu Desnoyers
Quoted 5 lines

This really doesn't make much sense to me. The whole basis for the int3 scheme itself is that single-byte updates are atomic, so if single-byte updates can't work -- and as I stated, we at Intel OTC currently believe it safe -- then int3 can't work either.

The additional characteristic of the int3 instruction (compared to the general case of a single-byte instruction) is that, when executed, it will trigger a trap, run a trap handler and return to the original code, typically with iret. This therefore implies that a serializing instruction is executed before returning to the instructions following the modification site when the breakpoint is hit.

Quoted 8 lines

So I hand out to Intel's expertise the question of whether single-byte instruction modification is safe or not in the general case. I'm just pointing out that I can very well imagine an aggressive superscalar architecture for which pipeline structure would support single-byte int3 patching without any problem due to the implied serialization, but would not support the general-case single-byte modification due to its lack of serialization.

Quoted 2 lines

This is utter and complete nonsense. You seem to think that everything
is guaranteed to hit the breakpoint, which is obviously false.

What I discuss above is: what actually happens when the breakpoint is hit.

I'm doing no assumption about whether it is hit or not. In the int3+IPI broadcast scheme, every cpu receive an IPI between seeing the old and new instructions. Only *some* cpus *may* hit the breakpoint that is put there temporarily.

Quoted 2 lines

Furthermore, until you have done the serialization, you're not guaranteed the *breakpoint* is seen,

Agreed,

Quoted 1 line

so you have the same condition.

Hrm ? Same as what exactly ? We have either the old instruction in place or the breakpoint (before the serialization). After the serialization, we have either the breakpoint or the new instruction.

What I am pointing out is that specifically turning a 1-byte instruction into a breakpoint can be safer than turning it into another 1-byte instruction directly, because *if* cpus hit the breakpoint, they *will* issue a synchronizing instruction at that point (implied by the breakpoint). This is not the case if you just modify the 1-byte instruction in place.

Quoted 12 lines
Quoted 11 lines

As we might have to port this algorithm to Itanium in a near future, I prefer to stay on the safe side. Intel's "by the book" recommendation is more or less that a serializing instruction must be executed on all CPUs before new code is executed, without mention of single-vs-multi byte instructions. The int3-based bypass follows this requirement, but the single-byte code patching does not.

Unless there is a visible performance gain to special-case the single-byte instruction, I would recommend to stick to the safest solution, which follows Intel "official" guide-lines too.

Quoted 6 lines

No, it doesn't. The only thing that follows the "official" guidelines is stop_machine.

As far as other architectures are concerned, other architectures can have very different and much stricter rules for I/D coherence. Trying to extrapolate from the x86 rules is aggravated insanity.

I agree that official Intel guidelines for XMC only discuss the stop_machine() scheme. OK then, let's see how patching single-byte instructions deals with the official _uniprocessor_ self-modifying code guidelines.

(ref. http://www.intel.com/Assets/PDF/specupdate/318586.pdf
7.1.3 Handling Self- and Cross-Modifying Code)

(* OPTION 1 *)
Store modified code (as data) into code segment;
Jump to new code or an intermediate location;
Execute new code;

(* OPTION 2 *)
Store modified code (as data) into code segment;
Execute a serializing instruction; (* For example, CPUID instruction *) Execute new code;

As you can see, if we self-modify the code on a single cpu machine with text_poke directly, even for a single-byte instruction, we _have_ to guarantee that either a jump or a serializing instruction is issued before the new code is executed.

What I discussed above was that int3 is a special-case, because it generates a trap, and therefore jumps to a different location.

So, back to the case where we could "simply patch-in any single-byte instruction in a SMP system", I argue that this is against the uniprocessor part of the errata, which clearly also applies to SMP.

By the way, I've looked at the Itanium documents a few years ago, and I have not seen any reason at that time why the breakpoint+IPI scheme would not work if we additionally perform the appropriate I and D cache flushes. The rest of the requirements are _very_ similar.

Thanks,

Mathieu

Quoted 2 lines

-hpa

Signature · 2 lines
Mathieu Desnoyers
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68
#25 lore raw

Re: [RFC PATCH 2/8] jump label v4 - x86: Introduce generic jump patching without stop_machine

In reply to Masami Hiramatsu
Quoted 3 lines · On Mon, 18 Jan 2010 10:59:30 -0500 Masami Hiramatsu <[email protected]> wrote:

Yeah, so in the latest patch, I updated it to use int3 even if len == 1. :-)

int3 is not making a difference for your case; there is no guarantee that the other processor even sees the "int3 inbetween state" at all; if it's not safe without int3 then it won't be safe with int3 either.

Signature · 3 lines
Arjan van de Ven 	Intel Open Source Technology Centre
For development, discussion and tips for power savings, 
visit http://www.lesswatts.org
#26 lore raw

Re: [RFC PATCH 2/8] jump label v4 - x86: Introduce generic jump patching without stop_machine

Quoted 11 lines · * Arjan van de Ven ([email protected]) wrote:
Quoted 3 lines · On Mon, 18 Jan 2010 10:59:30 -0500 Masami Hiramatsu <[email protected]> wrote:

Yeah, so in the latest patch, I updated it to use int3 even if len == 1. :-)

int3 is not making a difference for your case; there is no guarantee that the other processor even sees the "int3 inbetween state" at all; if it's not safe without int3 then it won't be safe with int3 either.

What Masami means is that he updated his patch to use the int3+IPI broadcast scheme.

Therefore, the CPUs not seeing the int3 inbetween state will be forced to issue a serializing instruction while the int3 is in place anyway.

Thanks,

Mathieu

Quoted 6 lines
Signature · 4 lines
-- 
Arjan van de Ven 	Intel Open Source Technology Centre
For development, discussion and tips for power savings, 
visit http://www.lesswatts.org
Signature · 2 lines
Mathieu Desnoyers
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68
#27 lore raw

Re: [RFC PATCH 2/8] jump label v4 - x86: Introduce generic jump patching without stop_machine

Quoted 9 lines · Mathieu Desnoyers
Quoted 8 lines · * Arjan van de Ven ([email protected]) wrote:
Quoted 3 lines · On Mon, 18 Jan 2010 10:59:30 -0500 Masami Hiramatsu <[email protected]> wrote:

Yeah, so in the latest patch, I updated it to use int3 even if len == 1. :-)

Quoted 6 lines
Quoted 3 lines

int3 is not making a difference for your case; there is no guarantee that the other processor even sees the "int3 inbetween state" at all; if it's not safe without int3 then it won't be safe with int3 either.

What Masami means is that he updated his patch to use the int3+IPI broadcast scheme.

Right.

Quoted 3 lines

Therefore, the CPUs not seeing the int3 inbetween state will be forced to issue a serializing instruction while the int3 is in place anyway.

By the way, in kprobes, we just use a text_poke() to put int3. I assume that we'd better send IPI afterward, wouldn't it?

Thank you,

Signature · 7 lines
Masami Hiramatsu

Software Engineer
Hitachi Computer Products (America), Inc.
Software Solutions Division

e-mail: [email protected]
#28 lore raw

Re: [RFC PATCH 2/8] jump label v4 - x86: Introduce generic jump patching without stop_machine

Quoted 17 lines · * Masami Hiramatsu ([email protected]) wrote:
Quoted 9 lines · Mathieu Desnoyers
Quoted 8 lines · * Arjan van de Ven ([email protected]) wrote:
Quoted 3 lines · On Mon, 18 Jan 2010 10:59:30 -0500 Masami Hiramatsu <[email protected]> wrote:

Yeah, so in the latest patch, I updated it to use int3 even if len == 1. :-)

Quoted 6 lines
Quoted 3 lines

int3 is not making a difference for your case; there is no guarantee that the other processor even sees the "int3 inbetween state" at all; if it's not safe without int3 then it won't be safe with int3 either.

What Masami means is that he updated his patch to use the int3+IPI broadcast scheme.

Quoted 8 lines

Right.

Quoted 3 lines

Therefore, the CPUs not seeing the int3 inbetween state will be forced to issue a serializing instruction while the int3 is in place anyway.

By the way, in kprobes, we just use a text_poke() to put int3. I assume that we'd better send IPI afterward, wouldn't it?

Only if you need to ensure that you reached a state where all CPUs are seeing the int3.

Note that kprobes already issues synchronize_sched() after breakpoint removal, which should have a similar effect. However, AFAIK, it does not synchronize after inserting the int3.

Thanks,

Mathieu

Quoted 12 lines

Thank you,

Signature · 7 lines
Masami Hiramatsu

Software Engineer
Hitachi Computer Products (America), Inc.
Software Solutions Division

e-mail: [email protected]
Signature · 2 lines
Mathieu Desnoyers
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68
#29 lore raw

RFC PATCH 3/8 jump label v4 - move opcode definitions

In reply to Jason Baron

Move x86 opcode macros from arch/x86/include/asm/kprobes.h to arch/x86/include/asm/alternative.h so they are useful outside of kprobes.

---
 arch/x86/include/asm/alternative.h |    5 +++++
 arch/x86/include/asm/kprobes.h     |    4 ----
 2 files changed, 5 insertions(+), 4 deletions(-)
arch/x86/include/asm/alternative.h +5 -0
index 9b856b7..7a7d457 100644
@@ -166,6 +166,11 @@ static inline void apply_paravirt(struct paravirt_patch_site *start,
  */
 extern void *text_poke(void *addr, const void *opcode, size_t len);
 
+#define BREAKPOINT_INSTRUCTION  0xcc
+#define RELATIVEJUMP_OPCODE 0xe9
+#define RELATIVEJUMP_SIZE 5
+#define MAX_INSN_SIZE 16
+
 /*
  * Setup int3 trap and fixup execution for cross-modifying on SMP case.
  * If the other cpus execute modifying instruction, it will hit int3
arch/x86/include/asm/kprobes.h +0 -4
index febab97..15b1b12 100644
@@ -31,10 +31,6 @@ struct pt_regs;
 struct kprobe;
 
 typedef u8 kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xcc
-#define RELATIVEJUMP_OPCODE 0xe9
-#define RELATIVEJUMP_SIZE 5
-#define MAX_INSN_SIZE 16
 #define MAX_STACK_SIZE 64
 #define MIN_STACK_SIZE(ADDR)					       \
 	(((MAX_STACK_SIZE) < (((unsigned long)current_thread_info()) + \
Signature · 1 line
1.6.5.1
#30 lore raw

RFC PATCH 4/8 jump label v4 - notifier atomic call chain notrace

In reply to Jason Baron

notifier atomic call chain notrace

In LTTng, being able to use the atomic notifier from cpu idle entry to ensure the tracer flush the last events in the current subbuffer requires the rcu read-side to be marked "notrace", otherwise it can end up calling back into lockdep and the tracer.

Also apply to the the die notifier.

---
 kernel/notifier.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)
kernel/notifier.c +3 -3
index acd24e7..5bde20a 100644
@@ -148,7 +148,7 @@ int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
 	spin_lock_irqsave(&nh->lock, flags);
 	ret = notifier_chain_unregister(&nh->head, n);
 	spin_unlock_irqrestore(&nh->lock, flags);
-	synchronize_rcu();
+	synchronize_sched();
 	return ret;
 }
 EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister);
@@ -178,9 +178,9 @@ int __kprobes __atomic_notifier_call_chain(struct atomic_notifier_head *nh,
 {
 	int ret;
 
-	rcu_read_lock();
+	rcu_read_lock_sched_notrace();
 	ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);
-	rcu_read_unlock();
+	rcu_read_unlock_sched_notrace();
 	return ret;
 }
 EXPORT_SYMBOL_GPL(__atomic_notifier_call_chain);
Signature · 1 line
1.6.5.1
#31 lore raw

RFC PATCH 5/8 jump label v4 - base patch

In reply to Jason Baron

base patch to implement 'jump labeling'. Based on a new 'asm goto' inline assembly gcc mechanism, we can now branch to labels from an 'asm goto' statment. This allows us to create a 'no-op' fastpath, which can subsequently be patched with a jump to the slowpath code. This is useful for code which might be rarely used, but which we'd like to be able to call, if needed. Tracepoints are the current usecase that these are being implemented for.

the patch is dependent on CONFIG_KPROBES. This is simply due to a reliance on the int3 trap handler code that is only enabled with kprobes. This, could be modified.

---
 include/asm-generic/vmlinux.lds.h |   10 ++-
 include/linux/jump_label.h        |   57 +++++++++++++
 kernel/Makefile                   |    2 +-
 kernel/jump_label.c               |  165 +++++++++++++++++++++++++++++++++++++
 4 files changed, 232 insertions(+), 2 deletions(-)
 create mode 100644 include/linux/jump_label.h
 create mode 100644 kernel/jump_label.c
include/asm-generic/vmlinux.lds.h +9 -1
index 67e6520..83a469d 100644
@@ -167,7 +167,8 @@
 	BRANCH_PROFILE()						\
 	TRACE_PRINTKS()							\
 	FTRACE_EVENTS()							\
-	TRACE_SYSCALLS()
+	TRACE_SYSCALLS()						\
+	JUMP_TABLE()							\
 
 /*
  * Data section helpers
@@ -206,6 +207,7 @@
 		*(__vermagic)		/* Kernel version magic */	\
 		*(__markers_strings)	/* Markers: strings */		\
 		*(__tracepoints_strings)/* Tracepoints: strings */	\
+		*(__jump_strings)/* Jump: strings */	\
 	}								\
 									\
 	.rodata1          : AT(ADDR(.rodata1) - LOAD_OFFSET) {		\
@@ -557,6 +559,12 @@
 #define BUG_TABLE
 #endif
 
+#define JUMP_TABLE()							\
+	. = ALIGN(64);							\
+		VMLINUX_SYMBOL(__start___jump_table) = .;		\
+		*(__jump_table)						\
+		VMLINUX_SYMBOL(__stop___jump_table) = .;		\
+
 #ifdef CONFIG_PM_TRACE
 #define TRACEDATA							\
 	. = ALIGN(4);							\
include/linux/jump_label.h new file +57 -0

57 lines not on this page · raw message

kernel/Makefile +1 -1
index 864ff75..4001389 100644
@@ -10,7 +10,7 @@ obj-y     = sched.o fork.o exec_domain.o panic.o printk.o \
 	    kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
 	    hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \
 	    notifier.o ksysfs.o pm_qos_params.o sched_clock.o cred.o \
-	    async.o
+	    async.o jump_label.o
 obj-y += groups.o
 
 ifdef CONFIG_FUNCTION_TRACER
kernel/jump_label.c new file +165 -0

165 lines not on this page · raw message

Signature · 1 line
1.6.5.1
#32 lore raw

RFC PATCH 6/8 jump label v4 - x86 support

In reply to Jason Baron

add x86 support for jump label. I'm keeping this patch separate so its clear to arch maintainers what was required for x86 support this new feature. hopefully, it wouldn't be too painful for other arches.

---
 arch/x86/include/asm/jump_label.h |   32 ++++++++++++++++++++++
 arch/x86/kernel/Makefile          |    2 +-
 arch/x86/kernel/jump_label.c      |   52 +++++++++++++++++++++++++++++++++++++
 3 files changed, 85 insertions(+), 1 deletions(-)
 create mode 100644 arch/x86/include/asm/jump_label.h
 create mode 100644 arch/x86/kernel/jump_label.c
arch/x86/include/asm/jump_label.h new file +32 -0
new file mode 100644
index 0000000..ac09c1c
@@ -0,0 +1,32 @@
+#ifndef _ASM_X86_JUMP_LABEL_H
+#define _ASM_X86_JUMP_LABEL_H
+
+#include <asm/nops.h>
+
+#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) && \
+	defined(CONFIG_KPROBES)
+# define __HAVE_ARCH_JUMP_LABEL
+#endif
+
+#ifdef __HAVE_ARCH_JUMP_LABEL
+
+# ifdef CONFIG_X86_64
+#  define JUMP_LABEL_NOP P6_NOP5
+# else
+#  define JUMP_LABEL_NOP ".byte 0xe9 \n\t .long 0\n\t"
+# endif
+
+# define JUMP_LABEL(tag, label, cond)				\
+	do {							\
+		extern const char __jlstrtab_##tag[];		\
+		asm goto("1:"					\
+			JUMP_LABEL_NOP				\
+			".pushsection __jump_table,  \"a\" \n\t"\
+			_ASM_PTR "1b, %l[" #label "], %c0 \n\t" \
+			".popsection \n\t"			\
+			: :  "i" (__jlstrtab_##tag) :  : label);\
+	} while (0)
+
+# endif
+
+#endif
arch/x86/kernel/Makefile +1 -1
index d87f09b..6c6fc98 100644
@@ -32,7 +32,7 @@ GCOV_PROFILE_paravirt.o		:= n
 obj-y			:= process_$(BITS).o signal.o entry_$(BITS).o
 obj-y			+= traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
 obj-y			+= time.o ioport.o ldt.o dumpstack.o
-obj-y			+= setup.o x86_init.o i8259.o irqinit.o
+obj-y			+= setup.o x86_init.o i8259.o irqinit.o jump_label.o
 obj-$(CONFIG_X86_VISWS)	+= visws_quirks.o
 obj-$(CONFIG_X86_32)	+= probe_roms_32.o
 obj-$(CONFIG_X86_32)	+= sys_i386_32.o i386_ksyms_32.o
arch/x86/kernel/jump_label.c new file +52 -0

52 lines not on this page · raw message

Signature · 1 line
1.6.5.1
#33 lore raw

RFC PATCH 7/8 jump label v4 - tracepoint support

In reply to Jason Baron

Make use of the jump label infrastructure for tracepoints.

---
 include/linux/tracepoint.h |   34 +++++++++++++++++++---------------
 kernel/tracepoint.c        |    8 ++++++++
 2 files changed, 27 insertions(+), 15 deletions(-)
include/linux/tracepoint.h +19 -15
index f59604e..c18b9c0 100644
@@ -16,6 +16,7 @@
 
 #include <linux/types.h>
 #include <linux/rcupdate.h>
+#include <linux/jump_label.h>
 
 struct module;
 struct tracepoint;
@@ -63,20 +64,22 @@ struct tracepoint {
  * not add unwanted padding between the beginning of the section and the
  * structure. Force alignment to the same alignment as the section start.
  */
-#define DECLARE_TRACE(name, proto, args)				\
-	extern struct tracepoint __tracepoint_##name;			\
-	static inline void trace_##name(proto)				\
-	{								\
-		if (unlikely(__tracepoint_##name.state))		\
-			__DO_TRACE(&__tracepoint_##name,		\
-				TP_PROTO(proto), TP_ARGS(args));	\
-	}								\
-	static inline int register_trace_##name(void (*probe)(proto))	\
-	{								\
-		return tracepoint_probe_register(#name, (void *)probe);	\
-	}								\
-	static inline int unregister_trace_##name(void (*probe)(proto))	\
-	{								\
+#define DECLARE_TRACE(name, proto, args)				 \
+	extern struct tracepoint __tracepoint_##name;			 \
+	static inline void trace_##name(proto)				 \
+	{								 \
+		JUMP_LABEL(name, do_trace, __tracepoint_##name.state);   \
+		return;							 \
+do_trace:								 \
+		__DO_TRACE(&__tracepoint_##name,			 \
+			   TP_PROTO(proto), TP_ARGS(args));		 \
+	}								 \
+	static inline int register_trace_##name(void (*probe)(proto))	 \
+	{								 \
+		return tracepoint_probe_register(#name, (void *)probe);	 \
+	}								 \
+	static inline int unregister_trace_##name(void (*probe)(proto))	 \
+	{								 \
 		return tracepoint_probe_unregister(#name, (void *)probe);\
 	}
 
@@ -86,7 +89,8 @@ struct tracepoint {
 	__attribute__((section("__tracepoints_strings"))) = #name;	\
 	struct tracepoint __tracepoint_##name				\
 	__attribute__((section("__tracepoints"), aligned(32))) =	\
-		{ __tpstrtab_##name, 0, reg, unreg, NULL }
+		{ __tpstrtab_##name, 0, reg, unreg, NULL };		\
+	DEFINE_JUMP_LABEL(name);
 
 #define DEFINE_TRACE(name)						\
 	DEFINE_TRACE_FN(name, NULL, NULL);
kernel/tracepoint.c +8 -0
index cc89be5..8acced8 100644
@@ -25,6 +25,7 @@
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
+#include <linux/jump_label.h>
 
 extern struct tracepoint __start___tracepoints[];
 extern struct tracepoint __stop___tracepoints[];
@@ -256,6 +257,10 @@ static void set_tracepoint(struct tracepoint_entry **entry,
 	 * is used.
 	 */
 	rcu_assign_pointer(elem->funcs, (*entry)->funcs);
+	if (!elem->state && active)
+		enable_jump_label(elem->name);
+	if (elem->state && !active)
+		disable_jump_label(elem->name);
 	elem->state = active;
 }
 
@@ -270,6 +275,9 @@ static void disable_tracepoint(struct tracepoint *elem)
 	if (elem->unregfunc && elem->state)
 		elem->unregfunc();
 
+	if (elem->state)
+		disable_jump_label(elem->name);
+
 	elem->state = 0;
 	rcu_assign_pointer(elem->funcs, NULL);
 }
Signature · 1 line
1.6.5.1
#34 lore raw

RFC PATCH 8/8 jump label v4 - add module support

In reply to Jason Baron

Add support for 'jump label' for modules.

---
 arch/x86/kernel/ptrace.c   |    1 +
 include/linux/jump_label.h |    3 +-
 include/linux/module.h     |    5 +-
 kernel/jump_label.c        |  136 ++++++++++++++++++++++++++++++++++++++++++++
 kernel/module.c            |    7 ++
 5 files changed, 150 insertions(+), 2 deletions(-)
arch/x86/kernel/ptrace.c +1 -0
index 017d937..94f5355 100644
@@ -24,6 +24,7 @@
 #include <linux/workqueue.h>
 #include <linux/perf_event.h>
 #include <linux/hw_breakpoint.h>
+#include <linux/module.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
include/linux/jump_label.h +2 -1
index 3d42e8c..fa81c0a 100644
@@ -21,7 +21,8 @@ extern struct jump_entry __stop___jump_table[];
 
 #define DEFINE_JUMP_LABEL(name)						\
 	const char __jlstrtab_##name[]					\
-	__used __attribute__((section("__jump_strings")))  = #name;
+	__used __attribute__((section("__jump_strings")))  = #name;	\
+	EXPORT_SYMBOL_GPL(__jlstrtab_##name);
 
 extern void arch_jump_label_transform(struct jump_entry *entry,
 				 enum jump_label_type type);
include/linux/module.h +4 -1
index 6cb1a3c..df499cf 100644
@@ -339,7 +339,10 @@ struct module
 	struct tracepoint *tracepoints;
 	unsigned int num_tracepoints;
 #endif
-
+#ifdef __HAVE_ARCH_JUMP_LABEL
+	struct jump_entry *jump_entries;
+	unsigned int num_jump_entries;
+#endif
 #ifdef CONFIG_TRACING
 	const char **trace_bprintk_fmt_start;
 	unsigned int num_trace_bprintk_fmt;
kernel/jump_label.c +136 -0

152 lines not on this page · raw message

kernel/module.c +7 -0
index f82386b..4324bb1 100644
@@ -55,6 +55,7 @@
 #include <linux/async.h>
 #include <linux/percpu.h>
 #include <linux/kmemleak.h>
+#include <linux/jump_label.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/module.h>
@@ -2245,6 +2246,12 @@ static noinline struct module *load_module(void __user *umod,
 					sizeof(*mod->tracepoints),
 					&mod->num_tracepoints);
 #endif
+#ifdef __HAVE_ARCH_JUMP_LABEL
+	mod->jump_entries = section_objs(hdr, sechdrs, secstrings,
+					"__jump_table",
+					sizeof(*mod->jump_entries),
+					&mod->num_jump_entries);
+#endif
 #ifdef CONFIG_EVENT_TRACING
 	mod->trace_events = section_objs(hdr, sechdrs, secstrings,
 					 "_ftrace_events",
Signature · 1 line
1.6.5.1