tracing vs world
Subsystems (27)
Peter Zijlstra
maintainerv4 cover tracing vs world
Hi all,
These here patches are the result of Mathieu and Steve trying to get commit 865e63b04e9b2 ("tracing: Add back in rcu_irq_enter/exit_irqson() for rcuidle tracepoints") reverted again.
One of the things discovered is that tracing MUST NOT happen before nmi_enter() or after nmi_exit(). Audit results of the previous version are still valid.
This then snowballed into auditing other exceptions, notably #MC, and #BP. Lots of patches came out of that.
I would love for some tooling in this area. Dan, smatch has full callchains right? Would it be possible to have an __assert_no_tracing__() marker of sorts that validates that no possible callchain reaching that assertion has hit tracing before that point?
It would mean you have to handle the various means of 'notrace' annotation (both the function attribute as well as the Makefile rules), recognising tracepoints and ideally handling NOKPROBE annotations.
NOTE:
patches 19,20,21 already live in tip/locking/kcsan and are included here because 20,21 are needed for the patches following to make sense. If/when this gets merged, we need to figure out how to resolve this.
Changes since -v3:
- Replaced the #DF patch with one from Boris
- Moved trace_rcu_{enter,exit}() into rcupdate.h
- Flipped TIF_SIGPENDING and TIF_NOTIFY_RESUME handling
- Added comment to nmi_enter()
- fixed various compile fails
- inlined bsearch()
- Added lockdep checking for USED <- IN-NMI recursion
- Added rcu_nmi_enter vs kprobes comment
Changes since -v2:
- #MC / ist_enter() audit -- first 4 patches. After this in_nmi() should always be set 'correctly'.
- RCU IRQ enter/exit function simplification
- #BP / poke_int3_handler() audit -- last many patches.
- pulled in some locking/kcsan patches
Changes since -v1:
- Added tags
- Changed #4; changed nmi_enter() to use __preempt_count_add() vs marking preempt_count_add() notrace.
- Changed #5; confusion on which functions are notrace due to Makefile
- Added #9; remove limitation on the perf-function-trace coupling
Peter Zijlstra
maintainerPATCH v4 1/27 lockdep: Teach lockdep about "USED" <- "IN-NMI" inversions
nmi_enter() does lockdep_off() and hence lockdep ignores everything.
And NMI context makes it impossible to do full IN-NMI tracking like we do IN-HARDIRQ, that could result in graph_lock recursion.
However, since look_up_lock_class() is lockless, we can find the class of a lock that has prior use and detect IN-NMI after USED, just not USED after IN-NMI.
NOTE: By shifting the lockdep_off() recursion count to bit-16, we can easily differentiate between actual recursion and off.
--- kernel/locking/lockdep.c | 53 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 3 deletions(-)
kernel/locking/lockdep.c +50 -3
@@ -379,13 +379,13 @@ void lockdep_init_task(struct task_strucvoid lockdep_off (void ) { - current->lockdep_recursion++; + current->lockdep_recursion +=BIT (16 ); }EXPORT_SYMBOL (lockdep_off);void lockdep_on (void ) { - current->lockdep_recursion--; + current->lockdep_recursion -=BIT (16 ); }EXPORT_SYMBOL (lockdep_on);
@@ -575,6 +575,7 @@ static const char *usage_str[] =#include "lockdep_states.h" #undef LOCKDEP_STATE [LOCK_USED] = "INITIAL USE", + [LOCK_USAGE_STATES] = "IN-NMI", };#endif
@@ -787,6 +788,7 @@ static int count_matching_names(struct lreturn count +1 ; } +/* used from NMI context -- must be lockless */ static inline struct lock_class *look_up_lock_class (const struct lockdep_map *lock,unsigned int subclass) {
@@ -4463,6 +4465,34 @@ void lock_downgrade(struct lockdep_map * }EXPORT_SYMBOL_GPL (lock_downgrade); +/* NMI context !!! */ +static void verify_lock_unused (struct lockdep_map *lock,struct held_lock *hlock,int subclass) +{ +struct lock_class *class =look_up_lock_class (lock, subclass); + +/* if it doesn't have a class (yet), it certainly hasn't been used yet */ +if (!class) +return ; + +if (!(class->usage_mask &LOCK_USED )) +return ; + + hlock->class_idx = class - lock_classes; + +print_usage_bug (current, hlock,LOCK_USED ,LOCK_USAGE_STATES ); +} + +static bool lockdep_nmi (void ) +{ +if (current->lockdep_recursion &0xFFFF ) +return false; + +if (!in_nmi ()) +return false; + +return true; +} +/* * We are not always called with irqs disabled - do that here, * and also avoid lockdep recursion:
@@ -4473,8 +4503,25 @@ void lock_acquire(struct lockdep_map *lo {unsigned long flags; -if (unlikely (current->lockdep_recursion)) +if (unlikely (current->lockdep_recursion)) { +/* XXX allow trylock from NMI ?!? */ +if (lockdep_nmi () && !trylock) { +struct held_lock hlock; + + hlock.acquire_ip = ip; + hlock.instance = lock; + hlock.nest_lock = nest_lock; + hlock.irq_context =2 ;// XXX + hlock.trylock = trylock; + hlock.read = read; + hlock.check = check; + hlock.hardirqs_off = true; + hlock.references =0 ; + +verify_lock_unused (lock, &hlock, subclass); + }return ; + }raw_local_irq_save (flags);check_flags (flags);
Steven Rostedt
maintainerRe: [PATCH v4 01/27] lockdep: Teach lockdep about "USED" <- "IN-NMI" inversions
Quoted 13 lines · On Fri, 21 Feb 2020 14:34:17 +0100 Peter Zijlstra <[email protected]> wrote:
kernel/locking/lockdep.c +1
-1@@ -379,13 +379,13 @@ void lockdep_init_task(struct task_strucvoid lockdep_off (void ) { - current->lockdep_recursion++; + current->lockdep_recursion +=BIT (16 ); }EXPORT_SYMBOL (lockdep_off);void lockdep_on (void ) {
kernel/locking/lockdep.c void lockdep_init_task(struct task_struc
Quoted 10 lines
kernel/locking/lockdep.c +5
-1- current->lockdep_recursion--; + current->lockdep_recursion -=BIT (16 ); }EXPORT_SYMBOL (lockdep_on); + +static bool lockdep_nmi (void ) +{ +if (current->lockdep_recursion &0xFFFF )
Nitpick, but the association with bit 16 and this mask really should be defined as a macro somewhere and not have hard coded numbers.
-- Steve
Quoted 8 lines
kernel/locking/lockdep.c +8
-0+return false; + +if (!in_nmi ()) +return false; + +return true; +} +
Peter Zijlstra
maintainerRe: [PATCH v4 01/27] lockdep: Teach lockdep about "USED" <- "IN-NMI" inversions
Quoted 22 lines · Steven Rostedt
Quoted 18 lines · On Fri, 21 Feb 2020 14:34:17 +0100 Peter Zijlstra <[email protected]> wrote:
kernel/locking/lockdep.c +2
-2@@ -379,13 +379,13 @@ void lockdep_init_task(struct task_strucvoid lockdep_off (void ) { - current->lockdep_recursion++; + current->lockdep_recursion +=BIT (16 ); }EXPORT_SYMBOL (lockdep_off);void lockdep_on (void ) { - current->lockdep_recursion--; + current->lockdep_recursion -=BIT (16 ); }EXPORT_SYMBOL (lockdep_on);
Quoted 7 lines
kernel/locking/lockdep.c void lock_downgrade(struct lockdep_map * · line 4487
Quoted 4 lines
kernel/locking/lockdep.c +4
-0+ +static bool lockdep_nmi (void ) +{ +if (current->lockdep_recursion &0xFFFF )Nitpick, but the association with bit 16 and this mask really should be defined as a macro somewhere and not have hard coded numbers.
Right, I suppose I can do something like:
#define LOCKDEP_RECURSION_BITS 16
#define LOCKDEP_OFF (1U << LOCKDEP_RECURSION_BITS) #define LOCKDEP_RECURSION_MASK (LOCKDEP_OFF - 1)
Steven Rostedt
maintainerRe: [PATCH v4 01/27] lockdep: Teach lockdep about "USED" <- "IN-NMI" inversions
Quoted 8 lines · On Fri, 21 Feb 2020 21:25:11 +0100 Peter Zijlstra <[email protected]> wrote:
Quoted 2 lines
Nitpick, but the association with bit 16 and this mask really should be defined as a macro somewhere and not have hard coded numbers.
Right, I suppose I can do something like:
#define
LOCKDEP_RECURSION_BITS16
#defineLOCKDEP_OFF(1U <<LOCKDEP_RECURSION_BITS) #defineLOCKDEP_RECURSION_MASK(LOCKDEP_OFF- 1)
LGTM
-- Steve
Re: [PATCH v4 01/27] lockdep: Teach lockdep about "USED" <- "IN-NMI" inversions
In reply to Peter ZijlstraQuoted 31 lines · Peter Zijlstra
Quoted 22 lines · Steven Rostedt
Quoted 18 lines · On Fri, 21 Feb 2020 14:34:17 +0100 Peter Zijlstra <[email protected]> wrote:
kernel/locking/lockdep.c +2
-2@@ -379,13 +379,13 @@ void lockdep_init_task(struct task_strucvoid lockdep_off (void ) { - current->lockdep_recursion++; + current->lockdep_recursion +=BIT (16 ); }EXPORT_SYMBOL (lockdep_off);void lockdep_on (void ) { - current->lockdep_recursion--; + current->lockdep_recursion -=BIT (16 ); }EXPORT_SYMBOL (lockdep_on);Quoted 7 lines
kernel/locking/lockdep.c void lock_downgrade(struct lockdep_map * · line 4487
Quoted 4 lines
kernel/locking/lockdep.c +4
-0+ +static bool lockdep_nmi (void ) +{ +if (current->lockdep_recursion &0xFFFF )Nitpick, but the association with bit 16 and this mask really should be defined as a macro somewhere and not have hard coded numbers.
Quoted 5 lines
Right, I suppose I can do something like:
#define
LOCKDEP_RECURSION_BITS16
#defineLOCKDEP_OFF(1U <<LOCKDEP_RECURSION_BITS) #defineLOCKDEP_RECURSION_MASK(LOCKDEP_OFF- 1)
With that I'd say
Re: [PATCH v4 01/27] lockdep: Teach lockdep about "USED" <- "IN-NMI" inversions
In reply to Peter ZijlstraQuoted 4 lines · Peter Zijlstra
nmi_enter()doeslockdep_off()and hence lockdep ignores everything.And NMI context makes it impossible to do full IN-NMI tracking like we do IN-HARDIRQ, that could result in
graph_lockrecursion.
The patch makes sense to me.
NOTE:
Also, I was wondering if we can detect the graph_lock recursion case and avoid doing anything bad, that way we enable more of the lockdep functionality for NMI where possible. Not sure if the suggestion makes sense though!
thanks,
- Joel
Quoted 110 lines
However, since
look_up_lock_class()is lockless, we can find the class of a lock that has prior use and detect IN-NMI after USED, just not USED after IN-NMI.NOTE: By shifting the
lockdep_off()recursion count to bit-16, we can easily differentiate between actual recursion and off.Signed-off-by Peter Zijlstra (Intel) <[email protected]>--- kernel/locking/lockdep.c | 53 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 3 deletions(-)kernel/locking/lockdep.c +50
-3@@ -379,13 +379,13 @@ void lockdep_init_task(struct task_strucvoid lockdep_off (void ) { - current->lockdep_recursion++; + current->lockdep_recursion +=BIT (16 ); }EXPORT_SYMBOL (lockdep_off);void lockdep_on (void ) { - current->lockdep_recursion--; + current->lockdep_recursion -=BIT (16 ); }EXPORT_SYMBOL (lockdep_on);@@ -575,6 +575,7 @@ static const char *usage_str[] =#include "lockdep_states.h" #undef LOCKDEP_STATE [LOCK_USED] = "INITIAL USE", + [LOCK_USAGE_STATES] = "IN-NMI", };#endif @@ -787,6 +788,7 @@ static int count_matching_names(struct lreturn count +1 ; } +/* used from NMI context -- must be lockless */ static inline struct lock_class *look_up_lock_class (const struct lockdep_map *lock,unsigned int subclass) {@@ -4463,6 +4465,34 @@ void lock_downgrade(struct lockdep_map * }EXPORT_SYMBOL_GPL (lock_downgrade); +/* NMI context !!! */ +static void verify_lock_unused (struct lockdep_map *lock,struct held_lock *hlock,int subclass) +{ +struct lock_class *class =look_up_lock_class (lock, subclass); + +/* if it doesn't have a class (yet), it certainly hasn't been used yet */ +if (!class) +return ; + +if (!(class->usage_mask &LOCK_USED )) +return ; + + hlock->class_idx = class - lock_classes; + +print_usage_bug (current, hlock,LOCK_USED ,LOCK_USAGE_STATES ); +} + +static bool lockdep_nmi (void ) +{ +if (current->lockdep_recursion &0xFFFF ) +return false; + +if (!in_nmi ()) +return false; + +return true; +} +/* * We are not always called with irqs disabled - do that here, * and also avoid lockdep recursion: @@ -4473,8 +4503,25 @@ void lock_acquire(struct lockdep_map *lo {unsigned long flags; -if (unlikely (current->lockdep_recursion)) +if (unlikely (current->lockdep_recursion)) { +/* XXX allow trylock from NMI ?!? */ +if (lockdep_nmi () && !trylock) { +struct held_lock hlock; + + hlock.acquire_ip = ip; + hlock.instance = lock; + hlock.nest_lock = nest_lock; + hlock.irq_context =2 ;// XXX + hlock.trylock = trylock; + hlock.read = read; + hlock.check = check; + hlock.hardirqs_off = true; + hlock.references =0 ; + +verify_lock_unused (lock, &hlock, subclass); + }return ; + }raw_local_irq_save (flags);check_flags (flags);
Peter Zijlstra
maintainerRe: [PATCH v4 01/27] lockdep: Teach lockdep about "USED" <- "IN-NMI" inversions
Quoted 8 lines · Joel Fernandes
Quoted 4 lines · Peter Zijlstra
nmi_enter()doeslockdep_off()and hence lockdep ignores everything.And NMI context makes it impossible to do full IN-NMI tracking like we do IN-HARDIRQ, that could result in
graph_lockrecursion.The patch makes sense to me.
Quoted 7 lines
Reviewed-by Joel Fernandes (Google) <[email protected]>NOTE:
Also, I was wondering if we can detect thegraph_lockrecursion case and avoid doing anything bad, that way we enable more of the lockdep functionality for NMI where possible. Not sure if the suggestion makes sense though!
Yeah, I considered playing trylock games, but figured I shouldn't make it more complicated that it needs to be.
Re: [PATCH v4 01/27] lockdep: Teach lockdep about "USED" <- "IN-NMI" inversions
Quoted 11 lines · Peter Zijlstra
Quoted 10 lines · Joel Fernandes
Quoted 4 lines · Peter Zijlstra
nmi_enter()doeslockdep_off()and hence lockdep ignores everything.And NMI context makes it impossible to do full IN-NMI tracking like we do IN-HARDIRQ, that could result in
graph_lockrecursion.The patch makes sense to me.
Reviewed-by Joel Fernandes (Google) <[email protected]>
Quoted 8 lines
Quoted 5 lines
NOTE:
Also, I was wondering if we can detect thegraph_lockrecursion case and avoid doing anything bad, that way we enable more of the lockdep functionality for NMI where possible. Not sure if the suggestion makes sense though!Yeah, I considered playing trylock games, but figured I shouldn't make it more complicated that it needs to be.
Yes, I agree with you. Thanks.
- Joel
[tip: locking/core] lockdep: Teach lockdep about "USED" <- "IN-NMI" inversions
In reply to Peter ZijlstraThe following commit has been merged into the locking/core branch of tip:
The following commit has been merged into the locking/core branch of tip:
Commit-ID: f6f48e18040402136874a6a71611e081b4d0788a Gitweb: https://git.kernel.org/tip/f6f48e18040402136874a6a71611e081b4d0788a Author: Peter Zijlstra <[email protected]> AuthorDate: Thu, 20 Feb 2020 09:45:02 +01:00 Committer: Peter Zijlstra <[email protected]> CommitterDate: Fri, 20 Mar 2020 13:06:25 +01:00
lockdep: Teach lockdep about "USED" <- "IN-NMI" inversions
nmi_enter() does lockdep_off() and hence lockdep ignores everything.
And NMI context makes it impossible to do full IN-NMI tracking like we do IN-HARDIRQ, that could result in graph_lock recursion.
However, since look_up_lock_class() is lockless, we can find the class of a lock that has prior use and detect IN-NMI after USED, just not USED after IN-NMI.
NOTE: By shifting the lockdep_off() recursion count to bit-16, we can easily differentiate between actual recursion and off.
--- kernel/locking/lockdep.c | 62 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 3 deletions(-)
kernel/locking/lockdep.c +59 -3
@@ -393,15 +393,22 @@ void lockdep_init_task(struct task_struct *task) task->lockdep_recursion =0 ; } +/* +* Split the recrursion counter in two to readily detect 'off' vs recursion. +*/ +#define LOCKDEP_RECURSION_BITS 16 +#define LOCKDEP_OFF (1U << LOCKDEP_RECURSION_BITS) +#define LOCKDEP_RECURSION_MASK (LOCKDEP_OFF - 1) +void lockdep_off (void ) { - current->lockdep_recursion++; + current->lockdep_recursion +=LOCKDEP_OFF ; }EXPORT_SYMBOL (lockdep_off);void lockdep_on (void ) { - current->lockdep_recursion--; + current->lockdep_recursion -=LOCKDEP_OFF ; }EXPORT_SYMBOL (lockdep_on);
@@ -597,6 +604,7 @@ static const char *usage_str[] =#include "lockdep_states.h" #undef LOCKDEP_STATE [LOCK_USED] = "INITIAL USE", + [LOCK_USAGE_STATES] = "IN-NMI", };#endif
@@ -809,6 +817,7 @@ static int count_matching_names(struct lock_class *new_class)return count +1 ; } +/* used from NMI context -- must be lockless */ static inline struct lock_class *look_up_lock_class (const struct lockdep_map *lock,unsigned int subclass) {
@@ -4720,6 +4729,36 @@ void lock_downgrade(struct lockdep_map *lock, unsigned long ip) }EXPORT_SYMBOL_GPL (lock_downgrade); +/* NMI context !!! */ +static void verify_lock_unused (struct lockdep_map *lock,struct held_lock *hlock,int subclass) +{ +#ifdef CONFIG_PROVE_LOCKING +struct lock_class *class =look_up_lock_class (lock, subclass); + +/* if it doesn't have a class (yet), it certainly hasn't been used yet */ +if (!class) +return ; + +if (!(class->usage_mask &LOCK_USED )) +return ; + + hlock->class_idx = class - lock_classes; + +print_usage_bug (current, hlock,LOCK_USED ,LOCK_USAGE_STATES ); +#endif +} + +static bool lockdep_nmi (void ) +{ +if (current->lockdep_recursion &LOCKDEP_RECURSION_MASK ) +return false; + +if (!in_nmi ()) +return false; + +return true; +} +/* * We are not always called with irqs disabled - do that here, * and also avoid lockdep recursion:
@@ -4730,8 +4769,25 @@ void lock_acquire(struct lockdep_map *lock, unsigned int subclass, {unsigned long flags; -if (unlikely (current->lockdep_recursion)) +if (unlikely (current->lockdep_recursion)) { +/* XXX allow trylock from NMI ?!? */ +if (lockdep_nmi () && !trylock) { +struct held_lock hlock; + + hlock.acquire_ip = ip; + hlock.instance = lock; + hlock.nest_lock = nest_lock; + hlock.irq_context =2 ;// XXX + hlock.trylock = trylock; + hlock.read = read; + hlock.check = check; + hlock.hardirqs_off = true; + hlock.references =0 ; + +verify_lock_unused (lock, &hlock, subclass); + }return ; + }raw_local_irq_save (flags);check_flags (flags);
Peter Zijlstra
maintainerPATCH v4 2/27 hardirq/nmi: Allow nested nmi_enter()
In reply to Peter ZijlstraSince there are already a number of sites (ARM64, PowerPC) that effectively nest nmi_enter(), lets make the primitive support this before adding even more.
--- arch/arm64/include/asm/hardirq.h | 4 ++-- arch/arm64/kernel/sdei.c | 14 ++------------ arch/arm64/kernel/traps.c | 8 ++------ arch/powerpc/kernel/traps.c | 22 ++++++---------------- include/linux/hardirq.h | 5 ++++- include/linux/preempt.h | 4 ++-- kernel/printk/printk_safe.c | 6 ++++-- 7 files changed, 22 insertions(+), 41 deletions(-)
arch/arm64/include/asm/hardirq.h +2 -2
@@ -38,7 +38,7 @@ DECLARE_PER_CPU(struct nmi_ctx, nmi_cont#define arch_nmi_enter () \ do { \ - if (is_kernel_in_hyp_mode()) { \ + if (is_kernel_in_hyp_mode() && !in_nmi()) { \ struct nmi_ctx *nmi_ctx = this_cpu_ptr(&nmi_contexts); \ nmi_ctx->hcr = read_sysreg(hcr_el2); \ if (!(nmi_ctx->hcr & HCR_TGE)) { \
@@ -50,7 +50,7 @@ DECLARE_PER_CPU(struct nmi_ctx, nmi_cont#define arch_nmi_exit () \ do { \ - if (is_kernel_in_hyp_mode()) { \ + if (is_kernel_in_hyp_mode() && !in_nmi()) { \ struct nmi_ctx *nmi_ctx = this_cpu_ptr(&nmi_contexts); \ if (!(nmi_ctx->hcr & HCR_TGE)) \ write_sysreg(nmi_ctx->hcr, hcr_el2); \
arch/arm64/kernel/sdei.c +2 -12
@@ -251,22 +251,12 @@ asmlinkage __kprobes notrace unsigned lo __sdei_handler(struct pt_regs *regs, struct sdei_registered_event *arg) { unsigned long ret; -bool do_nmi_exit = false; -/* -* nmi_enter() deals with printk() re-entrance and use of RCU when -* RCU believed this CPU was idle. Because critical events can -* interrupt normal events, we may already be in_nmi(). -*/ -if (!in_nmi ()) { -nmi_enter (); - do_nmi_exit = true; - } +nmi_enter (); ret =_sdei_handler (regs, arg); -if (do_nmi_exit) -nmi_exit (); +nmi_exit ();return ret; }
arch/arm64/kernel/traps.c +2 -6
@@ -906,17 +906,13 @@ bool arm64_is_fatal_ras_serror(struct pt asmlinkage void do_serror(struct pt_regs *regs, unsigned int esr) { -const bool was_in_nmi =in_nmi (); - -if (!was_in_nmi) -nmi_enter (); +nmi_enter ();/* non-RAS errors are not containable */ if (!arm64_is_ras_serror (esr) ||arm64_is_fatal_ras_serror (regs, esr))arm64_serror_panic (regs, esr); -if (!was_in_nmi) -nmi_exit (); +nmi_exit (); } asmlinkage void enter_from_user_mode(void)
arch/powerpc/kernel/traps.c +6 -16
@@ -441,15 +441,9 @@ void hv_nmi_check_nonrecoverable(structvoid system_reset_exception (struct pt_regs *regs) {unsigned long hsrr0, hsrr1; -bool nested =in_nmi ();bool saved_hsrrs = false; -/* -* Avoid crashes in case of nested NMI exceptions. Recoverability -* is determined by RI and in_nmi -*/ -if (!nested) -nmi_enter (); +nmi_enter ();/* * System reset can interrupt code where HSRRs are live and MSR[RI]=1.
@@ -521,8 +515,7 @@ void system_reset_exception(struct pt_remtspr (SPRN_HSRR1 , hsrr1); } -if (!nested) -nmi_exit (); +nmi_exit ();/* What should we do here? We could issue a shutdown or hard reset. */ }
@@ -823,9 +816,8 @@ int machine_check_generic(struct pt_regsvoid machine_check_exception (struct pt_regs *regs) {int recover =0 ; -bool nested =in_nmi (); -if (!nested) -nmi_enter (); + +nmi_enter ();__this_cpu_inc (irq_stat.mce_exceptions);
@@ -851,8 +843,7 @@ void machine_check_exception(struct pt_rif (check_io_access (regs)) goto bail; -if (!nested) -nmi_exit (); +nmi_exit ();die ("Machine check" , regs,SIGBUS );
@@ -863,8 +854,7 @@ void machine_check_exception(struct pt_rreturn ; bail: -if (!nested) -nmi_exit (); +nmi_exit (); }void SMIException (struct pt_regs *regs)
include/linux/hardirq.h +4 -1
@@ -65,13 +65,16 @@ extern void irq_exit(void);#define arch_nmi_exit () do { } while (0)#endif +/* +* nmi_enter() can nest up to 15 times; see NMI_BITS. +*/ #define nmi_enter () \ do { \ arch_nmi_enter(); \ printk_nmi_enter(); \ lockdep_off(); \ ftrace_nmi_enter(); \ - BUG_ON(in_nmi()); \ + BUG_ON(in_nmi() == NMI_MASK); \ preempt_count_add(NMI_OFFSET + HARDIRQ_OFFSET); \ rcu_nmi_enter(); \ trace_hardirq_enter(); \
include/linux/preempt.h +2 -2
@@ -26,13 +26,13 @@* PREEMPT_MASK: 0x000000ff * SOFTIRQ_MASK: 0x0000ff00 * HARDIRQ_MASK: 0x000f0000 -* NMI_MASK: 0x00100000 +* NMI_MASK: 0x00f00000 * PREEMPT_NEED_RESCHED: 0x80000000 */ #define PREEMPT_BITS 8#define SOFTIRQ_BITS 8#define HARDIRQ_BITS 4 -#define NMI_BITS 1 +#define NMI_BITS 4#define PREEMPT_SHIFT 0#define SOFTIRQ_SHIFT (PREEMPT_SHIFT + PREEMPT_BITS)
kernel/printk/printk_safe.c +4 -2
@@ -296,12 +296,14 @@ static __printf(1, 0) int vprintk_nmi(co void notrace printk_nmi_enter(void) { -this_cpu_or (printk_context,PRINTK_NMI_CONTEXT_MASK ); +if (!in_nmi ()) +this_cpu_or (printk_context,PRINTK_NMI_CONTEXT_MASK ); } void notrace printk_nmi_exit(void) { -this_cpu_and (printk_context, ~PRINTK_NMI_CONTEXT_MASK ); +if (!in_nmi ()) +this_cpu_and (printk_context, ~PRINTK_NMI_CONTEXT_MASK ); }/*
Frederic Weisbecker
maintainerRe: [PATCH v4 02/27] hardirq/nmi: Allow nested nmi_enter()
Quoted 25 lines · Peter Zijlstra
Since there are already a number of sites (ARM64, PowerPC) that effectively nest
nmi_enter(), lets make the primitive support this before adding even more.Signed-off-by Peter Zijlstra (Intel) <[email protected]>Reviewed-by Petr Mladek <[email protected]>Acked-by Will Deacon <[email protected]>Acked-by Marc Zyngier <[email protected]>--- arch/arm64/include/asm/hardirq.h | 4 ++-- arch/arm64/kernel/sdei.c | 14 ++------------ arch/arm64/kernel/traps.c | 8 ++------ arch/powerpc/kernel/traps.c | 22 ++++++---------------- include/linux/hardirq.h | 5 ++++- include/linux/preempt.h | 4 ++-- kernel/printk/printk_safe.c | 6 ++++-- 7 files changed, 22 insertions(+), 41 deletions(-)kernel/printk/printk_safe.c +0
-1@@ -296,12 +296,14 @@ static __printf(1, 0) int vprintk_nmi(co void notrace printk_nmi_enter(void) { -this_cpu_or (printk_context,PRINTK_NMI_CONTEXT_MASK );
kernel/printk/printk_safe.c static __printf(1, 0) int vprintk_nmi(co · line 307
Quoted 10 lines
kernel/printk/printk_safe.c +4
-1+if (!in_nmi ()) +this_cpu_or (printk_context,PRINTK_NMI_CONTEXT_MASK ); } void notrace printk_nmi_exit(void) { -this_cpu_and (printk_context, ~PRINTK_NMI_CONTEXT_MASK ); +if (!in_nmi ()) +this_cpu_and (printk_context, ~PRINTK_NMI_CONTEXT_MASK ); }
If the outermost NMI is interrupted while between printk_nmi_enter() and preempt_count_add(), there is still a risk that we race and clear?
Petr Mladek
maintainerRe: [PATCH v4 02/27] hardirq/nmi: Allow nested nmi_enter()
Quoted 30 lines · Frederic Weisbecker
Quoted 29 lines · Peter Zijlstra
Since there are already a number of sites (ARM64, PowerPC) that effectively nest
nmi_enter(), lets make the primitive support this before adding even more.Signed-off-by Peter Zijlstra (Intel) <[email protected]>Reviewed-by Petr Mladek <[email protected]>Acked-by Will Deacon <[email protected]>Acked-by Marc Zyngier <[email protected]>--- arch/arm64/include/asm/hardirq.h | 4 ++-- arch/arm64/kernel/sdei.c | 14 ++------------ arch/arm64/kernel/traps.c | 8 ++------ arch/powerpc/kernel/traps.c | 22 ++++++---------------- include/linux/hardirq.h | 5 ++++- include/linux/preempt.h | 4 ++-- kernel/printk/printk_safe.c | 6 ++++-- 7 files changed, 22 insertions(+), 41 deletions(-)kernel/printk/printk_safe.c +2
-1@@ -296,12 +296,14 @@ static __printf(1, 0) int vprintk_nmi(co void notrace printk_nmi_enter(void) { -this_cpu_or (printk_context,PRINTK_NMI_CONTEXT_MASK ); +if (!in_nmi ()) +this_cpu_or (printk_context,PRINTK_NMI_CONTEXT_MASK ); }
Quoted 9 lines
kernel/printk/printk_safe.c static __printf(1, 0) int vprintk_nmi(co · line 307
Quoted 6 lines
kernel/printk/printk_safe.c +2
-1void notrace printk_nmi_exit(void) { -this_cpu_and (printk_context, ~PRINTK_NMI_CONTEXT_MASK ); +if (!in_nmi ()) +this_cpu_and (printk_context, ~PRINTK_NMI_CONTEXT_MASK ); }If the outermost NMI is interrupted while between
printk_nmi_enter()andpreempt_count_add(), there is still a risk that we race and clear?
Great catch!
There is plenty of space in the printk_context variable. I would reserve one byte there for the NMI context to be on the safe side and be done with it.
It should never overflow. The BUG_ON(in_nmi() == NMI_MASK) in nmi_enter() will trigger much earlier.
Also I hope that printk_context will get removed with the lockless printk() implementation soon anyway.
kernel/printk/internal.h +5 -3
@@ -6,9 +6,11 @@#ifdef CONFIG_PRINTK -#define PRINTK_SAFE_CONTEXT_MASK 0x3fffffff -#define PRINTK_NMI_DIRECT_CONTEXT_MASK 0x40000000 -#define PRINTK_NMI_CONTEXT_MASK 0x80000000 +#define PRINTK_SAFE_CONTEXT_MASK 0x007ffffff +#define PRINTK_NMI_DIRECT_CONTEXT_MASK 0x008000000 +#define PRINTK_NMI_CONTEXT_MASK 0xff0000000 + +#define PRINTK_NMI_CONTEXT_OFFSET 0x010000000extern raw_spinlock_t logbuf_lock;
kernel/printk/printk_safe.c +2 -2
@@ -296,12 +296,12 @@ static __printf(1, 0) int vprintk_nmi(const char *fmt, va_list args) void notrace printk_nmi_enter(void) { -this_cpu_or (printk_context,PRINTK_NMI_CONTEXT_MASK ); +this_cpu_add (printk_context,PRINTK_NMI_CONTEXT_OFFSET ); } void notrace printk_nmi_exit(void) { -this_cpu_and (printk_context, ~PRINTK_NMI_CONTEXT_MASK ); +this_cpu_sub (printk_context,PRINTK_NMI_CONTEXT_OFFSET ); }/*
Best Regards,
Petr
Re: [PATCH v4 02/27] hardirq/nmi: Allow nested nmi_enter()
Quoted 10 lines · Petr Mladek
Quoted 2 lines · Frederic Weisbecker
If the outermost NMI is interrupted while between
printk_nmi_enter()andpreempt_count_add(), there is still a risk that we race and clear?Great catch!
There is plenty of space in the
printk_contextvariable. I would reserve one byte there for the NMI context to be on the safe side and be done with it.
Quoted 5 lines
It should never overflow. The
BUG_ON(in_nmi() == NMI_MASK)innmi_enter()will trigger much earlier.Also I hope that
printk_contextwill get removed with the locklessprintk()implementation soon anyway.
Cool, because it's sad that we have to mimic/mirror the preempt count with printk_context just for the sake of debugging preempt_count_add() and other early code in nmi_enter().
The diff below looks good, thanks!
Quoted 43 lines
kernel/printk/internal.h +5
-3@@ -6,9 +6,11 @@#ifdef CONFIG_PRINTK -#define PRINTK_SAFE_CONTEXT_MASK 0x3fffffff -#define PRINTK_NMI_DIRECT_CONTEXT_MASK 0x40000000 -#define PRINTK_NMI_CONTEXT_MASK 0x80000000 +#define PRINTK_SAFE_CONTEXT_MASK 0x007ffffff +#define PRINTK_NMI_DIRECT_CONTEXT_MASK 0x008000000 +#define PRINTK_NMI_CONTEXT_MASK 0xff0000000 + +#define PRINTK_NMI_CONTEXT_OFFSET 0x010000000extern raw_spinlock_t logbuf_lock;kernel/printk/printk_safe.c +2
-2@@ -296,12 +296,12 @@ static __printf(1, 0) int vprintk_nmi(const char *fmt, va_list args) void notrace printk_nmi_enter(void) { -this_cpu_or (printk_context,PRINTK_NMI_CONTEXT_MASK ); +this_cpu_add (printk_context,PRINTK_NMI_CONTEXT_OFFSET ); } void notrace printk_nmi_exit(void) { -this_cpu_and (printk_context, ~PRINTK_NMI_CONTEXT_MASK ); +this_cpu_sub (printk_context,PRINTK_NMI_CONTEXT_OFFSET ); }/* Best Regards,
Petr
Peter Zijlstra
maintainerRe: [PATCH v4 02/27] hardirq/nmi: Allow nested nmi_enter()
In reply to Frederic WeisbeckerQuoted 30 lines · Frederic Weisbecker
Quoted 29 lines · Peter Zijlstra
Since there are already a number of sites (ARM64, PowerPC) that effectively nest
nmi_enter(), lets make the primitive support this before adding even more.Signed-off-by Peter Zijlstra (Intel) <[email protected]>Reviewed-by Petr Mladek <[email protected]>Acked-by Will Deacon <[email protected]>Acked-by Marc Zyngier <[email protected]>--- arch/arm64/include/asm/hardirq.h | 4 ++-- arch/arm64/kernel/sdei.c | 14 ++------------ arch/arm64/kernel/traps.c | 8 ++------ arch/powerpc/kernel/traps.c | 22 ++++++---------------- include/linux/hardirq.h | 5 ++++- include/linux/preempt.h | 4 ++-- kernel/printk/printk_safe.c | 6 ++++-- 7 files changed, 22 insertions(+), 41 deletions(-)kernel/printk/printk_safe.c +2
-1@@ -296,12 +296,14 @@ static __printf(1, 0) int vprintk_nmi(co void notrace printk_nmi_enter(void) { -this_cpu_or (printk_context,PRINTK_NMI_CONTEXT_MASK ); +if (!in_nmi ()) +this_cpu_or (printk_context,PRINTK_NMI_CONTEXT_MASK ); }
Quoted 9 lines
kernel/printk/printk_safe.c static __printf(1, 0) int vprintk_nmi(co · line 307
Quoted 6 lines
kernel/printk/printk_safe.c +2
-1void notrace printk_nmi_exit(void) { -this_cpu_and (printk_context, ~PRINTK_NMI_CONTEXT_MASK ); +if (!in_nmi ()) +this_cpu_and (printk_context, ~PRINTK_NMI_CONTEXT_MASK ); }If the outermost NMI is interrupted while between
printk_nmi_enter()andpreempt_count_add(), there is still a risk that we race and clear?
Damn, true. That also means I need to fix the arm64 bits, and that's a little more tricky.
Something like so perhaps.. hmm?
---
arch/arm64/include/asm/hardirq.h +41 -19
@@ -32,30 +32,52 @@ u64 smp_irq_stat_cpu(unsigned int cpu);struct nmi_ctx {u64 hcr; +unsigned int cnt; }; DECLARE_PER_CPU(struct nmi_ctx, nmi_contexts); -#define arch_nmi_enter () \ - do { \ - if (is_kernel_in_hyp_mode() && !in_nmi()) { \ - struct nmi_ctx *nmi_ctx = this_cpu_ptr(&nmi_contexts); \ - nmi_ctx->hcr = read_sysreg(hcr_el2); \ - if (!(nmi_ctx->hcr & HCR_TGE)) { \ - write_sysreg(nmi_ctx->hcr | HCR_TGE, hcr_el2); \ - isb(); \ - } \ - } \ - } while (0) +#define arch_nmi_enter () \ +do { \ + struct nmi_ctx *___ctx; \ + unsigned int ___cnt; \ + \ + if (!is_kernel_in_hyp_mode() || in_nmi()) \ + break; \ + \ + ___ctx = this_cpu_ptr(&nmi_contexts); \ + ___cnt = ___ctx->cnt; \ + if (!(___cnt & 1) && __cnt) { \ + ___ctx->cnt += 2; \ + break; \ + } \ + \ + ___ctx->cnt |= 1; \ + barrier(); \ + nmi_ctx->hcr = read_sysreg(hcr_el2); \ + if (!(nmi_ctx->hcr & HCR_TGE)) { \ + write_sysreg(nmi_ctx->hcr | HCR_TGE, hcr_el2); \ + isb(); \ + } \ + barrier(); \ + if (!(___cnt & 1)) \ + ___ctx->cnt++; \ +} while (0) -#define arch_nmi_exit () \ - do { \ - if (is_kernel_in_hyp_mode() && !in_nmi()) { \ - struct nmi_ctx *nmi_ctx = this_cpu_ptr(&nmi_contexts); \ - if (!(nmi_ctx->hcr & HCR_TGE)) \ - write_sysreg(nmi_ctx->hcr, hcr_el2); \ - } \ - } while (0) +#define arch_nmi_exit () \ +do { \ + struct nmi_ctx *___ctx; \ + \ + if (!is_kernel_in_hyp_mode() || in_nmi()) \ + break; \ + \ + ___ctx = this_cpu_ptr(&nmi_contexts); \ + if ((___ctx->cnt & 1) || (___ctx->cnt -= 2)) \ + break; \ + \ + if (!(nmi_ctx->hcr & HCR_TGE)) \ + write_sysreg(nmi_ctx->hcr, hcr_el2); \ +} while (0)static inline void ack_bad_irq (unsigned int irq) {
Frederic Weisbecker
maintainerRe: [PATCH v4 02/27] hardirq/nmi: Allow nested nmi_enter()
Quoted 41 lines · Peter Zijlstra
Damn, true. That also means I need to fix the arm64 bits, and that's a little more tricky.
Something like so perhaps.. hmm?
---
arch/arm64/include/asm/hardirq.h +14
-11@@ -32,30 +32,52 @@ u64 smp_irq_stat_cpu(unsigned int cpu);struct nmi_ctx {u64 hcr; +unsigned int cnt; }; DECLARE_PER_CPU(struct nmi_ctx, nmi_contexts); -#define arch_nmi_enter () \ - do { \ - if (is_kernel_in_hyp_mode() && !in_nmi()) { \ - struct nmi_ctx *nmi_ctx = this_cpu_ptr(&nmi_contexts); \ - nmi_ctx->hcr = read_sysreg(hcr_el2); \ - if (!(nmi_ctx->hcr & HCR_TGE)) { \ - write_sysreg(nmi_ctx->hcr | HCR_TGE, hcr_el2); \ - isb(); \ - } \ - } \ - } while (0) +#define arch_nmi_enter () \ +do { \ + struct nmi_ctx *___ctx; \ + unsigned int ___cnt; \ + \ + if (!is_kernel_in_hyp_mode() || in_nmi()) \ + break; \ + \ + ___ctx = this_cpu_ptr(&nmi_contexts); \ + ___cnt = ___ctx->cnt; \ + if (!(___cnt & 1) && __cnt) { \ + ___ctx->cnt += 2; \ + break; \
arch/arm64/include/asm/hardirq.h u64 smp_irq_stat_cpu(unsigned int cpu); · line 62
Quoted 10 lines
arch/arm64/include/asm/hardirq.h +10
-0+ } \ + \ + ___ctx->cnt |=1 ; \ +barrier (); \ + nmi_ctx->hcr =read_sysreg (hcr_el2); \ +if (!(nmi_ctx->hcr &HCR_TGE )) { \ +write_sysreg (nmi_ctx->hcr |HCR_TGE , hcr_el2); \ +isb (); \ + } \ +barrier (); \
Suppose the first NMI is interrupted here. nmi_ctx->hcr has HCR_TGE unset. The new NMI is going to overwrite nmi_ctx->hcr with HCR_TGE set. Then the first NMI will not restore the correct value upon arch_nmi_exit().
So perhaps the below, but I bet I overlooked something obvious.
#define arch_nmi_enter() \
do { \
struct nmi_ctx *___ctx; \
u64 ___hcr; \
\
if (!is_kernel_in_hyp_mode()) \
break; \
\
___ctx = this_cpu_ptr(&nmi_contexts); \
if (___ctx->cnt) { \
___ctx->cnt++; \
break; \
} \
\
___hcr = read_sysreg(hcr_el2); \
if (!(___hcr & HCR_TGE)) { \
write_sysreg(___hcr | HCR_TGE, hcr_el2); \
isb(); \
} \
___ctx->cnt = 1; \
barrier(); \
___ctx->hcr = ___hcr; \
} while (0)#define arch_nmi_exit() \
do { \
struct nmi_ctx *___ctx; \
u64 ___hcr; \
\
if (!is_kernel_in_hyp_mode()) \
break; \
\
___ctx = this_cpu_ptr(&nmi_contexts); \
___hcr = nmi_ctx->hcr; \
barrier(); \
--___ctx->cnt; \
barrier(); \
if (!___ctx->cnt && !(___hcr & HCR_TGE)) \
write_sysreg(___hcr, hcr_el2); \
} while (0)Peter Zijlstra
maintainerRe: [PATCH v4 02/27] hardirq/nmi: Allow nested nmi_enter()
Quoted 30 lines · Frederic Weisbecker
Quoted 13 lines · Peter Zijlstra
arch/arm64/include/asm/hardirq.h +13
-0+#define arch_nmi_enter () \ +do { \ + struct nmi_ctx *___ctx; \ + unsigned int ___cnt; \ + \ + if (!is_kernel_in_hyp_mode() || in_nmi()) \ + break; \ + \ + ___ctx = this_cpu_ptr(&nmi_contexts); \ + ___cnt = ___ctx->cnt; \ + if (!(___cnt & 1) && __cnt) { \ + ___ctx->cnt += 2; \ + break; \arch/arm64/include/asm/hardirq.h u64 smp_irq_stat_cpu(unsigned int cpu); · line 62
Quoted 10 lines
arch/arm64/include/asm/hardirq.h +10
-0+ } \ + \ + ___ctx->cnt |=1 ; \ +barrier (); \ + nmi_ctx->hcr =read_sysreg (hcr_el2); \ +if (!(nmi_ctx->hcr &HCR_TGE )) { \ +write_sysreg (nmi_ctx->hcr |HCR_TGE , hcr_el2); \ +isb (); \ + } \ +barrier (); \Suppose the first NMI is interrupted here.
nmi_ctx->hcrhasHCR_TGEunset. The new NMI is going to overwritenmi_ctx->hcrwithHCR_TGEset. Then the first NMI will not restore the correct value uponarch_nmi_exit().
Quoted 1 line
So perhaps the below, but I bet I overlooked something obvious.
Well, none of this is obvious :/
The basic idea was that the LSB signifies 'pending/in-progress' and when that is set, nobody else touches no nothing. Enter will unconditionally (re) write_sysreg(), exit will nothing.
Obviously I messed that up.
How's this?
#define arch_nmi_enter() \
do { \
struct nmi_ctx *___ctx; \
unsigned int ___cnt; \
\
if (!is_kernel_in_hyp_mode() || in_nmi()) \
break; \
\
___ctx = this_cpu_ptr(&nmi_contexts); \
___cnt = ___ctx->cnt; \
if (!(___cnt & 1)) { /* !IN-PROGRESS */ \
if (___cnt) { \
___ctx->cnt += 2; \
break; \
} \
\
___ctx->hcr = read_sysreg(hcr_el2); \
barrier(); \
___ctx->cnt |= 1; /* IN-PROGRESS */ \
barrier(); \
} \
\
if (!(___ctx->hcr & HCR_TGE)) { \
write_sysreg(___ctx->hcr | HCR_TGE, hcr_el2); \
isb(); \
} \
barrier(); \
if (!(___cnt & 1)) \
___ctx->cnt++; /* COMPLETE */ \
} while (0)#define arch_nmi_exit() \
do { \
struct nmi_ctx *___ctx; \
\
if (!is_kernel_in_hyp_mode() || in_nmi()) \
break; \
\
___ctx = this_cpu_ptr(&nmi_contexts); \
if ((___ctx->cnt & 1) || (___ctx->cnt -= 2)) \
break; \
\
if (!(___ctx->hcr & HCR_TGE)) \
write_sysreg(___ctx->hcr, hcr_el2); \
} while (0)Frederic Weisbecker
maintainerRe: [PATCH v4 02/27] hardirq/nmi: Allow nested nmi_enter()
Quoted 75 lines · Peter Zijlstra
Quoted 30 lines · Frederic Weisbecker
Quoted 13 lines · Peter Zijlstra
arch/arm64/include/asm/hardirq.h +13
-0+#define arch_nmi_enter () \ +do { \ + struct nmi_ctx *___ctx; \ + unsigned int ___cnt; \ + \ + if (!is_kernel_in_hyp_mode() || in_nmi()) \ + break; \ + \ + ___ctx = this_cpu_ptr(&nmi_contexts); \ + ___cnt = ___ctx->cnt; \ + if (!(___cnt & 1) && __cnt) { \ + ___ctx->cnt += 2; \ + break; \arch/arm64/include/asm/hardirq.h u64 smp_irq_stat_cpu(unsigned int cpu); · line 62
Quoted 10 lines
arch/arm64/include/asm/hardirq.h +10
-0+ } \ + \ + ___ctx->cnt |=1 ; \ +barrier (); \ + nmi_ctx->hcr =read_sysreg (hcr_el2); \ +if (!(nmi_ctx->hcr &HCR_TGE )) { \ +write_sysreg (nmi_ctx->hcr |HCR_TGE , hcr_el2); \ +isb (); \ + } \ +barrier (); \Suppose the first NMI is interrupted here.
nmi_ctx->hcrhasHCR_TGEunset. The new NMI is going to overwritenmi_ctx->hcrwithHCR_TGEset. Then the first NMI will not restore the correct value uponarch_nmi_exit().Quoted 1 line
So perhaps the below, but I bet I overlooked something obvious.
Well, none of this is obvious :/
The basic idea was that the LSB signifies 'pending/in-progress' and when that is set, nobody else touches no nothing. Enter will unconditionally (re)
write_sysreg(), exit will nothing.Obviously I messed that up.
How's this?
#define
arch_nmi_enter()\do { \ struct nmi_ctx *___ctx; \ unsigned int ___cnt; \ \ if (!is_kernel_in_hyp_mode() || in_nmi()) \ break; \ \ ___ctx = this_cpu_ptr(&nmi_contexts); \ ___cnt = ___ctx->cnt; \ if (!(___cnt & 1)) { /* !IN-PROGRESS */ \ if (___cnt) { \ ___ctx->cnt += 2; \ break; \ } \ \ ___ctx->hcr = read_sysreg(hcr_el2); \ barrier(); \ ___ctx->cnt |= 1; /* IN-PROGRESS */ \ barrier(); \ } \ \ if (!(___ctx->hcr & HCR_TGE)) { \ write_sysreg(___ctx->hcr | HCR_TGE, hcr_el2); \ isb(); \ } \ barrier(); \ if (!(___cnt & 1)) \ ___ctx->cnt++; /* COMPLETE */ \ } while (0)#define
arch_nmi_exit()\
Quoted 9 lines
do { \
struct nmi_ctx *___ctx; \
\
if (!is_kernel_in_hyp_mode() || in_nmi()) \
break; \
\
___ctx = this_cpu_ptr(&nmi_contexts); \
if ((___ctx->cnt & 1) || (___ctx->cnt -= 2)) \
break; \If you're interrupted here and __ctx->cnt == 0, the new NMI is in its right to overwrite __ctx->hcr. It will find HCR_TGE set in the sysreg and write it back to ___ctx->hcr. So the following restore will fail.
\
Quoted 3 lines
if (!(___ctx->hcr & HCR_TGE)) \ write_sysreg(___ctx->hcr, hcr_el2); \ } while (0)
Frederic Weisbecker
maintainerRe: [PATCH v4 02/27] hardirq/nmi: Allow nested nmi_enter()
In reply to Peter ZijlstraQuoted 31 lines · Peter Zijlstra
Quoted 30 lines · Frederic Weisbecker
Quoted 13 lines · Peter Zijlstra
arch/arm64/include/asm/hardirq.h +13
-0+#define arch_nmi_enter () \ +do { \ + struct nmi_ctx *___ctx; \ + unsigned int ___cnt; \ + \ + if (!is_kernel_in_hyp_mode() || in_nmi()) \ + break; \ + \ + ___ctx = this_cpu_ptr(&nmi_contexts); \ + ___cnt = ___ctx->cnt; \ + if (!(___cnt & 1) && __cnt) { \ + ___ctx->cnt += 2; \ + break; \arch/arm64/include/asm/hardirq.h u64 smp_irq_stat_cpu(unsigned int cpu); · line 62
Quoted 10 lines
arch/arm64/include/asm/hardirq.h +10
-0+ } \ + \ + ___ctx->cnt |=1 ; \ +barrier (); \ + nmi_ctx->hcr =read_sysreg (hcr_el2); \ +if (!(nmi_ctx->hcr &HCR_TGE )) { \ +write_sysreg (nmi_ctx->hcr |HCR_TGE , hcr_el2); \ +isb (); \ + } \ +barrier (); \Suppose the first NMI is interrupted here.
nmi_ctx->hcrhasHCR_TGEunset. The new NMI is going to overwritenmi_ctx->hcrwithHCR_TGEset. Then the first NMI will not restore the correct value uponarch_nmi_exit().
Quoted 7 lines
Quoted 1 line
So perhaps the below, but I bet I overlooked something obvious.
Well, none of this is obvious :/
The basic idea was that the LSB signifies 'pending/in-progress' and when that is set, nobody else touches no nothing. Enter will unconditionally (re)
write_sysreg(), exit will nothing.
So here is my previous proposal, based on a simple counter, this time with comments and a few fixes:
#define arch_nmi_enter() \
do { \
struct nmi_ctx *___ctx; \
u64 ___hcr; \
\
if (!is_kernel_in_hyp_mode()) \
break; \
\
___ctx = this_cpu_ptr(&nmi_contexts); \
if (___ctx->cnt) { \
___ctx->cnt++; \
break; \
} \
\
___hcr = read_sysreg(hcr_el2); \
if (!(___hcr & HCR_TGE)) { \
write_sysreg(___hcr | HCR_TGE, hcr_el2); \
isb(); \
} \
/* \
* Make sure the sysreg write is performed before ___ctx->cnt \
* is set to 1. NMIs that see cnt == 1 will rely on us. \
*/ \
barrier(); \
___ctx->cnt = 1; \
/* \
* Make sure ___ctx->cnt is set before we save ___hcr. We \
* don't want ___ctx->hcr to be overwritten. \
*/ \
barrier(); \
___ctx->hcr = ___hcr; \
} while (0)#define arch_nmi_exit() \
do { \
struct nmi_ctx *___ctx; \
u64 ___hcr; \
\
if (!is_kernel_in_hyp_mode()) \
break; \
\
___ctx = this_cpu_ptr(&nmi_contexts); \
___hcr = ___ctx->hcr; \
/* \
* Make sure we read ___ctx->hcr before we release \
* ___ctx->cnt as it makes ___ctx->hcr updatable again. \
*/ \
barrier(); \
___ctx->cnt--; \
/* \
* Make sure ___ctx->cnt release is visible before we \
* restore the sysreg. Otherwise a new NMI occuring \
* right after write_sysreg() can be fooled and think \
* we secured things for it. \
*/ \
barrier(); \
if (!___ctx->cnt && !(___hcr & HCR_TGE)) \
write_sysreg(___hcr, hcr_el2); \
} while (0)Peter Zijlstra
maintainerRe: [PATCH v4 02/27] hardirq/nmi: Allow nested nmi_enter()
Quoted 2 lines · Frederic Weisbecker
So here is my previous proposal, based on a simple counter, this time with comments and a few fixes:
I've presumed your SoB and made this your patch.
Frederic Weisbecker
maintainerRe: [PATCH v4 02/27] hardirq/nmi: Allow nested nmi_enter()
Quoted 5 lines · Peter Zijlstra
Quoted 2 lines · Frederic Weisbecker
So here is my previous proposal, based on a simple counter, this time with comments and a few fixes:
I've presumed your SoB and made this your patch.
Ok, thanks!
Peter Zijlstra
maintainerPATCH v4 3/27 x86/entry: Flip _TIF_SIGPENDING and _TIF_NOTIFY_RESUME handling
In reply to Peter ZijlstraMake sure we run task_work before we hit any kind of userspace -- very much including signals.
--- arch/x86/entry/common.c | 8 usr/src/linux-2.6/arch/x86/entry/common.c | 440 ------------------------------ 2 files changed, 4 insertions(+), 444 deletions(-)
arch/x86/entry/common.c +4 -4
@@ -155,16 +155,16 @@ static void exit_to_usermode_loop(structif (cached_flags & _TIF_PATCH_PENDING)klp_update_patch_state (current); -/* deal with pending signal delivery */ -if (cached_flags & _TIF_SIGPENDING) -do_signal (regs); -if (cached_flags & _TIF_NOTIFY_RESUME) {clear_thread_flag (TIF_NOTIFY_RESUME );tracehook_notify_resume (regs);rseq_handle_notify_resume (NULL , regs); } +/* deal with pending signal delivery */ +if (cached_flags & _TIF_SIGPENDING) +do_signal (regs); +if (cached_flags & _TIF_USER_RETURN_NOTIFY)fire_user_return_notifiers ();
Peter Zijlstra
maintainerRe: [PATCH v4 03/27] x86/entry: Flip _TIF_SIGPENDING and _TIF_NOTIFY_RESUME handling
Quoted 20 lines · Peter Zijlstra
Make sure we run
task_workbefore we hit any kind of userspace -- very much including signals.Suggested-by Andy Lutomirski <[email protected]>Signed-off-by Peter Zijlstra (Intel) <[email protected]>--- arch/x86/entry/common.c | 8 usr/src/linux-2.6/arch/x86/entry/common.c | 440 ------------------------------ 2 files changed, 4 insertions(+), 444 deletions(-)arch/x86/entry/common.c +0
-4@@ -155,16 +155,16 @@ static void exit_to_usermode_loop(structif (cached_flags & _TIF_PATCH_PENDING)klp_update_patch_state (current); -/* deal with pending signal delivery */ -if (cached_flags & _TIF_SIGPENDING) -do_signal (regs); -
arch/x86/entry/common.c static void exit_to_usermode_loop(struct · line 167
Quoted 10 lines
arch/x86/entry/common.c +4
-0if (cached_flags & _TIF_NOTIFY_RESUME) {clear_thread_flag (TIF_NOTIFY_RESUME );tracehook_notify_resume (regs);rseq_handle_notify_resume (NULL , regs); } +/* deal with pending signal delivery */ +if (cached_flags & _TIF_SIGPENDING) +do_signal (regs); +
For giggles, I just found:
do_signal() get_signal() task_work_run()
Peter Zijlstra
maintainerPATCH v4 4/27 x86/mce: Delete ist_begin_non_atomic()
In reply to Peter ZijlstraIt is an abomination; and in prepration of removing the whole ist_enter() thing, it needs to go.
Convert #MC over to using task_work_add() instead; it will run the same code slightly later, on the return to user path of the same exception.
--- arch/x86/include/asm/traps.h | 2 - arch/x86/kernel/cpu/mce/core.c | 53 +++++++++++++++++++++++------------------ arch/x86/kernel/traps.c | 37 ---------------------------- include/linux/sched.h | 6 ++++ 4 files changed, 36 insertions(+), 62 deletions(-)
arch/x86/include/asm/traps.h +0 -2
@@ -123,8 +123,6 @@ asmlinkage void smp_irq_move_cleanup_intextern void ist_enter (struct pt_regs *regs);extern void ist_exit (struct pt_regs *regs); -extern void ist_begin_non_atomic (struct pt_regs *regs); -extern void ist_end_non_atomic (void );#ifdef CONFIG_VMAP_STACK void __noreturn handle_stack_overflow(const char *message,
arch/x86/kernel/cpu/mce/core.c +30 -23
78 lines not on this page · raw message
arch/x86/kernel/traps.c +0 -37
@@ -117,43 +117,6 @@ void ist_exit(struct pt_regs *regs)rcu_nmi_exit (); } -/** -* ist_begin_non_atomic() - begin a non-atomic section in an IST exception -* @regs: regs passed to the IST exception handler -* -* IST exception handlers normally cannot schedule. As a special -* exception, if the exception interrupted userspace code (i.e. -* user_mode(regs) would return true) and the exception was not -* a double fault, it can be safe to schedule. ist_begin_non_atomic() -* begins a non-atomic section within an ist_enter()/ist_exit() region. -* Callers are responsible for enabling interrupts themselves inside -* the non-atomic section, and callers must call ist_end_non_atomic() -* before ist_exit(). -*/ -void ist_begin_non_atomic (struct pt_regs *regs) -{ -BUG_ON (!user_mode (regs)); - -/* -* Sanity check: we need to be on the normal thread stack. This -* will catch asm bugs and any attempt to use ist_preempt_enable -* from double_fault. -*/ -BUG_ON (!on_thread_stack ()); - -preempt_enable_no_resched (); -} - -/** -* ist_end_non_atomic() - begin a non-atomic section in an IST exception -* -* Ends a non-atomic section started with ist_begin_non_atomic(). -*/ -void ist_end_non_atomic (void ) -{ -preempt_disable (); -} -int is_valid_bugaddr (unsigned long addr) {unsigned short ud;
include/linux/sched.h +6 -0
@@ -1285,6 +1285,12 @@ struct task_struct {unsigned long prev_lowest_stack;#endif +#ifdef CONFIG_X86_MCE +u64 mce_addr; +u64 mce_status; +struct callback_head mce_kill_me; +#endif +/* * New fields for task_struct should be added above here, so that * they are included in the randomized portion of task_struct.
Andy Lutomirski
maintainerRe: [PATCH v4 04/27] x86/mce: Delete ist_begin_non_atomic()
Quoted 7 lines · Peter Zijlstra
It is an abomination; and in prepration of removing the whole
ist_enter()thing, it needs to go.Convert #MC over to using
task_work_add()instead; it will run the same code slightly later, on the return to user path of the same exception.
This looks correct to me.
Re: [PATCH v4 04/27] x86/mce: Delete ist_begin_non_atomic()
In reply to Peter ZijlstraQuoted 8 lines · Peter Zijlstra
It is an abomination; and in prepration of removing the whole
ist_enter()thing, it needs to go.Convert #MC over to using
task_work_add()instead; it will run the same code slightly later, on the return to user path of the same exception.Signed-off-by Peter Zijlstra (Intel) <[email protected]>
Peter Zijlstra
maintainerPATCH v4 5/27 x86: Replace ist_enter() with nmi_enter()
In reply to Peter ZijlstraA few exceptions (like #DB and #BP) can happen at any location in the code, this then means that tracers should treat events from these exceptions as NMI-like. We could be holding locks with interrupts disabled for instance.
Similarly, #MC is an actual NMI-like exception.
All of them use ist_enter() which only concerns itself with RCU, but does not do any of the other setup that NMI's need. This means things like:
printk() raw_spin_lock_irq(&logbuf_lock); <#DB/#BP/#MC> printk() raw_spin_lock_irq(&logbuf_lock);
are entirely possible (well, not really since printk tries hard to play nice, but the concept stands).
So replace ist_enter() with nmi_enter(). Also observe that any nmi_enter() caller must be both notrace and NOKPROBE.
--- arch/x86/include/asm/traps.h | 3 - arch/x86/kernel/cpu/mce/core.c | 16 +++++---- arch/x86/kernel/cpu/mce/p5.c | 8 ++-- arch/x86/kernel/cpu/mce/winchip.c | 8 ++-- arch/x86/kernel/traps.c | 65 +++++++------------------------------- 5 files changed, 32 insertions(+), 68 deletions(-)
arch/x86/include/asm/traps.h +0 -3
@@ -121,9 +121,6 @@ void smp_spurious_interrupt(struct pt_revoid smp_error_interrupt (struct pt_regs *regs); asmlinkage void smp_irq_move_cleanup_interrupt(void); -extern void ist_enter (struct pt_regs *regs); -extern void ist_exit (struct pt_regs *regs); -#ifdef CONFIG_VMAP_STACK void __noreturn handle_stack_overflow(const char *message, struct pt_regs *regs,
arch/x86/kernel/cpu/mce/core.c +9 -7
@@ -43,6 +43,7 @@#include <linux/jump_label.h> #include <linux/set_memory.h> #include <linux/task_work.h> +#include <linux/hardirq.h> #include <asm/intel-family.h> #include <asm/processor.h>
@@ -1221,7 +1222,7 @@ static void kill_me_maybe(struct callbac* MCE broadcast. However some CPUs might be broken beyond repair, * so be always careful when synchronizing with others. */ -void do_machine_check (struct pt_regs *regs,long error_code) +notrace void do_machine_check(struct pt_regs *regs, long error_code) {DECLARE_BITMAP (valid_banks,MAX_NR_BANKS );DECLARE_BITMAP (toclear,MAX_NR_BANKS );
@@ -1255,10 +1256,10 @@ void do_machine_check(struct pt_regs *re*/ int lmce =1 ; -if (__mc_check_crashing_cpu (cpu)) -return ; +nmi_enter (); -ist_enter (regs); +if (__mc_check_crashing_cpu (cpu)) + goto out;this_cpu_inc (mce_exception_count);
@@ -1347,7 +1348,7 @@ void do_machine_check(struct pt_regs *resync_core ();if (worst !=MCE_AR_SEVERITY && !kill_it) - goto out_ist; + goto out;/* Fault was in user mode and we need to take some action */ if ((m.cs &3 ) ==3 ) {
@@ -1363,10 +1364,11 @@ void do_machine_check(struct pt_regs *remce_panic ("Failed kernel mode recovery" , &m, msg); } -out_ist: -ist_exit (regs); +out: +nmi_exit (); }EXPORT_SYMBOL_GPL (do_machine_check); +NOKPROBE_SYMBOL (do_machine_check);#ifndef CONFIG_MEMORY_FAILURE int memory_failure (unsigned long pfn,int flags)
arch/x86/kernel/cpu/mce/p5.c +5 -3
@@ -7,6 +7,7 @@#include <linux/kernel.h> #include <linux/types.h> #include <linux/smp.h> +#include <linux/hardirq.h> #include <asm/processor.h> #include <asm/traps.h>
@@ -20,11 +21,11 @@int mce_p5_enabled__read_mostly ;/* Machine check handler for Pentium class Intel CPUs: */ -static void pentium_machine_check (struct pt_regs *regs,long error_code) +static notrace void pentium_machine_check(struct pt_regs *regs, long error_code) {u32 loaddr, hi, lotype; -ist_enter (regs); +nmi_enter ();rdmsr (MSR_IA32_P5_MC_ADDR , loaddr, hi);rdmsr (MSR_IA32_P5_MC_TYPE , lotype, hi);
@@ -39,8 +40,9 @@ static void pentium_machine_check(structadd_taint (TAINT_MACHINE_CHECK ,LOCKDEP_NOW_UNRELIABLE ); -ist_exit (regs); +nmi_exit (); } +NOKPROBE_SYMBOL (pentium_machine_check);/* Set up machine check reporting for processors with Intel style MCE: */ void intel_p5_mcheck_init (struct cpuinfo_x86 *c)
arch/x86/kernel/cpu/mce/winchip.c +5 -3
@@ -6,6 +6,7 @@#include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/types.h> +#include <linux/hardirq.h> #include <asm/processor.h> #include <asm/traps.h>
@@ -16,15 +17,16 @@#include "internal.h" /* Machine check handler for WinChip C6: */ -static void winchip_machine_check (struct pt_regs *regs,long error_code) +static notrace void winchip_machine_check(struct pt_regs *regs, long error_code) { -ist_enter (regs); +nmi_enter ();pr_emerg ("CPU0: Machine Check Exception.\n" );add_taint (TAINT_MACHINE_CHECK ,LOCKDEP_NOW_UNRELIABLE ); -ist_exit (regs); +nmi_exit (); } +NOKPROBE_SYMBOL (winchip_machine_check);/* Set up machine check reporting on the Winchip C6 series */ void winchip_mcheck_init (struct cpuinfo_x86 *c)
arch/x86/kernel/traps.c +13 -52
138 lines not on this page · raw message
Andy Lutomirski
maintainerRe: [PATCH v4 05/27] x86: Replace ist_enter() with nmi_enter()
Quoted 14 lines · Peter Zijlstra
A few exceptions (like #DB and #BP) can happen at any location in the code, this then means that tracers should treat events from these exceptions as NMI-like. We could be holding locks with interrupts disabled for instance.
Similarly, #MC is an actual NMI-like exception.
arch/x86/kernel/traps.c +1
-1-dotraplinkage void notrace do_int3(struct pt_regs *regs, long error_code) +dotraplinkage notrace void do_int3(struct pt_regs *regs, long error_code) {if (poke_int3_handler (regs))return ;
arch/x86/kernel/traps.c dotraplinkage void do_general_protection · line 525
Quoted 10 lines
arch/x86/kernel/traps.c +1
-8-/* -* Use ist_enter despite the fact that we don't use an IST stack. -* We can be called from a kprobe in non-CONTEXT_KERNEL kernel -* mode or even during context tracking state changes. -* -* This means that we can't schedule. That's okay. -*/ -ist_enter (regs); +nmi_enter ();
I agree with the change, but some commentary might be nice. Maybe copy from here:
Peter Zijlstra
maintainerRe: [PATCH v4 05/27] x86: Replace ist_enter() with nmi_enter()
Quoted 10 lines · Andy Lutomirski
arch/x86/kernel/traps.c dotraplinkage void do_general_protection · line 525
Quoted 9 lines
arch/x86/kernel/traps.c +1
-8-/* -* Use ist_enter despite the fact that we don't use an IST stack. -* We can be called from a kprobe in non-CONTEXT_KERNEL kernel -* mode or even during context tracking state changes. -* -* This means that we can't schedule. That's okay. -*/ -ist_enter (regs); +nmi_enter ();
Quoted 4 lines
I agree with the change, but some commentary might be nice. Maybe copy from here:
Fair enough; I'll add something to #DB and #BP for that.
Peter Zijlstra
maintainerRe: [PATCH v4 05/27] x86: Replace ist_enter() with nmi_enter()
Quoted 12 lines · Peter Zijlstra
Quoted 10 lines · Andy Lutomirski
Quoted 9 lines
arch/x86/kernel/traps.c +1
-8-/* -* Use ist_enter despite the fact that we don't use an IST stack. -* We can be called from a kprobe in non-CONTEXT_KERNEL kernel -* mode or even during context tracking state changes. -* -* This means that we can't schedule. That's okay. -*/ -ist_enter (regs); +nmi_enter ();
Quoted 6 lines
Quoted 4 lines
I agree with the change, but some commentary might be nice. Maybe copy from here:
Fair enough; I'll add something to #DB and #BP for that.
do_int3() is now like:
@@ -529,19 +497,18 @@ dotraplinkage void do_general_protection
}
NOKPROBE_SYMBOL(do_general_protection);
-dotraplinkage void notrace do_int3(struct pt_regs *regs, long error_code) +dotraplinkage notrace void do_int3(struct pt_regs *regs, long error_code)
{
if (poke_int3_handler(regs))
return;
/*
- * Use ist_enter despite the fact that we don't use an IST stack.
- * We can be called from a kprobe in non-CONTEXT_KERNEL kernel
- * mode or even during context tracking state changes.
- *
- * This means that we can't schedule. That's okay.
+ * Unlike any other non-IST entry, we can be called from pretty much
+ * any location in the kernel through kprobes -- text_poke() will most
+ * likely be handled by poke_int3_handler() above. This means this
+ * handler is effectively NMI-like.
*/
- ist_enter(regs);
+ nmi_enter();
RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU");
#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
if (kgdb_ll_trap(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP,
@@ -563,7 +530,7 @@ dotraplinkage void notrace do_int3(struc
cond_local_irq_disable(regs);
exit:
- ist_exit(regs);
+ nmi_exit();
}
NOKPROBE_SYMBOL(do_int3);
And I'm going to have to do another (few) patches for do_debug(), because that comment it has it patently false and I remember we had a bunch of crud for that. Let me dig those out.
Steven Rostedt
maintainerRe: [PATCH v4 05/27] x86: Replace ist_enter() with nmi_enter()
Quoted 9 lines · On Mon, 24 Feb 2020 11:43:46 +0100 Peter Zijlstra <[email protected]> wrote:
arch/x86/kernel/traps.c +1
-3-dotraplinkage void notrace do_int3(struct pt_regs *regs, long error_code) +dotraplinkage notrace void do_int3(struct pt_regs *regs, long error_code) {if (poke_int3_handler (regs))return ;/* -* Use ist_enter despite the fact that we don't use an IST stack. -* We can be called from a kprobe in non-CONTEXT_KERNEL kernel
arch/x86/kernel/traps.c dotraplinkage void do_general_protection · line 525
Quoted 10 lines
arch/x86/kernel/traps.c +5
-4-* mode or even during context tracking state changes. -* -* This means that we can't schedule. That's okay. +* Unlike any other non-IST entry, we can be called from pretty much +* any location in the kernel through kprobes -- text_poke() will most +* likely be handled by poke_int3_handler() above. This means this +* handler is effectively NMI-like. */ -ist_enter (regs); +nmi_enter ();
Hmm, note that nmi_enter() calls other functions. Did you make sure all of them are not able to be kprobed. This is different than just being "NMI like", it's that if they are kprobed, then this will go into an infinite loop because nothing can have a kprobe before the kprobe int3 handler is called here.
-- Steve
Quoted 11 lines
arch/x86/kernel/traps.c +1
-1RCU_LOCKDEP_WARN (!rcu_is_watching (),"entry code didn't wake RCU" );#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP if (kgdb_ll_trap(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP,@@ -563,7 +530,7 @@ dotraplinkage void notrace do_int3(struccond_local_irq_disable (regs); exit: -ist_exit (regs); +nmi_exit (); }NOKPROBE_SYMBOL (do_int3);
Peter Zijlstra
maintainerRe: [PATCH v4 05/27] x86: Replace ist_enter() with nmi_enter()
Quoted 20 lines · Steven Rostedt
Quoted 17 lines · On Mon, 24 Feb 2020 11:43:46 +0100 Peter Zijlstra <[email protected]> wrote:
arch/x86/kernel/traps.c +5
-6-dotraplinkage void notrace do_int3(struct pt_regs *regs, long error_code) +dotraplinkage notrace void do_int3(struct pt_regs *regs, long error_code) {if (poke_int3_handler (regs))return ;/* -* Use ist_enter despite the fact that we don't use an IST stack. -* We can be called from a kprobe in non-CONTEXT_KERNEL kernel -* mode or even during context tracking state changes. -* -* This means that we can't schedule. That's okay. +* Unlike any other non-IST entry, we can be called from pretty much +* any location in the kernel through kprobes -- text_poke() will most +* likely be handled by poke_int3_handler() above. This means this +* handler is effectively NMI-like. */
Quoted 8 lines
Review
Quoted 2 lines
(quoted diff) +1
-1- ist_enter(regs); + nmi_enter();Hmm, note that
nmi_enter()calls other functions. Did you make sure all of them are not able to be kprobed. This is different than just being "NMI like", it's that if they are kprobed, then this will go into an infinite loop because nothing can have a kprobe before the kprobe int3 handler is called here.
I did not audit that; I went with the fact that hitting kprobes before in_nmi() is true is a bug.
Looking at nmi_enter(), that leaves trace_hardirq_enter(), since we know we marked rcu_nmi_enter() as NOKPROBES, per the patches elsewhere in this series.
Steven Rostedt
maintainerRe: [PATCH v4 05/27] x86: Replace ist_enter() with nmi_enter()
Quoted 3 lines · On Mon, 24 Feb 2020 17:34:09 +0100 Peter Zijlstra <[email protected]> wrote:
Looking at
nmi_enter(), that leavestrace_hardirq_enter(), since we know we markedrcu_nmi_enter()as NOKPROBES, per the patches elsewhere in this series.
Maybe this was addressed already in the series, but I'm just looking at Linus's master branch we have:
#define nmi_enter() \
do { \
arch_nmi_enter(); \
printk_nmi_enter(); \
lockdep_off(); \
ftrace_nmi_enter(); \
BUG_ON(in_nmi()); \
preempt_count_add(NMI_OFFSET + HARDIRQ_OFFSET); \
rcu_nmi_enter(); \
trace_hardirq_enter(); \
} while (0)Just want to confirm that printk_nmi_enter(), lockdep_off(), and ftrace_nmi_enter() are all marked fully with NOKPROBE.
-- Steve
Peter Zijlstra
maintainerRe: [PATCH v4 05/27] x86: Replace ist_enter() with nmi_enter()
Quoted 23 lines · Steven Rostedt
Quoted 3 lines · On Mon, 24 Feb 2020 17:34:09 +0100 Peter Zijlstra <[email protected]> wrote:
Looking at
nmi_enter(), that leavestrace_hardirq_enter(), since we know we markedrcu_nmi_enter()as NOKPROBES, per the patches elsewhere in this series.Maybe this was addressed already in the series, but I'm just looking at Linus's master branch we have:
#define nmi_enter() \ do { \ arch_nmi_enter(); \ printk_nmi_enter(); \ lockdep_off(); \ ftrace_nmi_enter(); \ BUG_ON(in_nmi()); \ preempt_count_add(NMI_OFFSET + HARDIRQ_OFFSET); \ rcu_nmi_enter(); \ trace_hardirq_enter(); \ } while (0)
Quoted 2 lines
Just want to confirm that
printk_nmi_enter(),lockdep_off(), andftrace_nmi_enter()are all marked fully with NOKPROBE.
*sigh*, right you are, I only looked at notrace, not nokprobe.
In particular the ftrace one is a bit off a mess, let me sort through that.
Steven Rostedt
maintainerRe: [PATCH v4 05/27] x86: Replace ist_enter() with nmi_enter()
Quoted 7 lines · On Mon, 24 Feb 2020 22:31:39 +0100 Peter Zijlstra <[email protected]> wrote:
Quoted 2 lines
Just want to confirm that
printk_nmi_enter(),lockdep_off(), andftrace_nmi_enter()are all marked fully with NOKPROBE.*sigh*, right you are, I only looked at notrace, not nokprobe.
In particular the ftrace one is a bit off a mess, let me sort through that.
ftrace_nmi_enter() has two purposes. One, for archs that need to deal with NMIs while they still use stop machine. Although, it appears sh is the only arch that does that. I can look to see if it can be ripped out.
The other is for the hwlat detector that measures the time it was in an NMI, as NMIs appear as a hardware latency too.
-- Steve
Peter Zijlstra
maintainerRe: [PATCH v4 05/27] x86: Replace ist_enter() with nmi_enter()
Quoted 6 lines · Steven Rostedt
Quoted 3 lines · On Mon, 24 Feb 2020 22:31:39 +0100 Peter Zijlstra <[email protected]> wrote:
Quoted 2 lines
Just want to confirm that
printk_nmi_enter(),lockdep_off(), andftrace_nmi_enter()are all marked fully with NOKPROBE.
Quoted 8 lines
Quoted 4 lines
*sigh*, right you are, I only looked at notrace, not nokprobe.
In particular the ftrace one is a bit off a mess, let me sort through that.
ftrace_nmi_enter()has two purposes. One, for archs that need to deal with NMIs while they still use stop machine. Although, it appears sh is the only arch that does that. I can look to see if it can be ripped out.
Already done :-)
---
Subject: sh/ftrace: Move arch_ftrace_nmi_{enter,exit} into nmi exception
From: Peter Zijlstra <[email protected]>
Date: Mon Feb 24 22:26:21 CET 2020
SuperH is the last remaining user of arch_ftrace_nmi_{enter,exit}(), remove it from the generic code and into the SuperH code.
--- Documentation/trace/ftrace-design.rst | 8 -------- arch/sh/Kconfig | 1 - arch/sh/kernel/traps.c | 12 ++++++++++++ include/linux/ftrace_irq.h | 11 ----------- kernel/trace/Kconfig | 10 ---------- 5 files changed, 12 insertions(+), 30 deletions(-)
Documentation/trace/ftrace-design.rst +0 -8
@@ -229,14 +229,6 @@ Adding support for it is easy: just defi pass the return address pointer as the 'retp' argument to ftrace_push_return_trace(). -HAVE_FTRACE_NMI_ENTER ---------------------- - -If you can't trace NMI functions, then skip this option. - -<details to be filled> - - HAVE_SYSCALL_TRACEPOINTS ------------------------
arch/sh/Kconfig +0 -1
@@ -71,7 +71,6 @@ config SUPERH32 select HAVE_FUNCTION_TRACER select HAVE_FTRACE_MCOUNT_RECORD select HAVE_DYNAMIC_FTRACE - select HAVE_FTRACE_NMI_ENTER if DYNAMIC_FTRACE select ARCH_WANT_IPC_PARSE_VERSION select HAVE_FUNCTION_GRAPH_TRACER select HAVE_ARCH_KGDB
arch/sh/kernel/traps.c +12 -0
@@ -170,11 +170,21 @@ BUILD_TRAP_HANDLER(bug)force_sig (SIGTRAP ); } +#ifdef CONFIG_HAVE_DYNAMIC_FTRACE +extern void arch_ftrace_nmi_enter (void ); +extern void arch_ftrace_nmi_exit (void ); +#else +static inline void arch_ftrace_nmi_enter (void ) { } +static inline void arch_ftrace_nmi_exit (void ) { } +#endif +BUILD_TRAP_HANDLER (nmi) {unsigned int cpu =smp_processor_id ();TRAP_HANDLER_DECL ; +arch_ftrace_nmi_enter (); +nmi_enter ();nmi_count (cpu)++;
@@ -190,4 +200,6 @@ BUILD_TRAP_HANDLER(nmi) }nmi_exit (); + +arch_ftrace_nmi_exit (); }
include/linux/ftrace_irq.h +0 -11
@@ -2,15 +2,6 @@#ifndef _LINUX_FTRACE_IRQ_H#define _LINUX_FTRACE_IRQ_H - -#ifdef CONFIG_FTRACE_NMI_ENTER -extern void arch_ftrace_nmi_enter (void ); -extern void arch_ftrace_nmi_exit (void ); -#else -static inline void arch_ftrace_nmi_enter (void ) { } -static inline void arch_ftrace_nmi_exit (void ) { } -#endif -#ifdef CONFIG_HWLAT_TRACER extern bool trace_hwlat_callback_enabled;extern void trace_hwlat_callback (bool enter);
@@ -22,12 +13,10 @@ static inline void ftrace_nmi_enter(voidif (trace_hwlat_callback_enabled)trace_hwlat_callback (true);#endif -arch_ftrace_nmi_enter (); }static inline void ftrace_nmi_exit (void ) { -arch_ftrace_nmi_exit ();#ifdef CONFIG_HWLAT_TRACER if (trace_hwlat_callback_enabled)trace_hwlat_callback (false);
kernel/trace/Kconfig +0 -10
@@ -10,11 +10,6 @@ config USER_STACKTRACE_SUPPORT config NOP_TRACER bool -config HAVE_FTRACE_NMI_ENTER - bool - help - See Documentation/trace/ftrace-design.rst - config HAVE_FUNCTION_TRACER bool help
@@ -72,11 +67,6 @@ config RING_BUFFER select TRACE_CLOCK select IRQ_WORK -config FTRACE_NMI_ENTER - bool - depends on HAVE_FTRACE_NMI_ENTER - default y - config EVENT_TRACING select CONTEXT_SWITCH_TRACER select GLOB
Peter Zijlstra
maintainerRe: [PATCH v4 05/27] x86: Replace ist_enter() with nmi_enter()
Quoted 13 lines · Peter Zijlstra
Subject: sh/ftrace: Move arch_ftrace_nmi_{enter,exit} into nmi exception
From: Peter Zijlstra <[email protected]>
Date: Mon Feb 24 22:26:21 CET 2020SuperH is the last remaining user of arch_ftrace_nmi_{enter,exit}(), remove it from the generic code and into the SuperH code.
Signed-off-by Peter Zijlstra (Intel) <[email protected]>---
arch/sh/kernel/traps.c BUILD_TRAP_HANDLER(bug) · line 173
Quoted 4 lines
arch/sh/kernel/traps.c +1
-0@@ -170,11 +170,21 @@ BUILD_TRAP_HANDLER(bug)force_sig (SIGTRAP ); } +#ifdef CONFIG_HAVE_DYNAMIC_FTRACE
build robot just informed me that this ought to s/HAVE_//
Quoted 6 lines
arch/sh/kernel/traps.c +6
-0+extern void arch_ftrace_nmi_enter (void ); +extern void arch_ftrace_nmi_exit (void ); +#else +static inline void arch_ftrace_nmi_enter (void ) { } +static inline void arch_ftrace_nmi_exit (void ) { } +#endif
Peter Zijlstra
maintainerRe: [PATCH v4 05/27] x86: Replace ist_enter() with nmi_enter()
In reply to Steven RostedtQuoted 2 lines · Steven Rostedt
The other is for the hwlat detector that measures the time it was in an NMI, as NMIs appear as a hardware latency too.
Yeah,.. I hate that one. But I ended up with this patch.
And yes, I know some of those notrace annotations are strictly unnessecary due to Makefile crap, but having them is _SO_ much easier.
---
Subject: x86,tracing: Robustify ftrace_nmi_enter()
From: Peter Zijlstra <[email protected]>
Date: Mon Feb 24 23:40:29 CET 2020
ftrace_nmi_enter()
trace_hwlat_callback()
trace_clock_local()
sched_clock()
paravirt_sched_clock()
native_sched_clock()
All must not be traced or kprobed, it will be called from do_debug() before the kprobe handler.
--- arch/x86/include/asm/paravirt.h | 2 +- arch/x86/kernel/tsc.c | 7 +++++-- include/linux/ftrace_irq.h | 4 ++-- kernel/trace/trace_clock.c | 2 ++ kernel/trace/trace_hwlat.c | 4 +++- 5 files changed, 13 insertions(+), 6 deletions(-)
arch/x86/include/asm/paravirt.h +1 -1
@@ -17,7 +17,7 @@#include <linux/cpumask.h> #include <asm/frame.h> -static inline unsigned long long paravirt_sched_clock (void ) +static __always_inline unsigned long long paravirt_sched_clock (void ) { return PVOP_CALL0(unsigned long long, time.sched_clock); }
arch/x86/kernel/tsc.c +5 -2
@@ -14,6 +14,7 @@#include <linux/percpu.h> #include <linux/timex.h> #include <linux/static_key.h> +#include <linux/kprobes.h> #include <asm/hpet.h> #include <asm/timer.h>
@@ -207,7 +208,7 @@ static void __init cyc2ns_init_secondary/* * Scheduler clock - returns current time in nanosec units. */ -u64 native_sched_clock (void ) +notrace u64 native_sched_clock(void) {if (static_branch_likely (&__use_tsc)) {u64 tsc_now =rdtsc ();
@@ -228,6 +229,7 @@ u64 native_sched_clock(void)/* No locking but a rare wrong value is not a big deal: */ return (jiffies_64 -INITIAL_JIFFIES ) * (1000000000 /HZ ); } +NOKPROBE_SYMBOL (native_sched_clock);/* * Generate a sched_clock if you already have a TSC value.
@@ -240,10 +242,11 @@ u64 native_sched_clock_from_tsc(u64 tsc)/* We need to define a real function for sched_clock, to override the weak default version */ #ifdef CONFIG_PARAVIRT -unsigned long long sched_clock (void ) +notrace unsigned long long sched_clock (void ) {return paravirt_sched_clock (); } +NOKPROBE_SYMBOL (sched_clock);bool using_native_sched_clock (void ) {
include/linux/ftrace_irq.h +2 -2
@@ -7,7 +7,7 @@ extern bool trace_hwlat_callback_enabledextern void trace_hwlat_callback (bool enter);#endif -static inline void ftrace_nmi_enter (void ) +static __always_inline void ftrace_nmi_enter(void) {#ifdef CONFIG_HWLAT_TRACER if (trace_hwlat_callback_enabled)
@@ -15,7 +15,7 @@ static inline void ftrace_nmi_enter(void#endif } -static inline void ftrace_nmi_exit (void ) +static __always_inline void ftrace_nmi_exit(void) {#ifdef CONFIG_HWLAT_TRACER if (trace_hwlat_callback_enabled)
kernel/trace/trace_clock.c +2 -0
@@ -22,6 +22,7 @@#include <linux/sched/clock.h> #include <linux/ktime.h> #include <linux/trace_clock.h> +#include <linux/kprobes.h> /* * trace_clock_local(): the simplest and least coherent tracing clock.
@@ -44,6 +45,7 @@ u64 notrace trace_clock_local(void)return clock; } +NOKPROBE_SYMBOL (trace_clock_local);EXPORT_SYMBOL_GPL (trace_clock_local);/*
kernel/trace/trace_hwlat.c +3 -1
@@ -43,6 +43,7 @@#include <linux/cpumask.h> #include <linux/delay.h> #include <linux/sched/clock.h> +#include <linux/kprobes.h> #include "trace.h" static struct trace_array *hwlat_trace;
@@ -137,7 +138,7 @@ static void trace_hwlat_sample(struct hw#define init_time (a, b) (a = b)#define time_u64 (a) a -void trace_hwlat_callback (bool enter) +notrace void trace_hwlat_callback(bool enter) {if (smp_processor_id () != nmi_cpu)return ;
@@ -156,6 +157,7 @@ void trace_hwlat_callback(bool enter)if (enter) nmi_count++; } +NOKPROBE_SYMBOL (trace_hwlat_callback);/** * get_sample - sample the CPU TSC and look for likely hardware latencies
Re: [PATCH v4 05/27] x86: Replace ist_enter() with nmi_enter()
Quoted 22 lines · On Wed, 26 Feb 2020 11:27:58 +0100 Peter Zijlstra <[email protected]> wrote:
Quoted 2 lines · Steven Rostedt
The other is for the hwlat detector that measures the time it was in an NMI, as NMIs appear as a hardware latency too.
Yeah,.. I hate that one. But I ended up with this patch.
And yes, I know some of those notrace annotations are strictly unnessecary due to
Makefilecrap, but having them is _SO_ much easier.---
Subject: x86,tracing: Robustifyftrace_nmi_enter()
From: Peter Zijlstra <[email protected]>
Date: Mon Feb 24 23:40:29 CET 2020
ftrace_nmi_enter()
trace_hwlat_callback()
trace_clock_local()
sched_clock()
paravirt_sched_clock()
native_sched_clock()
Quoted 3 lines
All must not be traced or kprobed, it will be called from
do_debug()before the kprobe handler.
-- Steve
Quoted 9 lines
Signed-off-by Peter Zijlstra (Intel) <[email protected]>--- arch/x86/include/asm/paravirt.h | 2 +- arch/x86/kernel/tsc.c | 7 +++++-- include/linux/ftrace_irq.h | 4 ++-- kernel/trace/trace_clock.c | 2 ++ kernel/trace/trace_hwlat.c | 4 +++- 5 files changed, 13 insertions(+), 6 deletions(-)
Re: [PATCH v4 05/27] x86: Replace ist_enter() with nmi_enter()
In reply to Peter ZijlstraHi Peter,
Quoted 22 lines · On Wed, 26 Feb 2020 11:27:58 +0100 Peter Zijlstra <[email protected]> wrote:
Quoted 2 lines · Steven Rostedt
The other is for the hwlat detector that measures the time it was in an NMI, as NMIs appear as a hardware latency too.
Yeah,.. I hate that one. But I ended up with this patch.
And yes, I know some of those notrace annotations are strictly unnessecary due to
Makefilecrap, but having them is _SO_ much easier.---
Subject: x86,tracing: Robustifyftrace_nmi_enter()
From: Peter Zijlstra <[email protected]>
Date: Mon Feb 24 23:40:29 CET 2020
ftrace_nmi_enter()
trace_hwlat_callback()
trace_clock_local()
sched_clock()
paravirt_sched_clock()
native_sched_clock()
Quoted 2 lines
All must not be traced or kprobed, it will be called from
do_debug()before the kprobe handler.
As I found today, we need to make NOKPROBE on exit side too, and this covers exit side.
Thank you,
Quoted 126 lines
Signed-off-by Peter Zijlstra (Intel) <[email protected]>--- arch/x86/include/asm/paravirt.h | 2 +- arch/x86/kernel/tsc.c | 7 +++++-- include/linux/ftrace_irq.h | 4 ++-- kernel/trace/trace_clock.c | 2 ++ kernel/trace/trace_hwlat.c | 4 +++- 5 files changed, 13 insertions(+), 6 deletions(-)arch/x86/include/asm/paravirt.h +1
-1@@ -17,7 +17,7 @@#include <linux/cpumask.h> #include <asm/frame.h> -static inline unsigned long long paravirt_sched_clock (void ) +static __always_inline unsigned long long paravirt_sched_clock (void ) { return PVOP_CALL0(unsigned long long, time.sched_clock); }arch/x86/kernel/tsc.c +5
-2@@ -14,6 +14,7 @@#include <linux/percpu.h> #include <linux/timex.h> #include <linux/static_key.h> +#include <linux/kprobes.h> #include <asm/hpet.h> #include <asm/timer.h> @@ -207,7 +208,7 @@ static void __init cyc2ns_init_secondary/* * Scheduler clock - returns current time in nanosec units. */ -u64 native_sched_clock (void ) +notrace u64 native_sched_clock(void) {if (static_branch_likely (&__use_tsc)) {u64 tsc_now =rdtsc ();@@ -228,6 +229,7 @@ u64 native_sched_clock(void)/* No locking but a rare wrong value is not a big deal: */ return (jiffies_64 -INITIAL_JIFFIES ) * (1000000000 /HZ ); } +NOKPROBE_SYMBOL (native_sched_clock);/* * Generate a sched_clock if you already have a TSC value. @@ -240,10 +242,11 @@ u64 native_sched_clock_from_tsc(u64 tsc)/* We need to define a real function for sched_clock, to override the weak default version */ #ifdef CONFIG_PARAVIRT -unsigned long long sched_clock (void ) +notrace unsigned long long sched_clock (void ) {return paravirt_sched_clock (); } +NOKPROBE_SYMBOL (sched_clock);bool using_native_sched_clock (void ) {include/linux/ftrace_irq.h +2
-2@@ -7,7 +7,7 @@ extern bool trace_hwlat_callback_enabledextern void trace_hwlat_callback (bool enter);#endif -static inline void ftrace_nmi_enter (void ) +static __always_inline void ftrace_nmi_enter(void) {#ifdef CONFIG_HWLAT_TRACER if (trace_hwlat_callback_enabled)@@ -15,7 +15,7 @@ static inline void ftrace_nmi_enter(void#endif } -static inline void ftrace_nmi_exit (void ) +static __always_inline void ftrace_nmi_exit(void) {#ifdef CONFIG_HWLAT_TRACER if (trace_hwlat_callback_enabled)kernel/trace/trace_clock.c +2
-0@@ -22,6 +22,7 @@#include <linux/sched/clock.h> #include <linux/ktime.h> #include <linux/trace_clock.h> +#include <linux/kprobes.h> /* * trace_clock_local(): the simplest and least coherent tracing clock. @@ -44,6 +45,7 @@ u64 notrace trace_clock_local(void)return clock; } +NOKPROBE_SYMBOL (trace_clock_local);EXPORT_SYMBOL_GPL (trace_clock_local);/* kernel/trace/trace_hwlat.c +3
-1@@ -43,6 +43,7 @@#include <linux/cpumask.h> #include <linux/delay.h> #include <linux/sched/clock.h> +#include <linux/kprobes.h> #include "trace.h" static struct trace_array *hwlat_trace;@@ -137,7 +138,7 @@ static void trace_hwlat_sample(struct hw#define init_time (a, b) (a = b)#define time_u64 (a) a -void trace_hwlat_callback (bool enter) +notrace void trace_hwlat_callback(bool enter) {if (smp_processor_id () != nmi_cpu)return ;@@ -156,6 +157,7 @@ void trace_hwlat_callback(bool enter)if (enter) nmi_count++; } +NOKPROBE_SYMBOL (trace_hwlat_callback);/** * get_sample - sample the CPU TSC and look for likely hardware latencies
Signature · 1 line
Masami Hiramatsu <[email protected]>
Peter Zijlstra
maintainerPATCH v4 6/27 x86/doublefault: Remove memmove() call
In reply to Peter ZijlstraUse of memmove() in #DF is problematic when you consider tracing and other instrumentation.
Remove the memmove() call and simply write out what need doing; Boris argues the ranges should not overlap.
Survives selftests/x86, specifically sigreturn_64.
(Andy ?!)
--- arch/x86/kernel/traps.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
arch/x86/kernel/traps.c +6 -1
@@ -278,6 +278,7 @@ dotraplinkage void do_double_fault(struc regs->ip == (unsigned long)native_irq_return_iret) {struct pt_regs *gpregs = (struct pt_regs *)this_cpu_read (cpu_tss_rw.x86_tss.sp0) -1 ; +unsigned long *p = (unsigned long *)regs->sp;/* * regs->sp points to the failing IRET frame on the
@@ -285,7 +286,11 @@ dotraplinkage void do_double_fault(struc* in gpregs->ss through gpregs->ip. * */ -memmove (&gpregs->ip, (void *)regs->sp,5 *8 ); + gpregs->ip = p[0 ]; + gpregs->cs = p[1 ]; + gpregs->flags = p[2 ]; + gpregs->sp = p[3 ]; + gpregs->ss = p[4 ]; gpregs->orig_ax =0 ;/* Missing (lost) #GP error code */ /*
Re: [PATCH v4 06/27] x86/doublefault: Remove memmove() call
Quoted 10 lines · Peter Zijlstra
Use of
memmove()in #DF is problematic when you consider tracing and other instrumentation.Remove the
memmove()call and simply write out what need doing; Boris argues the ranges should not overlap.Survives selftests/x86, specifically
sigreturn_64.(Andy ?!)
Even ignoring the tracing issue, I think this is nicer than the original code.
Peter Zijlstra
maintainerPATCH v4 7/27 rcu: Make RCU IRQ enter/exit functions rely on in_nmi()
In reply to Peter ZijlstraFrom: Paul E. McKenney <[email protected]>
The rcu_nmi_enter_common() and rcu_nmi_exit_common() functions take an "irq" parameter that indicates whether these functions are invoked from an irq handler (irq==true) or an NMI handler (irq==false). However, recent changes have applied notrace to a few critical functions such that rcu_nmi_enter_common() and rcu_nmi_exit_common() many now rely on in_nmi(). Note that in_nmi() works no differently than before, but rather that tracing is now prohibited in code regions where in_nmi() would incorrectly report NMI state.
This commit therefore removes the "irq" parameter and inlines rcu_nmi_enter_common() and rcu_nmi_exit_common() into rcu_nmi_enter() and rcu_nmi_exit(), respectively.
--- kernel/rcu/tree.c | 45 ++++++++++++++------------------------------- 1 file changed, 14 insertions(+), 31 deletions(-)
kernel/rcu/tree.c +14 -31
@@ -614,16 +614,18 @@ void rcu_user_enter(void) }#endif /* CONFIG_NO_HZ_FULL */ -/* +/** +* rcu_nmi_exit - inform RCU of exit from NMI context +* * If we are returning from the outermost NMI handler that interrupted an * RCU-idle period, update rdp->dynticks and rdp->dynticks_nmi_nesting * to let the RCU grace-period handling know that the CPU is back to * being RCU-idle. * -* If you add or remove a call to rcu_nmi_exit_common(), be sure to test +* If you add or remove a call to rcu_nmi_exit(), be sure to test * with CONFIG_RCU_EQS_DEBUG=y. */ -static __always_inline void rcu_nmi_exit_common(bool irq) +void rcu_nmi_exit (void ) {struct rcu_data *rdp =this_cpu_ptr (&rcu_data);
@@ -651,27 +653,16 @@ static __always_inline void rcu_nmi_exittrace_rcu_dyntick (TPS ("Startirq" ), rdp->dynticks_nmi_nesting,0 ,atomic_read (&rdp->dynticks));WRITE_ONCE (rdp->dynticks_nmi_nesting,0 );/* Avoid store tearing. */ -if (irq) +if (!in_nmi ())rcu_prepare_for_idle ();rcu_dynticks_eqs_enter (); -if (irq) +if (!in_nmi ())rcu_dynticks_task_enter (); }/** -* rcu_nmi_exit - inform RCU of exit from NMI context -* -* If you add or remove a call to rcu_nmi_exit(), be sure to test -* with CONFIG_RCU_EQS_DEBUG=y. -*/ -void rcu_nmi_exit (void ) -{ -rcu_nmi_exit_common (false); -} - -/** * rcu_irq_exit - inform RCU that current CPU is exiting irq towards idle * * Exit from an interrupt handler, which might possibly result in entering
@@ -693,7 +684,7 @@ void rcu_nmi_exit(void)void rcu_irq_exit (void ) {lockdep_assert_irqs_disabled (); -rcu_nmi_exit_common (true); +rcu_nmi_exit (); }/*
@@ -777,7 +768,7 @@ void rcu_user_exit(void)#endif /* CONFIG_NO_HZ_FULL */ /** -* rcu_nmi_enter_common - inform RCU of entry to NMI context +* rcu_nmi_enter - inform RCU of entry to NMI context * @irq: Is this call from rcu_irq_enter? * * If the CPU was idle from RCU's viewpoint, update rdp->dynticks and
@@ -786,10 +777,10 @@ void rcu_user_exit(void)* long as the nesting level does not overflow an int. (You will probably * run out of stack space first.) * -* If you add or remove a call to rcu_nmi_enter_common(), be sure to test +* If you add or remove a call to rcu_nmi_enter(), be sure to test * with CONFIG_RCU_EQS_DEBUG=y. */ -static __always_inline void rcu_nmi_enter_common(bool irq) +void rcu_nmi_enter (void ) {long incby =2 ;struct rcu_data *rdp =this_cpu_ptr (&rcu_data);
@@ -807,12 +798,12 @@ static __always_inline void rcu_nmi_ente*/ if (rcu_dynticks_curr_cpu_in_eqs ()) { -if (irq) +if (!in_nmi ())rcu_dynticks_task_exit ();rcu_dynticks_eqs_exit (); -if (irq) +if (!in_nmi ())rcu_cleanup_after_idle (); incby =1 ;
@@ -834,14 +825,6 @@ static __always_inline void rcu_nmi_ente rdp->dynticks_nmi_nesting + incby);barrier (); } - -/** -* rcu_nmi_enter - inform RCU of entry to NMI context -*/ -void rcu_nmi_enter (void ) -{ -rcu_nmi_enter_common (false); -}NOKPROBE_SYMBOL (rcu_nmi_enter);/**
@@ -869,7 +852,7 @@ NOKPROBE_SYMBOL(rcu_nmi_enter);void rcu_irq_enter (void ) {lockdep_assert_irqs_disabled (); -rcu_nmi_enter_common (true); +rcu_nmi_enter (); }/*
Re: [PATCH v4 07/27] rcu: Make RCU IRQ enter/exit functions rely on in_nmi()
Quoted 11 lines · Peter Zijlstra
From: Paul E. McKenney <[email protected]>
The
rcu_nmi_enter_common()andrcu_nmi_exit_common()functions take an "irq" parameter that indicates whether these functions are invoked from an irq handler (irq==true) or an NMI handler (irq==false). However, recent changes have applied notrace to a few critical functions such thatrcu_nmi_enter_common()andrcu_nmi_exit_common()many now rely onin_nmi(). Note thatin_nmi()works no differently than before, but rather that tracing is now prohibited in code regions wherein_nmi()would incorrectly report NMI state.
Quoted 6 lines
This commit therefore removes the "irq" parameter and inlines
rcu_nmi_enter_common()andrcu_nmi_exit_common()intorcu_nmi_enter()andrcu_nmi_exit(), respectively.Signed-off-by Paul E. McKenney <[email protected]>Signed-off-by Peter Zijlstra (Intel) <[email protected]>
Although in the end, from a naming POV, it would make more sense to have rcu_nmi_enter() calling rcu_irq_enter() rather than the opposite. But the result would be another level of function in the way to keep the NOKPROBE property, so I guess we'll stick with that layout.
Peter Zijlstra
maintainerPATCH v4 8/27 rcu/kprobes: Comment why rcu_nmi_enter() is marked NOKPROBE
In reply to Peter ZijlstraFrom: Steven Rostedt (VMware) <[email protected]>
It's confusing that rcu_nmi_enter() is marked NOKPROBE and rcu_nmi_exit() is not. One may think that the exit needs to be marked for the same reason the enter is, as rcu_nmi_exit() reverts the RCU state back to what it was before rcu_nmi_enter(). But the reason has nothing to do with the state of RCU.
The breakpoint handler (int3 on x86) must not have any kprobe on it until the kprobe handler is called. Otherwise, it can cause an infinite recursion and crash the machine. It just so happens that rcu_nmi_enter() is called by the int3 handler before the kprobe handler can run, and therefore needs to be marked as NOKPROBE.
Comment this to remove the confusion to why rcu_nmi_enter() is marked NOKPROBE but rcu_nmi_exit() is not.
--- kernel/rcu/tree.c | 8 ++++++++ 1 file changed, 8 insertions(+)
kernel/rcu/tree.c +8 -0
@@ -825,6 +825,14 @@ void rcu_nmi_enter(void) rdp->dynticks_nmi_nesting + incby);barrier (); } +/* +* All functions called in the breakpoint trap handler (e.g. do_int3() +* on x86), must not allow kprobes until the kprobe breakpoint handler +* is called, otherwise it can cause an infinite recursion. +* On some archs, rcu_nmi_enter() is called in the breakpoint handler +* before the kprobe breakpoint handler is called, thus it must be +* marked as NOKPROBE. +*/ NOKPROBE_SYMBOL (rcu_nmi_enter);/**
Re: [PATCH v4 08/27] rcu/kprobes: Comment why rcu_nmi_enter() is marked NOKPROBE
Quoted 17 lines · Peter Zijlstra
From: Steven Rostedt (VMware) <[email protected]>
It's confusing that
rcu_nmi_enter()is marked NOKPROBE andrcu_nmi_exit()is not. One may think that the exit needs to be marked for the same reason the enter is, asrcu_nmi_exit()reverts the RCU state back to what it was beforercu_nmi_enter(). But the reason has nothing to do with the state of RCU.The breakpoint handler (int3 on x86) must not have any kprobe on it until the kprobe handler is called. Otherwise, it can cause an infinite recursion and crash the machine. It just so happens that
rcu_nmi_enter()is called by the int3 handler before the kprobe handler can run, and therefore needs to be marked as NOKPROBE.Comment this to remove the confusion to why
rcu_nmi_enter()is marked NOKPROBE butrcu_nmi_exit()is not.
Quoted 7 lines
Reported-by Joel Fernandes (Google) <[email protected]>Signed-off-by Steven Rostedt (VMware) <[email protected]>Signed-off-by Peter Zijlstra (Intel) <[email protected]>Reviewed-by Paul E. McKenney <[email protected]>Reviewed-by Masami Hiramatsu <[email protected]>
Peter Zijlstra
maintainerPATCH v4 9/27 rcu: Rename rcu_irq_{enter,exit}_irqson()
In reply to Peter ZijlstraThe functions do in fact use local_irq_{save,restore}() and can therefore be used when IRQs are in fact disabled. Worse, they are already used in places where IRQs are disabled, leading to great confusion when reading the code.
Rename them to fix this confusion.
--- include/linux/rcupdate.h | 4 ++-- include/linux/rcutiny.h | 4 ++-- include/linux/rcutree.h | 4 ++-- include/linux/tracepoint.h | 4 ++-- kernel/cpu_pm.c | 4 ++-- kernel/rcu/tree.c | 8 ++++---- kernel/trace/trace.c | 4 ++-- 7 files changed, 16 insertions(+), 16 deletions(-)
include/linux/rcupdate.h +2 -2
@@ -120,9 +120,9 @@ static inline void rcu_init_nohz(void) {*/ #define RCU_NONIDLE (a) \ do { \ - rcu_irq_enter_irqson(); \ + rcu_irq_enter_irqsave(); \ do { a; } while (0); \ - rcu_irq_exit_irqson(); \ + rcu_irq_exit_irqsave(); \ } while (0)/*
include/linux/rcutiny.h +2 -2
@@ -68,8 +68,8 @@ static inline int rcu_jiffies_till_stallstatic inline void rcu_idle_enter (void ) { }static inline void rcu_idle_exit (void ) { }static inline void rcu_irq_enter (void ) { } -static inline void rcu_irq_exit_irqson (void ) { } -static inline void rcu_irq_enter_irqson (void ) { } +static inline void rcu_irq_exit_irqsave (void ) { } +static inline void rcu_irq_enter_irqsave (void ) { }static inline void rcu_irq_exit (void ) { }static inline void exit_rcu (void ) { }static inline bool rcu_preempt_need_deferred_qs (struct task_struct *t)
include/linux/rcutree.h +2 -2
@@ -46,8 +46,8 @@ void rcu_idle_enter(void);void rcu_idle_exit (void );void rcu_irq_enter (void );void rcu_irq_exit (void ); -void rcu_irq_enter_irqson (void ); -void rcu_irq_exit_irqson (void ); +void rcu_irq_enter_irqsave (void ); +void rcu_irq_exit_irqsave (void );void exit_rcu (void );
include/linux/tracepoint.h +2 -2
@@ -181,7 +181,7 @@ static inline struct tracepoint *tracepo*/ \if (rcuidle) { \ __idx =srcu_read_lock_notrace (&tracepoint_srcu);\ -rcu_irq_enter_irqson (); \ +rcu_irq_enter_irqsave (); \ } \ \ it_func_ptr =rcu_dereference_raw ((tp)->funcs); \
@@ -195,7 +195,7 @@ static inline struct tracepoint *tracepo } \ \if (rcuidle) { \ -rcu_irq_exit_irqson (); \ +rcu_irq_exit_irqsave (); \srcu_read_unlock_notrace (&tracepoint_srcu, __idx);\ } \ \
kernel/cpu_pm.c +2 -2
@@ -24,10 +24,10 @@ static int cpu_pm_notify(enum cpu_pm_eve* could be disfunctional in cpu idle. Copy RCU_NONIDLE code to let * RCU know this. */ -rcu_irq_enter_irqson (); +rcu_irq_enter_irqsave (); ret =__atomic_notifier_call_chain (&cpu_pm_notifier_chain, event,NULL , nr_to_call, nr_calls); -rcu_irq_exit_irqson (); +rcu_irq_exit_irqsave ();return notifier_to_errno (ret); }
kernel/rcu/tree.c +4 -4
@@ -699,10 +699,10 @@ void rcu_irq_exit(void)/* * Wrapper for rcu_irq_exit() where interrupts are enabled. * -* If you add or remove a call to rcu_irq_exit_irqson(), be sure to test +* If you add or remove a call to rcu_irq_exit_irqsave(), be sure to test * with CONFIG_RCU_EQS_DEBUG=y. */ -void rcu_irq_exit_irqson (void ) +void rcu_irq_exit_irqsave (void ) {unsigned long flags;
@@ -875,10 +875,10 @@ void rcu_irq_enter(void)/* * Wrapper for rcu_irq_enter() where interrupts are enabled. * -* If you add or remove a call to rcu_irq_enter_irqson(), be sure to test +* If you add or remove a call to rcu_irq_enter_irqsave(), be sure to test * with CONFIG_RCU_EQS_DEBUG=y. */ -void rcu_irq_enter_irqson (void ) +void rcu_irq_enter_irqsave (void ) {unsigned long flags;
kernel/trace/trace.c +2 -2
@@ -3004,9 +3004,9 @@ void __trace_stack(struct trace_array *tif (unlikely (in_nmi ()))return ; -rcu_irq_enter_irqson (); +rcu_irq_enter_irqsave ();__ftrace_trace_stack (buffer, flags, skip, pc,NULL ); -rcu_irq_exit_irqson (); +rcu_irq_exit_irqsave (); }/**
Steven Rostedt
maintainerRe: [PATCH v4 09/27] rcu: Rename rcu_irq_{enter,exit}_irqson()
kernel/rcu/tree.c void rcu_irq_exit(void) · line 700
Quoted 5 lines · On Fri, 21 Feb 2020 14:34:25 +0100 Peter Zijlstra <[email protected]> wrote:
kernel/rcu/tree.c +0
-0@@ -699,10 +699,10 @@ void rcu_irq_exit(void)/* * Wrapper for rcu_irq_exit() where interrupts are enabled.
where interrupts may be enabled.
kernel/rcu/tree.c void rcu_irq_enter(void) · line 876
Quoted 13 lines
kernel/rcu/tree.c +2
-2* -* If you add or remove a call to rcu_irq_exit_irqson(), be sure to test +* If you add or remove a call to rcu_irq_exit_irqsave(), be sure to test * with CONFIG_RCU_EQS_DEBUG=y. */ -void rcu_irq_exit_irqson (void ) +void rcu_irq_exit_irqsave (void ) {unsigned long flags;@@ -875,10 +875,10 @@ void rcu_irq_enter(void)/* * Wrapper for rcu_irq_enter() where interrupts are enabled.
where interrupts may be enabled.
-- Steve
Quoted 10 lines
kernel/rcu/tree.c +2
-2* -* If you add or remove a call to rcu_irq_enter_irqson(), be sure to test +* If you add or remove a call to rcu_irq_enter_irqsave(), be sure to test * with CONFIG_RCU_EQS_DEBUG=y. */ -void rcu_irq_enter_irqson (void ) +void rcu_irq_enter_irqsave (void ) {unsigned long flags;
Peter Zijlstra
maintainerRe: [PATCH v4 09/27] rcu: Rename rcu_irq_{enter,exit}_irqson()
Quoted 21 lines · Steven Rostedt
kernel/rcu/tree.c void rcu_irq_exit(void) · line 700
Quoted 5 lines · On Fri, 21 Feb 2020 14:34:25 +0100 Peter Zijlstra <[email protected]> wrote:
kernel/rcu/tree.c +0
-0@@ -699,10 +699,10 @@ void rcu_irq_exit(void)/* * Wrapper for rcu_irq_exit() where interrupts are enabled. where interrupts may be enabled.
Quoted 10 lines
kernel/rcu/tree.c +2
-2* -* If you add or remove a call to rcu_irq_exit_irqson(), be sure to test +* If you add or remove a call to rcu_irq_exit_irqsave(), be sure to test * with CONFIG_RCU_EQS_DEBUG=y. */ -void rcu_irq_exit_irqson (void ) +void rcu_irq_exit_irqsave (void ) {unsigned long flags;
Quoted 6 lines
kernel/rcu/tree.c void rcu_irq_enter(void) · line 876
Quoted 3 lines
kernel/rcu/tree.c +0
-0@@ -875,10 +875,10 @@ void rcu_irq_enter(void)/* * Wrapper for rcu_irq_enter() where interrupts are enabled. where interrupts may be enabled.
Thanks, done!
Re: [PATCH v4 09/27] rcu: Rename rcu_irq_{enter,exit}_irqson()
In reply to Peter ZijlstraQuoted 9 lines · Peter Zijlstra
The functions do in fact use local_irq_{save,restore}() and can therefore be used when IRQs are in fact disabled. Worse, they are already used in places where IRQs are disabled, leading to great confusion when reading the code.
Rename them to fix this confusion.
Signed-off-by Peter Zijlstra (Intel) <[email protected]>Reviewed-by Paul E. McKenney <[email protected]>
FWIW I'd have called that _irqsafe() as irqsave() suggests some return value to later restore.
Peter Zijlstra
maintainerPATCH v4 10/27 rcu: Mark rcu_dynticks_curr_cpu_in_eqs() inline
In reply to Peter ZijlstraSince rcu_is_watching() is notrace (and needs to be, as it can be called from the tracers), make sure everything it in turn calls is notrace too.
To that effect, mark rcu_dynticks_curr_cpu_in_eqs() inline, which implies notrace, as the function is tiny.
--- kernel/rcu/tree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/rcu/tree.c +1 -1
@@ -294,7 +294,7 @@ static void rcu_dynticks_eqs_online(void* * No ordering, as we are sampling CPU-local information. */ -static bool rcu_dynticks_curr_cpu_in_eqs (void ) +static inline bool rcu_dynticks_curr_cpu_in_eqs (void ) {struct rcu_data *rdp =this_cpu_ptr (&rcu_data);
Peter Zijlstra
maintainerPATCH v4 11/27 rcu,tracing: Create trace_rcu_{enter,exit}()
In reply to Peter ZijlstraTo facilitate tracers that need RCU, add some helpers to wrap the magic required.
The problem is that we can call into tracers (trace events and function tracing) while RCU isn't watching and this can happen from any context, including NMI.
--- include/linux/rcupdate.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)
include/linux/rcupdate.h +29 -0
@@ -175,6 +175,35 @@ do { \#error "Unknown RCU implementation specified to kernel configuration"#endif +/** +* trace_rcu_enter - Force RCU to be active, for code that needs RCU readers +* +* Very similar to RCU_NONIDLE() above. +* +* Tracing can happen while RCU isn't active yet, for instance in the idle loop +* between rcu_idle_enter() and rcu_idle_exit(), or early in exception entry. +* RCU will happily ignore any read-side critical sections in this case. +* +* This function ensures that RCU is aware hereafter and the code can readily +* rely on RCU read-side critical sections working as expected. +* +* This function is NMI safe -- provided in_nmi() is correct and will nest up-to +* INT_MAX/2 times. +*/ +static inline int trace_rcu_enter (void ) +{ +int state = !rcu_is_watching (); +if (state) +rcu_irq_enter_irqsave (); +return state; +} + +static inline void trace_rcu_exit (int state) +{ +if (state) +rcu_irq_exit_irqsave (); +} +/* * The init_rcu_head_on_stack() and destroy_rcu_head_on_stack() calls * are needed for dynamic initialization and destruction of rcu_head
Peter Zijlstra
maintainerRe: [PATCH v4 11/27] rcu,tracing: Create trace_rcu_{enter,exit}()
Quoted 41 lines · Peter Zijlstra
To facilitate tracers that need RCU, add some helpers to wrap the magic required.
The problem is that we can call into tracers (trace events and function tracing) while RCU isn't watching and this can happen from any context, including NMI.
Signed-off-by Peter Zijlstra (Intel) <[email protected]>Reviewed-by Paul E. McKenney <[email protected]>--- include/linux/rcupdate.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)include/linux/rcupdate.h +22
-0@@ -175,6 +175,35 @@ do { \#error "Unknown RCU implementation specified to kernel configuration"#endif +/** +* trace_rcu_enter - Force RCU to be active, for code that needs RCU readers +* +* Very similar to RCU_NONIDLE() above. +* +* Tracing can happen while RCU isn't active yet, for instance in the idle loop +* between rcu_idle_enter() and rcu_idle_exit(), or early in exception entry. +* RCU will happily ignore any read-side critical sections in this case. +* +* This function ensures that RCU is aware hereafter and the code can readily +* rely on RCU read-side critical sections working as expected. +* +* This function is NMI safe -- provided in_nmi() is correct and will nest up-to +* INT_MAX/2 times. +*/ +static inline int trace_rcu_enter (void ) +{ +int state = !rcu_is_watching (); +if (state) +rcu_irq_enter_irqsave (); +return state; +}
include/linux/rcupdate.h do { \ · line 209
Quoted 10 lines
include/linux/rcupdate.h +7
-0+ +static inline void trace_rcu_exit (int state) +{ +if (state) +rcu_irq_exit_irqsave (); +} +/* * The init_rcu_head_on_stack() and destroy_rcu_head_on_stack() calls * are needed for dynamic initialization and destruction of rcu_head
Massmi; afaict we also need the below. That is, when you stick an optimized kprobe in a region RCU is not watching, nothing will make RCU go.
---
kernel/kprobes.c +2 -0
@@ -370,6 +370,7 @@ static bool kprobes_allow_optimization;*/ void opt_pre_handler (struct kprobe *p,struct pt_regs *regs) { +int rcu_flags =trace_rcu_enter ();struct kprobe *kp;list_for_each_entry_rcu (kp, &p->list, list) {
@@ -379,6 +380,7 @@ void opt_pre_handler(struct kprobe *p, struct pt_regs *regs) }reset_kprobe_instance (); } +trace_rcu_exit (rcu_flags); }NOKPROBE_SYMBOL (opt_pre_handler);
Peter Zijlstra
maintainerRe: [PATCH v4 11/27] rcu,tracing: Create trace_rcu_{enter,exit}()
Quoted 9 lines · Peter Zijlstra
Quoted 9 lines
(quoted diff) +9
-0+static inline int trace_rcu_enter(void) +{ + int state = !rcu_is_watching(); + if (state) + rcu_irq_enter_irqsave(); + return state; +} + +static inline void trace_rcu_exit(int state)
Quoted 8 lines
Review
Quoted 8 lines
(quoted diff) +5
-0+{ + if (state) + rcu_irq_exit_irqsave(); +} + /* * The init_rcu_head_on_stack() and destroy_rcu_head_on_stack() calls * are needed for dynamic initialization and destruction of rcu_head
Also, I just noticed these read like tracepoints, so I'm going to rename
them: rcu_trace_{enter,exit}().
Peter Zijlstra
maintainerPATCH v4 12/27 sched,rcu,tracing: Avoid tracing before in_nmi() is correct
In reply to Peter ZijlstraIf we call into a tracer before in_nmi() becomes true, the tracer can no longer detect it is called from NMI context and behave correctly.
Therefore change nmi_{enter,exit}() to use __preempt_count_{add,sub}() as the normal preempt_count_{add,sub}() have a (desired) function trace entry.
This fixes a potential issue with current code; AFAICT when the function-tracer has stack-tracing enabled __trace_stack() will malfunction when it hits the preempt_count_add() function entry from NMI context.
--- include/linux/hardirq.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
include/linux/hardirq.h +11 -2
@@ -66,6 +66,15 @@ extern void irq_exit(void);#endif /* +* NMI vs Tracing +* -------------- +* +* We must not land in a tracer until (or after) we've changed preempt_count +* such that in_nmi() becomes true. To that effect all NMI C entry points must +* be marked 'notrace' and call nmi_enter() as soon as possible. +*/ + +/* * nmi_enter() can nest up to 15 times; see NMI_BITS. */ #define nmi_enter () \
@@ -75,7 +84,7 @@ extern void irq_exit(void);lockdep_off (); \ftrace_nmi_enter (); \BUG_ON (in_nmi () ==NMI_MASK ); \ -preempt_count_add (NMI_OFFSET +HARDIRQ_OFFSET ); \ +__preempt_count_add (NMI_OFFSET +HARDIRQ_OFFSET ); \rcu_nmi_enter (); \trace_hardirq_enter (); \ }while (0 )
@@ -85,7 +94,7 @@ extern void irq_exit(void);trace_hardirq_exit (); \rcu_nmi_exit (); \BUG_ON (!in_nmi ()); \ -preempt_count_sub (NMI_OFFSET +HARDIRQ_OFFSET ); \ +__preempt_count_sub (NMI_OFFSET +HARDIRQ_OFFSET ); \ftrace_nmi_exit (); \lockdep_on (); \printk_nmi_exit (); \
Peter Zijlstra
maintainerPATCH v4 13/27 x86,tracing: Add comments to do_nmi()
In reply to Peter ZijlstraAdd a few comments to do_nmi() as a result of the audit.
--- arch/x86/kernel/nmi.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
arch/x86/kernel/nmi.c +8 -2
@@ -529,11 +529,14 @@ do_nmi(struct pt_regs *regs, long error_* continue to use the NMI stack. */ if (unlikely (is_debug_stack (regs->sp))) { -debug_stack_set_zero (); +debug_stack_set_zero ();/* notrace due to Makefile */ this_cpu_write (update_debug_stack,1 ); }#endif +/* +* It is important that no tracing happens before nmi_enter()! +*/ nmi_enter ();inc_irq_stat (__nmi_count);
@@ -542,10 +545,13 @@ do_nmi(struct pt_regs *regs, long error_default_do_nmi (regs);nmi_exit (); +/* +* No tracing after nmi_exit()! +*/ #ifdef CONFIG_X86_64 if (unlikely (this_cpu_read (update_debug_stack))) { -debug_stack_reset (); +debug_stack_reset ();/* notrace due to Makefile */ this_cpu_write (update_debug_stack,0 ); }#endif
Peter Zijlstra
maintainerPATCH v4 14/27 perf,tracing: Prepare the perf-trace interface for RCU changes
In reply to Peter ZijlstraThe tracepoint interface will stop providing regular RCU context; make sure we do it ourselves, since perf makes use of regular RCU protected data.
--- kernel/events/core.c | 5 +++++ 1 file changed, 5 insertions(+)
kernel/events/core.c +5 -0
@@ -8950,6 +8950,7 @@ void perf_tp_event(u16 event_type, u64 c {struct perf_sample_data data;struct perf_event *event; +int rcu_flags;struct perf_raw_record raw = { .frag = {
@@ -8961,6 +8962,8 @@ void perf_tp_event(u16 event_type, u64 cperf_sample_data_init (&data,0 ,0 ); data.raw = &raw; + rcu_flags =trace_rcu_enter (); +perf_trace_buf_update (record, event_type);hlist_for_each_entry_rcu (event, head, hlist_entry) {
@@ -8996,6 +8999,8 @@ void perf_tp_event(u16 event_type, u64 c }perf_swevent_put_recursion_context (rctx); + +trace_rcu_exit (rcu_flags); }EXPORT_SYMBOL_GPL (perf_tp_event);
Peter Zijlstra
maintainerPATCH v4 15/27 tracing: Employ trace_rcu_{enter,exit}()
In reply to Peter ZijlstraReplace the opencoded (and incomplete) RCU manipulations with the new helpers to ensure a regular RCU context when calling into __ftrace_trace_stack().
--- kernel/trace/trace.c | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-)
kernel/trace/trace.c +3 -16
@@ -2989,24 +2989,11 @@ void __trace_stack(struct trace_array *t int pc) {struct trace_buffer *buffer = tr->array_buffer.buffer; +int rcu_flags; -if (rcu_is_watching ()) { -__ftrace_trace_stack (buffer, flags, skip, pc,NULL ); -return ; - } - -/* -* When an NMI triggers, RCU is enabled via rcu_nmi_enter(), -* but if the above rcu_is_watching() failed, then the NMI -* triggered someplace critical, and rcu_irq_enter() should -* not be called from NMI. -*/ -if (unlikely (in_nmi ())) -return ; - -rcu_irq_enter_irqsave (); + rcu_flags =trace_rcu_enter ();__ftrace_trace_stack (buffer, flags, skip, pc,NULL ); -rcu_irq_exit_irqsave (); +trace_rcu_exit (rcu_flags); }/**
Peter Zijlstra
maintainerPATCH v4 16/27 tracing: Remove regular RCU context for _rcuidle tracepoints (again)
In reply to Peter ZijlstraEffectively revert commit 865e63b04e9b2 ("tracing: Add back in rcu_irq_enter/exit_irqson() for rcuidle tracepoints") now that we've taught perf how to deal with not having an RCU context provided.
--- include/linux/tracepoint.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)
include/linux/tracepoint.h +2 -6
@@ -179,10 +179,8 @@ static inline struct tracepoint *tracepo* For rcuidle callers, use srcu since sched-rcu \ * doesn't work from the idle path. \ */ \ -if (rcuidle) { \ +if (rcuidle) \ __idx =srcu_read_lock_notrace (&tracepoint_srcu);\ -rcu_irq_enter_irqsave (); \ - } \ \ it_func_ptr =rcu_dereference_raw ((tp)->funcs); \ \
@@ -194,10 +192,8 @@ static inline struct tracepoint *tracepo }while ((++it_func_ptr)->func); \ } \ \ -if (rcuidle) { \ -rcu_irq_exit_irqsave (); \ +if (rcuidle) \srcu_read_unlock_notrace (&tracepoint_srcu, __idx);\ - } \ \preempt_enable_notrace (); \ }while (0 )
Peter Zijlstra
maintainerRe: [PATCH v4 16/27] tracing: Remove regular RCU context for _rcuidle tracepoints (again)
Quoted 26 lines · Peter Zijlstra
Effectively revert commit
865e63b04e9b2("tracing: Add back in rcu_irq_enter/exit_irqson() for rcuidle tracepoints") now that we've taught perf how to deal with not having an RCU context provided.Signed-off-by Peter Zijlstra (Intel) <[email protected]>Reviewed-by Steven Rostedt (VMware) <[email protected]>--- include/linux/tracepoint.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)include/linux/tracepoint.h +1
-3@@ -179,10 +179,8 @@ static inline struct tracepoint *tracepo* For rcuidle callers, use srcu since sched-rcu \ * doesn't work from the idle path. \ */ \ -if (rcuidle) { \ +if (rcuidle) \ __idx =srcu_read_lock_notrace (&tracepoint_srcu);\ -rcu_irq_enter_irqsave (); \ - } \ \ it_func_ptr =rcu_dereference_raw ((tp)->funcs); \ \@@ -194,10 +192,8 @@ static inline struct tracepoint *tracepo }while ((++it_func_ptr)->func); \
include/linux/tracepoint.h static inline struct tracepoint *tracepo · line 199
Quoted 10 lines
include/linux/tracepoint.h +1
-3} \ \ -if (rcuidle) { \ -rcu_irq_exit_irqsave (); \ +if (rcuidle) \srcu_read_unlock_notrace (&tracepoint_srcu, __idx);\ - } \ \preempt_enable_notrace (); \ }while (0 )
So what happens when BPF registers for these tracepoints? BPF very much wants RCU on AFAIU.
Peter Zijlstra
maintainerRe: [PATCH v4 16/27] tracing: Remove regular RCU context for _rcuidle tracepoints (again)
Quoted 32 lines · Peter Zijlstra
Quoted 31 lines · Peter Zijlstra
Effectively revert commit
865e63b04e9b2("tracing: Add back in rcu_irq_enter/exit_irqson() for rcuidle tracepoints") now that we've taught perf how to deal with not having an RCU context provided.Signed-off-by Peter Zijlstra (Intel) <[email protected]>Reviewed-by Steven Rostedt (VMware) <[email protected]>--- include/linux/tracepoint.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)include/linux/tracepoint.h +2
-5@@ -179,10 +179,8 @@ static inline struct tracepoint *tracepo* For rcuidle callers, use srcu since sched-rcu \ * doesn't work from the idle path. \ */ \ -if (rcuidle) { \ +if (rcuidle) \ __idx =srcu_read_lock_notrace (&tracepoint_srcu);\ -rcu_irq_enter_irqsave (); \ - } \ \ it_func_ptr =rcu_dereference_raw ((tp)->funcs); \ \@@ -194,10 +192,8 @@ static inline struct tracepoint *tracepo }while ((++it_func_ptr)->func); \ } \ \ -if (rcuidle) { \ -rcu_irq_exit_irqsave (); \ +if (rcuidle) \
Quoted 8 lines
include/linux/tracepoint.h static inline struct tracepoint *tracepo · line 199
Quoted 5 lines
include/linux/tracepoint.h +0
-1srcu_read_unlock_notrace (&tracepoint_srcu, __idx);\ - } \ \preempt_enable_notrace (); \ }while (0 )So what happens when BPF registers for these tracepoints? BPF very much wants RCU on AFAIU.
I suspect we needs something like this...
kernel/trace/bpf_trace.c +2 -0
@@ -1475,11 +1475,13 @@ void bpf_put_raw_tracepoint(struct bpf_raw_event_map *btp)static __always_inline void __bpf_trace_run(struct bpf_prog *prog, u64 *args) { +int rcu_flags =trace_rcu_enter ();rcu_read_lock ();preempt_disable (); (void )BPF_PROG_RUN (prog, args);preempt_enable ();rcu_read_unlock (); +trace_rcu_exit (rcu_flags); }#define UNPACK (...) __VA_ARGS__
Re: [PATCH v4 16/27] tracing: Remove regular RCU context for _rcuidle tracepoints (again)
Quoted 50 lines · Peter Zijlstra
Quoted 32 lines · Peter Zijlstra
Quoted 31 lines · Peter Zijlstra
Effectively revert commit
865e63b04e9b2("tracing: Add back in rcu_irq_enter/exit_irqson() for rcuidle tracepoints") now that we've taught perf how to deal with not having an RCU context provided.Signed-off-by Peter Zijlstra (Intel) <[email protected]>Reviewed-by Steven Rostedt (VMware) <[email protected]>--- include/linux/tracepoint.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)include/linux/tracepoint.h +2
-5@@ -179,10 +179,8 @@ static inline struct tracepoint *tracepo* For rcuidle callers, use srcu since sched-rcu \ * doesn't work from the idle path. \ */ \ -if (rcuidle) { \ +if (rcuidle) \ __idx =srcu_read_lock_notrace (&tracepoint_srcu);\ -rcu_irq_enter_irqsave (); \ - } \ \ it_func_ptr =rcu_dereference_raw ((tp)->funcs); \ \@@ -194,10 +192,8 @@ static inline struct tracepoint *tracepo }while ((++it_func_ptr)->func); \ } \ \ -if (rcuidle) { \ -rcu_irq_exit_irqsave (); \ +if (rcuidle) \Quoted 8 lines
include/linux/tracepoint.h static inline struct tracepoint *tracepo · line 199
Quoted 5 lines
include/linux/tracepoint.h +0
-1srcu_read_unlock_notrace (&tracepoint_srcu, __idx);\ - } \ \preempt_enable_notrace (); \ }while (0 )So what happens when BPF registers for these tracepoints? BPF very much wants RCU on AFAIU.
I suspect we needs something like this...
kernel/trace/bpf_trace.c +0
-0
kernel/trace/bpf_trace.c void bpf_put_raw_tracepoint(struct bpf_raw_event_map *btp) · line 1484
Quoted 10 lines
kernel/trace/bpf_trace.c +2
-0@@ -1475,11 +1475,13 @@ void bpf_put_raw_tracepoint(struct bpf_raw_event_map *btp)static __always_inline void __bpf_trace_run(struct bpf_prog *prog, u64 *args) { +int rcu_flags =trace_rcu_enter ();rcu_read_lock ();preempt_disable (); (void )BPF_PROG_RUN (prog, args);preempt_enable ();rcu_read_unlock (); +trace_rcu_exit (rcu_flags);
One big NACK.
I will not slowdown 99% of cases because of one dumb user. Absolutely no way.
Mathieu Desnoyers
reviewerRe: [PATCH v4 16/27] tracing: Remove regular RCU context for _rcuidle tracepoints (again)
Quoted 58 lines · ----- On Mar 6, 2020, at 10:51 AM, Alexei Starovoitov…
Quoted 57 lines · Peter Zijlstra
Quoted 32 lines · Peter Zijlstra
Quoted 31 lines · Peter Zijlstra
Effectively revert commit
865e63b04e9b2("tracing: Add back in rcu_irq_enter/exit_irqson() for rcuidle tracepoints") now that we've taught perf how to deal with not having an RCU context provided.Signed-off-by Peter Zijlstra (Intel) <[email protected]>Reviewed-by Steven Rostedt (VMware) <[email protected]>--- include/linux/tracepoint.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)include/linux/tracepoint.h +2
-5@@ -179,10 +179,8 @@ static inline struct tracepoint *tracepo* For rcuidle callers, use srcu since sched-rcu \ * doesn't work from the idle path. \ */ \ -if (rcuidle) { \ +if (rcuidle) \ __idx =srcu_read_lock_notrace (&tracepoint_srcu);\ -rcu_irq_enter_irqsave (); \ - } \ \ it_func_ptr =rcu_dereference_raw ((tp)->funcs); \ \@@ -194,10 +192,8 @@ static inline struct tracepoint *tracepo }while ((++it_func_ptr)->func); \ } \ \ -if (rcuidle) { \ -rcu_irq_exit_irqsave (); \ +if (rcuidle) \Quoted 8 lines
include/linux/tracepoint.h static inline struct tracepoint *tracepo · line 199
Quoted 5 lines
include/linux/tracepoint.h +0
-1srcu_read_unlock_notrace (&tracepoint_srcu, __idx);\ - } \ \preempt_enable_notrace (); \ }while (0 )So what happens when BPF registers for these tracepoints? BPF very much wants RCU on AFAIU.
I suspect we needs something like this...
kernel/trace/bpf_trace.c +1
-0@@ -1475,11 +1475,13 @@ void bpf_put_raw_tracepoint(struct bpf_raw_event_map *btp)static __always_inline void __bpf_trace_run(struct bpf_prog *prog, u64 *args) { +int rcu_flags =trace_rcu_enter ();rcu_read_lock ();preempt_disable ();
Quoted 8 lines
kernel/trace/bpf_trace.c void bpf_put_raw_tracepoint(struct bpf_raw_event_map *btp) · line 1484
Quoted 4 lines
kernel/trace/bpf_trace.c +1
-0(void )BPF_PROG_RUN (prog, args);preempt_enable ();rcu_read_unlock (); +trace_rcu_exit (rcu_flags);One big NACK.
I will not slowdown 99% of cases because of one dumb user. Absolutely no way.
If we care about not adding those extra branches on the fast-path, there is an alternative way to do things: BPF could provide two distinct probe callbacks, one meant for rcuidle tracepoints (which would have the trace_rcu_enter/exit), and the other for the for 99% of the other callsites which have RCU watching.
I would recommend performing benchmarks justifying the choice of one approach over the other though.
Thanks,
Mathieu
Signature · 3 lines
Mathieu Desnoyers EfficiOS Inc. http://www.efficios.com
Steven Rostedt
maintainerRe: [PATCH v4 16/27] tracing: Remove regular RCU context for _rcuidle tracepoints (again)
Quoted 7 lines · On Fri, 6 Mar 2020 11:04:28 -0500 (EST) Mathieu Desnoyers…
If we care about not adding those extra branches on the fast-path, there is an alternative way to do things: BPF could provide two distinct probe callbacks, one meant for rcuidle tracepoints (which would have the trace_rcu_enter/exit), and the other for the for 99% of the other callsites which have RCU watching.
I would recommend performing benchmarks justifying the choice of one approach over the other though.
I just whipped this up (haven't even tried to compile it), but this should satisfy everyone. Those that register a callback that needs RCU protection simply registers with one of the _rcu versions, and all will be done. And since DO_TRACE is a macro, and rcuidle is a constant, the rcu protection code will be compiled out for locations that it is not needed.
With this, perf doesn't even need to do anything extra but register with the "_rcu" version.
-- Steve
include/linux/tracepoint-defs.h +1 -0
@@ -25,6 +25,7 @@ struct tracepoint_func {void *func;void *data;int prio; +int requires_rcu; };struct tracepoint {
include/linux/tracepoint.h +9 -6
@@ -179,25 +179,28 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)* For rcuidle callers, use srcu since sched-rcu \ * doesn't work from the idle path. \ */ \ -if (rcuidle) { \ +if (rcuidle) \ __idx =srcu_read_lock_notrace (&tracepoint_srcu);\ -rcu_irq_enter_irqson (); \ - } \ \ it_func_ptr =rcu_dereference_raw ((tp)->funcs); \ \if (it_func_ptr) { \do { \ +int rcu_flags; \ it_func = (it_func_ptr)->func; \ +if (rcuidle && \ + (it_func_ptr)->requires_rcu) \ + rcu_flags =trace_rcu_enter (); \ __data = (it_func_ptr)->data; \ ((void (*)(proto ))(it_func))(args); \ +if (rcuidle && \ + (it_func_ptr)->requires_rcu) \ +trace_rcu_exit (rcu_flags); \ }while ((++it_func_ptr)->func); \ } \ \ -if (rcuidle) { \ +if (rcuidle) \rcu_irq_exit_irqson (); \ -srcu_read_unlock_notrace (&tracepoint_srcu, __idx);\ - } \ \preempt_enable_notrace (); \ }while (0 )
kernel/tracepoint.c +45 -3
78 lines not on this page · raw message
Re: [PATCH v4 16/27] tracing: Remove regular RCU context for _rcuidle tracepoints (again)
Quoted 11 lines · Steven Rostedt
Quoted 7 lines · On Fri, 6 Mar 2020 11:04:28 -0500 (EST) Mathieu Desnoyers…
If we care about not adding those extra branches on the fast-path, there is an alternative way to do things: BPF could provide two distinct probe callbacks, one meant for rcuidle tracepoints (which would have the trace_rcu_enter/exit), and the other for the for 99% of the other callsites which have RCU watching.
I would recommend performing benchmarks justifying the choice of one approach over the other though.
Quoted 8 lines
I just whipped this up (haven't even tried to compile it), but this should satisfy everyone. Those that register a callback that needs RCU protection simply registers with one of the
_rcuversions, and all will be done. And sinceDO_TRACEis a macro, and rcuidle is a constant, the rcu protection code will be compiled out for locations that it is not needed.With this, perf doesn't even need to do anything extra but register with the "
_rcu" version.
Looks nice! Some comments below:
Quoted 19 lines
-- Steve
include/linux/tracepoint-defs.h +1
-0@@ -25,6 +25,7 @@ struct tracepoint_func {void *func;void *data;int prio; +int requires_rcu; };struct tracepoint {include/linux/tracepoint.h +0
-0
include/linux/tracepoint.h static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p) · line 183
Quoted 6 lines
include/linux/tracepoint.h +1
-1@@ -179,25 +179,28 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)* For rcuidle callers, use srcu since sched-rcu \ * doesn't work from the idle path. \ */ \ -if (rcuidle) { \ +if (rcuidle) \ __idx =srcu_read_lock_notrace (&tracepoint_srcu);\
Small addition:
To prevent confusion, we could make more clear that SRCU here is just to protect the tracepoint function table and not the callbacks themselves.
Quoted 7 lines
include/linux/tracepoint.h +0
-2-rcu_irq_enter_irqson (); \ - } \ \ it_func_ptr =rcu_dereference_raw ((tp)->funcs); \ \if (it_func_ptr) { \ do { \
include/linux/tracepoint.h static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p) · line 198
Quoted 10 lines
include/linux/tracepoint.h +7
-0+int rcu_flags; \ it_func = (it_func_ptr)->func; \ +if (rcuidle && \ + (it_func_ptr)->requires_rcu) \ + rcu_flags =trace_rcu_enter (); \ __data = (it_func_ptr)->data; \ ((void (*)(proto ))(it_func))(args); \ +if (rcuidle && \ + (it_func_ptr)->requires_rcu) \ +trace_rcu_exit (rcu_flags); \
Nit: If we have incurred the cost of trace_rcu_enter() once, we can call it only once and then call trace_rcu_exit() after the do-while loop. That way we pay the price only once.
thanks,
- Joel
Quoted 97 lines
include/linux/tracepoint.h +1
-3}while ((++it_func_ptr)->func); \ } \ \ -if (rcuidle) { \ +if (rcuidle) \rcu_irq_exit_irqson (); \ -srcu_read_unlock_notrace (&tracepoint_srcu, __idx);\ - } \ \preempt_enable_notrace (); \ }while (0 )kernel/tracepoint.c +45
-3@@ -295,6 +295,7 @@ static int tracepoint_remove_func(struct tracepoint *tp,* @probe: probe handler * @data: tracepoint data * @prio: priority of this function over other registered functions +* @rcu: set to non zero if the callback requires RCU protection * * Returns 0 if ok, error value on error. * Note: if @tp is within a module, the caller is responsible for @@ -302,8 +303,8 @@ static int tracepoint_remove_func(struct tracepoint *tp,* performed either with a tracepoint module going notifier, or from * within module exit functions. */ -int tracepoint_probe_register_prio (struct tracepoint *tp,void *probe, -void *data,int prio) +int tracepoint_probe_register_prio_rcu (struct tracepoint *tp,void *probe, +void *data,int prio,int rcu) {struct tracepoint_func tp_func;int ret;@@ -312,12 +313,52 @@ int tracepoint_probe_register_prio(struct tracepoint *tp, void *probe, tp_func.func = probe; tp_func.data = data; tp_func.prio = prio; + tp_func.requires_rcu = rcu; ret =tracepoint_add_func (tp, &tp_func, prio);mutex_unlock (&tracepoints_mutex);return ret; } +EXPORT_SYMBOL_GPL (tracepoint_probe_register_prio_rcu); + +/** +* tracepoint_probe_register_prio - Connect a probe to a tracepoint with priority +* @tp: tracepoint +* @probe: probe handler +* @data: tracepoint data +* @prio: priority of this function over other registered functions +* +* Returns 0 if ok, error value on error. +* Note: if @tp is within a module, the caller is responsible for +* unregistering the probe before the module is gone. This can be +* performed either with a tracepoint module going notifier, or from +* within module exit functions. +*/ +int tracepoint_probe_register_prio (struct tracepoint *tp,void *probe, +void *data,int prio) +{ +return tracepoint_probe_register_prio_rcu (tp, probe, data, prio,0 ); +}EXPORT_SYMBOL_GPL (tracepoint_probe_register_prio); +/** +* tracepoint_probe_register_rcu - Connect a probe to a tracepoint +* @tp: tracepoint +* @probe: probe handler +* @data: tracepoint data +* +* Returns 0 if ok, error value on error. +* Note: if @tp is within a module, the caller is responsible for +* unregistering the probe before the module is gone. This can be +* performed either with a tracepoint module going notifier, or from +* within module exit functions. +*/ +int tracepoint_probe_register_rcu (struct tracepoint *tp,void *probe,void *data) +{ +return tracepoint_probe_register_prio_rcu (tp, probe, data, +TRACEPOINT_DEFAULT_PRIO ,1 ); +} +EXPORT_SYMBOL_GPL (tracepoint_probe_register_rcu); +/** * tracepoint_probe_register - Connect a probe to a tracepoint * @tp: tracepoint @@ -332,7 +373,8 @@ EXPORT_SYMBOL_GPL(tracepoint_probe_register_prio);*/ int tracepoint_probe_register (struct tracepoint *tp,void *probe,void *data) { -return tracepoint_probe_register_prio (tp, probe, data,TRACEPOINT_DEFAULT_PRIO ); +return tracepoint_probe_register_prio_rcu (tp, probe, data, +TRACEPOINT_DEFAULT_PRIO ,0 ); }EXPORT_SYMBOL_GPL (tracepoint_probe_register);
Steven Rostedt
maintainerRe: [PATCH v4 16/27] tracing: Remove regular RCU context for _rcuidle tracepoints (again)
Quoted 66 lines · On Fri, 6 Mar 2020 13:45:38 -0500 Joel Fernandes <[email protected]> wrote:
Quoted 11 lines · Steven Rostedt
Quoted 7 lines · On Fri, 6 Mar 2020 11:04:28 -0500 (EST) Mathieu Desnoyers…
If we care about not adding those extra branches on the fast-path, there is an alternative way to do things: BPF could provide two distinct probe callbacks, one meant for rcuidle tracepoints (which would have the trace_rcu_enter/exit), and the other for the for 99% of the other callsites which have RCU watching.
I would recommend performing benchmarks justifying the choice of one approach over the other though.
Quoted 8 lines
I just whipped this up (haven't even tried to compile it), but this should satisfy everyone. Those that register a callback that needs RCU protection simply registers with one of the
_rcuversions, and all will be done. And sinceDO_TRACEis a macro, and rcuidle is a constant, the rcu protection code will be compiled out for locations that it is not needed.With this, perf doesn't even need to do anything extra but register with the "
_rcu" version.Looks nice! Some comments below:
Quoted 19 lines
-- Steve
include/linux/tracepoint-defs.h +1
-0@@ -25,6 +25,7 @@ struct tracepoint_func {void *func;void *data;int prio; +int requires_rcu; };struct tracepoint {include/linux/tracepoint.h +0
-0include/linux/tracepoint.h static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p) · line 183
Quoted 6 lines
include/linux/tracepoint.h +1
-1@@ -179,25 +179,28 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)* For rcuidle callers, use srcu since sched-rcu \ * doesn't work from the idle path. \ */ \ -if (rcuidle) { \ +if (rcuidle) \ __idx = srcu_read_lock_notrace(&tracepoint_srcu);\Small addition:
To prevent confusion, we could make more clear that SRCU here is just to protect the tracepoint function table and not the callbacks themselves.Quoted 13 lines
include/linux/tracepoint.h +4
-2-rcu_irq_enter_irqson (); \ - } \ \ it_func_ptr =rcu_dereference_raw ((tp)->funcs); \ \if (it_func_ptr) { \ do { \ + int rcu_flags; \ it_func = (it_func_ptr)->func; \ + if (rcuidle && \ + (it_func_ptr)->requires_rcu) \ + rcu_flags = trace_rcu_enter(); \ __data = (it_func_ptr)->data; \
Quoted 9 lines
include/linux/tracepoint.h static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p) · line 198
Quoted 4 lines
include/linux/tracepoint.h +3
-0((void (*)(proto ))(it_func))(args); \ +if (rcuidle && \ + (it_func_ptr)->requires_rcu) \ + trace_rcu_exit(rcu_flags); \Nit: If we have incurred the cost of
trace_rcu_enter()once, we can call it only once and then calltrace_rcu_exit()after the do-while loop. That way we pay the price only once.
I thought about that, but the common case is only one callback attached at a time. To make the code complex for the non common case seemed too much of an overkill. If we find that it does help, it's best to do that as a separate patch because then if something goes wrong we know where it happened.
Currently, this provides the same overhead as if each callback did it themselves like we were proposing (but without the added need to do it for all instances of the callback).
-- Steve
Re: [PATCH v4 16/27] tracing: Remove regular RCU context for _rcuidle tracepoints (again)
On Fri, Mar 06, 2020 at 01:59:25PM -0500, Steven Rostedt wrote:
[snip]
Quoted 29 lines
Quoted 13 lines
Quoted 13 lines
include/linux/tracepoint.h +4
-2-rcu_irq_enter_irqson (); \ - } \ \ it_func_ptr =rcu_dereference_raw ((tp)->funcs); \ \if (it_func_ptr) { \ do { \ + int rcu_flags; \ it_func = (it_func_ptr)->func; \ + if (rcuidle && \ + (it_func_ptr)->requires_rcu) \ + rcu_flags = trace_rcu_enter(); \ __data = (it_func_ptr)->data; \Quoted 9 lines
include/linux/tracepoint.h static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p) · line 198
Quoted 4 lines
include/linux/tracepoint.h +3
-0((void (*)(proto ))(it_func))(args); \ +if (rcuidle && \ + (it_func_ptr)->requires_rcu) \ + trace_rcu_exit(rcu_flags); \Nit: If we have incurred the cost of
trace_rcu_enter()once, we can call it only once and then calltrace_rcu_exit()after the do-while loop. That way we pay the price only once.I thought about that, but the common case is only one callback attached at a time. To make the code complex for the non common case seemed too much of an overkill. If we find that it does help, it's best to do that as a separate patch because then if something goes wrong we know where it happened.
Quoted 3 lines
Currently, this provides the same overhead as if each callback did it themselves like we were proposing (but without the added need to do it for all instances of the callback).
That's ok, it could be a separate patch.
thanks,
- Joel
Mathieu Desnoyers
reviewerRe: [PATCH v4 16/27] tracing: Remove regular RCU context for _rcuidle tracepoints (again)
In reply to Steven RostedtQuoted 24 lines · ----- On Mar 6, 2020, at 12:55 PM, rostedt [email protected] wrote:
Quoted 9 lines · On Fri, 6 Mar 2020 11:04:28 -0500 (EST) Mathieu Desnoyers…
If we care about not adding those extra branches on the fast-path, there is an alternative way to do things: BPF could provide two distinct probe callbacks, one meant for rcuidle tracepoints (which would have the trace_rcu_enter/exit), and
the other for the for 99% of the other callsites which have RCU watching.I would recommend performing benchmarks justifying the choice of one approach over
the other though.I just whipped this up (haven't even tried to compile it), but this should satisfy everyone. Those that register a callback that needs RCU protection simply registers with one of the
_rcuversions, and all will be done. And sinceDO_TRACEis a macro, and rcuidle is a constant, the rcu protection code will be compiled out for locations that it is not needed.With this, perf doesn't even need to do anything extra but register with the "
_rcu" version.-- Steve
[...]
Quoted 13 lines
kernel/tracepoint.c +1
-0@@ -295,6 +295,7 @@ static int tracepoint_remove_func(struct tracepoint *tp,* @probe: probe handler * @data: tracepoint data * @prio: priority of this function over other registered functions +* @rcu: set to non zero if the callback requires RCU protection * * Returns 0 if ok, error value on error. * Note: if @tp is within a module, the caller is responsible for
kernel/tracepoint.c static int tracepoint_remove_func(struct tracepoint *tp, · line 307
Quoted 7 lines
kernel/tracepoint.c +2
-2@@ -302,8 +303,8 @@ static int tracepoint_remove_func(struct tracepoint *tp,* performed either with a tracepoint module going notifier, or from * within module exit functions. */ -int tracepoint_probe_register_prio (struct tracepoint *tp,void *probe, -void *data,int prio) +int tracepoint_probe_register_prio_rcu (struct tracepoint *tp,void *probe, +void *data,int prio,int rcu)
I agree with the overall approach. Just a bit of nitpicking on the API:
I understand that the "prio" argument is a separate argument because it can take many values. However, "rcu" is just a boolean, so I wonder if we should not rather introduce a "int flags" with a bitmask enum, e.g.
int tracepoint_probe_register_prio_flags(struct tracepoint *tp, void *probe,
void *data, int prio, int flags)
where flags would be populated through OR between labels of this enum:
enum tracepoint_flags {
TRACEPOINT_FLAG_RCU = (1U << 0),
};
We can then be future-proof for additional flags without ending up calling e.g.
tracepoint_probe_register_featurea_featureb_featurec(tp, probe, data, 0, 1, 0, 1)
which seems rather error-prone and less readable than a set of flags.
Thanks,
Mathieu
Signature · 3 lines
Mathieu Desnoyers EfficiOS Inc. http://www.efficios.com
Steven Rostedt
maintainerRe: [PATCH v4 16/27] tracing: Remove regular RCU context for _rcuidle tracepoints (again)
Quoted 5 lines · On Fri, 6 Mar 2020 15:22:46 -0500 (EST) Mathieu Desnoyers…
I agree with the overall approach. Just a bit of nitpicking on the API:
I understand that the "prio" argument is a separate argument because it can take many values. However, "rcu" is just a boolean, so I wonder if we should not rather introduce a "int flags" with a bitmask enum, e.g.
I thought about this approach, but thought it was a bit overkill. As the kernel doesn't have an internal API, I figured we can switch this over to flags when we get another flag to add. Unless you can think of one in the near future.
Quoted 6 lines
int tracepoint_probe_register_prio_flags(struct tracepoint *tp, void *probe,
void *data, int prio, int flags)where flags would be populated through OR between labels of this enum:
Quoted 7 lines
enum
tracepoint_flags{
TRACEPOINT_FLAG_RCU= (1U << 0),
};We can then be future-proof for additional flags without ending up calling e.g.
tracepoint_probe_register_featurea_featureb_featurec(tp, probe, data, 0, 1, 0, 1)
No, as soon as there is another boolean to add, the rcu version would be switched to flags. I even thought about making the rcu and prio into one, and change prio to be a SHRT_MAX max, and have the other 16 bits be for flags.
-- Steve
Quoted 2 lines
which seems rather error-prone and less readable than a set of flags.
Mathieu Desnoyers
reviewerRe: [PATCH v4 16/27] tracing: Remove regular RCU context for _rcuidle tracepoints (again)
Quoted 10 lines · ----- On Mar 6, 2020, at 3:45 PM, rostedt [email protected] wrote:
Quoted 6 lines · On Fri, 6 Mar 2020 15:22:46 -0500 (EST) Mathieu Desnoyers…
I agree with the overall approach. Just a bit of nitpicking on the API:
I understand that the "prio" argument is a separate argument because it can take many values. However, "rcu" is just a boolean, so I wonder if we should not rather
introduce a "int flags" with a bitmask enum, e.g.
Quoted 4 lines
I thought about this approach, but thought it was a bit overkill. As the kernel doesn't have an internal API, I figured we can switch this over to flags when we get another flag to add. Unless you can think of one in the near future.
The additional feature I have in mind for near future would be to register a probe which can take a page fault to a "sleepable" tracepoint. This would require preemption to be enabled and use of SRCU.
We can always change things when we get there.
Thanks,
Mathieu
Quoted 26 lines
Quoted 7 lines
int tracepoint_probe_register_prio_flags(struct tracepoint *tp, void *probe,
void *data, int prio, int flags)where flags would be populated through OR between labels of this enum:
Quoted 8 lines
enum
tracepoint_flags{
TRACEPOINT_FLAG_RCU= (1U << 0),
};We can then be future-proof for additional flags without ending up calling e.g.
tracepoint_probe_register_featurea_featureb_featurec(tp, probe, data, 0, 1, 0,
1)No, as soon as there is another boolean to add, the rcu version would be switched to flags. I even thought about making the rcu and prio into one, and change prio to be a
SHRT_MAXmax, and have the other 16 bits be for flags.-- Steve
Quoted 2 lines
which seems rather error-prone and less readable than a set of flags.
Signature · 3 lines
Mathieu Desnoyers EfficiOS Inc. http://www.efficios.com
Steven Rostedt
maintainerRe: [PATCH v4 16/27] tracing: Remove regular RCU context for _rcuidle tracepoints (again)
Quoted 17 lines · On Fri, 6 Mar 2020 15:55:24 -0500 (EST) Mathieu Desnoyers…
Quoted 10 lines · ----- On Mar 6, 2020, at 3:45 PM, rostedt [email protected] wrote:
Quoted 6 lines · On Fri, 6 Mar 2020 15:22:46 -0500 (EST) Mathieu Desnoyers…
I agree with the overall approach. Just a bit of nitpicking on the API:
I understand that the "prio" argument is a separate argument because it can take many values. However, "rcu" is just a boolean, so I wonder if we should not rather
introduce a "int flags" with a bitmask enum, e.g.Quoted 4 lines
I thought about this approach, but thought it was a bit overkill. As the kernel doesn't have an internal API, I figured we can switch this over to flags when we get another flag to add. Unless you can think of one in the near future.
Quoted 5 lines
The additional feature I have in mind for near future would be to register a probe which can take a page fault to a "sleepable" tracepoint. This would require preemption to be enabled and use of SRCU.
We can always change things when we get there.
Yeah, let's rename it if we get there.
-- Steve
Re: [PATCH v4 16/27] tracing: Remove regular RCU context for _rcuidle tracepoints (again)
In reply to Mathieu DesnoyersQuoted 13 lines · Mathieu Desnoyers
Quoted 10 lines · ----- On Mar 6, 2020, at 3:45 PM, rostedt [email protected] wrote:
Quoted 6 lines · On Fri, 6 Mar 2020 15:22:46 -0500 (EST) Mathieu Desnoyers…
I agree with the overall approach. Just a bit of nitpicking on the API:
I understand that the "prio" argument is a separate argument because it can take many values. However, "rcu" is just a boolean, so I wonder if we should not rather
introduce a "int flags" with a bitmask enum, e.g.
Quoted 8 lines
Quoted 4 lines
I thought about this approach, but thought it was a bit overkill. As the kernel doesn't have an internal API, I figured we can switch this over to flags when we get another flag to add. Unless you can think of one in the near future.
The additional feature I have in mind for near future would be to register a probe which can take a page fault to a "sleepable" tracepoint. This would require preemption to be enabled and use of SRCU.
I'm working on sleepable bpf as well and this extra flag for tracepoints would come very handy, so I would go with flags approach right away. We wouldn't need to touch the same protos multiple times, less conflicts for us all, etc.
Re: [PATCH v4 16/27] tracing: Remove regular RCU context for _rcuidle tracepoints (again)
In reply to Alexei StarovoitovQuoted 57 lines · Alexei Starovoitov
Quoted 56 lines · Peter Zijlstra
Quoted 32 lines · Peter Zijlstra
Quoted 31 lines · Peter Zijlstra
Effectively revert commit
865e63b04e9b2("tracing: Add back in rcu_irq_enter/exit_irqson() for rcuidle tracepoints") now that we've taught perf how to deal with not having an RCU context provided.Signed-off-by Peter Zijlstra (Intel) <[email protected]>Reviewed-by Steven Rostedt (VMware) <[email protected]>--- include/linux/tracepoint.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)include/linux/tracepoint.h +2
-5@@ -179,10 +179,8 @@ static inline struct tracepoint *tracepo* For rcuidle callers, use srcu since sched-rcu \ * doesn't work from the idle path. \ */ \ -if (rcuidle) { \ +if (rcuidle) \ __idx =srcu_read_lock_notrace (&tracepoint_srcu);\ -rcu_irq_enter_irqsave (); \ - } \ \ it_func_ptr =rcu_dereference_raw ((tp)->funcs); \ \@@ -194,10 +192,8 @@ static inline struct tracepoint *tracepo }while ((++it_func_ptr)->func); \ } \ \ -if (rcuidle) { \ -rcu_irq_exit_irqsave (); \ +if (rcuidle) \Quoted 8 lines
include/linux/tracepoint.h static inline struct tracepoint *tracepo · line 199
Quoted 5 lines
include/linux/tracepoint.h +0
-1srcu_read_unlock_notrace (&tracepoint_srcu, __idx);\ - } \ \preempt_enable_notrace (); \ }while (0 )So what happens when BPF registers for these tracepoints? BPF very much wants RCU on AFAIU.
I suspect we needs something like this...
kernel/trace/bpf_trace.c +1
-0@@ -1475,11 +1475,13 @@ void bpf_put_raw_tracepoint(struct bpf_raw_event_map *btp)static __always_inline void __bpf_trace_run(struct bpf_prog *prog, u64 *args) { +int rcu_flags =trace_rcu_enter ();rcu_read_lock ();preempt_disable ();
Quoted 8 lines
kernel/trace/bpf_trace.c void bpf_put_raw_tracepoint(struct bpf_raw_event_map *btp) · line 1484
Quoted 4 lines
kernel/trace/bpf_trace.c +1
-0(void )BPF_PROG_RUN (prog, args);preempt_enable ();rcu_read_unlock (); +trace_rcu_exit (rcu_flags);One big NACK.
I will not slowdown 99% of cases because of one dumb user. Absolutely no way.
For the 99% usecases, they incur an additional atomic_read and a branch, with the above. Is that the concern? Just want to make sure we are talking about same thing.
Speaking of slowdowns, you don't really need that rcu_read_lock/unlock() pair in __bpf_trace_run() AFAICS. The rcu_read_unlock() can run into the rcu_read_unlock_special() slowpath and if not, at least has branches. Most importantly, RCU is consolidated which means preempt_disable() implies rcu_read_lock().
thanks,
- Joel
Peter Zijlstra
maintainerPATCH v4 17/27 perf,tracing: Allow function tracing when !RCU
In reply to Peter ZijlstraSince perf is now able to deal with !rcu_is_watching() contexts, remove the restraint.
--- kernel/trace/trace_event_perf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/trace/trace_event_perf.c +1 -1
@@ -477,7 +477,7 @@ static int perf_ftrace_function_register {struct ftrace_ops *ops = &event->ftrace_ops; - ops->flags =FTRACE_OPS_FL_RCU ; + ops->flags =0 ; ops->func = perf_ftrace_function_call; ops->private = (void *)(unsigned long )nr_cpu_ids;
Peter Zijlstra
maintainerPATCH v4 18/27 x86/int3: Ensure that poke_int3_handler() is not traced
In reply to Peter ZijlstraFrom: Thomas Gleixner <[email protected]>
In order to ensure poke_int3_handler() is completely self contained -- we call this while we're modifying other text, imagine the fun of hitting another INT3 -- ensure that everything it uses is not traced.
The primary means here is to force inlining; bsearch() is notrace because all of lib/ is.
--- arch/x86/include/asm/ptrace.h | 2 +- arch/x86/include/asm/text-patching.h | 11 +++++++---- arch/x86/kernel/alternative.c | 11 +++++++---- 3 files changed, 15 insertions(+), 9 deletions(-)
arch/x86/include/asm/ptrace.h +1 -1
@@ -123,7 +123,7 @@ static inline void regs_set_return_value* On x86_64, vm86 mode is mercifully nonexistent, and we don't need * the extra check. */ -static inline int user_mode (struct pt_regs *regs) +static __always_inline int user_mode(struct pt_regs *regs) {#ifdef CONFIG_X86_32 return ((regs->cs &SEGMENT_RPL_MASK ) | (regs->flags &X86_VM_MASK )) >=USER_RPL ;
arch/x86/include/asm/text-patching.h +7 -4
@@ -64,7 +64,7 @@ extern void text_poke_finish(void);#define DISP32_SIZE 4 -static inline int text_opcode_size (u8 opcode) +static __always_inline int text_opcode_size(u8 opcode) {int size =0 ;
@@ -118,12 +118,14 @@ extern __ro_after_init struct mm_structextern __ro_after_init unsigned long poking_addr;#ifndef CONFIG_UML_X86 -static inline void int3_emulate_jmp (struct pt_regs *regs,unsigned long ip) +static __always_inline +void int3_emulate_jmp(struct pt_regs *regs, unsigned long ip) { regs->ip = ip; } -static inline void int3_emulate_push (struct pt_regs *regs,unsigned long val) +static __always_inline +void int3_emulate_push(struct pt_regs *regs, unsigned long val) {/* * The int3 handler in entry_64.S adds a gap between the
@@ -138,7 +140,8 @@ static inline void int3_emulate_push(str *(unsigned long *)regs->sp = val; } -static inline void int3_emulate_call (struct pt_regs *regs,unsigned long func) +static __always_inline +void int3_emulate_call(struct pt_regs *regs, unsigned long func) {int3_emulate_push (regs, regs->ip -INT3_INSN_SIZE +CALL_INSN_SIZE );int3_emulate_jmp (regs, func);
arch/x86/kernel/alternative.c +4 -3
@@ -956,7 +956,8 @@ struct bp_patching_desc {static struct bp_patching_desc *bp_desc; -static inline struct bp_patching_desc *try_get_desc (struct bp_patching_desc **descp) +static __always_inline +struct bp_patching_desc *try_get_desc(struct bp_patching_desc **descp) {struct bp_patching_desc *desc =READ_ONCE (*descp);/* rcu_dereference */
@@ -966,13 +967,13 @@ static inline struct bp_patching_desc *treturn desc; } -static inline void put_desc (struct bp_patching_desc *desc) +static __always_inline void put_desc(struct bp_patching_desc *desc) {smp_mb__before_atomic ();atomic_dec (&desc->refs); } -static inline void *text_poke_addr (struct text_poke_loc *tp) +static __always_inline void *text_poke_addr(struct text_poke_loc *tp) {return _stext + tp->rel_addr; }
Peter Zijlstra
maintainerPATCH v4 19/27 locking/atomics, kcsan: Add KCSAN instrumentation
In reply to Peter ZijlstraFrom: Marco Elver <[email protected]>
This adds KCSAN instrumentation to atomic-instrumented.h.
--- include/asm-generic/atomic-instrumented.h | 390 +++++++++++++++--------------- scripts/atomic/gen-atomic-instrumented.sh | 14 - 2 files changed, 212 insertions(+), 192 deletions(-)
include/asm-generic/atomic-instrumented.h +200 -190
@@ -20,10 +20,20 @@#include <linux/build_bug.h> #include <linux/kasan-checks.h> +static inline void __atomic_check_read (const volatile void *v,size_t size) +{ +kasan_check_read (v, size); +} + +static inline void __atomic_check_write (const volatile void *v,size_t size) +{ +kasan_check_write (v, size); +} +static inline int atomic_read (const atomic_t *v) { -kasan_check_read (v,sizeof (*v)); +__atomic_check_read (v,sizeof (*v));return arch_atomic_read (v); }#define atomic_read atomic_read
@@ -32,7 +42,7 @@ atomic_read(const atomic_t *v)static inline int atomic_read_acquire (const atomic_t *v) { -kasan_check_read (v,sizeof (*v)); +__atomic_check_read (v,sizeof (*v));return arch_atomic_read_acquire (v); }#define atomic_read_acquire atomic_read_acquire
@@ -41,7 +51,7 @@ atomic_read_acquire(const atomic_t *v)static inline void atomic_set (atomic_t *v,int i) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic_set (v, i); }#define atomic_set atomic_set
@@ -50,7 +60,7 @@ atomic_set(atomic_t *v, int i)static inline void atomic_set_release (atomic_t *v,int i) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic_set_release (v, i); }#define atomic_set_release atomic_set_release
@@ -59,7 +69,7 @@ atomic_set_release(atomic_t *v, int i)static inline void atomic_add (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic_add (i, v); }#define atomic_add atomic_add
@@ -68,7 +78,7 @@ atomic_add(int i, atomic_t *v)static inline int atomic_add_return (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_add_return (i, v); }#define atomic_add_return atomic_add_return
@@ -78,7 +88,7 @@ atomic_add_return(int i, atomic_t *v)static inline int atomic_add_return_acquire (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_add_return_acquire (i, v); }#define atomic_add_return_acquire atomic_add_return_acquire
@@ -88,7 +98,7 @@ atomic_add_return_acquire(int i, atomic_static inline int atomic_add_return_release (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_add_return_release (i, v); }#define atomic_add_return_release atomic_add_return_release
@@ -98,7 +108,7 @@ atomic_add_return_release(int i, atomic_static inline int atomic_add_return_relaxed (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_add_return_relaxed (i, v); }#define atomic_add_return_relaxed atomic_add_return_relaxed
@@ -108,7 +118,7 @@ atomic_add_return_relaxed(int i, atomic_static inline int atomic_fetch_add (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_add (i, v); }#define atomic_fetch_add atomic_fetch_add
@@ -118,7 +128,7 @@ atomic_fetch_add(int i, atomic_t *v)static inline int atomic_fetch_add_acquire (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_add_acquire (i, v); }#define atomic_fetch_add_acquire atomic_fetch_add_acquire
@@ -128,7 +138,7 @@ atomic_fetch_add_acquire(int i, atomic_tstatic inline int atomic_fetch_add_release (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_add_release (i, v); }#define atomic_fetch_add_release atomic_fetch_add_release
@@ -138,7 +148,7 @@ atomic_fetch_add_release(int i, atomic_tstatic inline int atomic_fetch_add_relaxed (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_add_relaxed (i, v); }#define atomic_fetch_add_relaxed atomic_fetch_add_relaxed
@@ -147,7 +157,7 @@ atomic_fetch_add_relaxed(int i, atomic_tstatic inline void atomic_sub (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic_sub (i, v); }#define atomic_sub atomic_sub
@@ -156,7 +166,7 @@ atomic_sub(int i, atomic_t *v)static inline int atomic_sub_return (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_sub_return (i, v); }#define atomic_sub_return atomic_sub_return
@@ -166,7 +176,7 @@ atomic_sub_return(int i, atomic_t *v)static inline int atomic_sub_return_acquire (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_sub_return_acquire (i, v); }#define atomic_sub_return_acquire atomic_sub_return_acquire
@@ -176,7 +186,7 @@ atomic_sub_return_acquire(int i, atomic_static inline int atomic_sub_return_release (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_sub_return_release (i, v); }#define atomic_sub_return_release atomic_sub_return_release
@@ -186,7 +196,7 @@ atomic_sub_return_release(int i, atomic_static inline int atomic_sub_return_relaxed (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_sub_return_relaxed (i, v); }#define atomic_sub_return_relaxed atomic_sub_return_relaxed
@@ -196,7 +206,7 @@ atomic_sub_return_relaxed(int i, atomic_static inline int atomic_fetch_sub (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_sub (i, v); }#define atomic_fetch_sub atomic_fetch_sub
@@ -206,7 +216,7 @@ atomic_fetch_sub(int i, atomic_t *v)static inline int atomic_fetch_sub_acquire (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_sub_acquire (i, v); }#define atomic_fetch_sub_acquire atomic_fetch_sub_acquire
@@ -216,7 +226,7 @@ atomic_fetch_sub_acquire(int i, atomic_tstatic inline int atomic_fetch_sub_release (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_sub_release (i, v); }#define atomic_fetch_sub_release atomic_fetch_sub_release
@@ -226,7 +236,7 @@ atomic_fetch_sub_release(int i, atomic_tstatic inline int atomic_fetch_sub_relaxed (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_sub_relaxed (i, v); }#define atomic_fetch_sub_relaxed atomic_fetch_sub_relaxed
@@ -236,7 +246,7 @@ atomic_fetch_sub_relaxed(int i, atomic_tstatic inline void atomic_inc (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic_inc (v); }#define atomic_inc atomic_inc
@@ -246,7 +256,7 @@ atomic_inc(atomic_t *v)static inline int atomic_inc_return (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_inc_return (v); }#define atomic_inc_return atomic_inc_return
@@ -256,7 +266,7 @@ atomic_inc_return(atomic_t *v)static inline int atomic_inc_return_acquire (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_inc_return_acquire (v); }#define atomic_inc_return_acquire atomic_inc_return_acquire
@@ -266,7 +276,7 @@ atomic_inc_return_acquire(atomic_t *v)static inline int atomic_inc_return_release (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_inc_return_release (v); }#define atomic_inc_return_release atomic_inc_return_release
@@ -276,7 +286,7 @@ atomic_inc_return_release(atomic_t *v)static inline int atomic_inc_return_relaxed (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_inc_return_relaxed (v); }#define atomic_inc_return_relaxed atomic_inc_return_relaxed
@@ -286,7 +296,7 @@ atomic_inc_return_relaxed(atomic_t *v)static inline int atomic_fetch_inc (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_inc (v); }#define atomic_fetch_inc atomic_fetch_inc
@@ -296,7 +306,7 @@ atomic_fetch_inc(atomic_t *v)static inline int atomic_fetch_inc_acquire (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_inc_acquire (v); }#define atomic_fetch_inc_acquire atomic_fetch_inc_acquire
@@ -306,7 +316,7 @@ atomic_fetch_inc_acquire(atomic_t *v)static inline int atomic_fetch_inc_release (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_inc_release (v); }#define atomic_fetch_inc_release atomic_fetch_inc_release
@@ -316,7 +326,7 @@ atomic_fetch_inc_release(atomic_t *v)static inline int atomic_fetch_inc_relaxed (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_inc_relaxed (v); }#define atomic_fetch_inc_relaxed atomic_fetch_inc_relaxed
@@ -326,7 +336,7 @@ atomic_fetch_inc_relaxed(atomic_t *v)static inline void atomic_dec (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic_dec (v); }#define atomic_dec atomic_dec
@@ -336,7 +346,7 @@ atomic_dec(atomic_t *v)static inline int atomic_dec_return (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_dec_return (v); }#define atomic_dec_return atomic_dec_return
@@ -346,7 +356,7 @@ atomic_dec_return(atomic_t *v)static inline int atomic_dec_return_acquire (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_dec_return_acquire (v); }#define atomic_dec_return_acquire atomic_dec_return_acquire
@@ -356,7 +366,7 @@ atomic_dec_return_acquire(atomic_t *v)static inline int atomic_dec_return_release (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_dec_return_release (v); }#define atomic_dec_return_release atomic_dec_return_release
@@ -366,7 +376,7 @@ atomic_dec_return_release(atomic_t *v)static inline int atomic_dec_return_relaxed (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_dec_return_relaxed (v); }#define atomic_dec_return_relaxed atomic_dec_return_relaxed
@@ -376,7 +386,7 @@ atomic_dec_return_relaxed(atomic_t *v)static inline int atomic_fetch_dec (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_dec (v); }#define atomic_fetch_dec atomic_fetch_dec
@@ -386,7 +396,7 @@ atomic_fetch_dec(atomic_t *v)static inline int atomic_fetch_dec_acquire (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_dec_acquire (v); }#define atomic_fetch_dec_acquire atomic_fetch_dec_acquire
@@ -396,7 +406,7 @@ atomic_fetch_dec_acquire(atomic_t *v)static inline int atomic_fetch_dec_release (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_dec_release (v); }#define atomic_fetch_dec_release atomic_fetch_dec_release
@@ -406,7 +416,7 @@ atomic_fetch_dec_release(atomic_t *v)static inline int atomic_fetch_dec_relaxed (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_dec_relaxed (v); }#define atomic_fetch_dec_relaxed atomic_fetch_dec_relaxed
@@ -415,7 +425,7 @@ atomic_fetch_dec_relaxed(atomic_t *v)static inline void atomic_and (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic_and (i, v); }#define atomic_and atomic_and
@@ -424,7 +434,7 @@ atomic_and(int i, atomic_t *v)static inline int atomic_fetch_and (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_and (i, v); }#define atomic_fetch_and atomic_fetch_and
@@ -434,7 +444,7 @@ atomic_fetch_and(int i, atomic_t *v)static inline int atomic_fetch_and_acquire (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_and_acquire (i, v); }#define atomic_fetch_and_acquire atomic_fetch_and_acquire
@@ -444,7 +454,7 @@ atomic_fetch_and_acquire(int i, atomic_tstatic inline int atomic_fetch_and_release (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_and_release (i, v); }#define atomic_fetch_and_release atomic_fetch_and_release
@@ -454,7 +464,7 @@ atomic_fetch_and_release(int i, atomic_tstatic inline int atomic_fetch_and_relaxed (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_and_relaxed (i, v); }#define atomic_fetch_and_relaxed atomic_fetch_and_relaxed
@@ -464,7 +474,7 @@ atomic_fetch_and_relaxed(int i, atomic_tstatic inline void atomic_andnot (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic_andnot (i, v); }#define atomic_andnot atomic_andnot
@@ -474,7 +484,7 @@ atomic_andnot(int i, atomic_t *v)static inline int atomic_fetch_andnot (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_andnot (i, v); }#define atomic_fetch_andnot atomic_fetch_andnot
@@ -484,7 +494,7 @@ atomic_fetch_andnot(int i, atomic_t *v)static inline int atomic_fetch_andnot_acquire (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_andnot_acquire (i, v); }#define atomic_fetch_andnot_acquire atomic_fetch_andnot_acquire
@@ -494,7 +504,7 @@ atomic_fetch_andnot_acquire(int i, atomistatic inline int atomic_fetch_andnot_release (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_andnot_release (i, v); }#define atomic_fetch_andnot_release atomic_fetch_andnot_release
@@ -504,7 +514,7 @@ atomic_fetch_andnot_release(int i, atomistatic inline int atomic_fetch_andnot_relaxed (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_andnot_relaxed (i, v); }#define atomic_fetch_andnot_relaxed atomic_fetch_andnot_relaxed
@@ -513,7 +523,7 @@ atomic_fetch_andnot_relaxed(int i, atomistatic inline void atomic_or (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic_or (i, v); }#define atomic_or atomic_or
@@ -522,7 +532,7 @@ atomic_or(int i, atomic_t *v)static inline int atomic_fetch_or (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_or (i, v); }#define atomic_fetch_or atomic_fetch_or
@@ -532,7 +542,7 @@ atomic_fetch_or(int i, atomic_t *v)static inline int atomic_fetch_or_acquire (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_or_acquire (i, v); }#define atomic_fetch_or_acquire atomic_fetch_or_acquire
@@ -542,7 +552,7 @@ atomic_fetch_or_acquire(int i, atomic_tstatic inline int atomic_fetch_or_release (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_or_release (i, v); }#define atomic_fetch_or_release atomic_fetch_or_release
@@ -552,7 +562,7 @@ atomic_fetch_or_release(int i, atomic_tstatic inline int atomic_fetch_or_relaxed (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_or_relaxed (i, v); }#define atomic_fetch_or_relaxed atomic_fetch_or_relaxed
@@ -561,7 +571,7 @@ atomic_fetch_or_relaxed(int i, atomic_tstatic inline void atomic_xor (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic_xor (i, v); }#define atomic_xor atomic_xor
@@ -570,7 +580,7 @@ atomic_xor(int i, atomic_t *v)static inline int atomic_fetch_xor (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_xor (i, v); }#define atomic_fetch_xor atomic_fetch_xor
@@ -580,7 +590,7 @@ atomic_fetch_xor(int i, atomic_t *v)static inline int atomic_fetch_xor_acquire (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_xor_acquire (i, v); }#define atomic_fetch_xor_acquire atomic_fetch_xor_acquire
@@ -590,7 +600,7 @@ atomic_fetch_xor_acquire(int i, atomic_tstatic inline int atomic_fetch_xor_release (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_xor_release (i, v); }#define atomic_fetch_xor_release atomic_fetch_xor_release
@@ -600,7 +610,7 @@ atomic_fetch_xor_release(int i, atomic_tstatic inline int atomic_fetch_xor_relaxed (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_xor_relaxed (i, v); }#define atomic_fetch_xor_relaxed atomic_fetch_xor_relaxed
@@ -610,7 +620,7 @@ atomic_fetch_xor_relaxed(int i, atomic_tstatic inline int atomic_xchg (atomic_t *v,int i) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_xchg (v, i); }#define atomic_xchg atomic_xchg
@@ -620,7 +630,7 @@ atomic_xchg(atomic_t *v, int i)static inline int atomic_xchg_acquire (atomic_t *v,int i) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_xchg_acquire (v, i); }#define atomic_xchg_acquire atomic_xchg_acquire
@@ -630,7 +640,7 @@ atomic_xchg_acquire(atomic_t *v, int i)static inline int atomic_xchg_release (atomic_t *v,int i) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_xchg_release (v, i); }#define atomic_xchg_release atomic_xchg_release
@@ -640,7 +650,7 @@ atomic_xchg_release(atomic_t *v, int i)static inline int atomic_xchg_relaxed (atomic_t *v,int i) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_xchg_relaxed (v, i); }#define atomic_xchg_relaxed atomic_xchg_relaxed
@@ -650,7 +660,7 @@ atomic_xchg_relaxed(atomic_t *v, int i)static inline int atomic_cmpxchg (atomic_t *v,int old,int new) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_cmpxchg (v, old, new); }#define atomic_cmpxchg atomic_cmpxchg
@@ -660,7 +670,7 @@ atomic_cmpxchg(atomic_t *v, int old, intstatic inline int atomic_cmpxchg_acquire (atomic_t *v,int old,int new) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_cmpxchg_acquire (v, old, new); }#define atomic_cmpxchg_acquire atomic_cmpxchg_acquire
@@ -670,7 +680,7 @@ atomic_cmpxchg_acquire(atomic_t *v, intstatic inline int atomic_cmpxchg_release (atomic_t *v,int old,int new) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_cmpxchg_release (v, old, new); }#define atomic_cmpxchg_release atomic_cmpxchg_release
@@ -680,7 +690,7 @@ atomic_cmpxchg_release(atomic_t *v, intstatic inline int atomic_cmpxchg_relaxed (atomic_t *v,int old,int new) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_cmpxchg_relaxed (v, old, new); }#define atomic_cmpxchg_relaxed atomic_cmpxchg_relaxed
@@ -690,8 +700,8 @@ atomic_cmpxchg_relaxed(atomic_t *v, intstatic inline bool atomic_try_cmpxchg (atomic_t *v,int *old,int new) { -kasan_check_write (v,sizeof (*v)); -kasan_check_write (old,sizeof (*old)); +__atomic_check_write (v,sizeof (*v)); +__atomic_check_write (old,sizeof (*old));return arch_atomic_try_cmpxchg (v, old, new); }#define atomic_try_cmpxchg atomic_try_cmpxchg
@@ -701,8 +711,8 @@ atomic_try_cmpxchg(atomic_t *v, int *oldstatic inline bool atomic_try_cmpxchg_acquire (atomic_t *v,int *old,int new) { -kasan_check_write (v,sizeof (*v)); -kasan_check_write (old,sizeof (*old)); +__atomic_check_write (v,sizeof (*v)); +__atomic_check_write (old,sizeof (*old));return arch_atomic_try_cmpxchg_acquire (v, old, new); }#define atomic_try_cmpxchg_acquire atomic_try_cmpxchg_acquire
@@ -712,8 +722,8 @@ atomic_try_cmpxchg_acquire(atomic_t *v,static inline bool atomic_try_cmpxchg_release (atomic_t *v,int *old,int new) { -kasan_check_write (v,sizeof (*v)); -kasan_check_write (old,sizeof (*old)); +__atomic_check_write (v,sizeof (*v)); +__atomic_check_write (old,sizeof (*old));return arch_atomic_try_cmpxchg_release (v, old, new); }#define atomic_try_cmpxchg_release atomic_try_cmpxchg_release
@@ -723,8 +733,8 @@ atomic_try_cmpxchg_release(atomic_t *v,static inline bool atomic_try_cmpxchg_relaxed (atomic_t *v,int *old,int new) { -kasan_check_write (v,sizeof (*v)); -kasan_check_write (old,sizeof (*old)); +__atomic_check_write (v,sizeof (*v)); +__atomic_check_write (old,sizeof (*old));return arch_atomic_try_cmpxchg_relaxed (v, old, new); }#define atomic_try_cmpxchg_relaxed atomic_try_cmpxchg_relaxed
@@ -734,7 +744,7 @@ atomic_try_cmpxchg_relaxed(atomic_t *v,static inline bool atomic_sub_and_test (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_sub_and_test (i, v); }#define atomic_sub_and_test atomic_sub_and_test
@@ -744,7 +754,7 @@ atomic_sub_and_test(int i, atomic_t *v)static inline bool atomic_dec_and_test (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_dec_and_test (v); }#define atomic_dec_and_test atomic_dec_and_test
@@ -754,7 +764,7 @@ atomic_dec_and_test(atomic_t *v)static inline bool atomic_inc_and_test (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_inc_and_test (v); }#define atomic_inc_and_test atomic_inc_and_test
@@ -764,7 +774,7 @@ atomic_inc_and_test(atomic_t *v)static inline bool atomic_add_negative (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_add_negative (i, v); }#define atomic_add_negative atomic_add_negative
@@ -774,7 +784,7 @@ atomic_add_negative(int i, atomic_t *v)static inline int atomic_fetch_add_unless (atomic_t *v,int a,int u) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_add_unless (v, a, u); }#define atomic_fetch_add_unless atomic_fetch_add_unless
@@ -784,7 +794,7 @@ atomic_fetch_add_unless(atomic_t *v, intstatic inline bool atomic_add_unless (atomic_t *v,int a,int u) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_add_unless (v, a, u); }#define atomic_add_unless atomic_add_unless
@@ -794,7 +804,7 @@ atomic_add_unless(atomic_t *v, int a, instatic inline bool atomic_inc_not_zero (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_inc_not_zero (v); }#define atomic_inc_not_zero atomic_inc_not_zero
@@ -804,7 +814,7 @@ atomic_inc_not_zero(atomic_t *v)static inline bool atomic_inc_unless_negative (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_inc_unless_negative (v); }#define atomic_inc_unless_negative atomic_inc_unless_negative
@@ -814,7 +824,7 @@ atomic_inc_unless_negative(atomic_t *v)static inline bool atomic_dec_unless_positive (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_dec_unless_positive (v); }#define atomic_dec_unless_positive atomic_dec_unless_positive
@@ -824,7 +834,7 @@ atomic_dec_unless_positive(atomic_t *v)static inline int atomic_dec_if_positive (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_dec_if_positive (v); }#define atomic_dec_if_positive atomic_dec_if_positive
@@ -833,7 +843,7 @@ atomic_dec_if_positive(atomic_t *v)static inline s64 atomic64_read (const atomic64_t *v) { -kasan_check_read (v,sizeof (*v)); +__atomic_check_read (v,sizeof (*v));return arch_atomic64_read (v); }#define atomic64_read atomic64_read
@@ -842,7 +852,7 @@ atomic64_read(const atomic64_t *v)static inline s64 atomic64_read_acquire (const atomic64_t *v) { -kasan_check_read (v,sizeof (*v)); +__atomic_check_read (v,sizeof (*v));return arch_atomic64_read_acquire (v); }#define atomic64_read_acquire atomic64_read_acquire
@@ -851,7 +861,7 @@ atomic64_read_acquire(const atomic64_t *static inline void atomic64_set (atomic64_t *v,s64 i) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic64_set (v, i); }#define atomic64_set atomic64_set
@@ -860,7 +870,7 @@ atomic64_set(atomic64_t *v, s64 i)static inline void atomic64_set_release (atomic64_t *v,s64 i) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic64_set_release (v, i); }#define atomic64_set_release atomic64_set_release
@@ -869,7 +879,7 @@ atomic64_set_release(atomic64_t *v, s64static inline void atomic64_add (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic64_add (i, v); }#define atomic64_add atomic64_add
@@ -878,7 +888,7 @@ atomic64_add(s64 i, atomic64_t *v)static inline s64 atomic64_add_return (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_add_return (i, v); }#define atomic64_add_return atomic64_add_return
@@ -888,7 +898,7 @@ atomic64_add_return(s64 i, atomic64_t *vstatic inline s64 atomic64_add_return_acquire (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_add_return_acquire (i, v); }#define atomic64_add_return_acquire atomic64_add_return_acquire
@@ -898,7 +908,7 @@ atomic64_add_return_acquire(s64 i, atomistatic inline s64 atomic64_add_return_release (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_add_return_release (i, v); }#define atomic64_add_return_release atomic64_add_return_release
@@ -908,7 +918,7 @@ atomic64_add_return_release(s64 i, atomistatic inline s64 atomic64_add_return_relaxed (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_add_return_relaxed (i, v); }#define atomic64_add_return_relaxed atomic64_add_return_relaxed
@@ -918,7 +928,7 @@ atomic64_add_return_relaxed(s64 i, atomistatic inline s64 atomic64_fetch_add (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_add (i, v); }#define atomic64_fetch_add atomic64_fetch_add
@@ -928,7 +938,7 @@ atomic64_fetch_add(s64 i, atomic64_t *v)static inline s64 atomic64_fetch_add_acquire (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_add_acquire (i, v); }#define atomic64_fetch_add_acquire atomic64_fetch_add_acquire
@@ -938,7 +948,7 @@ atomic64_fetch_add_acquire(s64 i, atomicstatic inline s64 atomic64_fetch_add_release (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_add_release (i, v); }#define atomic64_fetch_add_release atomic64_fetch_add_release
@@ -948,7 +958,7 @@ atomic64_fetch_add_release(s64 i, atomicstatic inline s64 atomic64_fetch_add_relaxed (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_add_relaxed (i, v); }#define atomic64_fetch_add_relaxed atomic64_fetch_add_relaxed
@@ -957,7 +967,7 @@ atomic64_fetch_add_relaxed(s64 i, atomicstatic inline void atomic64_sub (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic64_sub (i, v); }#define atomic64_sub atomic64_sub
@@ -966,7 +976,7 @@ atomic64_sub(s64 i, atomic64_t *v)static inline s64 atomic64_sub_return (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_sub_return (i, v); }#define atomic64_sub_return atomic64_sub_return
@@ -976,7 +986,7 @@ atomic64_sub_return(s64 i, atomic64_t *vstatic inline s64 atomic64_sub_return_acquire (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_sub_return_acquire (i, v); }#define atomic64_sub_return_acquire atomic64_sub_return_acquire
@@ -986,7 +996,7 @@ atomic64_sub_return_acquire(s64 i, atomistatic inline s64 atomic64_sub_return_release (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_sub_return_release (i, v); }#define atomic64_sub_return_release atomic64_sub_return_release
@@ -996,7 +1006,7 @@ atomic64_sub_return_release(s64 i, atomistatic inline s64 atomic64_sub_return_relaxed (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_sub_return_relaxed (i, v); }#define atomic64_sub_return_relaxed atomic64_sub_return_relaxed
@@ -1006,7 +1016,7 @@ atomic64_sub_return_relaxed(s64 i, atomistatic inline s64 atomic64_fetch_sub (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_sub (i, v); }#define atomic64_fetch_sub atomic64_fetch_sub
@@ -1016,7 +1026,7 @@ atomic64_fetch_sub(s64 i, atomic64_t *v)static inline s64 atomic64_fetch_sub_acquire (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_sub_acquire (i, v); }#define atomic64_fetch_sub_acquire atomic64_fetch_sub_acquire
@@ -1026,7 +1036,7 @@ atomic64_fetch_sub_acquire(s64 i, atomicstatic inline s64 atomic64_fetch_sub_release (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_sub_release (i, v); }#define atomic64_fetch_sub_release atomic64_fetch_sub_release
@@ -1036,7 +1046,7 @@ atomic64_fetch_sub_release(s64 i, atomicstatic inline s64 atomic64_fetch_sub_relaxed (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_sub_relaxed (i, v); }#define atomic64_fetch_sub_relaxed atomic64_fetch_sub_relaxed
@@ -1046,7 +1056,7 @@ atomic64_fetch_sub_relaxed(s64 i, atomicstatic inline void atomic64_inc (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic64_inc (v); }#define atomic64_inc atomic64_inc
@@ -1056,7 +1066,7 @@ atomic64_inc(atomic64_t *v)static inline s64 atomic64_inc_return (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_inc_return (v); }#define atomic64_inc_return atomic64_inc_return
@@ -1066,7 +1076,7 @@ atomic64_inc_return(atomic64_t *v)static inline s64 atomic64_inc_return_acquire (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_inc_return_acquire (v); }#define atomic64_inc_return_acquire atomic64_inc_return_acquire
@@ -1076,7 +1086,7 @@ atomic64_inc_return_acquire(atomic64_t *static inline s64 atomic64_inc_return_release (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_inc_return_release (v); }#define atomic64_inc_return_release atomic64_inc_return_release
@@ -1086,7 +1096,7 @@ atomic64_inc_return_release(atomic64_t *static inline s64 atomic64_inc_return_relaxed (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_inc_return_relaxed (v); }#define atomic64_inc_return_relaxed atomic64_inc_return_relaxed
@@ -1096,7 +1106,7 @@ atomic64_inc_return_relaxed(atomic64_t *static inline s64 atomic64_fetch_inc (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_inc (v); }#define atomic64_fetch_inc atomic64_fetch_inc
@@ -1106,7 +1116,7 @@ atomic64_fetch_inc(atomic64_t *v)static inline s64 atomic64_fetch_inc_acquire (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_inc_acquire (v); }#define atomic64_fetch_inc_acquire atomic64_fetch_inc_acquire
@@ -1116,7 +1126,7 @@ atomic64_fetch_inc_acquire(atomic64_t *vstatic inline s64 atomic64_fetch_inc_release (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_inc_release (v); }#define atomic64_fetch_inc_release atomic64_fetch_inc_release
@@ -1126,7 +1136,7 @@ atomic64_fetch_inc_release(atomic64_t *vstatic inline s64 atomic64_fetch_inc_relaxed (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_inc_relaxed (v); }#define atomic64_fetch_inc_relaxed atomic64_fetch_inc_relaxed
@@ -1136,7 +1146,7 @@ atomic64_fetch_inc_relaxed(atomic64_t *vstatic inline void atomic64_dec (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic64_dec (v); }#define atomic64_dec atomic64_dec
@@ -1146,7 +1156,7 @@ atomic64_dec(atomic64_t *v)static inline s64 atomic64_dec_return (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_dec_return (v); }#define atomic64_dec_return atomic64_dec_return
@@ -1156,7 +1166,7 @@ atomic64_dec_return(atomic64_t *v)static inline s64 atomic64_dec_return_acquire (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_dec_return_acquire (v); }#define atomic64_dec_return_acquire atomic64_dec_return_acquire
@@ -1166,7 +1176,7 @@ atomic64_dec_return_acquire(atomic64_t *static inline s64 atomic64_dec_return_release (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_dec_return_release (v); }#define atomic64_dec_return_release atomic64_dec_return_release
@@ -1176,7 +1186,7 @@ atomic64_dec_return_release(atomic64_t *static inline s64 atomic64_dec_return_relaxed (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_dec_return_relaxed (v); }#define atomic64_dec_return_relaxed atomic64_dec_return_relaxed
@@ -1186,7 +1196,7 @@ atomic64_dec_return_relaxed(atomic64_t *static inline s64 atomic64_fetch_dec (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_dec (v); }#define atomic64_fetch_dec atomic64_fetch_dec
@@ -1196,7 +1206,7 @@ atomic64_fetch_dec(atomic64_t *v)static inline s64 atomic64_fetch_dec_acquire (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_dec_acquire (v); }#define atomic64_fetch_dec_acquire atomic64_fetch_dec_acquire
@@ -1206,7 +1216,7 @@ atomic64_fetch_dec_acquire(atomic64_t *vstatic inline s64 atomic64_fetch_dec_release (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_dec_release (v); }#define atomic64_fetch_dec_release atomic64_fetch_dec_release
@@ -1216,7 +1226,7 @@ atomic64_fetch_dec_release(atomic64_t *vstatic inline s64 atomic64_fetch_dec_relaxed (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_dec_relaxed (v); }#define atomic64_fetch_dec_relaxed atomic64_fetch_dec_relaxed
@@ -1225,7 +1235,7 @@ atomic64_fetch_dec_relaxed(atomic64_t *vstatic inline void atomic64_and (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic64_and (i, v); }#define atomic64_and atomic64_and
@@ -1234,7 +1244,7 @@ atomic64_and(s64 i, atomic64_t *v)static inline s64 atomic64_fetch_and (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_and (i, v); }#define atomic64_fetch_and atomic64_fetch_and
@@ -1244,7 +1254,7 @@ atomic64_fetch_and(s64 i, atomic64_t *v)static inline s64 atomic64_fetch_and_acquire (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_and_acquire (i, v); }#define atomic64_fetch_and_acquire atomic64_fetch_and_acquire
@@ -1254,7 +1264,7 @@ atomic64_fetch_and_acquire(s64 i, atomicstatic inline s64 atomic64_fetch_and_release (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_and_release (i, v); }#define atomic64_fetch_and_release atomic64_fetch_and_release
@@ -1264,7 +1274,7 @@ atomic64_fetch_and_release(s64 i, atomicstatic inline s64 atomic64_fetch_and_relaxed (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_and_relaxed (i, v); }#define atomic64_fetch_and_relaxed atomic64_fetch_and_relaxed
@@ -1274,7 +1284,7 @@ atomic64_fetch_and_relaxed(s64 i, atomicstatic inline void atomic64_andnot (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic64_andnot (i, v); }#define atomic64_andnot atomic64_andnot
@@ -1284,7 +1294,7 @@ atomic64_andnot(s64 i, atomic64_t *v)static inline s64 atomic64_fetch_andnot (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_andnot (i, v); }#define atomic64_fetch_andnot atomic64_fetch_andnot
@@ -1294,7 +1304,7 @@ atomic64_fetch_andnot(s64 i, atomic64_tstatic inline s64 atomic64_fetch_andnot_acquire (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_andnot_acquire (i, v); }#define atomic64_fetch_andnot_acquire atomic64_fetch_andnot_acquire
@@ -1304,7 +1314,7 @@ atomic64_fetch_andnot_acquire(s64 i, atostatic inline s64 atomic64_fetch_andnot_release (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_andnot_release (i, v); }#define atomic64_fetch_andnot_release atomic64_fetch_andnot_release
@@ -1314,7 +1324,7 @@ atomic64_fetch_andnot_release(s64 i, atostatic inline s64 atomic64_fetch_andnot_relaxed (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_andnot_relaxed (i, v); }#define atomic64_fetch_andnot_relaxed atomic64_fetch_andnot_relaxed
@@ -1323,7 +1333,7 @@ atomic64_fetch_andnot_relaxed(s64 i, atostatic inline void atomic64_or (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic64_or (i, v); }#define atomic64_or atomic64_or
@@ -1332,7 +1342,7 @@ atomic64_or(s64 i, atomic64_t *v)static inline s64 atomic64_fetch_or (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_or (i, v); }#define atomic64_fetch_or atomic64_fetch_or
@@ -1342,7 +1352,7 @@ atomic64_fetch_or(s64 i, atomic64_t *v)static inline s64 atomic64_fetch_or_acquire (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_or_acquire (i, v); }#define atomic64_fetch_or_acquire atomic64_fetch_or_acquire
@@ -1352,7 +1362,7 @@ atomic64_fetch_or_acquire(s64 i, atomic6static inline s64 atomic64_fetch_or_release (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_or_release (i, v); }#define atomic64_fetch_or_release atomic64_fetch_or_release
@@ -1362,7 +1372,7 @@ atomic64_fetch_or_release(s64 i, atomic6static inline s64 atomic64_fetch_or_relaxed (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_or_relaxed (i, v); }#define atomic64_fetch_or_relaxed atomic64_fetch_or_relaxed
@@ -1371,7 +1381,7 @@ atomic64_fetch_or_relaxed(s64 i, atomic6static inline void atomic64_xor (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic64_xor (i, v); }#define atomic64_xor atomic64_xor
@@ -1380,7 +1390,7 @@ atomic64_xor(s64 i, atomic64_t *v)static inline s64 atomic64_fetch_xor (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_xor (i, v); }#define atomic64_fetch_xor atomic64_fetch_xor
@@ -1390,7 +1400,7 @@ atomic64_fetch_xor(s64 i, atomic64_t *v)static inline s64 atomic64_fetch_xor_acquire (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_xor_acquire (i, v); }#define atomic64_fetch_xor_acquire atomic64_fetch_xor_acquire
@@ -1400,7 +1410,7 @@ atomic64_fetch_xor_acquire(s64 i, atomicstatic inline s64 atomic64_fetch_xor_release (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_xor_release (i, v); }#define atomic64_fetch_xor_release atomic64_fetch_xor_release
@@ -1410,7 +1420,7 @@ atomic64_fetch_xor_release(s64 i, atomicstatic inline s64 atomic64_fetch_xor_relaxed (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_xor_relaxed (i, v); }#define atomic64_fetch_xor_relaxed atomic64_fetch_xor_relaxed
@@ -1420,7 +1430,7 @@ atomic64_fetch_xor_relaxed(s64 i, atomicstatic inline s64 atomic64_xchg (atomic64_t *v,s64 i) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_xchg (v, i); }#define atomic64_xchg atomic64_xchg
@@ -1430,7 +1440,7 @@ atomic64_xchg(atomic64_t *v, s64 i)static inline s64 atomic64_xchg_acquire (atomic64_t *v,s64 i) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_xchg_acquire (v, i); }#define atomic64_xchg_acquire atomic64_xchg_acquire
@@ -1440,7 +1450,7 @@ atomic64_xchg_acquire(atomic64_t *v, s64static inline s64 atomic64_xchg_release (atomic64_t *v,s64 i) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_xchg_release (v, i); }#define atomic64_xchg_release atomic64_xchg_release
@@ -1450,7 +1460,7 @@ atomic64_xchg_release(atomic64_t *v, s64static inline s64 atomic64_xchg_relaxed (atomic64_t *v,s64 i) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_xchg_relaxed (v, i); }#define atomic64_xchg_relaxed atomic64_xchg_relaxed
@@ -1460,7 +1470,7 @@ atomic64_xchg_relaxed(atomic64_t *v, s64static inline s64 atomic64_cmpxchg (atomic64_t *v,s64 old,s64 new) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_cmpxchg (v, old, new); }#define atomic64_cmpxchg atomic64_cmpxchg
@@ -1470,7 +1480,7 @@ atomic64_cmpxchg(atomic64_t *v, s64 old,static inline s64 atomic64_cmpxchg_acquire (atomic64_t *v,s64 old,s64 new) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_cmpxchg_acquire (v, old, new); }#define atomic64_cmpxchg_acquire atomic64_cmpxchg_acquire
@@ -1480,7 +1490,7 @@ atomic64_cmpxchg_acquire(atomic64_t *v,static inline s64 atomic64_cmpxchg_release (atomic64_t *v,s64 old,s64 new) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_cmpxchg_release (v, old, new); }#define atomic64_cmpxchg_release atomic64_cmpxchg_release
@@ -1490,7 +1500,7 @@ atomic64_cmpxchg_release(atomic64_t *v,static inline s64 atomic64_cmpxchg_relaxed (atomic64_t *v,s64 old,s64 new) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_cmpxchg_relaxed (v, old, new); }#define atomic64_cmpxchg_relaxed atomic64_cmpxchg_relaxed
@@ -1500,8 +1510,8 @@ atomic64_cmpxchg_relaxed(atomic64_t *v,static inline bool atomic64_try_cmpxchg (atomic64_t *v,s64 *old,s64 new) { -kasan_check_write (v,sizeof (*v)); -kasan_check_write (old,sizeof (*old)); +__atomic_check_write (v,sizeof (*v)); +__atomic_check_write (old,sizeof (*old));return arch_atomic64_try_cmpxchg (v, old, new); }#define atomic64_try_cmpxchg atomic64_try_cmpxchg
@@ -1511,8 +1521,8 @@ atomic64_try_cmpxchg(atomic64_t *v, s64static inline bool atomic64_try_cmpxchg_acquire (atomic64_t *v,s64 *old,s64 new) { -kasan_check_write (v,sizeof (*v)); -kasan_check_write (old,sizeof (*old)); +__atomic_check_write (v,sizeof (*v)); +__atomic_check_write (old,sizeof (*old));return arch_atomic64_try_cmpxchg_acquire (v, old, new); }#define atomic64_try_cmpxchg_acquire atomic64_try_cmpxchg_acquire
@@ -1522,8 +1532,8 @@ atomic64_try_cmpxchg_acquire(atomic64_tstatic inline bool atomic64_try_cmpxchg_release (atomic64_t *v,s64 *old,s64 new) { -kasan_check_write (v,sizeof (*v)); -kasan_check_write (old,sizeof (*old)); +__atomic_check_write (v,sizeof (*v)); +__atomic_check_write (old,sizeof (*old));return arch_atomic64_try_cmpxchg_release (v, old, new); }#define atomic64_try_cmpxchg_release atomic64_try_cmpxchg_release
@@ -1533,8 +1543,8 @@ atomic64_try_cmpxchg_release(atomic64_tstatic inline bool atomic64_try_cmpxchg_relaxed (atomic64_t *v,s64 *old,s64 new) { -kasan_check_write (v,sizeof (*v)); -kasan_check_write (old,sizeof (*old)); +__atomic_check_write (v,sizeof (*v)); +__atomic_check_write (old,sizeof (*old));return arch_atomic64_try_cmpxchg_relaxed (v, old, new); }#define atomic64_try_cmpxchg_relaxed atomic64_try_cmpxchg_relaxed
@@ -1544,7 +1554,7 @@ atomic64_try_cmpxchg_relaxed(atomic64_tstatic inline bool atomic64_sub_and_test (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_sub_and_test (i, v); }#define atomic64_sub_and_test atomic64_sub_and_test
@@ -1554,7 +1564,7 @@ atomic64_sub_and_test(s64 i, atomic64_tstatic inline bool atomic64_dec_and_test (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_dec_and_test (v); }#define atomic64_dec_and_test atomic64_dec_and_test
@@ -1564,7 +1574,7 @@ atomic64_dec_and_test(atomic64_t *v)static inline bool atomic64_inc_and_test (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_inc_and_test (v); }#define atomic64_inc_and_test atomic64_inc_and_test
@@ -1574,7 +1584,7 @@ atomic64_inc_and_test(atomic64_t *v)static inline bool atomic64_add_negative (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_add_negative (i, v); }#define atomic64_add_negative atomic64_add_negative
@@ -1584,7 +1594,7 @@ atomic64_add_negative(s64 i, atomic64_tstatic inline s64 atomic64_fetch_add_unless (atomic64_t *v,s64 a,s64 u) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_add_unless (v, a, u); }#define atomic64_fetch_add_unless atomic64_fetch_add_unless
@@ -1594,7 +1604,7 @@ atomic64_fetch_add_unless(atomic64_t *v,static inline bool atomic64_add_unless (atomic64_t *v,s64 a,s64 u) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_add_unless (v, a, u); }#define atomic64_add_unless atomic64_add_unless
@@ -1604,7 +1614,7 @@ atomic64_add_unless(atomic64_t *v, s64 astatic inline bool atomic64_inc_not_zero (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_inc_not_zero (v); }#define atomic64_inc_not_zero atomic64_inc_not_zero
@@ -1614,7 +1624,7 @@ atomic64_inc_not_zero(atomic64_t *v)static inline bool atomic64_inc_unless_negative (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_inc_unless_negative (v); }#define atomic64_inc_unless_negative atomic64_inc_unless_negative
@@ -1624,7 +1634,7 @@ atomic64_inc_unless_negative(atomic64_tstatic inline bool atomic64_dec_unless_positive (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_dec_unless_positive (v); }#define atomic64_dec_unless_positive atomic64_dec_unless_positive
@@ -1634,7 +1644,7 @@ atomic64_dec_unless_positive(atomic64_tstatic inline s64 atomic64_dec_if_positive (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_dec_if_positive (v); }#define atomic64_dec_if_positive atomic64_dec_if_positive
@@ -1644,7 +1654,7 @@ atomic64_dec_if_positive(atomic64_t *v)#define xchg (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ arch_xchg(__ai_ptr, __VA_ARGS__); \ })#endif
@@ -1653,7 +1663,7 @@ atomic64_dec_if_positive(atomic64_t *v)#define xchg_acquire (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ arch_xchg_acquire(__ai_ptr, __VA_ARGS__); \ })#endif
@@ -1662,7 +1672,7 @@ atomic64_dec_if_positive(atomic64_t *v)#define xchg_release (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ arch_xchg_release(__ai_ptr, __VA_ARGS__); \ })#endif
@@ -1671,7 +1681,7 @@ atomic64_dec_if_positive(atomic64_t *v)#define xchg_relaxed (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ arch_xchg_relaxed(__ai_ptr, __VA_ARGS__); \ })#endif
@@ -1680,7 +1690,7 @@ atomic64_dec_if_positive(atomic64_t *v)#define cmpxchg (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ arch_cmpxchg(__ai_ptr, __VA_ARGS__); \ })#endif
@@ -1689,7 +1699,7 @@ atomic64_dec_if_positive(atomic64_t *v)#define cmpxchg_acquire (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ arch_cmpxchg_acquire(__ai_ptr, __VA_ARGS__); \ })#endif
@@ -1698,7 +1708,7 @@ atomic64_dec_if_positive(atomic64_t *v)#define cmpxchg_release (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ arch_cmpxchg_release(__ai_ptr, __VA_ARGS__); \ })#endif
@@ -1707,7 +1717,7 @@ atomic64_dec_if_positive(atomic64_t *v)#define cmpxchg_relaxed (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ arch_cmpxchg_relaxed(__ai_ptr, __VA_ARGS__); \ })#endif
@@ -1716,7 +1726,7 @@ atomic64_dec_if_positive(atomic64_t *v)#define cmpxchg64 (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ arch_cmpxchg64(__ai_ptr, __VA_ARGS__); \ })#endif
@@ -1725,7 +1735,7 @@ atomic64_dec_if_positive(atomic64_t *v)#define cmpxchg64_acquire (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ arch_cmpxchg64_acquire(__ai_ptr, __VA_ARGS__); \ })#endif
@@ -1734,7 +1744,7 @@ atomic64_dec_if_positive(atomic64_t *v)#define cmpxchg64_release (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ arch_cmpxchg64_release(__ai_ptr, __VA_ARGS__); \ })#endif
@@ -1743,7 +1753,7 @@ atomic64_dec_if_positive(atomic64_t *v)#define cmpxchg64_relaxed (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ arch_cmpxchg64_relaxed(__ai_ptr, __VA_ARGS__); \ })#endif
@@ -1751,28 +1761,28 @@ atomic64_dec_if_positive(atomic64_t *v)#define cmpxchg_local (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ arch_cmpxchg_local(__ai_ptr, __VA_ARGS__); \ })#define cmpxchg64_local (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ arch_cmpxchg64_local(__ai_ptr, __VA_ARGS__); \ })#define sync_cmpxchg (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ arch_sync_cmpxchg(__ai_ptr, __VA_ARGS__); \ })#define cmpxchg_double (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, 2 * sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, 2 * sizeof(*__ai_ptr)); \ arch_cmpxchg_double(__ai_ptr, __VA_ARGS__); \ })
@@ -1780,9 +1790,9 @@ atomic64_dec_if_positive(atomic64_t *v)#define cmpxchg_double_local (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, 2 * sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, 2 * sizeof(*__ai_ptr)); \ arch_cmpxchg_double_local(__ai_ptr, __VA_ARGS__); \ })#endif /* _ASM_GENERIC_ATOMIC_INSTRUMENTED_H */ -// b29b625d5de9280f680e42c7be859b55b15e5f6a +// aa929c117bdd954a0957b91fe509f118ca8b9707
scripts/atomic/gen-atomic-instrumented.sh +12 -2
@@ -20,7 +20,7 @@ gen_param_check() # We don't write to constant parameters [ ${type#c} != ${type} ] && rw="read" - printf "\tkasan_check_${rw}(${name}, sizeof(*${name}));\n" + printf "\t__atomic_check_${rw}(${name}, sizeof(*${name}));\n" } #gen_param_check(arg...)
@@ -107,7 +107,7 @@ cat <<EOF #define ${xchg}(ptr, ...) \\ ({ \\ typeof(ptr) __ai_ptr = (ptr); \\ - kasan_check_write(__ai_ptr, ${mult}sizeof(*__ai_ptr)); \\ + __atomic_check_write(__ai_ptr, ${mult}sizeof(*__ai_ptr)); \\ arch_${xchg}(__ai_ptr, __VA_ARGS__); \\ }) EOF
@@ -149,6 +149,16 @@ cat << EOF #include <linux/build_bug.h> #include <linux/kasan-checks.h> +static inline void __atomic_check_read(const volatile void *v, size_t size) +{ + kasan_check_read(v, size); +} + +static inline void __atomic_check_write(const volatile void *v, size_t size) +{ + kasan_check_write(v, size); +} + EOF grep '^[a-z]' "$1" | while read name meta args; do
Peter Zijlstra
maintainerPATCH v4 20/27 asm-generic/atomic: Use __always_inline for pure wrappers
In reply to Peter ZijlstraFrom: Marco Elver <[email protected]>
Prefer __always_inline for atomic wrappers. When building for size (CC_OPTIMIZE_FOR_SIZE), some compilers appear to be less inclined to inline even relatively small static inline functions that are assumed to be inlinable such as atomic ops. This can cause problems, for example in UACCESS regions.
By using __always_inline, we let the real implementation and not the wrapper determine the final inlining preference.
For x86 tinyconfig we observe:
- vmlinux baseline: 1316204
- vmlinux with patch: 1315988 (-216 bytes)
This came up when addressing UACCESS warnings with CC_OPTIMIZE_FOR_SIZE in the KCSAN runtime:
http://lkml.kernel.org/r/[email protected]
---
--- include/asm-generic/atomic-instrumented.h | 335 +++++++++++++++--------------- include/asm-generic/atomic-long.h | 331 ++++++++++++++--------------- scripts/atomic/gen-atomic-instrumented.sh | 7 scripts/atomic/gen-atomic-long.sh | 3 4 files changed, 340 insertions(+), 336 deletions(-)
include/asm-generic/atomic-instrumented.h +168 -167
@@ -18,19 +18,20 @@#define _ASM_GENERIC_ATOMIC_INSTRUMENTED_H#include <linux/build_bug.h> +#include <linux/compiler.h> #include <linux/kasan-checks.h> -static inline void __atomic_check_read (const volatile void *v,size_t size) +static __always_inline void __atomic_check_read(const volatile void *v, size_t size) {kasan_check_read (v, size); } -static inline void __atomic_check_write (const volatile void *v,size_t size) +static __always_inline void __atomic_check_write(const volatile void *v, size_t size) {kasan_check_write (v, size); } -static inline int +static __always_inline intatomic_read (const atomic_t *v) {__atomic_check_read (v,sizeof (*v));
@@ -39,7 +40,7 @@ atomic_read(const atomic_t *v)#define atomic_read atomic_read#if defined(arch_atomic_read_acquire) -static inline int +static __always_inline intatomic_read_acquire (const atomic_t *v) {__atomic_check_read (v,sizeof (*v));
@@ -48,7 +49,7 @@ atomic_read_acquire(const atomic_t *v)#define atomic_read_acquire atomic_read_acquire#endif -static inline void +static __always_inline voidatomic_set (atomic_t *v,int i) {__atomic_check_write (v,sizeof (*v));
@@ -57,7 +58,7 @@ atomic_set(atomic_t *v, int i)#define atomic_set atomic_set#if defined(arch_atomic_set_release) -static inline void +static __always_inline voidatomic_set_release (atomic_t *v,int i) {__atomic_check_write (v,sizeof (*v));
@@ -66,7 +67,7 @@ atomic_set_release(atomic_t *v, int i)#define atomic_set_release atomic_set_release#endif -static inline void +static __always_inline voidatomic_add (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -75,7 +76,7 @@ atomic_add(int i, atomic_t *v)#define atomic_add atomic_add#if !defined(arch_atomic_add_return_relaxed) || defined(arch_atomic_add_return) -static inline int +static __always_inline intatomic_add_return (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -85,7 +86,7 @@ atomic_add_return(int i, atomic_t *v)#endif #if defined(arch_atomic_add_return_acquire) -static inline int +static __always_inline intatomic_add_return_acquire (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -95,7 +96,7 @@ atomic_add_return_acquire(int i, atomic_#endif #if defined(arch_atomic_add_return_release) -static inline int +static __always_inline intatomic_add_return_release (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -105,7 +106,7 @@ atomic_add_return_release(int i, atomic_#endif #if defined(arch_atomic_add_return_relaxed) -static inline int +static __always_inline intatomic_add_return_relaxed (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -115,7 +116,7 @@ atomic_add_return_relaxed(int i, atomic_#endif #if !defined(arch_atomic_fetch_add_relaxed) || defined(arch_atomic_fetch_add) -static inline int +static __always_inline intatomic_fetch_add (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -125,7 +126,7 @@ atomic_fetch_add(int i, atomic_t *v)#endif #if defined(arch_atomic_fetch_add_acquire) -static inline int +static __always_inline intatomic_fetch_add_acquire (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -135,7 +136,7 @@ atomic_fetch_add_acquire(int i, atomic_t#endif #if defined(arch_atomic_fetch_add_release) -static inline int +static __always_inline intatomic_fetch_add_release (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -145,7 +146,7 @@ atomic_fetch_add_release(int i, atomic_t#endif #if defined(arch_atomic_fetch_add_relaxed) -static inline int +static __always_inline intatomic_fetch_add_relaxed (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -154,7 +155,7 @@ atomic_fetch_add_relaxed(int i, atomic_t#define atomic_fetch_add_relaxed atomic_fetch_add_relaxed#endif -static inline void +static __always_inline voidatomic_sub (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -163,7 +164,7 @@ atomic_sub(int i, atomic_t *v)#define atomic_sub atomic_sub#if !defined(arch_atomic_sub_return_relaxed) || defined(arch_atomic_sub_return) -static inline int +static __always_inline intatomic_sub_return (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -173,7 +174,7 @@ atomic_sub_return(int i, atomic_t *v)#endif #if defined(arch_atomic_sub_return_acquire) -static inline int +static __always_inline intatomic_sub_return_acquire (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -183,7 +184,7 @@ atomic_sub_return_acquire(int i, atomic_#endif #if defined(arch_atomic_sub_return_release) -static inline int +static __always_inline intatomic_sub_return_release (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -193,7 +194,7 @@ atomic_sub_return_release(int i, atomic_#endif #if defined(arch_atomic_sub_return_relaxed) -static inline int +static __always_inline intatomic_sub_return_relaxed (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -203,7 +204,7 @@ atomic_sub_return_relaxed(int i, atomic_#endif #if !defined(arch_atomic_fetch_sub_relaxed) || defined(arch_atomic_fetch_sub) -static inline int +static __always_inline intatomic_fetch_sub (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -213,7 +214,7 @@ atomic_fetch_sub(int i, atomic_t *v)#endif #if defined(arch_atomic_fetch_sub_acquire) -static inline int +static __always_inline intatomic_fetch_sub_acquire (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -223,7 +224,7 @@ atomic_fetch_sub_acquire(int i, atomic_t#endif #if defined(arch_atomic_fetch_sub_release) -static inline int +static __always_inline intatomic_fetch_sub_release (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -233,7 +234,7 @@ atomic_fetch_sub_release(int i, atomic_t#endif #if defined(arch_atomic_fetch_sub_relaxed) -static inline int +static __always_inline intatomic_fetch_sub_relaxed (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -243,7 +244,7 @@ atomic_fetch_sub_relaxed(int i, atomic_t#endif #if defined(arch_atomic_inc) -static inline void +static __always_inline voidatomic_inc (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -253,7 +254,7 @@ atomic_inc(atomic_t *v)#endif #if defined(arch_atomic_inc_return) -static inline int +static __always_inline intatomic_inc_return (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -263,7 +264,7 @@ atomic_inc_return(atomic_t *v)#endif #if defined(arch_atomic_inc_return_acquire) -static inline int +static __always_inline intatomic_inc_return_acquire (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -273,7 +274,7 @@ atomic_inc_return_acquire(atomic_t *v)#endif #if defined(arch_atomic_inc_return_release) -static inline int +static __always_inline intatomic_inc_return_release (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -283,7 +284,7 @@ atomic_inc_return_release(atomic_t *v)#endif #if defined(arch_atomic_inc_return_relaxed) -static inline int +static __always_inline intatomic_inc_return_relaxed (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -293,7 +294,7 @@ atomic_inc_return_relaxed(atomic_t *v)#endif #if defined(arch_atomic_fetch_inc) -static inline int +static __always_inline intatomic_fetch_inc (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -303,7 +304,7 @@ atomic_fetch_inc(atomic_t *v)#endif #if defined(arch_atomic_fetch_inc_acquire) -static inline int +static __always_inline intatomic_fetch_inc_acquire (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -313,7 +314,7 @@ atomic_fetch_inc_acquire(atomic_t *v)#endif #if defined(arch_atomic_fetch_inc_release) -static inline int +static __always_inline intatomic_fetch_inc_release (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -323,7 +324,7 @@ atomic_fetch_inc_release(atomic_t *v)#endif #if defined(arch_atomic_fetch_inc_relaxed) -static inline int +static __always_inline intatomic_fetch_inc_relaxed (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -333,7 +334,7 @@ atomic_fetch_inc_relaxed(atomic_t *v)#endif #if defined(arch_atomic_dec) -static inline void +static __always_inline voidatomic_dec (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -343,7 +344,7 @@ atomic_dec(atomic_t *v)#endif #if defined(arch_atomic_dec_return) -static inline int +static __always_inline intatomic_dec_return (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -353,7 +354,7 @@ atomic_dec_return(atomic_t *v)#endif #if defined(arch_atomic_dec_return_acquire) -static inline int +static __always_inline intatomic_dec_return_acquire (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -363,7 +364,7 @@ atomic_dec_return_acquire(atomic_t *v)#endif #if defined(arch_atomic_dec_return_release) -static inline int +static __always_inline intatomic_dec_return_release (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -373,7 +374,7 @@ atomic_dec_return_release(atomic_t *v)#endif #if defined(arch_atomic_dec_return_relaxed) -static inline int +static __always_inline intatomic_dec_return_relaxed (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -383,7 +384,7 @@ atomic_dec_return_relaxed(atomic_t *v)#endif #if defined(arch_atomic_fetch_dec) -static inline int +static __always_inline intatomic_fetch_dec (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -393,7 +394,7 @@ atomic_fetch_dec(atomic_t *v)#endif #if defined(arch_atomic_fetch_dec_acquire) -static inline int +static __always_inline intatomic_fetch_dec_acquire (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -403,7 +404,7 @@ atomic_fetch_dec_acquire(atomic_t *v)#endif #if defined(arch_atomic_fetch_dec_release) -static inline int +static __always_inline intatomic_fetch_dec_release (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -413,7 +414,7 @@ atomic_fetch_dec_release(atomic_t *v)#endif #if defined(arch_atomic_fetch_dec_relaxed) -static inline int +static __always_inline intatomic_fetch_dec_relaxed (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -422,7 +423,7 @@ atomic_fetch_dec_relaxed(atomic_t *v)#define atomic_fetch_dec_relaxed atomic_fetch_dec_relaxed#endif -static inline void +static __always_inline voidatomic_and (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -431,7 +432,7 @@ atomic_and(int i, atomic_t *v)#define atomic_and atomic_and#if !defined(arch_atomic_fetch_and_relaxed) || defined(arch_atomic_fetch_and) -static inline int +static __always_inline intatomic_fetch_and (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -441,7 +442,7 @@ atomic_fetch_and(int i, atomic_t *v)#endif #if defined(arch_atomic_fetch_and_acquire) -static inline int +static __always_inline intatomic_fetch_and_acquire (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -451,7 +452,7 @@ atomic_fetch_and_acquire(int i, atomic_t#endif #if defined(arch_atomic_fetch_and_release) -static inline int +static __always_inline intatomic_fetch_and_release (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -461,7 +462,7 @@ atomic_fetch_and_release(int i, atomic_t#endif #if defined(arch_atomic_fetch_and_relaxed) -static inline int +static __always_inline intatomic_fetch_and_relaxed (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -471,7 +472,7 @@ atomic_fetch_and_relaxed(int i, atomic_t#endif #if defined(arch_atomic_andnot) -static inline void +static __always_inline voidatomic_andnot (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -481,7 +482,7 @@ atomic_andnot(int i, atomic_t *v)#endif #if defined(arch_atomic_fetch_andnot) -static inline int +static __always_inline intatomic_fetch_andnot (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -491,7 +492,7 @@ atomic_fetch_andnot(int i, atomic_t *v)#endif #if defined(arch_atomic_fetch_andnot_acquire) -static inline int +static __always_inline intatomic_fetch_andnot_acquire (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -501,7 +502,7 @@ atomic_fetch_andnot_acquire(int i, atomi#endif #if defined(arch_atomic_fetch_andnot_release) -static inline int +static __always_inline intatomic_fetch_andnot_release (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -511,7 +512,7 @@ atomic_fetch_andnot_release(int i, atomi#endif #if defined(arch_atomic_fetch_andnot_relaxed) -static inline int +static __always_inline intatomic_fetch_andnot_relaxed (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -520,7 +521,7 @@ atomic_fetch_andnot_relaxed(int i, atomi#define atomic_fetch_andnot_relaxed atomic_fetch_andnot_relaxed#endif -static inline void +static __always_inline voidatomic_or (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -529,7 +530,7 @@ atomic_or(int i, atomic_t *v)#define atomic_or atomic_or#if !defined(arch_atomic_fetch_or_relaxed) || defined(arch_atomic_fetch_or) -static inline int +static __always_inline intatomic_fetch_or (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -539,7 +540,7 @@ atomic_fetch_or(int i, atomic_t *v)#endif #if defined(arch_atomic_fetch_or_acquire) -static inline int +static __always_inline intatomic_fetch_or_acquire (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -549,7 +550,7 @@ atomic_fetch_or_acquire(int i, atomic_t#endif #if defined(arch_atomic_fetch_or_release) -static inline int +static __always_inline intatomic_fetch_or_release (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -559,7 +560,7 @@ atomic_fetch_or_release(int i, atomic_t#endif #if defined(arch_atomic_fetch_or_relaxed) -static inline int +static __always_inline intatomic_fetch_or_relaxed (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -568,7 +569,7 @@ atomic_fetch_or_relaxed(int i, atomic_t#define atomic_fetch_or_relaxed atomic_fetch_or_relaxed#endif -static inline void +static __always_inline voidatomic_xor (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -577,7 +578,7 @@ atomic_xor(int i, atomic_t *v)#define atomic_xor atomic_xor#if !defined(arch_atomic_fetch_xor_relaxed) || defined(arch_atomic_fetch_xor) -static inline int +static __always_inline intatomic_fetch_xor (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -587,7 +588,7 @@ atomic_fetch_xor(int i, atomic_t *v)#endif #if defined(arch_atomic_fetch_xor_acquire) -static inline int +static __always_inline intatomic_fetch_xor_acquire (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -597,7 +598,7 @@ atomic_fetch_xor_acquire(int i, atomic_t#endif #if defined(arch_atomic_fetch_xor_release) -static inline int +static __always_inline intatomic_fetch_xor_release (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -607,7 +608,7 @@ atomic_fetch_xor_release(int i, atomic_t#endif #if defined(arch_atomic_fetch_xor_relaxed) -static inline int +static __always_inline intatomic_fetch_xor_relaxed (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -617,7 +618,7 @@ atomic_fetch_xor_relaxed(int i, atomic_t#endif #if !defined(arch_atomic_xchg_relaxed) || defined(arch_atomic_xchg) -static inline int +static __always_inline intatomic_xchg (atomic_t *v,int i) {__atomic_check_write (v,sizeof (*v));
@@ -627,7 +628,7 @@ atomic_xchg(atomic_t *v, int i)#endif #if defined(arch_atomic_xchg_acquire) -static inline int +static __always_inline intatomic_xchg_acquire (atomic_t *v,int i) {__atomic_check_write (v,sizeof (*v));
@@ -637,7 +638,7 @@ atomic_xchg_acquire(atomic_t *v, int i)#endif #if defined(arch_atomic_xchg_release) -static inline int +static __always_inline intatomic_xchg_release (atomic_t *v,int i) {__atomic_check_write (v,sizeof (*v));
@@ -647,7 +648,7 @@ atomic_xchg_release(atomic_t *v, int i)#endif #if defined(arch_atomic_xchg_relaxed) -static inline int +static __always_inline intatomic_xchg_relaxed (atomic_t *v,int i) {__atomic_check_write (v,sizeof (*v));
@@ -657,7 +658,7 @@ atomic_xchg_relaxed(atomic_t *v, int i)#endif #if !defined(arch_atomic_cmpxchg_relaxed) || defined(arch_atomic_cmpxchg) -static inline int +static __always_inline intatomic_cmpxchg (atomic_t *v,int old,int new) {__atomic_check_write (v,sizeof (*v));
@@ -667,7 +668,7 @@ atomic_cmpxchg(atomic_t *v, int old, int#endif #if defined(arch_atomic_cmpxchg_acquire) -static inline int +static __always_inline intatomic_cmpxchg_acquire (atomic_t *v,int old,int new) {__atomic_check_write (v,sizeof (*v));
@@ -677,7 +678,7 @@ atomic_cmpxchg_acquire(atomic_t *v, int#endif #if defined(arch_atomic_cmpxchg_release) -static inline int +static __always_inline intatomic_cmpxchg_release (atomic_t *v,int old,int new) {__atomic_check_write (v,sizeof (*v));
@@ -687,7 +688,7 @@ atomic_cmpxchg_release(atomic_t *v, int#endif #if defined(arch_atomic_cmpxchg_relaxed) -static inline int +static __always_inline intatomic_cmpxchg_relaxed (atomic_t *v,int old,int new) {__atomic_check_write (v,sizeof (*v));
@@ -697,7 +698,7 @@ atomic_cmpxchg_relaxed(atomic_t *v, int#endif #if defined(arch_atomic_try_cmpxchg) -static inline bool +static __always_inline boolatomic_try_cmpxchg (atomic_t *v,int *old,int new) {__atomic_check_write (v,sizeof (*v));
@@ -708,7 +709,7 @@ atomic_try_cmpxchg(atomic_t *v, int *old#endif #if defined(arch_atomic_try_cmpxchg_acquire) -static inline bool +static __always_inline boolatomic_try_cmpxchg_acquire (atomic_t *v,int *old,int new) {__atomic_check_write (v,sizeof (*v));
@@ -719,7 +720,7 @@ atomic_try_cmpxchg_acquire(atomic_t *v,#endif #if defined(arch_atomic_try_cmpxchg_release) -static inline bool +static __always_inline boolatomic_try_cmpxchg_release (atomic_t *v,int *old,int new) {__atomic_check_write (v,sizeof (*v));
@@ -730,7 +731,7 @@ atomic_try_cmpxchg_release(atomic_t *v,#endif #if defined(arch_atomic_try_cmpxchg_relaxed) -static inline bool +static __always_inline boolatomic_try_cmpxchg_relaxed (atomic_t *v,int *old,int new) {__atomic_check_write (v,sizeof (*v));
@@ -741,7 +742,7 @@ atomic_try_cmpxchg_relaxed(atomic_t *v,#endif #if defined(arch_atomic_sub_and_test) -static inline bool +static __always_inline boolatomic_sub_and_test (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -751,7 +752,7 @@ atomic_sub_and_test(int i, atomic_t *v)#endif #if defined(arch_atomic_dec_and_test) -static inline bool +static __always_inline boolatomic_dec_and_test (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -761,7 +762,7 @@ atomic_dec_and_test(atomic_t *v)#endif #if defined(arch_atomic_inc_and_test) -static inline bool +static __always_inline boolatomic_inc_and_test (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -771,7 +772,7 @@ atomic_inc_and_test(atomic_t *v)#endif #if defined(arch_atomic_add_negative) -static inline bool +static __always_inline boolatomic_add_negative (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -781,7 +782,7 @@ atomic_add_negative(int i, atomic_t *v)#endif #if defined(arch_atomic_fetch_add_unless) -static inline int +static __always_inline intatomic_fetch_add_unless (atomic_t *v,int a,int u) {__atomic_check_write (v,sizeof (*v));
@@ -791,7 +792,7 @@ atomic_fetch_add_unless(atomic_t *v, int#endif #if defined(arch_atomic_add_unless) -static inline bool +static __always_inline boolatomic_add_unless (atomic_t *v,int a,int u) {__atomic_check_write (v,sizeof (*v));
@@ -801,7 +802,7 @@ atomic_add_unless(atomic_t *v, int a, in#endif #if defined(arch_atomic_inc_not_zero) -static inline bool +static __always_inline boolatomic_inc_not_zero (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -811,7 +812,7 @@ atomic_inc_not_zero(atomic_t *v)#endif #if defined(arch_atomic_inc_unless_negative) -static inline bool +static __always_inline boolatomic_inc_unless_negative (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -821,7 +822,7 @@ atomic_inc_unless_negative(atomic_t *v)#endif #if defined(arch_atomic_dec_unless_positive) -static inline bool +static __always_inline boolatomic_dec_unless_positive (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -831,7 +832,7 @@ atomic_dec_unless_positive(atomic_t *v)#endif #if defined(arch_atomic_dec_if_positive) -static inline int +static __always_inline intatomic_dec_if_positive (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -840,7 +841,7 @@ atomic_dec_if_positive(atomic_t *v)#define atomic_dec_if_positive atomic_dec_if_positive#endif -static inline s64 +static __always_inline s64atomic64_read (const atomic64_t *v) {__atomic_check_read (v,sizeof (*v));
@@ -849,7 +850,7 @@ atomic64_read(const atomic64_t *v)#define atomic64_read atomic64_read#if defined(arch_atomic64_read_acquire) -static inline s64 +static __always_inline s64atomic64_read_acquire (const atomic64_t *v) {__atomic_check_read (v,sizeof (*v));
@@ -858,7 +859,7 @@ atomic64_read_acquire(const atomic64_t *#define atomic64_read_acquire atomic64_read_acquire#endif -static inline void +static __always_inline voidatomic64_set (atomic64_t *v,s64 i) {__atomic_check_write (v,sizeof (*v));
@@ -867,7 +868,7 @@ atomic64_set(atomic64_t *v, s64 i)#define atomic64_set atomic64_set#if defined(arch_atomic64_set_release) -static inline void +static __always_inline voidatomic64_set_release (atomic64_t *v,s64 i) {__atomic_check_write (v,sizeof (*v));
@@ -876,7 +877,7 @@ atomic64_set_release(atomic64_t *v, s64#define atomic64_set_release atomic64_set_release#endif -static inline void +static __always_inline voidatomic64_add (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -885,7 +886,7 @@ atomic64_add(s64 i, atomic64_t *v)#define atomic64_add atomic64_add#if !defined(arch_atomic64_add_return_relaxed) || defined(arch_atomic64_add_return) -static inline s64 +static __always_inline s64atomic64_add_return (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -895,7 +896,7 @@ atomic64_add_return(s64 i, atomic64_t *v#endif #if defined(arch_atomic64_add_return_acquire) -static inline s64 +static __always_inline s64atomic64_add_return_acquire (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -905,7 +906,7 @@ atomic64_add_return_acquire(s64 i, atomi#endif #if defined(arch_atomic64_add_return_release) -static inline s64 +static __always_inline s64atomic64_add_return_release (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -915,7 +916,7 @@ atomic64_add_return_release(s64 i, atomi#endif #if defined(arch_atomic64_add_return_relaxed) -static inline s64 +static __always_inline s64atomic64_add_return_relaxed (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -925,7 +926,7 @@ atomic64_add_return_relaxed(s64 i, atomi#endif #if !defined(arch_atomic64_fetch_add_relaxed) || defined(arch_atomic64_fetch_add) -static inline s64 +static __always_inline s64atomic64_fetch_add (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -935,7 +936,7 @@ atomic64_fetch_add(s64 i, atomic64_t *v)#endif #if defined(arch_atomic64_fetch_add_acquire) -static inline s64 +static __always_inline s64atomic64_fetch_add_acquire (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -945,7 +946,7 @@ atomic64_fetch_add_acquire(s64 i, atomic#endif #if defined(arch_atomic64_fetch_add_release) -static inline s64 +static __always_inline s64atomic64_fetch_add_release (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -955,7 +956,7 @@ atomic64_fetch_add_release(s64 i, atomic#endif #if defined(arch_atomic64_fetch_add_relaxed) -static inline s64 +static __always_inline s64atomic64_fetch_add_relaxed (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -964,7 +965,7 @@ atomic64_fetch_add_relaxed(s64 i, atomic#define atomic64_fetch_add_relaxed atomic64_fetch_add_relaxed#endif -static inline void +static __always_inline voidatomic64_sub (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -973,7 +974,7 @@ atomic64_sub(s64 i, atomic64_t *v)#define atomic64_sub atomic64_sub#if !defined(arch_atomic64_sub_return_relaxed) || defined(arch_atomic64_sub_return) -static inline s64 +static __always_inline s64atomic64_sub_return (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -983,7 +984,7 @@ atomic64_sub_return(s64 i, atomic64_t *v#endif #if defined(arch_atomic64_sub_return_acquire) -static inline s64 +static __always_inline s64atomic64_sub_return_acquire (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -993,7 +994,7 @@ atomic64_sub_return_acquire(s64 i, atomi#endif #if defined(arch_atomic64_sub_return_release) -static inline s64 +static __always_inline s64atomic64_sub_return_release (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1003,7 +1004,7 @@ atomic64_sub_return_release(s64 i, atomi#endif #if defined(arch_atomic64_sub_return_relaxed) -static inline s64 +static __always_inline s64atomic64_sub_return_relaxed (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1013,7 +1014,7 @@ atomic64_sub_return_relaxed(s64 i, atomi#endif #if !defined(arch_atomic64_fetch_sub_relaxed) || defined(arch_atomic64_fetch_sub) -static inline s64 +static __always_inline s64atomic64_fetch_sub (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1023,7 +1024,7 @@ atomic64_fetch_sub(s64 i, atomic64_t *v)#endif #if defined(arch_atomic64_fetch_sub_acquire) -static inline s64 +static __always_inline s64atomic64_fetch_sub_acquire (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1033,7 +1034,7 @@ atomic64_fetch_sub_acquire(s64 i, atomic#endif #if defined(arch_atomic64_fetch_sub_release) -static inline s64 +static __always_inline s64atomic64_fetch_sub_release (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1043,7 +1044,7 @@ atomic64_fetch_sub_release(s64 i, atomic#endif #if defined(arch_atomic64_fetch_sub_relaxed) -static inline s64 +static __always_inline s64atomic64_fetch_sub_relaxed (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1053,7 +1054,7 @@ atomic64_fetch_sub_relaxed(s64 i, atomic#endif #if defined(arch_atomic64_inc) -static inline void +static __always_inline voidatomic64_inc (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1063,7 +1064,7 @@ atomic64_inc(atomic64_t *v)#endif #if defined(arch_atomic64_inc_return) -static inline s64 +static __always_inline s64atomic64_inc_return (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1073,7 +1074,7 @@ atomic64_inc_return(atomic64_t *v)#endif #if defined(arch_atomic64_inc_return_acquire) -static inline s64 +static __always_inline s64atomic64_inc_return_acquire (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1083,7 +1084,7 @@ atomic64_inc_return_acquire(atomic64_t *#endif #if defined(arch_atomic64_inc_return_release) -static inline s64 +static __always_inline s64atomic64_inc_return_release (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1093,7 +1094,7 @@ atomic64_inc_return_release(atomic64_t *#endif #if defined(arch_atomic64_inc_return_relaxed) -static inline s64 +static __always_inline s64atomic64_inc_return_relaxed (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1103,7 +1104,7 @@ atomic64_inc_return_relaxed(atomic64_t *#endif #if defined(arch_atomic64_fetch_inc) -static inline s64 +static __always_inline s64atomic64_fetch_inc (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1113,7 +1114,7 @@ atomic64_fetch_inc(atomic64_t *v)#endif #if defined(arch_atomic64_fetch_inc_acquire) -static inline s64 +static __always_inline s64atomic64_fetch_inc_acquire (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1123,7 +1124,7 @@ atomic64_fetch_inc_acquire(atomic64_t *v#endif #if defined(arch_atomic64_fetch_inc_release) -static inline s64 +static __always_inline s64atomic64_fetch_inc_release (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1133,7 +1134,7 @@ atomic64_fetch_inc_release(atomic64_t *v#endif #if defined(arch_atomic64_fetch_inc_relaxed) -static inline s64 +static __always_inline s64atomic64_fetch_inc_relaxed (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1143,7 +1144,7 @@ atomic64_fetch_inc_relaxed(atomic64_t *v#endif #if defined(arch_atomic64_dec) -static inline void +static __always_inline voidatomic64_dec (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1153,7 +1154,7 @@ atomic64_dec(atomic64_t *v)#endif #if defined(arch_atomic64_dec_return) -static inline s64 +static __always_inline s64atomic64_dec_return (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1163,7 +1164,7 @@ atomic64_dec_return(atomic64_t *v)#endif #if defined(arch_atomic64_dec_return_acquire) -static inline s64 +static __always_inline s64atomic64_dec_return_acquire (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1173,7 +1174,7 @@ atomic64_dec_return_acquire(atomic64_t *#endif #if defined(arch_atomic64_dec_return_release) -static inline s64 +static __always_inline s64atomic64_dec_return_release (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1183,7 +1184,7 @@ atomic64_dec_return_release(atomic64_t *#endif #if defined(arch_atomic64_dec_return_relaxed) -static inline s64 +static __always_inline s64atomic64_dec_return_relaxed (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1193,7 +1194,7 @@ atomic64_dec_return_relaxed(atomic64_t *#endif #if defined(arch_atomic64_fetch_dec) -static inline s64 +static __always_inline s64atomic64_fetch_dec (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1203,7 +1204,7 @@ atomic64_fetch_dec(atomic64_t *v)#endif #if defined(arch_atomic64_fetch_dec_acquire) -static inline s64 +static __always_inline s64atomic64_fetch_dec_acquire (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1213,7 +1214,7 @@ atomic64_fetch_dec_acquire(atomic64_t *v#endif #if defined(arch_atomic64_fetch_dec_release) -static inline s64 +static __always_inline s64atomic64_fetch_dec_release (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1223,7 +1224,7 @@ atomic64_fetch_dec_release(atomic64_t *v#endif #if defined(arch_atomic64_fetch_dec_relaxed) -static inline s64 +static __always_inline s64atomic64_fetch_dec_relaxed (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1232,7 +1233,7 @@ atomic64_fetch_dec_relaxed(atomic64_t *v#define atomic64_fetch_dec_relaxed atomic64_fetch_dec_relaxed#endif -static inline void +static __always_inline voidatomic64_and (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1241,7 +1242,7 @@ atomic64_and(s64 i, atomic64_t *v)#define atomic64_and atomic64_and#if !defined(arch_atomic64_fetch_and_relaxed) || defined(arch_atomic64_fetch_and) -static inline s64 +static __always_inline s64atomic64_fetch_and (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1251,7 +1252,7 @@ atomic64_fetch_and(s64 i, atomic64_t *v)#endif #if defined(arch_atomic64_fetch_and_acquire) -static inline s64 +static __always_inline s64atomic64_fetch_and_acquire (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1261,7 +1262,7 @@ atomic64_fetch_and_acquire(s64 i, atomic#endif #if defined(arch_atomic64_fetch_and_release) -static inline s64 +static __always_inline s64atomic64_fetch_and_release (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1271,7 +1272,7 @@ atomic64_fetch_and_release(s64 i, atomic#endif #if defined(arch_atomic64_fetch_and_relaxed) -static inline s64 +static __always_inline s64atomic64_fetch_and_relaxed (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1281,7 +1282,7 @@ atomic64_fetch_and_relaxed(s64 i, atomic#endif #if defined(arch_atomic64_andnot) -static inline void +static __always_inline voidatomic64_andnot (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1291,7 +1292,7 @@ atomic64_andnot(s64 i, atomic64_t *v)#endif #if defined(arch_atomic64_fetch_andnot) -static inline s64 +static __always_inline s64atomic64_fetch_andnot (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1301,7 +1302,7 @@ atomic64_fetch_andnot(s64 i, atomic64_t#endif #if defined(arch_atomic64_fetch_andnot_acquire) -static inline s64 +static __always_inline s64atomic64_fetch_andnot_acquire (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1311,7 +1312,7 @@ atomic64_fetch_andnot_acquire(s64 i, ato#endif #if defined(arch_atomic64_fetch_andnot_release) -static inline s64 +static __always_inline s64atomic64_fetch_andnot_release (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1321,7 +1322,7 @@ atomic64_fetch_andnot_release(s64 i, ato#endif #if defined(arch_atomic64_fetch_andnot_relaxed) -static inline s64 +static __always_inline s64atomic64_fetch_andnot_relaxed (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1330,7 +1331,7 @@ atomic64_fetch_andnot_relaxed(s64 i, ato#define atomic64_fetch_andnot_relaxed atomic64_fetch_andnot_relaxed#endif -static inline void +static __always_inline voidatomic64_or (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1339,7 +1340,7 @@ atomic64_or(s64 i, atomic64_t *v)#define atomic64_or atomic64_or#if !defined(arch_atomic64_fetch_or_relaxed) || defined(arch_atomic64_fetch_or) -static inline s64 +static __always_inline s64atomic64_fetch_or (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1349,7 +1350,7 @@ atomic64_fetch_or(s64 i, atomic64_t *v)#endif #if defined(arch_atomic64_fetch_or_acquire) -static inline s64 +static __always_inline s64atomic64_fetch_or_acquire (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1359,7 +1360,7 @@ atomic64_fetch_or_acquire(s64 i, atomic6#endif #if defined(arch_atomic64_fetch_or_release) -static inline s64 +static __always_inline s64atomic64_fetch_or_release (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1369,7 +1370,7 @@ atomic64_fetch_or_release(s64 i, atomic6#endif #if defined(arch_atomic64_fetch_or_relaxed) -static inline s64 +static __always_inline s64atomic64_fetch_or_relaxed (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1378,7 +1379,7 @@ atomic64_fetch_or_relaxed(s64 i, atomic6#define atomic64_fetch_or_relaxed atomic64_fetch_or_relaxed#endif -static inline void +static __always_inline voidatomic64_xor (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1387,7 +1388,7 @@ atomic64_xor(s64 i, atomic64_t *v)#define atomic64_xor atomic64_xor#if !defined(arch_atomic64_fetch_xor_relaxed) || defined(arch_atomic64_fetch_xor) -static inline s64 +static __always_inline s64atomic64_fetch_xor (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1397,7 +1398,7 @@ atomic64_fetch_xor(s64 i, atomic64_t *v)#endif #if defined(arch_atomic64_fetch_xor_acquire) -static inline s64 +static __always_inline s64atomic64_fetch_xor_acquire (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1407,7 +1408,7 @@ atomic64_fetch_xor_acquire(s64 i, atomic#endif #if defined(arch_atomic64_fetch_xor_release) -static inline s64 +static __always_inline s64atomic64_fetch_xor_release (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1417,7 +1418,7 @@ atomic64_fetch_xor_release(s64 i, atomic#endif #if defined(arch_atomic64_fetch_xor_relaxed) -static inline s64 +static __always_inline s64atomic64_fetch_xor_relaxed (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1427,7 +1428,7 @@ atomic64_fetch_xor_relaxed(s64 i, atomic#endif #if !defined(arch_atomic64_xchg_relaxed) || defined(arch_atomic64_xchg) -static inline s64 +static __always_inline s64atomic64_xchg (atomic64_t *v,s64 i) {__atomic_check_write (v,sizeof (*v));
@@ -1437,7 +1438,7 @@ atomic64_xchg(atomic64_t *v, s64 i)#endif #if defined(arch_atomic64_xchg_acquire) -static inline s64 +static __always_inline s64atomic64_xchg_acquire (atomic64_t *v,s64 i) {__atomic_check_write (v,sizeof (*v));
@@ -1447,7 +1448,7 @@ atomic64_xchg_acquire(atomic64_t *v, s64#endif #if defined(arch_atomic64_xchg_release) -static inline s64 +static __always_inline s64atomic64_xchg_release (atomic64_t *v,s64 i) {__atomic_check_write (v,sizeof (*v));
@@ -1457,7 +1458,7 @@ atomic64_xchg_release(atomic64_t *v, s64#endif #if defined(arch_atomic64_xchg_relaxed) -static inline s64 +static __always_inline s64atomic64_xchg_relaxed (atomic64_t *v,s64 i) {__atomic_check_write (v,sizeof (*v));
@@ -1467,7 +1468,7 @@ atomic64_xchg_relaxed(atomic64_t *v, s64#endif #if !defined(arch_atomic64_cmpxchg_relaxed) || defined(arch_atomic64_cmpxchg) -static inline s64 +static __always_inline s64atomic64_cmpxchg (atomic64_t *v,s64 old,s64 new) {__atomic_check_write (v,sizeof (*v));
@@ -1477,7 +1478,7 @@ atomic64_cmpxchg(atomic64_t *v, s64 old,#endif #if defined(arch_atomic64_cmpxchg_acquire) -static inline s64 +static __always_inline s64atomic64_cmpxchg_acquire (atomic64_t *v,s64 old,s64 new) {__atomic_check_write (v,sizeof (*v));
@@ -1487,7 +1488,7 @@ atomic64_cmpxchg_acquire(atomic64_t *v,#endif #if defined(arch_atomic64_cmpxchg_release) -static inline s64 +static __always_inline s64atomic64_cmpxchg_release (atomic64_t *v,s64 old,s64 new) {__atomic_check_write (v,sizeof (*v));
@@ -1497,7 +1498,7 @@ atomic64_cmpxchg_release(atomic64_t *v,#endif #if defined(arch_atomic64_cmpxchg_relaxed) -static inline s64 +static __always_inline s64atomic64_cmpxchg_relaxed (atomic64_t *v,s64 old,s64 new) {__atomic_check_write (v,sizeof (*v));
@@ -1507,7 +1508,7 @@ atomic64_cmpxchg_relaxed(atomic64_t *v,#endif #if defined(arch_atomic64_try_cmpxchg) -static inline bool +static __always_inline boolatomic64_try_cmpxchg (atomic64_t *v,s64 *old,s64 new) {__atomic_check_write (v,sizeof (*v));
@@ -1518,7 +1519,7 @@ atomic64_try_cmpxchg(atomic64_t *v, s64#endif #if defined(arch_atomic64_try_cmpxchg_acquire) -static inline bool +static __always_inline boolatomic64_try_cmpxchg_acquire (atomic64_t *v,s64 *old,s64 new) {__atomic_check_write (v,sizeof (*v));
@@ -1529,7 +1530,7 @@ atomic64_try_cmpxchg_acquire(atomic64_t#endif #if defined(arch_atomic64_try_cmpxchg_release) -static inline bool +static __always_inline boolatomic64_try_cmpxchg_release (atomic64_t *v,s64 *old,s64 new) {__atomic_check_write (v,sizeof (*v));
@@ -1540,7 +1541,7 @@ atomic64_try_cmpxchg_release(atomic64_t#endif #if defined(arch_atomic64_try_cmpxchg_relaxed) -static inline bool +static __always_inline boolatomic64_try_cmpxchg_relaxed (atomic64_t *v,s64 *old,s64 new) {__atomic_check_write (v,sizeof (*v));
@@ -1551,7 +1552,7 @@ atomic64_try_cmpxchg_relaxed(atomic64_t#endif #if defined(arch_atomic64_sub_and_test) -static inline bool +static __always_inline boolatomic64_sub_and_test (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1561,7 +1562,7 @@ atomic64_sub_and_test(s64 i, atomic64_t#endif #if defined(arch_atomic64_dec_and_test) -static inline bool +static __always_inline boolatomic64_dec_and_test (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1571,7 +1572,7 @@ atomic64_dec_and_test(atomic64_t *v)#endif #if defined(arch_atomic64_inc_and_test) -static inline bool +static __always_inline boolatomic64_inc_and_test (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1581,7 +1582,7 @@ atomic64_inc_and_test(atomic64_t *v)#endif #if defined(arch_atomic64_add_negative) -static inline bool +static __always_inline boolatomic64_add_negative (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1591,7 +1592,7 @@ atomic64_add_negative(s64 i, atomic64_t#endif #if defined(arch_atomic64_fetch_add_unless) -static inline s64 +static __always_inline s64atomic64_fetch_add_unless (atomic64_t *v,s64 a,s64 u) {__atomic_check_write (v,sizeof (*v));
@@ -1601,7 +1602,7 @@ atomic64_fetch_add_unless(atomic64_t *v,#endif #if defined(arch_atomic64_add_unless) -static inline bool +static __always_inline boolatomic64_add_unless (atomic64_t *v,s64 a,s64 u) {__atomic_check_write (v,sizeof (*v));
@@ -1611,7 +1612,7 @@ atomic64_add_unless(atomic64_t *v, s64 a#endif #if defined(arch_atomic64_inc_not_zero) -static inline bool +static __always_inline boolatomic64_inc_not_zero (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1621,7 +1622,7 @@ atomic64_inc_not_zero(atomic64_t *v)#endif #if defined(arch_atomic64_inc_unless_negative) -static inline bool +static __always_inline boolatomic64_inc_unless_negative (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1631,7 +1632,7 @@ atomic64_inc_unless_negative(atomic64_t#endif #if defined(arch_atomic64_dec_unless_positive) -static inline bool +static __always_inline boolatomic64_dec_unless_positive (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1641,7 +1642,7 @@ atomic64_dec_unless_positive(atomic64_t#endif #if defined(arch_atomic64_dec_if_positive) -static inline s64 +static __always_inline s64atomic64_dec_if_positive (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1795,4 +1796,4 @@ atomic64_dec_if_positive(atomic64_t *v) })#endif /* _ASM_GENERIC_ATOMIC_INSTRUMENTED_H */ -// aa929c117bdd954a0957b91fe509f118ca8b9707 +// 6c1b0b614b55b76c258f89e205622e8f004871af
include/asm-generic/atomic-long.h +166 -165
1,162 lines not on this page · raw message
scripts/atomic/gen-atomic-instrumented.sh +4 -3
@@ -84,7 +84,7 @@ gen_proto_order_variant() [ ! -z "${guard}" ] && printf "#if ${guard}\n" cat <<EOF -static inline ${ret} +static __always_inline ${ret} ${atomicname}(${params}) { ${checks}
@@ -147,14 +147,15 @@ cat << EOF #define _ASM_GENERIC_ATOMIC_INSTRUMENTED_H #include <linux/build_bug.h> +#include <linux/compiler.h> #include <linux/kasan-checks.h> -static inline void __atomic_check_read(const volatile void *v, size_t size) +static __always_inline void __atomic_check_read(const volatile void *v, size_t size) { kasan_check_read(v, size); } -static inline void __atomic_check_write(const volatile void *v, size_t size) +static __always_inline void __atomic_check_write(const volatile void *v, size_t size) { kasan_check_write(v, size); }
scripts/atomic/gen-atomic-long.sh +2 -1
@@ -46,7 +46,7 @@ gen_proto_order_variant() local retstmt="$(gen_ret_stmt "${meta}")" cat <<EOF -static inline ${ret} +static __always_inline ${ret} atomic_long_${name}(${params}) { ${retstmt}${atomic}_${name}(${argscast});
@@ -64,6 +64,7 @@ cat << EOF #ifndef _ASM_GENERIC_ATOMIC_LONG_H #define _ASM_GENERIC_ATOMIC_LONG_H +#include <linux/compiler.h> #include <asm/types.h> #ifdef CONFIG_64BIT
Peter Zijlstra
maintainerPATCH v4 21/27 asm-generic/atomic: Use __always_inline for fallback wrappers
In reply to Peter ZijlstraFrom: Marco Elver <[email protected]>
Use __always_inline for atomic fallback wrappers. When building for size (CC_OPTIMIZE_FOR_SIZE), some compilers appear to be less inclined to inline even relatively small static inline functions that are assumed to be inlinable such as atomic ops. This can cause problems, for example in UACCESS regions.
While the fallback wrappers aren't pure wrappers, they are trivial nonetheless, and the function they wrap should determine the final inlining policy.
For x86 tinyconfig we observe:
- vmlinux baseline: 1315988
- vmlinux with patch: 1315928 (-60 bytes)
---
include/linux/atomic-fallback.h +171 -169
@@ -6,6 +6,8 @@#ifndef _LINUX_ATOMIC_FALLBACK_H#define _LINUX_ATOMIC_FALLBACK_H +#include <linux/compiler.h> +#ifndef xchg_relaxed#define xchg_relaxed xchg#define xchg_acquire xchg
@@ -76,7 +78,7 @@#endif /* cmpxchg64_relaxed */ #ifndef atomic_read_acquire -static inline int +static __always_inline intatomic_read_acquire (const atomic_t *v) {return smp_load_acquire (&(v)->counter);
@@ -85,7 +87,7 @@ atomic_read_acquire(const atomic_t *v)#endif #ifndef atomic_set_release -static inline void +static __always_inline voidatomic_set_release (atomic_t *v,int i) {smp_store_release (&(v)->counter, i);
@@ -100,7 +102,7 @@ atomic_set_release(atomic_t *v, int i) #else /* atomic_add_return_relaxed */ #ifndef atomic_add_return_acquire -static inline int +static __always_inline int atomic_add_return_acquire(int i, atomic_t *v) { int ret = atomic_add_return_relaxed(i, v);
@@ -111,7 +113,7 @@ atomic_add_return_acquire(int i, atomic_t *v)#endif #ifndef atomic_add_return_release -static inline int +static __always_inline intatomic_add_return_release (int i,atomic_t *v) {__atomic_release_fence ();
@@ -121,7 +123,7 @@ atomic_add_return_release(int i, atomic_t *v)#endif #ifndef atomic_add_return -static inline int +static __always_inline intatomic_add_return (int i,atomic_t *v) {int ret;
@@ -142,7 +144,7 @@ atomic_add_return(int i, atomic_t *v) #else /* atomic_fetch_add_relaxed */ #ifndef atomic_fetch_add_acquire -static inline int +static __always_inline int atomic_fetch_add_acquire(int i, atomic_t *v) { int ret = atomic_fetch_add_relaxed(i, v);
@@ -153,7 +155,7 @@ atomic_fetch_add_acquire(int i, atomic_t *v)#endif #ifndef atomic_fetch_add_release -static inline int +static __always_inline intatomic_fetch_add_release (int i,atomic_t *v) {__atomic_release_fence ();
@@ -163,7 +165,7 @@ atomic_fetch_add_release(int i, atomic_t *v)#endif #ifndef atomic_fetch_add -static inline int +static __always_inline intatomic_fetch_add (int i,atomic_t *v) {int ret;
@@ -184,7 +186,7 @@ atomic_fetch_add(int i, atomic_t *v) #else /* atomic_sub_return_relaxed */ #ifndef atomic_sub_return_acquire -static inline int +static __always_inline int atomic_sub_return_acquire(int i, atomic_t *v) { int ret = atomic_sub_return_relaxed(i, v);
@@ -195,7 +197,7 @@ atomic_sub_return_acquire(int i, atomic_t *v)#endif #ifndef atomic_sub_return_release -static inline int +static __always_inline intatomic_sub_return_release (int i,atomic_t *v) {__atomic_release_fence ();
@@ -205,7 +207,7 @@ atomic_sub_return_release(int i, atomic_t *v)#endif #ifndef atomic_sub_return -static inline int +static __always_inline intatomic_sub_return (int i,atomic_t *v) {int ret;
@@ -226,7 +228,7 @@ atomic_sub_return(int i, atomic_t *v) #else /* atomic_fetch_sub_relaxed */ #ifndef atomic_fetch_sub_acquire -static inline int +static __always_inline int atomic_fetch_sub_acquire(int i, atomic_t *v) { int ret = atomic_fetch_sub_relaxed(i, v);
@@ -237,7 +239,7 @@ atomic_fetch_sub_acquire(int i, atomic_t *v)#endif #ifndef atomic_fetch_sub_release -static inline int +static __always_inline intatomic_fetch_sub_release (int i,atomic_t *v) {__atomic_release_fence ();
@@ -247,7 +249,7 @@ atomic_fetch_sub_release(int i, atomic_t *v)#endif #ifndef atomic_fetch_sub -static inline int +static __always_inline intatomic_fetch_sub (int i,atomic_t *v) {int ret;
@@ -262,7 +264,7 @@ atomic_fetch_sub(int i, atomic_t *v)#endif /* atomic_fetch_sub_relaxed */ #ifndef atomic_inc -static inline void +static __always_inline voidatomic_inc (atomic_t *v) {atomic_add (1 , v);
@@ -278,7 +280,7 @@ atomic_inc(atomic_t *v)#endif /* atomic_inc_return */ #ifndef atomic_inc_return -static inline int +static __always_inline intatomic_inc_return (atomic_t *v) {return atomic_add_return (1 , v);
@@ -287,7 +289,7 @@ atomic_inc_return(atomic_t *v)#endif #ifndef atomic_inc_return_acquire -static inline int +static __always_inline intatomic_inc_return_acquire (atomic_t *v) {return atomic_add_return_acquire (1 , v);
@@ -296,7 +298,7 @@ atomic_inc_return_acquire(atomic_t *v)#endif #ifndef atomic_inc_return_release -static inline int +static __always_inline intatomic_inc_return_release (atomic_t *v) {return atomic_add_return_release (1 , v);
@@ -305,7 +307,7 @@ atomic_inc_return_release(atomic_t *v)#endif #ifndef atomic_inc_return_relaxed -static inline int +static __always_inline intatomic_inc_return_relaxed (atomic_t *v) {return atomic_add_return_relaxed (1 , v);
@@ -316,7 +318,7 @@ atomic_inc_return_relaxed(atomic_t *v) #else /* atomic_inc_return_relaxed */ #ifndef atomic_inc_return_acquire -static inline int +static __always_inline int atomic_inc_return_acquire(atomic_t *v) { int ret = atomic_inc_return_relaxed(v);
@@ -327,7 +329,7 @@ atomic_inc_return_acquire(atomic_t *v)#endif #ifndef atomic_inc_return_release -static inline int +static __always_inline intatomic_inc_return_release (atomic_t *v) {__atomic_release_fence ();
@@ -337,7 +339,7 @@ atomic_inc_return_release(atomic_t *v)#endif #ifndef atomic_inc_return -static inline int +static __always_inline intatomic_inc_return (atomic_t *v) {int ret;
@@ -359,7 +361,7 @@ atomic_inc_return(atomic_t *v)#endif /* atomic_fetch_inc */ #ifndef atomic_fetch_inc -static inline int +static __always_inline intatomic_fetch_inc (atomic_t *v) {return atomic_fetch_add (1 , v);
@@ -368,7 +370,7 @@ atomic_fetch_inc(atomic_t *v)#endif #ifndef atomic_fetch_inc_acquire -static inline int +static __always_inline intatomic_fetch_inc_acquire (atomic_t *v) {return atomic_fetch_add_acquire (1 , v);
@@ -377,7 +379,7 @@ atomic_fetch_inc_acquire(atomic_t *v)#endif #ifndef atomic_fetch_inc_release -static inline int +static __always_inline intatomic_fetch_inc_release (atomic_t *v) {return atomic_fetch_add_release (1 , v);
@@ -386,7 +388,7 @@ atomic_fetch_inc_release(atomic_t *v)#endif #ifndef atomic_fetch_inc_relaxed -static inline int +static __always_inline intatomic_fetch_inc_relaxed (atomic_t *v) {return atomic_fetch_add_relaxed (1 , v);
@@ -397,7 +399,7 @@ atomic_fetch_inc_relaxed(atomic_t *v) #else /* atomic_fetch_inc_relaxed */ #ifndef atomic_fetch_inc_acquire -static inline int +static __always_inline int atomic_fetch_inc_acquire(atomic_t *v) { int ret = atomic_fetch_inc_relaxed(v);
@@ -408,7 +410,7 @@ atomic_fetch_inc_acquire(atomic_t *v)#endif #ifndef atomic_fetch_inc_release -static inline int +static __always_inline intatomic_fetch_inc_release (atomic_t *v) {__atomic_release_fence ();
@@ -418,7 +420,7 @@ atomic_fetch_inc_release(atomic_t *v)#endif #ifndef atomic_fetch_inc -static inline int +static __always_inline intatomic_fetch_inc (atomic_t *v) {int ret;
@@ -433,7 +435,7 @@ atomic_fetch_inc(atomic_t *v)#endif /* atomic_fetch_inc_relaxed */ #ifndef atomic_dec -static inline void +static __always_inline voidatomic_dec (atomic_t *v) {atomic_sub (1 , v);
@@ -449,7 +451,7 @@ atomic_dec(atomic_t *v)#endif /* atomic_dec_return */ #ifndef atomic_dec_return -static inline int +static __always_inline intatomic_dec_return (atomic_t *v) {return atomic_sub_return (1 , v);
@@ -458,7 +460,7 @@ atomic_dec_return(atomic_t *v)#endif #ifndef atomic_dec_return_acquire -static inline int +static __always_inline intatomic_dec_return_acquire (atomic_t *v) {return atomic_sub_return_acquire (1 , v);
@@ -467,7 +469,7 @@ atomic_dec_return_acquire(atomic_t *v)#endif #ifndef atomic_dec_return_release -static inline int +static __always_inline intatomic_dec_return_release (atomic_t *v) {return atomic_sub_return_release (1 , v);
@@ -476,7 +478,7 @@ atomic_dec_return_release(atomic_t *v)#endif #ifndef atomic_dec_return_relaxed -static inline int +static __always_inline intatomic_dec_return_relaxed (atomic_t *v) {return atomic_sub_return_relaxed (1 , v);
@@ -487,7 +489,7 @@ atomic_dec_return_relaxed(atomic_t *v) #else /* atomic_dec_return_relaxed */ #ifndef atomic_dec_return_acquire -static inline int +static __always_inline int atomic_dec_return_acquire(atomic_t *v) { int ret = atomic_dec_return_relaxed(v);
@@ -498,7 +500,7 @@ atomic_dec_return_acquire(atomic_t *v)#endif #ifndef atomic_dec_return_release -static inline int +static __always_inline intatomic_dec_return_release (atomic_t *v) {__atomic_release_fence ();
@@ -508,7 +510,7 @@ atomic_dec_return_release(atomic_t *v)#endif #ifndef atomic_dec_return -static inline int +static __always_inline intatomic_dec_return (atomic_t *v) {int ret;
@@ -530,7 +532,7 @@ atomic_dec_return(atomic_t *v)#endif /* atomic_fetch_dec */ #ifndef atomic_fetch_dec -static inline int +static __always_inline intatomic_fetch_dec (atomic_t *v) {return atomic_fetch_sub (1 , v);
@@ -539,7 +541,7 @@ atomic_fetch_dec(atomic_t *v)#endif #ifndef atomic_fetch_dec_acquire -static inline int +static __always_inline intatomic_fetch_dec_acquire (atomic_t *v) {return atomic_fetch_sub_acquire (1 , v);
@@ -548,7 +550,7 @@ atomic_fetch_dec_acquire(atomic_t *v)#endif #ifndef atomic_fetch_dec_release -static inline int +static __always_inline intatomic_fetch_dec_release (atomic_t *v) {return atomic_fetch_sub_release (1 , v);
@@ -557,7 +559,7 @@ atomic_fetch_dec_release(atomic_t *v)#endif #ifndef atomic_fetch_dec_relaxed -static inline int +static __always_inline intatomic_fetch_dec_relaxed (atomic_t *v) {return atomic_fetch_sub_relaxed (1 , v);
@@ -568,7 +570,7 @@ atomic_fetch_dec_relaxed(atomic_t *v) #else /* atomic_fetch_dec_relaxed */ #ifndef atomic_fetch_dec_acquire -static inline int +static __always_inline int atomic_fetch_dec_acquire(atomic_t *v) { int ret = atomic_fetch_dec_relaxed(v);
@@ -579,7 +581,7 @@ atomic_fetch_dec_acquire(atomic_t *v)#endif #ifndef atomic_fetch_dec_release -static inline int +static __always_inline intatomic_fetch_dec_release (atomic_t *v) {__atomic_release_fence ();
@@ -589,7 +591,7 @@ atomic_fetch_dec_release(atomic_t *v)#endif #ifndef atomic_fetch_dec -static inline int +static __always_inline intatomic_fetch_dec (atomic_t *v) {int ret;
@@ -610,7 +612,7 @@ atomic_fetch_dec(atomic_t *v) #else /* atomic_fetch_and_relaxed */ #ifndef atomic_fetch_and_acquire -static inline int +static __always_inline int atomic_fetch_and_acquire(int i, atomic_t *v) { int ret = atomic_fetch_and_relaxed(i, v);
@@ -621,7 +623,7 @@ atomic_fetch_and_acquire(int i, atomic_t *v)#endif #ifndef atomic_fetch_and_release -static inline int +static __always_inline intatomic_fetch_and_release (int i,atomic_t *v) {__atomic_release_fence ();
@@ -631,7 +633,7 @@ atomic_fetch_and_release(int i, atomic_t *v)#endif #ifndef atomic_fetch_and -static inline int +static __always_inline intatomic_fetch_and (int i,atomic_t *v) {int ret;
@@ -646,7 +648,7 @@ atomic_fetch_and(int i, atomic_t *v)#endif /* atomic_fetch_and_relaxed */ #ifndef atomic_andnot -static inline void +static __always_inline voidatomic_andnot (int i,atomic_t *v) {atomic_and (~i, v);
@@ -662,7 +664,7 @@ atomic_andnot(int i, atomic_t *v)#endif /* atomic_fetch_andnot */ #ifndef atomic_fetch_andnot -static inline int +static __always_inline intatomic_fetch_andnot (int i,atomic_t *v) {return atomic_fetch_and (~i, v);
@@ -671,7 +673,7 @@ atomic_fetch_andnot(int i, atomic_t *v)#endif #ifndef atomic_fetch_andnot_acquire -static inline int +static __always_inline intatomic_fetch_andnot_acquire (int i,atomic_t *v) {return atomic_fetch_and_acquire (~i, v);
@@ -680,7 +682,7 @@ atomic_fetch_andnot_acquire(int i, atomic_t *v)#endif #ifndef atomic_fetch_andnot_release -static inline int +static __always_inline intatomic_fetch_andnot_release (int i,atomic_t *v) {return atomic_fetch_and_release (~i, v);
@@ -689,7 +691,7 @@ atomic_fetch_andnot_release(int i, atomic_t *v)#endif #ifndef atomic_fetch_andnot_relaxed -static inline int +static __always_inline intatomic_fetch_andnot_relaxed (int i,atomic_t *v) {return atomic_fetch_and_relaxed (~i, v);
@@ -700,7 +702,7 @@ atomic_fetch_andnot_relaxed(int i, atomic_t *v) #else /* atomic_fetch_andnot_relaxed */ #ifndef atomic_fetch_andnot_acquire -static inline int +static __always_inline int atomic_fetch_andnot_acquire(int i, atomic_t *v) { int ret = atomic_fetch_andnot_relaxed(i, v);
@@ -711,7 +713,7 @@ atomic_fetch_andnot_acquire(int i, atomic_t *v)#endif #ifndef atomic_fetch_andnot_release -static inline int +static __always_inline intatomic_fetch_andnot_release (int i,atomic_t *v) {__atomic_release_fence ();
@@ -721,7 +723,7 @@ atomic_fetch_andnot_release(int i, atomic_t *v)#endif #ifndef atomic_fetch_andnot -static inline int +static __always_inline intatomic_fetch_andnot (int i,atomic_t *v) {int ret;
@@ -742,7 +744,7 @@ atomic_fetch_andnot(int i, atomic_t *v) #else /* atomic_fetch_or_relaxed */ #ifndef atomic_fetch_or_acquire -static inline int +static __always_inline int atomic_fetch_or_acquire(int i, atomic_t *v) { int ret = atomic_fetch_or_relaxed(i, v);
@@ -753,7 +755,7 @@ atomic_fetch_or_acquire(int i, atomic_t *v)#endif #ifndef atomic_fetch_or_release -static inline int +static __always_inline intatomic_fetch_or_release (int i,atomic_t *v) {__atomic_release_fence ();
@@ -763,7 +765,7 @@ atomic_fetch_or_release(int i, atomic_t *v)#endif #ifndef atomic_fetch_or -static inline int +static __always_inline intatomic_fetch_or (int i,atomic_t *v) {int ret;
@@ -784,7 +786,7 @@ atomic_fetch_or(int i, atomic_t *v) #else /* atomic_fetch_xor_relaxed */ #ifndef atomic_fetch_xor_acquire -static inline int +static __always_inline int atomic_fetch_xor_acquire(int i, atomic_t *v) { int ret = atomic_fetch_xor_relaxed(i, v);
@@ -795,7 +797,7 @@ atomic_fetch_xor_acquire(int i, atomic_t *v)#endif #ifndef atomic_fetch_xor_release -static inline int +static __always_inline intatomic_fetch_xor_release (int i,atomic_t *v) {__atomic_release_fence ();
@@ -805,7 +807,7 @@ atomic_fetch_xor_release(int i, atomic_t *v)#endif #ifndef atomic_fetch_xor -static inline int +static __always_inline intatomic_fetch_xor (int i,atomic_t *v) {int ret;
@@ -826,7 +828,7 @@ atomic_fetch_xor(int i, atomic_t *v) #else /* atomic_xchg_relaxed */ #ifndef atomic_xchg_acquire -static inline int +static __always_inline int atomic_xchg_acquire(atomic_t *v, int i) { int ret = atomic_xchg_relaxed(v, i);
@@ -837,7 +839,7 @@ atomic_xchg_acquire(atomic_t *v, int i)#endif #ifndef atomic_xchg_release -static inline int +static __always_inline intatomic_xchg_release (atomic_t *v,int i) {__atomic_release_fence ();
@@ -847,7 +849,7 @@ atomic_xchg_release(atomic_t *v, int i)#endif #ifndef atomic_xchg -static inline int +static __always_inline intatomic_xchg (atomic_t *v,int i) {int ret;
@@ -868,7 +870,7 @@ atomic_xchg(atomic_t *v, int i) #else /* atomic_cmpxchg_relaxed */ #ifndef atomic_cmpxchg_acquire -static inline int +static __always_inline int atomic_cmpxchg_acquire(atomic_t *v, int old, int new) { int ret = atomic_cmpxchg_relaxed(v, old, new);
@@ -879,7 +881,7 @@ atomic_cmpxchg_acquire(atomic_t *v, int old, int new)#endif #ifndef atomic_cmpxchg_release -static inline int +static __always_inline intatomic_cmpxchg_release (atomic_t *v,int old,int new) {__atomic_release_fence ();
@@ -889,7 +891,7 @@ atomic_cmpxchg_release(atomic_t *v, int old, int new)#endif #ifndef atomic_cmpxchg -static inline int +static __always_inline intatomic_cmpxchg (atomic_t *v,int old,int new) {int ret;
@@ -911,7 +913,7 @@ atomic_cmpxchg(atomic_t *v, int old, int new)#endif /* atomic_try_cmpxchg */ #ifndef atomic_try_cmpxchg -static inline bool +static __always_inline boolatomic_try_cmpxchg (atomic_t *v,int *old,int new) {int r, o = *old;
@@ -924,7 +926,7 @@ atomic_try_cmpxchg(atomic_t *v, int *old, int new)#endif #ifndef atomic_try_cmpxchg_acquire -static inline bool +static __always_inline boolatomic_try_cmpxchg_acquire (atomic_t *v,int *old,int new) {int r, o = *old;
@@ -937,7 +939,7 @@ atomic_try_cmpxchg_acquire(atomic_t *v, int *old, int new)#endif #ifndef atomic_try_cmpxchg_release -static inline bool +static __always_inline boolatomic_try_cmpxchg_release (atomic_t *v,int *old,int new) {int r, o = *old;
@@ -950,7 +952,7 @@ atomic_try_cmpxchg_release(atomic_t *v, int *old, int new)#endif #ifndef atomic_try_cmpxchg_relaxed -static inline bool +static __always_inline boolatomic_try_cmpxchg_relaxed (atomic_t *v,int *old,int new) {int r, o = *old;
@@ -965,7 +967,7 @@ atomic_try_cmpxchg_relaxed(atomic_t *v, int *old, int new) #else /* atomic_try_cmpxchg_relaxed */ #ifndef atomic_try_cmpxchg_acquire -static inline bool +static __always_inline bool atomic_try_cmpxchg_acquire(atomic_t *v, int *old, int new) { bool ret = atomic_try_cmpxchg_relaxed(v, old, new);
@@ -976,7 +978,7 @@ atomic_try_cmpxchg_acquire(atomic_t *v, int *old, int new)#endif #ifndef atomic_try_cmpxchg_release -static inline bool +static __always_inline boolatomic_try_cmpxchg_release (atomic_t *v,int *old,int new) {__atomic_release_fence ();
@@ -986,7 +988,7 @@ atomic_try_cmpxchg_release(atomic_t *v, int *old, int new)#endif #ifndef atomic_try_cmpxchg -static inline bool +static __always_inline boolatomic_try_cmpxchg (atomic_t *v,int *old,int new) {bool ret;
@@ -1010,7 +1012,7 @@ atomic_try_cmpxchg(atomic_t *v, int *old, int new)* true if the result is zero, or false for all * other cases. */ -static inline bool +static __always_inline boolatomic_sub_and_test (int i,atomic_t *v) {return atomic_sub_return (i, v) ==0 ;
@@ -1027,7 +1029,7 @@ atomic_sub_and_test(int i, atomic_t *v)* returns true if the result is 0, or false for all other * cases. */ -static inline bool +static __always_inline boolatomic_dec_and_test (atomic_t *v) {return atomic_dec_return (v) ==0 ;
@@ -1044,7 +1046,7 @@ atomic_dec_and_test(atomic_t *v)* and returns true if the result is zero, or false for all * other cases. */ -static inline bool +static __always_inline boolatomic_inc_and_test (atomic_t *v) {return atomic_inc_return (v) ==0 ;
@@ -1062,7 +1064,7 @@ atomic_inc_and_test(atomic_t *v)* if the result is negative, or false when * result is greater than or equal to zero. */ -static inline bool +static __always_inline boolatomic_add_negative (int i,atomic_t *v) {return atomic_add_return (i, v) <0 ;
@@ -1080,7 +1082,7 @@ atomic_add_negative(int i, atomic_t *v)* Atomically adds @a to @v, so long as @v was not already @u. * Returns original value of @v */ -static inline int +static __always_inline intatomic_fetch_add_unless (atomic_t *v,int a,int u) {int c =atomic_read (v);
@@ -1105,7 +1107,7 @@ atomic_fetch_add_unless(atomic_t *v, int a, int u)* Atomically adds @a to @v, if @v was not already @u. * Returns true if the addition was done. */ -static inline bool +static __always_inline boolatomic_add_unless (atomic_t *v,int a,int u) {return atomic_fetch_add_unless (v, a, u) != u;
@@ -1121,7 +1123,7 @@ atomic_add_unless(atomic_t *v, int a, int u)* Atomically increments @v by 1, if @v is non-zero. * Returns true if the increment was done. */ -static inline bool +static __always_inline boolatomic_inc_not_zero (atomic_t *v) {return atomic_add_unless (v,1 ,0 );
@@ -1130,7 +1132,7 @@ atomic_inc_not_zero(atomic_t *v)#endif #ifndef atomic_inc_unless_negative -static inline bool +static __always_inline boolatomic_inc_unless_negative (atomic_t *v) {int c =atomic_read (v);
@@ -1146,7 +1148,7 @@ atomic_inc_unless_negative(atomic_t *v)#endif #ifndef atomic_dec_unless_positive -static inline bool +static __always_inline boolatomic_dec_unless_positive (atomic_t *v) {int c =atomic_read (v);
@@ -1162,7 +1164,7 @@ atomic_dec_unless_positive(atomic_t *v)#endif #ifndef atomic_dec_if_positive -static inline int +static __always_inline intatomic_dec_if_positive (atomic_t *v) {int dec, c =atomic_read (v);
@@ -1186,7 +1188,7 @@ atomic_dec_if_positive(atomic_t *v)#endif #ifndef atomic64_read_acquire -static inline s64 +static __always_inline s64atomic64_read_acquire (const atomic64_t *v) {return smp_load_acquire (&(v)->counter);
@@ -1195,7 +1197,7 @@ atomic64_read_acquire(const atomic64_t *v)#endif #ifndef atomic64_set_release -static inline void +static __always_inline voidatomic64_set_release (atomic64_t *v,s64 i) {smp_store_release (&(v)->counter, i);
@@ -1210,7 +1212,7 @@ atomic64_set_release(atomic64_t *v, s64 i) #else /* atomic64_add_return_relaxed */ #ifndef atomic64_add_return_acquire -static inline s64 +static __always_inline s64 atomic64_add_return_acquire(s64 i, atomic64_t *v) { s64 ret = atomic64_add_return_relaxed(i, v);
@@ -1221,7 +1223,7 @@ atomic64_add_return_acquire(s64 i, atomic64_t *v)#endif #ifndef atomic64_add_return_release -static inline s64 +static __always_inline s64atomic64_add_return_release (s64 i,atomic64_t *v) {__atomic_release_fence ();
@@ -1231,7 +1233,7 @@ atomic64_add_return_release(s64 i, atomic64_t *v)#endif #ifndef atomic64_add_return -static inline s64 +static __always_inline s64atomic64_add_return (s64 i,atomic64_t *v) {s64 ret;
@@ -1252,7 +1254,7 @@ atomic64_add_return(s64 i, atomic64_t *v) #else /* atomic64_fetch_add_relaxed */ #ifndef atomic64_fetch_add_acquire -static inline s64 +static __always_inline s64 atomic64_fetch_add_acquire(s64 i, atomic64_t *v) { s64 ret = atomic64_fetch_add_relaxed(i, v);
@@ -1263,7 +1265,7 @@ atomic64_fetch_add_acquire(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_add_release -static inline s64 +static __always_inline s64atomic64_fetch_add_release (s64 i,atomic64_t *v) {__atomic_release_fence ();
@@ -1273,7 +1275,7 @@ atomic64_fetch_add_release(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_add -static inline s64 +static __always_inline s64atomic64_fetch_add (s64 i,atomic64_t *v) {s64 ret;
@@ -1294,7 +1296,7 @@ atomic64_fetch_add(s64 i, atomic64_t *v) #else /* atomic64_sub_return_relaxed */ #ifndef atomic64_sub_return_acquire -static inline s64 +static __always_inline s64 atomic64_sub_return_acquire(s64 i, atomic64_t *v) { s64 ret = atomic64_sub_return_relaxed(i, v);
@@ -1305,7 +1307,7 @@ atomic64_sub_return_acquire(s64 i, atomic64_t *v)#endif #ifndef atomic64_sub_return_release -static inline s64 +static __always_inline s64atomic64_sub_return_release (s64 i,atomic64_t *v) {__atomic_release_fence ();
@@ -1315,7 +1317,7 @@ atomic64_sub_return_release(s64 i, atomic64_t *v)#endif #ifndef atomic64_sub_return -static inline s64 +static __always_inline s64atomic64_sub_return (s64 i,atomic64_t *v) {s64 ret;
@@ -1336,7 +1338,7 @@ atomic64_sub_return(s64 i, atomic64_t *v) #else /* atomic64_fetch_sub_relaxed */ #ifndef atomic64_fetch_sub_acquire -static inline s64 +static __always_inline s64 atomic64_fetch_sub_acquire(s64 i, atomic64_t *v) { s64 ret = atomic64_fetch_sub_relaxed(i, v);
@@ -1347,7 +1349,7 @@ atomic64_fetch_sub_acquire(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_sub_release -static inline s64 +static __always_inline s64atomic64_fetch_sub_release (s64 i,atomic64_t *v) {__atomic_release_fence ();
@@ -1357,7 +1359,7 @@ atomic64_fetch_sub_release(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_sub -static inline s64 +static __always_inline s64atomic64_fetch_sub (s64 i,atomic64_t *v) {s64 ret;
@@ -1372,7 +1374,7 @@ atomic64_fetch_sub(s64 i, atomic64_t *v)#endif /* atomic64_fetch_sub_relaxed */ #ifndef atomic64_inc -static inline void +static __always_inline voidatomic64_inc (atomic64_t *v) {atomic64_add (1 , v);
@@ -1388,7 +1390,7 @@ atomic64_inc(atomic64_t *v)#endif /* atomic64_inc_return */ #ifndef atomic64_inc_return -static inline s64 +static __always_inline s64atomic64_inc_return (atomic64_t *v) {return atomic64_add_return (1 , v);
@@ -1397,7 +1399,7 @@ atomic64_inc_return(atomic64_t *v)#endif #ifndef atomic64_inc_return_acquire -static inline s64 +static __always_inline s64atomic64_inc_return_acquire (atomic64_t *v) {return atomic64_add_return_acquire (1 , v);
@@ -1406,7 +1408,7 @@ atomic64_inc_return_acquire(atomic64_t *v)#endif #ifndef atomic64_inc_return_release -static inline s64 +static __always_inline s64atomic64_inc_return_release (atomic64_t *v) {return atomic64_add_return_release (1 , v);
@@ -1415,7 +1417,7 @@ atomic64_inc_return_release(atomic64_t *v)#endif #ifndef atomic64_inc_return_relaxed -static inline s64 +static __always_inline s64atomic64_inc_return_relaxed (atomic64_t *v) {return atomic64_add_return_relaxed (1 , v);
@@ -1426,7 +1428,7 @@ atomic64_inc_return_relaxed(atomic64_t *v) #else /* atomic64_inc_return_relaxed */ #ifndef atomic64_inc_return_acquire -static inline s64 +static __always_inline s64 atomic64_inc_return_acquire(atomic64_t *v) { s64 ret = atomic64_inc_return_relaxed(v);
@@ -1437,7 +1439,7 @@ atomic64_inc_return_acquire(atomic64_t *v)#endif #ifndef atomic64_inc_return_release -static inline s64 +static __always_inline s64atomic64_inc_return_release (atomic64_t *v) {__atomic_release_fence ();
@@ -1447,7 +1449,7 @@ atomic64_inc_return_release(atomic64_t *v)#endif #ifndef atomic64_inc_return -static inline s64 +static __always_inline s64atomic64_inc_return (atomic64_t *v) {s64 ret;
@@ -1469,7 +1471,7 @@ atomic64_inc_return(atomic64_t *v)#endif /* atomic64_fetch_inc */ #ifndef atomic64_fetch_inc -static inline s64 +static __always_inline s64atomic64_fetch_inc (atomic64_t *v) {return atomic64_fetch_add (1 , v);
@@ -1478,7 +1480,7 @@ atomic64_fetch_inc(atomic64_t *v)#endif #ifndef atomic64_fetch_inc_acquire -static inline s64 +static __always_inline s64atomic64_fetch_inc_acquire (atomic64_t *v) {return atomic64_fetch_add_acquire (1 , v);
@@ -1487,7 +1489,7 @@ atomic64_fetch_inc_acquire(atomic64_t *v)#endif #ifndef atomic64_fetch_inc_release -static inline s64 +static __always_inline s64atomic64_fetch_inc_release (atomic64_t *v) {return atomic64_fetch_add_release (1 , v);
@@ -1496,7 +1498,7 @@ atomic64_fetch_inc_release(atomic64_t *v)#endif #ifndef atomic64_fetch_inc_relaxed -static inline s64 +static __always_inline s64atomic64_fetch_inc_relaxed (atomic64_t *v) {return atomic64_fetch_add_relaxed (1 , v);
@@ -1507,7 +1509,7 @@ atomic64_fetch_inc_relaxed(atomic64_t *v) #else /* atomic64_fetch_inc_relaxed */ #ifndef atomic64_fetch_inc_acquire -static inline s64 +static __always_inline s64 atomic64_fetch_inc_acquire(atomic64_t *v) { s64 ret = atomic64_fetch_inc_relaxed(v);
@@ -1518,7 +1520,7 @@ atomic64_fetch_inc_acquire(atomic64_t *v)#endif #ifndef atomic64_fetch_inc_release -static inline s64 +static __always_inline s64atomic64_fetch_inc_release (atomic64_t *v) {__atomic_release_fence ();
@@ -1528,7 +1530,7 @@ atomic64_fetch_inc_release(atomic64_t *v)#endif #ifndef atomic64_fetch_inc -static inline s64 +static __always_inline s64atomic64_fetch_inc (atomic64_t *v) {s64 ret;
@@ -1543,7 +1545,7 @@ atomic64_fetch_inc(atomic64_t *v)#endif /* atomic64_fetch_inc_relaxed */ #ifndef atomic64_dec -static inline void +static __always_inline voidatomic64_dec (atomic64_t *v) {atomic64_sub (1 , v);
@@ -1559,7 +1561,7 @@ atomic64_dec(atomic64_t *v)#endif /* atomic64_dec_return */ #ifndef atomic64_dec_return -static inline s64 +static __always_inline s64atomic64_dec_return (atomic64_t *v) {return atomic64_sub_return (1 , v);
@@ -1568,7 +1570,7 @@ atomic64_dec_return(atomic64_t *v)#endif #ifndef atomic64_dec_return_acquire -static inline s64 +static __always_inline s64atomic64_dec_return_acquire (atomic64_t *v) {return atomic64_sub_return_acquire (1 , v);
@@ -1577,7 +1579,7 @@ atomic64_dec_return_acquire(atomic64_t *v)#endif #ifndef atomic64_dec_return_release -static inline s64 +static __always_inline s64atomic64_dec_return_release (atomic64_t *v) {return atomic64_sub_return_release (1 , v);
@@ -1586,7 +1588,7 @@ atomic64_dec_return_release(atomic64_t *v)#endif #ifndef atomic64_dec_return_relaxed -static inline s64 +static __always_inline s64atomic64_dec_return_relaxed (atomic64_t *v) {return atomic64_sub_return_relaxed (1 , v);
@@ -1597,7 +1599,7 @@ atomic64_dec_return_relaxed(atomic64_t *v) #else /* atomic64_dec_return_relaxed */ #ifndef atomic64_dec_return_acquire -static inline s64 +static __always_inline s64 atomic64_dec_return_acquire(atomic64_t *v) { s64 ret = atomic64_dec_return_relaxed(v);
@@ -1608,7 +1610,7 @@ atomic64_dec_return_acquire(atomic64_t *v)#endif #ifndef atomic64_dec_return_release -static inline s64 +static __always_inline s64atomic64_dec_return_release (atomic64_t *v) {__atomic_release_fence ();
@@ -1618,7 +1620,7 @@ atomic64_dec_return_release(atomic64_t *v)#endif #ifndef atomic64_dec_return -static inline s64 +static __always_inline s64atomic64_dec_return (atomic64_t *v) {s64 ret;
@@ -1640,7 +1642,7 @@ atomic64_dec_return(atomic64_t *v)#endif /* atomic64_fetch_dec */ #ifndef atomic64_fetch_dec -static inline s64 +static __always_inline s64atomic64_fetch_dec (atomic64_t *v) {return atomic64_fetch_sub (1 , v);
@@ -1649,7 +1651,7 @@ atomic64_fetch_dec(atomic64_t *v)#endif #ifndef atomic64_fetch_dec_acquire -static inline s64 +static __always_inline s64atomic64_fetch_dec_acquire (atomic64_t *v) {return atomic64_fetch_sub_acquire (1 , v);
@@ -1658,7 +1660,7 @@ atomic64_fetch_dec_acquire(atomic64_t *v)#endif #ifndef atomic64_fetch_dec_release -static inline s64 +static __always_inline s64atomic64_fetch_dec_release (atomic64_t *v) {return atomic64_fetch_sub_release (1 , v);
@@ -1667,7 +1669,7 @@ atomic64_fetch_dec_release(atomic64_t *v)#endif #ifndef atomic64_fetch_dec_relaxed -static inline s64 +static __always_inline s64atomic64_fetch_dec_relaxed (atomic64_t *v) {return atomic64_fetch_sub_relaxed (1 , v);
@@ -1678,7 +1680,7 @@ atomic64_fetch_dec_relaxed(atomic64_t *v) #else /* atomic64_fetch_dec_relaxed */ #ifndef atomic64_fetch_dec_acquire -static inline s64 +static __always_inline s64 atomic64_fetch_dec_acquire(atomic64_t *v) { s64 ret = atomic64_fetch_dec_relaxed(v);
@@ -1689,7 +1691,7 @@ atomic64_fetch_dec_acquire(atomic64_t *v)#endif #ifndef atomic64_fetch_dec_release -static inline s64 +static __always_inline s64atomic64_fetch_dec_release (atomic64_t *v) {__atomic_release_fence ();
@@ -1699,7 +1701,7 @@ atomic64_fetch_dec_release(atomic64_t *v)#endif #ifndef atomic64_fetch_dec -static inline s64 +static __always_inline s64atomic64_fetch_dec (atomic64_t *v) {s64 ret;
@@ -1720,7 +1722,7 @@ atomic64_fetch_dec(atomic64_t *v) #else /* atomic64_fetch_and_relaxed */ #ifndef atomic64_fetch_and_acquire -static inline s64 +static __always_inline s64 atomic64_fetch_and_acquire(s64 i, atomic64_t *v) { s64 ret = atomic64_fetch_and_relaxed(i, v);
@@ -1731,7 +1733,7 @@ atomic64_fetch_and_acquire(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_and_release -static inline s64 +static __always_inline s64atomic64_fetch_and_release (s64 i,atomic64_t *v) {__atomic_release_fence ();
@@ -1741,7 +1743,7 @@ atomic64_fetch_and_release(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_and -static inline s64 +static __always_inline s64atomic64_fetch_and (s64 i,atomic64_t *v) {s64 ret;
@@ -1756,7 +1758,7 @@ atomic64_fetch_and(s64 i, atomic64_t *v)#endif /* atomic64_fetch_and_relaxed */ #ifndef atomic64_andnot -static inline void +static __always_inline voidatomic64_andnot (s64 i,atomic64_t *v) {atomic64_and (~i, v);
@@ -1772,7 +1774,7 @@ atomic64_andnot(s64 i, atomic64_t *v)#endif /* atomic64_fetch_andnot */ #ifndef atomic64_fetch_andnot -static inline s64 +static __always_inline s64atomic64_fetch_andnot (s64 i,atomic64_t *v) {return atomic64_fetch_and (~i, v);
@@ -1781,7 +1783,7 @@ atomic64_fetch_andnot(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_andnot_acquire -static inline s64 +static __always_inline s64atomic64_fetch_andnot_acquire (s64 i,atomic64_t *v) {return atomic64_fetch_and_acquire (~i, v);
@@ -1790,7 +1792,7 @@ atomic64_fetch_andnot_acquire(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_andnot_release -static inline s64 +static __always_inline s64atomic64_fetch_andnot_release (s64 i,atomic64_t *v) {return atomic64_fetch_and_release (~i, v);
@@ -1799,7 +1801,7 @@ atomic64_fetch_andnot_release(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_andnot_relaxed -static inline s64 +static __always_inline s64atomic64_fetch_andnot_relaxed (s64 i,atomic64_t *v) {return atomic64_fetch_and_relaxed (~i, v);
@@ -1810,7 +1812,7 @@ atomic64_fetch_andnot_relaxed(s64 i, atomic64_t *v) #else /* atomic64_fetch_andnot_relaxed */ #ifndef atomic64_fetch_andnot_acquire -static inline s64 +static __always_inline s64 atomic64_fetch_andnot_acquire(s64 i, atomic64_t *v) { s64 ret = atomic64_fetch_andnot_relaxed(i, v);
@@ -1821,7 +1823,7 @@ atomic64_fetch_andnot_acquire(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_andnot_release -static inline s64 +static __always_inline s64atomic64_fetch_andnot_release (s64 i,atomic64_t *v) {__atomic_release_fence ();
@@ -1831,7 +1833,7 @@ atomic64_fetch_andnot_release(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_andnot -static inline s64 +static __always_inline s64atomic64_fetch_andnot (s64 i,atomic64_t *v) {s64 ret;
@@ -1852,7 +1854,7 @@ atomic64_fetch_andnot(s64 i, atomic64_t *v) #else /* atomic64_fetch_or_relaxed */ #ifndef atomic64_fetch_or_acquire -static inline s64 +static __always_inline s64 atomic64_fetch_or_acquire(s64 i, atomic64_t *v) { s64 ret = atomic64_fetch_or_relaxed(i, v);
@@ -1863,7 +1865,7 @@ atomic64_fetch_or_acquire(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_or_release -static inline s64 +static __always_inline s64atomic64_fetch_or_release (s64 i,atomic64_t *v) {__atomic_release_fence ();
@@ -1873,7 +1875,7 @@ atomic64_fetch_or_release(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_or -static inline s64 +static __always_inline s64atomic64_fetch_or (s64 i,atomic64_t *v) {s64 ret;
@@ -1894,7 +1896,7 @@ atomic64_fetch_or(s64 i, atomic64_t *v) #else /* atomic64_fetch_xor_relaxed */ #ifndef atomic64_fetch_xor_acquire -static inline s64 +static __always_inline s64 atomic64_fetch_xor_acquire(s64 i, atomic64_t *v) { s64 ret = atomic64_fetch_xor_relaxed(i, v);
@@ -1905,7 +1907,7 @@ atomic64_fetch_xor_acquire(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_xor_release -static inline s64 +static __always_inline s64atomic64_fetch_xor_release (s64 i,atomic64_t *v) {__atomic_release_fence ();
@@ -1915,7 +1917,7 @@ atomic64_fetch_xor_release(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_xor -static inline s64 +static __always_inline s64atomic64_fetch_xor (s64 i,atomic64_t *v) {s64 ret;
@@ -1936,7 +1938,7 @@ atomic64_fetch_xor(s64 i, atomic64_t *v) #else /* atomic64_xchg_relaxed */ #ifndef atomic64_xchg_acquire -static inline s64 +static __always_inline s64 atomic64_xchg_acquire(atomic64_t *v, s64 i) { s64 ret = atomic64_xchg_relaxed(v, i);
@@ -1947,7 +1949,7 @@ atomic64_xchg_acquire(atomic64_t *v, s64 i)#endif #ifndef atomic64_xchg_release -static inline s64 +static __always_inline s64atomic64_xchg_release (atomic64_t *v,s64 i) {__atomic_release_fence ();
@@ -1957,7 +1959,7 @@ atomic64_xchg_release(atomic64_t *v, s64 i)#endif #ifndef atomic64_xchg -static inline s64 +static __always_inline s64atomic64_xchg (atomic64_t *v,s64 i) {s64 ret;
@@ -1978,7 +1980,7 @@ atomic64_xchg(atomic64_t *v, s64 i) #else /* atomic64_cmpxchg_relaxed */ #ifndef atomic64_cmpxchg_acquire -static inline s64 +static __always_inline s64 atomic64_cmpxchg_acquire(atomic64_t *v, s64 old, s64 new) { s64 ret = atomic64_cmpxchg_relaxed(v, old, new);
@@ -1989,7 +1991,7 @@ atomic64_cmpxchg_acquire(atomic64_t *v, s64 old, s64 new)#endif #ifndef atomic64_cmpxchg_release -static inline s64 +static __always_inline s64atomic64_cmpxchg_release (atomic64_t *v,s64 old,s64 new) {__atomic_release_fence ();
@@ -1999,7 +2001,7 @@ atomic64_cmpxchg_release(atomic64_t *v, s64 old, s64 new)#endif #ifndef atomic64_cmpxchg -static inline s64 +static __always_inline s64atomic64_cmpxchg (atomic64_t *v,s64 old,s64 new) {s64 ret;
@@ -2021,7 +2023,7 @@ atomic64_cmpxchg(atomic64_t *v, s64 old, s64 new)#endif /* atomic64_try_cmpxchg */ #ifndef atomic64_try_cmpxchg -static inline bool +static __always_inline boolatomic64_try_cmpxchg (atomic64_t *v,s64 *old,s64 new) {s64 r, o = *old;
@@ -2034,7 +2036,7 @@ atomic64_try_cmpxchg(atomic64_t *v, s64 *old, s64 new)#endif #ifndef atomic64_try_cmpxchg_acquire -static inline bool +static __always_inline boolatomic64_try_cmpxchg_acquire (atomic64_t *v,s64 *old,s64 new) {s64 r, o = *old;
@@ -2047,7 +2049,7 @@ atomic64_try_cmpxchg_acquire(atomic64_t *v, s64 *old, s64 new)#endif #ifndef atomic64_try_cmpxchg_release -static inline bool +static __always_inline boolatomic64_try_cmpxchg_release (atomic64_t *v,s64 *old,s64 new) {s64 r, o = *old;
@@ -2060,7 +2062,7 @@ atomic64_try_cmpxchg_release(atomic64_t *v, s64 *old, s64 new)#endif #ifndef atomic64_try_cmpxchg_relaxed -static inline bool +static __always_inline boolatomic64_try_cmpxchg_relaxed (atomic64_t *v,s64 *old,s64 new) {s64 r, o = *old;
@@ -2075,7 +2077,7 @@ atomic64_try_cmpxchg_relaxed(atomic64_t *v, s64 *old, s64 new) #else /* atomic64_try_cmpxchg_relaxed */ #ifndef atomic64_try_cmpxchg_acquire -static inline bool +static __always_inline bool atomic64_try_cmpxchg_acquire(atomic64_t *v, s64 *old, s64 new) { bool ret = atomic64_try_cmpxchg_relaxed(v, old, new);
@@ -2086,7 +2088,7 @@ atomic64_try_cmpxchg_acquire(atomic64_t *v, s64 *old, s64 new)#endif #ifndef atomic64_try_cmpxchg_release -static inline bool +static __always_inline boolatomic64_try_cmpxchg_release (atomic64_t *v,s64 *old,s64 new) {__atomic_release_fence ();
@@ -2096,7 +2098,7 @@ atomic64_try_cmpxchg_release(atomic64_t *v, s64 *old, s64 new)#endif #ifndef atomic64_try_cmpxchg -static inline bool +static __always_inline boolatomic64_try_cmpxchg (atomic64_t *v,s64 *old,s64 new) {bool ret;
@@ -2120,7 +2122,7 @@ atomic64_try_cmpxchg(atomic64_t *v, s64 *old, s64 new)* true if the result is zero, or false for all * other cases. */ -static inline bool +static __always_inline boolatomic64_sub_and_test (s64 i,atomic64_t *v) {return atomic64_sub_return (i, v) ==0 ;
@@ -2137,7 +2139,7 @@ atomic64_sub_and_test(s64 i, atomic64_t *v)* returns true if the result is 0, or false for all other * cases. */ -static inline bool +static __always_inline boolatomic64_dec_and_test (atomic64_t *v) {return atomic64_dec_return (v) ==0 ;
@@ -2154,7 +2156,7 @@ atomic64_dec_and_test(atomic64_t *v)* and returns true if the result is zero, or false for all * other cases. */ -static inline bool +static __always_inline boolatomic64_inc_and_test (atomic64_t *v) {return atomic64_inc_return (v) ==0 ;
@@ -2172,7 +2174,7 @@ atomic64_inc_and_test(atomic64_t *v)* if the result is negative, or false when * result is greater than or equal to zero. */ -static inline bool +static __always_inline boolatomic64_add_negative (s64 i,atomic64_t *v) {return atomic64_add_return (i, v) <0 ;
@@ -2190,7 +2192,7 @@ atomic64_add_negative(s64 i, atomic64_t *v)* Atomically adds @a to @v, so long as @v was not already @u. * Returns original value of @v */ -static inline s64 +static __always_inline s64atomic64_fetch_add_unless (atomic64_t *v,s64 a,s64 u) {s64 c =atomic64_read (v);
@@ -2215,7 +2217,7 @@ atomic64_fetch_add_unless(atomic64_t *v, s64 a, s64 u)* Atomically adds @a to @v, if @v was not already @u. * Returns true if the addition was done. */ -static inline bool +static __always_inline boolatomic64_add_unless (atomic64_t *v,s64 a,s64 u) {return atomic64_fetch_add_unless (v, a, u) != u;
@@ -2231,7 +2233,7 @@ atomic64_add_unless(atomic64_t *v, s64 a, s64 u)* Atomically increments @v by 1, if @v is non-zero. * Returns true if the increment was done. */ -static inline bool +static __always_inline boolatomic64_inc_not_zero (atomic64_t *v) {return atomic64_add_unless (v,1 ,0 );
@@ -2240,7 +2242,7 @@ atomic64_inc_not_zero(atomic64_t *v)#endif #ifndef atomic64_inc_unless_negative -static inline bool +static __always_inline boolatomic64_inc_unless_negative (atomic64_t *v) {s64 c =atomic64_read (v);
@@ -2256,7 +2258,7 @@ atomic64_inc_unless_negative(atomic64_t *v)#endif #ifndef atomic64_dec_unless_positive -static inline bool +static __always_inline boolatomic64_dec_unless_positive (atomic64_t *v) {s64 c =atomic64_read (v);
@@ -2272,7 +2274,7 @@ atomic64_dec_unless_positive(atomic64_t *v)#endif #ifndef atomic64_dec_if_positive -static inline s64 +static __always_inline s64atomic64_dec_if_positive (atomic64_t *v) {s64 dec, c =atomic64_read (v);
@@ -2292,4 +2294,4 @@ atomic64_dec_if_positive(atomic64_t *v)#define atomic64_cond_read_relaxed (v, c) smp_cond_load_relaxed(&(v)->counter, (c))#endif /* _LINUX_ATOMIC_FALLBACK_H */ -// 25de4a2804d70f57e994fe3b419148658bb5378a +// baaf45f4c24ed88ceae58baca39d7fd80bb8101b
scripts/atomic/fallbacks/acquire +1 -1
@@ -1,5 +1,5 @@ cat <<EOF -static inline ${ret} +static __always_inline ${ret} ${atomic}_${pfx}${name}${sfx}_acquire(${params}) { ${ret} ret = ${atomic}_${pfx}${name}${sfx}_relaxed(${args});
scripts/atomic/fallbacks/add_negative +1 -1
@@ -8,7 +8,7 @@ cat <<EOF * if the result is negative, or false when * result is greater than or equal to zero. */ -static inline bool +static __always_inline bool ${atomic}_add_negative(${int} i, ${atomic}_t *v) { return ${atomic}_add_return(i, v) < 0;
scripts/atomic/fallbacks/add_unless +1 -1
@@ -8,7 +8,7 @@ cat << EOF * Atomically adds @a to @v, if @v was not already @u. * Returns true if the addition was done. */ -static inline bool +static __always_inline bool ${atomic}_add_unless(${atomic}_t *v, ${int} a, ${int} u) { return ${atomic}_fetch_add_unless(v, a, u) != u;
scripts/atomic/fallbacks/andnot +1 -1
@@ -1,5 +1,5 @@ cat <<EOF -static inline ${ret} +static __always_inline ${ret} ${atomic}_${pfx}andnot${sfx}${order}(${int} i, ${atomic}_t *v) { ${retstmt}${atomic}_${pfx}and${sfx}${order}(~i, v);
scripts/atomic/fallbacks/dec +1 -1
@@ -1,5 +1,5 @@ cat <<EOF -static inline ${ret} +static __always_inline ${ret} ${atomic}_${pfx}dec${sfx}${order}(${atomic}_t *v) { ${retstmt}${atomic}_${pfx}sub${sfx}${order}(1, v);
scripts/atomic/fallbacks/dec_and_test +1 -1
@@ -7,7 +7,7 @@ cat <<EOF * returns true if the result is 0, or false for all other * cases. */ -static inline bool +static __always_inline bool ${atomic}_dec_and_test(${atomic}_t *v) { return ${atomic}_dec_return(v) == 0;
scripts/atomic/fallbacks/dec_if_positive +1 -1
@@ -1,5 +1,5 @@ cat <<EOF -static inline ${ret} +static __always_inline ${ret} ${atomic}_dec_if_positive(${atomic}_t *v) { ${int} dec, c = ${atomic}_read(v);
scripts/atomic/fallbacks/dec_unless_positive +1 -1
@@ -1,5 +1,5 @@ cat <<EOF -static inline bool +static __always_inline bool ${atomic}_dec_unless_positive(${atomic}_t *v) { ${int} c = ${atomic}_read(v);
scripts/atomic/fallbacks/fence +1 -1
@@ -1,5 +1,5 @@ cat <<EOF -static inline ${ret} +static __always_inline ${ret} ${atomic}_${pfx}${name}${sfx}(${params}) { ${ret} ret;
scripts/atomic/fallbacks/fetch_add_unless +1 -1
@@ -8,7 +8,7 @@ cat << EOF * Atomically adds @a to @v, so long as @v was not already @u. * Returns original value of @v */ -static inline ${int} +static __always_inline ${int} ${atomic}_fetch_add_unless(${atomic}_t *v, ${int} a, ${int} u) { ${int} c = ${atomic}_read(v);
scripts/atomic/fallbacks/inc +1 -1
@@ -1,5 +1,5 @@ cat <<EOF -static inline ${ret} +static __always_inline ${ret} ${atomic}_${pfx}inc${sfx}${order}(${atomic}_t *v) { ${retstmt}${atomic}_${pfx}add${sfx}${order}(1, v);
scripts/atomic/fallbacks/inc_and_test +1 -1
@@ -7,7 +7,7 @@ cat <<EOF * and returns true if the result is zero, or false for all * other cases. */ -static inline bool +static __always_inline bool ${atomic}_inc_and_test(${atomic}_t *v) { return ${atomic}_inc_return(v) == 0;
scripts/atomic/fallbacks/inc_not_zero +1 -1
@@ -6,7 +6,7 @@ cat <<EOF * Atomically increments @v by 1, if @v is non-zero. * Returns true if the increment was done. */ -static inline bool +static __always_inline bool ${atomic}_inc_not_zero(${atomic}_t *v) { return ${atomic}_add_unless(v, 1, 0);
scripts/atomic/fallbacks/inc_unless_negative +1 -1
@@ -1,5 +1,5 @@ cat <<EOF -static inline bool +static __always_inline bool ${atomic}_inc_unless_negative(${atomic}_t *v) { ${int} c = ${atomic}_read(v);
scripts/atomic/fallbacks/read_acquire +1 -1
@@ -1,5 +1,5 @@ cat <<EOF -static inline ${ret} +static __always_inline ${ret} ${atomic}_read_acquire(const ${atomic}_t *v) { return smp_load_acquire(&(v)->counter);
scripts/atomic/fallbacks/release +1 -1
@@ -1,5 +1,5 @@ cat <<EOF -static inline ${ret} +static __always_inline ${ret} ${atomic}_${pfx}${name}${sfx}_release(${params}) { __atomic_release_fence();
scripts/atomic/fallbacks/set_release +1 -1
@@ -1,5 +1,5 @@ cat <<EOF -static inline void +static __always_inline void ${atomic}_set_release(${atomic}_t *v, ${int} i) { smp_store_release(&(v)->counter, i);
scripts/atomic/fallbacks/sub_and_test +1 -1
@@ -8,7 +8,7 @@ cat <<EOF * true if the result is zero, or false for all * other cases. */ -static inline bool +static __always_inline bool ${atomic}_sub_and_test(${int} i, ${atomic}_t *v) { return ${atomic}_sub_return(i, v) == 0;
scripts/atomic/fallbacks/try_cmpxchg +1 -1
@@ -1,5 +1,5 @@ cat <<EOF -static inline bool +static __always_inline bool ${atomic}_try_cmpxchg${order}(${atomic}_t *v, ${int} *old, ${int} new) { ${int} r, o = *old;
scripts/atomic/gen-atomic-fallback.sh +2 -0
@@ -149,6 +149,8 @@ cat << EOF #ifndef _LINUX_ATOMIC_FALLBACK_H #define _LINUX_ATOMIC_FALLBACK_H +#include <linux/compiler.h> + EOF for xchg in "xchg" "cmpxchg" "cmpxchg64"; do
Peter Zijlstra
maintainerPATCH v4 22/27 compiler: Simple READ/WRITE_ONCE() implementations
In reply to Peter ZijlstraBecause I need WRITE_ONCE_NOCHECK() and in anticipation of Will's READ_ONCE rewrite, provide __{READ,WRITE}_ONCE_SCALAR().
--- include/linux/compiler.h | 8 ++++++++ 1 file changed, 8 insertions(+)
include/linux/compiler.h +8 -0
@@ -289,6 +289,14 @@ unsigned long read_word_at_a_time(const __u.__val; \ }) +#define __READ_ONCE_SCALAR (x) \ + (*(const volatile typeof(x) *)&(x)) + +#define __WRITE_ONCE_SCALAR (x, val) \ +do { \ + *(volatile typeof(x) *)&(x) = val; \ +} while (0) +#endif /* __KERNEL__ */ /*
Peter Zijlstra
maintainerPATCH v4 23/27 locking/atomics: Flip fallbacks and instrumentation
In reply to Peter ZijlstraCurrently instrumentation of atomic primitives is done at the architecture level, while composites or fallbacks are provided at the generic level.
The result is that there are no uninstrumented variants of the fallbacks. Since there is now need of such (see the next patch), invert this ordering.
Doing this means moving the instrumentation into the generic code as well as having (for now) two variants of the fallbacks.
Notes:
- the various *cond_read* primitives are not proper fallbacks and got moved into linux/atomic.c. No arch_ variants are generated because the base primitives smp_cond_load*() are instrumented.
- once all architectures are moved over to arch_atomic_ we can remove one of the fallback variants and reclaim some 2300 lines.
- atomic_{read,set}*() are no longer double-instrumented
--- arch/arm64/include/asm/atomic.h | 6 arch/x86/include/asm/atomic.h | 17 arch/x86/include/asm/atomic64_32.h | 9 arch/x86/include/asm/atomic64_64.h | 15 include/linux/atomic-arch-fallback.h | 2291 +++++++++++++++++++++++++++ include/linux/atomic-fallback.h | 8 include/linux/atomic.h | 11 scripts/atomic/fallbacks/acquire | 4 scripts/atomic/fallbacks/add_negative | 6 scripts/atomic/fallbacks/add_unless | 6 scripts/atomic/fallbacks/andnot | 4 scripts/atomic/fallbacks/dec | 4 scripts/atomic/fallbacks/dec_and_test | 6 scripts/atomic/fallbacks/dec_if_positive | 6 scripts/atomic/fallbacks/dec_unless_positive | 6 scripts/atomic/fallbacks/fence | 4 scripts/atomic/fallbacks/fetch_add_unless | 8 scripts/atomic/fallbacks/inc | 4 scripts/atomic/fallbacks/inc_and_test | 6 scripts/atomic/fallbacks/inc_not_zero | 6 scripts/atomic/fallbacks/inc_unless_negative | 6 scripts/atomic/fallbacks/read_acquire | 2 scripts/atomic/fallbacks/release | 4 scripts/atomic/fallbacks/set_release | 2 scripts/atomic/fallbacks/sub_and_test | 6 scripts/atomic/fallbacks/try_cmpxchg | 4 scripts/atomic/gen-atomic-fallback.sh | 29 scripts/atomic/gen-atomics.sh | 5 28 files changed, 2403 insertions(+), 82 deletions(-)
arch/arm64/include/asm/atomic.h +3 -3
@@ -101,8 +101,8 @@ static inline long arch_atomic64_dec_if_#define ATOMIC_INIT (i) { (i) } -#define arch_atomic_read (v) READ_ONCE((v)->counter) -#define arch_atomic_set (v, i) WRITE_ONCE(((v)->counter), (i)) +#define arch_atomic_read (v) __READ_ONCE_SCALAR((v)->counter) +#define arch_atomic_set (v, i) __WRITE_ONCE_SCALAR(((v)->counter), (i))#define arch_atomic_add_return_relaxed arch_atomic_add_return_relaxed#define arch_atomic_add_return_acquire arch_atomic_add_return_acquire
@@ -225,6 +225,6 @@ static inline long arch_atomic64_dec_if_#define arch_atomic64_dec_if_positive arch_atomic64_dec_if_positive -#include <asm-generic/atomic-instrumented.h> +#define ARCH_ATOMIC #endif /* __ASM_ATOMIC_H */
arch/x86/include/asm/atomic.h +13 -4
@@ -28,7 +28,7 @@ static __always_inline int arch_atomic_r* Note for KASAN: we deliberately don't use READ_ONCE_NOCHECK() here, * it's non-inlined function that increases binary size and stack usage. */ -return READ_ONCE ((v)->counter); +return __READ_ONCE_SCALAR ((v)->counter); }/**
@@ -40,7 +40,7 @@ static __always_inline int arch_atomic_r*/ static __always_inline void arch_atomic_set(atomic_t *v, int i) { -WRITE_ONCE (v->counter, i); +__WRITE_ONCE_SCALAR (v->counter, i); }/**
@@ -166,6 +166,7 @@ static __always_inline int arch_atomic_a {return i +xadd (&v->counter, i); } +#define arch_atomic_add_return arch_atomic_add_return/** * arch_atomic_sub_return - subtract integer and return
@@ -178,32 +179,37 @@ static __always_inline int arch_atomic_s {return arch_atomic_add_return (-i, v); } +#define arch_atomic_sub_return arch_atomic_sub_return static __always_inline int arch_atomic_fetch_add(int i, atomic_t *v) {return xadd (&v->counter, i); } +#define arch_atomic_fetch_add arch_atomic_fetch_add static __always_inline int arch_atomic_fetch_sub(int i, atomic_t *v) {return xadd (&v->counter, -i); } +#define arch_atomic_fetch_sub arch_atomic_fetch_sub static __always_inline int arch_atomic_cmpxchg(atomic_t *v, int old, int new) {return arch_cmpxchg (&v->counter, old, new); } +#define arch_atomic_cmpxchg arch_atomic_cmpxchg -#define arch_atomic_try_cmpxchg arch_atomic_try_cmpxchg static __always_inline bool arch_atomic_try_cmpxchg(atomic_t *v, int *old, int new) {return try_cmpxchg (&v->counter, old, new); } +#define arch_atomic_try_cmpxchg arch_atomic_try_cmpxchgstatic inline int arch_atomic_xchg (atomic_t *v,int new) {return arch_xchg (&v->counter, new); } +#define arch_atomic_xchg arch_atomic_xchgstatic inline void arch_atomic_and (int i,atomic_t *v) {
@@ -221,6 +227,7 @@ static inline int arch_atomic_fetch_and(return val; } +#define arch_atomic_fetch_and arch_atomic_fetch_andstatic inline void arch_atomic_or (int i,atomic_t *v) {
@@ -238,6 +245,7 @@ static inline int arch_atomic_fetch_or(ireturn val; } +#define arch_atomic_fetch_or arch_atomic_fetch_orstatic inline void arch_atomic_xor (int i,atomic_t *v) {
@@ -255,6 +263,7 @@ static inline int arch_atomic_fetch_xor(return val; } +#define arch_atomic_fetch_xor arch_atomic_fetch_xor#ifdef CONFIG_X86_32 # include <asm/atomic64_32.h>
@@ -262,6 +271,6 @@ static inline int arch_atomic_fetch_xor(# include <asm/atomic64_64.h> #endif -#include <asm-generic/atomic-instrumented.h> +#define ARCH_ATOMIC #endif /* _ASM_X86_ATOMIC_H */
arch/x86/include/asm/atomic64_32.h +9 -0
@@ -75,6 +75,7 @@ static inline s64 arch_atomic64_cmpxchg( {return arch_cmpxchg64 (&v->counter, o, n); } +#define arch_atomic64_cmpxchg arch_atomic64_cmpxchg/** * arch_atomic64_xchg - xchg atomic64 variable
@@ -94,6 +95,7 @@ static inline s64 arch_atomic64_xchg(ato : "memory");return o; } +#define arch_atomic64_xchg arch_atomic64_xchg/** * arch_atomic64_set - set atomic64 variable
@@ -138,6 +140,7 @@ static inline s64 arch_atomic64_add_retu ASM_NO_INPUT_CLOBBER("memory"));return i; } +#define arch_atomic64_add_return arch_atomic64_add_return/* * Other variants with different arithmetic operators:
@@ -149,6 +152,7 @@ static inline s64 arch_atomic64_sub_retu ASM_NO_INPUT_CLOBBER("memory"));return i; } +#define arch_atomic64_sub_return arch_atomic64_sub_returnstatic inline s64 arch_atomic64_inc_return (atomic64_t *v) {
@@ -242,6 +246,7 @@ static inline int arch_atomic64_add_unle "S" (v) : "memory"); return (int)a; } +#define arch_atomic64_add_unless arch_atomic64_add_unlessstatic inline int arch_atomic64_inc_not_zero (atomic64_t *v) {
@@ -281,6 +286,7 @@ static inline s64 arch_atomic64_fetch_anreturn old; } +#define arch_atomic64_fetch_and arch_atomic64_fetch_andstatic inline void arch_atomic64_or (s64 i,atomic64_t *v) {
@@ -299,6 +305,7 @@ static inline s64 arch_atomic64_fetch_orreturn old; } +#define arch_atomic64_fetch_or arch_atomic64_fetch_orstatic inline void arch_atomic64_xor (s64 i,atomic64_t *v) {
@@ -317,6 +324,7 @@ static inline s64 arch_atomic64_fetch_xoreturn old; } +#define arch_atomic64_fetch_xor arch_atomic64_fetch_xorstatic inline s64 arch_atomic64_fetch_add (s64 i,atomic64_t *v) {
@@ -327,6 +335,7 @@ static inline s64 arch_atomic64_fetch_adreturn old; } +#define arch_atomic64_fetch_add arch_atomic64_fetch_add#define arch_atomic64_fetch_sub (i, v) arch_atomic64_fetch_add(-(i), (v))
arch/x86/include/asm/atomic64_64.h +12 -3
@@ -19,7 +19,7 @@*/ static inline s64 arch_atomic64_read (const atomic64_t *v) { -return READ_ONCE ((v)->counter); +return __READ_ONCE_SCALAR ((v)->counter); }/**
@@ -31,7 +31,7 @@ static inline s64 arch_atomic64_read(con*/ static inline void arch_atomic64_set (atomic64_t *v,s64 i) { -WRITE_ONCE (v->counter, i); +__WRITE_ONCE_SCALAR (v->counter, i); }/**
@@ -159,37 +159,43 @@ static __always_inline s64 arch_atomic64 {return i +xadd (&v->counter, i); } +#define arch_atomic64_add_return arch_atomic64_add_returnstatic inline s64 arch_atomic64_sub_return (s64 i,atomic64_t *v) {return arch_atomic64_add_return (-i, v); } +#define arch_atomic64_sub_return arch_atomic64_sub_returnstatic inline s64 arch_atomic64_fetch_add (s64 i,atomic64_t *v) {return xadd (&v->counter, i); } +#define arch_atomic64_fetch_add arch_atomic64_fetch_addstatic inline s64 arch_atomic64_fetch_sub (s64 i,atomic64_t *v) {return xadd (&v->counter, -i); } +#define arch_atomic64_fetch_sub arch_atomic64_fetch_substatic inline s64 arch_atomic64_cmpxchg (atomic64_t *v,s64 old,s64 new) {return arch_cmpxchg (&v->counter, old, new); } +#define arch_atomic64_cmpxchg arch_atomic64_cmpxchg -#define arch_atomic64_try_cmpxchg arch_atomic64_try_cmpxchg static __always_inline bool arch_atomic64_try_cmpxchg(atomic64_t *v, s64 *old, s64 new) {return try_cmpxchg (&v->counter, old, new); } +#define arch_atomic64_try_cmpxchg arch_atomic64_try_cmpxchgstatic inline s64 arch_atomic64_xchg (atomic64_t *v,s64 new) {return arch_xchg (&v->counter, new); } +#define arch_atomic64_xchg arch_atomic64_xchgstatic inline void arch_atomic64_and (s64 i,atomic64_t *v) {
@@ -207,6 +213,7 @@ static inline s64 arch_atomic64_fetch_an }while (!arch_atomic64_try_cmpxchg (v, &val, val & i));return val; } +#define arch_atomic64_fetch_and arch_atomic64_fetch_andstatic inline void arch_atomic64_or (s64 i,atomic64_t *v) {
@@ -224,6 +231,7 @@ static inline s64 arch_atomic64_fetch_or }while (!arch_atomic64_try_cmpxchg (v, &val, val | i));return val; } +#define arch_atomic64_fetch_or arch_atomic64_fetch_orstatic inline void arch_atomic64_xor (s64 i,atomic64_t *v) {
@@ -241,5 +249,6 @@ static inline s64 arch_atomic64_fetch_xo } while (!arch_atomic64_try_cmpxchg(v, &val, val ^ i));return val; } +#define arch_atomic64_fetch_xor arch_atomic64_fetch_xor#endif /* _ASM_X86_ATOMIC64_64_H */
include/linux/atomic-arch-fallback.h new file +2291 -0
2,291 lines not on this page · raw message
include/linux/atomic-fallback.h +1 -7
@@ -1180,9 +1180,6 @@ atomic_dec_if_positive(atomic_t *v)#define atomic_dec_if_positive atomic_dec_if_positive#endif -#define atomic_cond_read_acquire (v, c) smp_cond_load_acquire(&(v)->counter, (c)) -#define atomic_cond_read_relaxed (v, c) smp_cond_load_relaxed(&(v)->counter, (c)) -#ifdef CONFIG_GENERIC_ATOMIC64 #include <asm-generic/atomic64.h> #endif
@@ -2290,8 +2287,5 @@ atomic64_dec_if_positive(atomic64_t *v)#define atomic64_dec_if_positive atomic64_dec_if_positive#endif -#define atomic64_cond_read_acquire (v, c) smp_cond_load_acquire(&(v)->counter, (c)) -#define atomic64_cond_read_relaxed (v, c) smp_cond_load_relaxed(&(v)->counter, (c)) -#endif /* _LINUX_ATOMIC_FALLBACK_H */ -// baaf45f4c24ed88ceae58baca39d7fd80bb8101b +// 1fac0941c79bf0ae100723cc2ac9b94061f0b67a
include/linux/atomic.h +11 -0
@@ -25,6 +25,12 @@* See Documentation/memory-barriers.txt for ACQUIRE/RELEASE definitions. */ +#define atomic_cond_read_acquire (v, c) smp_cond_load_acquire(&(v)->counter, (c)) +#define atomic_cond_read_relaxed (v, c) smp_cond_load_relaxed(&(v)->counter, (c)) + +#define atomic64_cond_read_acquire (v, c) smp_cond_load_acquire(&(v)->counter, (c)) +#define atomic64_cond_read_relaxed (v, c) smp_cond_load_relaxed(&(v)->counter, (c)) +/* * The idea here is to build acquire/release variants by adding explicit * barriers on top of the relaxed variant. In the case where the relaxed
@@ -71,7 +77,12 @@ __ret; \ }) +#ifdef ARCH_ATOMIC +#include <linux/atomic-arch-fallback.h> +#include <asm-generic/atomic-instrumented.h> +#else #include <linux/atomic-fallback.h> +#endif #include <asm-generic/atomic-long.h>
scripts/atomic/fallbacks/acquire +2 -2
@@ -1,8 +1,8 @@ cat <<EOF static __always_inline ${ret} -${atomic}_${pfx}${name}${sfx}_acquire(${params}) +${arch}${atomic}_${pfx}${name}${sfx}_acquire(${params}) { - ${ret} ret = ${atomic}_${pfx}${name}${sfx}_relaxed(${args}); + ${ret} ret = ${arch}${atomic}_${pfx}${name}${sfx}_relaxed(${args}); __atomic_acquire_fence(); return ret; }
scripts/atomic/fallbacks/add_negative +3 -3
@@ -1,6 +1,6 @@ cat <<EOF /** - * ${atomic}_add_negative - add and test if negative + * ${arch}${atomic}_add_negative - add and test if negative * @i: integer value to add * @v: pointer of type ${atomic}_t *
@@ -9,8 +9,8 @@ cat <<EOF * result is greater than or equal to zero. */ static __always_inline bool -${atomic}_add_negative(${int} i, ${atomic}_t *v) +${arch}${atomic}_add_negative(${int} i, ${atomic}_t *v) { - return ${atomic}_add_return(i, v) < 0; + return ${arch}${atomic}_add_return(i, v) < 0; } EOF
scripts/atomic/fallbacks/add_unless +3 -3
@@ -1,6 +1,6 @@ cat << EOF /** - * ${atomic}_add_unless - add unless the number is already a given value + * ${arch}${atomic}_add_unless - add unless the number is already a given value * @v: pointer of type ${atomic}_t * @a: the amount to add to v... * @u: ...unless v is equal to u.
@@ -9,8 +9,8 @@ cat << EOF * Returns true if the addition was done. */ static __always_inline bool -${atomic}_add_unless(${atomic}_t *v, ${int} a, ${int} u) +${arch}${atomic}_add_unless(${atomic}_t *v, ${int} a, ${int} u) { - return ${atomic}_fetch_add_unless(v, a, u) != u; + return ${arch}${atomic}_fetch_add_unless(v, a, u) != u; } EOF
scripts/atomic/fallbacks/andnot +2 -2
@@ -1,7 +1,7 @@ cat <<EOF static __always_inline ${ret} -${atomic}_${pfx}andnot${sfx}${order}(${int} i, ${atomic}_t *v) +${arch}${atomic}_${pfx}andnot${sfx}${order}(${int} i, ${atomic}_t *v) { - ${retstmt}${atomic}_${pfx}and${sfx}${order}(~i, v); + ${retstmt}${arch}${atomic}_${pfx}and${sfx}${order}(~i, v); } EOF
scripts/atomic/fallbacks/dec +2 -2
@@ -1,7 +1,7 @@ cat <<EOF static __always_inline ${ret} -${atomic}_${pfx}dec${sfx}${order}(${atomic}_t *v) +${arch}${atomic}_${pfx}dec${sfx}${order}(${atomic}_t *v) { - ${retstmt}${atomic}_${pfx}sub${sfx}${order}(1, v); + ${retstmt}${arch}${atomic}_${pfx}sub${sfx}${order}(1, v); } EOF
scripts/atomic/fallbacks/dec_and_test +3 -3
@@ -1,6 +1,6 @@ cat <<EOF /** - * ${atomic}_dec_and_test - decrement and test + * ${arch}${atomic}_dec_and_test - decrement and test * @v: pointer of type ${atomic}_t * * Atomically decrements @v by 1 and
@@ -8,8 +8,8 @@ cat <<EOF * cases. */ static __always_inline bool -${atomic}_dec_and_test(${atomic}_t *v) +${arch}${atomic}_dec_and_test(${atomic}_t *v) { - return ${atomic}_dec_return(v) == 0; + return ${arch}${atomic}_dec_return(v) == 0; } EOF
scripts/atomic/fallbacks/dec_if_positive +3 -3
@@ -1,14 +1,14 @@ cat <<EOF static __always_inline ${ret} -${atomic}_dec_if_positive(${atomic}_t *v) +${arch}${atomic}_dec_if_positive(${atomic}_t *v) { - ${int} dec, c = ${atomic}_read(v); + ${int} dec, c = ${arch}${atomic}_read(v); do { dec = c - 1; if (unlikely(dec < 0)) break; - } while (!${atomic}_try_cmpxchg(v, &c, dec)); + } while (!${arch}${atomic}_try_cmpxchg(v, &c, dec)); return dec; }
scripts/atomic/fallbacks/dec_unless_positive +3 -3
@@ -1,13 +1,13 @@ cat <<EOF static __always_inline bool -${atomic}_dec_unless_positive(${atomic}_t *v) +${arch}${atomic}_dec_unless_positive(${atomic}_t *v) { - ${int} c = ${atomic}_read(v); + ${int} c = ${arch}${atomic}_read(v); do { if (unlikely(c > 0)) return false; - } while (!${atomic}_try_cmpxchg(v, &c, c - 1)); + } while (!${arch}${atomic}_try_cmpxchg(v, &c, c - 1)); return true; }
scripts/atomic/fallbacks/fence +2 -2
@@ -1,10 +1,10 @@ cat <<EOF static __always_inline ${ret} -${atomic}_${pfx}${name}${sfx}(${params}) +${arch}${atomic}_${pfx}${name}${sfx}(${params}) { ${ret} ret; __atomic_pre_full_fence(); - ret = ${atomic}_${pfx}${name}${sfx}_relaxed(${args}); + ret = ${arch}${atomic}_${pfx}${name}${sfx}_relaxed(${args}); __atomic_post_full_fence(); return ret; }
scripts/atomic/fallbacks/fetch_add_unless +4 -4
@@ -1,6 +1,6 @@ cat << EOF /** - * ${atomic}_fetch_add_unless - add unless the number is already a given value + * ${arch}${atomic}_fetch_add_unless - add unless the number is already a given value * @v: pointer of type ${atomic}_t * @a: the amount to add to v... * @u: ...unless v is equal to u.
@@ -9,14 +9,14 @@ cat << EOF * Returns original value of @v */ static __always_inline ${int} -${atomic}_fetch_add_unless(${atomic}_t *v, ${int} a, ${int} u) +${arch}${atomic}_fetch_add_unless(${atomic}_t *v, ${int} a, ${int} u) { - ${int} c = ${atomic}_read(v); + ${int} c = ${arch}${atomic}_read(v); do { if (unlikely(c == u)) break; - } while (!${atomic}_try_cmpxchg(v, &c, c + a)); + } while (!${arch}${atomic}_try_cmpxchg(v, &c, c + a)); return c; }
scripts/atomic/fallbacks/inc +2 -2
@@ -1,7 +1,7 @@ cat <<EOF static __always_inline ${ret} -${atomic}_${pfx}inc${sfx}${order}(${atomic}_t *v) +${arch}${atomic}_${pfx}inc${sfx}${order}(${atomic}_t *v) { - ${retstmt}${atomic}_${pfx}add${sfx}${order}(1, v); + ${retstmt}${arch}${atomic}_${pfx}add${sfx}${order}(1, v); } EOF
scripts/atomic/fallbacks/inc_and_test +3 -3
@@ -1,6 +1,6 @@ cat <<EOF /** - * ${atomic}_inc_and_test - increment and test + * ${arch}${atomic}_inc_and_test - increment and test * @v: pointer of type ${atomic}_t * * Atomically increments @v by 1
@@ -8,8 +8,8 @@ cat <<EOF * other cases. */ static __always_inline bool -${atomic}_inc_and_test(${atomic}_t *v) +${arch}${atomic}_inc_and_test(${atomic}_t *v) { - return ${atomic}_inc_return(v) == 0; + return ${arch}${atomic}_inc_return(v) == 0; } EOF
scripts/atomic/fallbacks/inc_not_zero +3 -3
@@ -1,14 +1,14 @@ cat <<EOF /** - * ${atomic}_inc_not_zero - increment unless the number is zero + * ${arch}${atomic}_inc_not_zero - increment unless the number is zero * @v: pointer of type ${atomic}_t * * Atomically increments @v by 1, if @v is non-zero. * Returns true if the increment was done. */ static __always_inline bool -${atomic}_inc_not_zero(${atomic}_t *v) +${arch}${atomic}_inc_not_zero(${atomic}_t *v) { - return ${atomic}_add_unless(v, 1, 0); + return ${arch}${atomic}_add_unless(v, 1, 0); } EOF
scripts/atomic/fallbacks/inc_unless_negative +3 -3
@@ -1,13 +1,13 @@ cat <<EOF static __always_inline bool -${atomic}_inc_unless_negative(${atomic}_t *v) +${arch}${atomic}_inc_unless_negative(${atomic}_t *v) { - ${int} c = ${atomic}_read(v); + ${int} c = ${arch}${atomic}_read(v); do { if (unlikely(c < 0)) return false; - } while (!${atomic}_try_cmpxchg(v, &c, c + 1)); + } while (!${arch}${atomic}_try_cmpxchg(v, &c, c + 1)); return true; }
scripts/atomic/fallbacks/read_acquire +1 -1
@@ -1,6 +1,6 @@ cat <<EOF static __always_inline ${ret} -${atomic}_read_acquire(const ${atomic}_t *v) +${arch}${atomic}_read_acquire(const ${atomic}_t *v) { return smp_load_acquire(&(v)->counter); }
scripts/atomic/fallbacks/release +2 -2
@@ -1,8 +1,8 @@ cat <<EOF static __always_inline ${ret} -${atomic}_${pfx}${name}${sfx}_release(${params}) +${arch}${atomic}_${pfx}${name}${sfx}_release(${params}) { __atomic_release_fence(); - ${retstmt}${atomic}_${pfx}${name}${sfx}_relaxed(${args}); + ${retstmt}${arch}${atomic}_${pfx}${name}${sfx}_relaxed(${args}); } EOF
scripts/atomic/fallbacks/set_release +1 -1
@@ -1,6 +1,6 @@ cat <<EOF static __always_inline void -${atomic}_set_release(${atomic}_t *v, ${int} i) +${arch}${atomic}_set_release(${atomic}_t *v, ${int} i) { smp_store_release(&(v)->counter, i); }
scripts/atomic/fallbacks/sub_and_test +3 -3
@@ -1,6 +1,6 @@ cat <<EOF /** - * ${atomic}_sub_and_test - subtract value from variable and test result + * ${arch}${atomic}_sub_and_test - subtract value from variable and test result * @i: integer value to subtract * @v: pointer of type ${atomic}_t *
@@ -9,8 +9,8 @@ cat <<EOF * other cases. */ static __always_inline bool -${atomic}_sub_and_test(${int} i, ${atomic}_t *v) +${arch}${atomic}_sub_and_test(${int} i, ${atomic}_t *v) { - return ${atomic}_sub_return(i, v) == 0; + return ${arch}${atomic}_sub_return(i, v) == 0; } EOF
scripts/atomic/fallbacks/try_cmpxchg +2 -2
@@ -1,9 +1,9 @@ cat <<EOF static __always_inline bool -${atomic}_try_cmpxchg${order}(${atomic}_t *v, ${int} *old, ${int} new) +${arch}${atomic}_try_cmpxchg${order}(${atomic}_t *v, ${int} *old, ${int} new) { ${int} r, o = *old; - r = ${atomic}_cmpxchg${order}(v, o, new); + r = ${arch}${atomic}_cmpxchg${order}(v, o, new); if (unlikely(r != o)) *old = r; return likely(r == o);
scripts/atomic/gen-atomic-fallback.sh +13 -16
@@ -2,10 +2,11 @@ # SPDX-License-Identifier: GPL-2.0 ATOMICDIR=$(dirname $0) +ARCH=$2 . ${ATOMICDIR}/atomic-tbl.sh -#gen_template_fallback(template, meta, pfx, name, sfx, order, atomic, int, args...) +#gen_template_fallback(template, meta, pfx, name, sfx, order, arch, atomic, int, args...) gen_template_fallback() { local template="$1"; shift
@@ -14,10 +15,11 @@ gen_template_fallback() local name="$1"; shift local sfx="$1"; shift local order="$1"; shift + local arch="$1"; shift local atomic="$1"; shift local int="$1"; shift - local atomicname="${atomic}_${pfx}${name}${sfx}${order}" + local atomicname="${arch}${atomic}_${pfx}${name}${sfx}${order}" local ret="$(gen_ret_type "${meta}" "${int}")" local retstmt="$(gen_ret_stmt "${meta}")"
@@ -32,7 +34,7 @@ gen_template_fallback() fi } -#gen_proto_fallback(meta, pfx, name, sfx, order, atomic, int, args...) +#gen_proto_fallback(meta, pfx, name, sfx, order, arch, atomic, int, args...) gen_proto_fallback() { local meta="$1"; shift
@@ -56,16 +58,17 @@ cat << EOF EOF } -#gen_proto_order_variants(meta, pfx, name, sfx, atomic, int, args...) +#gen_proto_order_variants(meta, pfx, name, sfx, arch, atomic, int, args...) gen_proto_order_variants() { local meta="$1"; shift local pfx="$1"; shift local name="$1"; shift local sfx="$1"; shift - local atomic="$1" + local arch="$1" + local atomic="$2" - local basename="${atomic}_${pfx}${name}${sfx}" + local basename="${arch}${atomic}_${pfx}${name}${sfx}" local template="$(find_fallback_template "${pfx}" "${name}" "${sfx}" "${order}")"
@@ -94,7 +97,7 @@ gen_proto_order_variants() gen_basic_fallbacks "${basename}" if [ ! -z "${template}" ]; then - printf "#endif /* ${atomic}_${pfx}${name}${sfx} */\n\n" + printf "#endif /* ${arch}${atomic}_${pfx}${name}${sfx} */\n\n" gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "" "$@" gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "_acquire" "$@" gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "_release" "$@"
@@ -153,18 +156,15 @@ cat << EOF EOF -for xchg in "xchg" "cmpxchg" "cmpxchg64"; do +for xchg in "${ARCH}xchg" "${ARCH}cmpxchg" "${ARCH}cmpxchg64"; do gen_xchg_fallbacks "${xchg}" done grep '^[a-z]' "$1" | while read name meta args; do - gen_proto "${meta}" "${name}" "atomic" "int" ${args} + gen_proto "${meta}" "${name}" "${ARCH}" "atomic" "int" ${args} done cat <<EOF -#define atomic_cond_read_acquire(v, c) smp_cond_load_acquire(&(v)->counter, (c)) -#define atomic_cond_read_relaxed(v, c) smp_cond_load_relaxed(&(v)->counter, (c)) - #ifdef CONFIG_GENERIC_ATOMIC64 #include <asm-generic/atomic64.h> #endif
@@ -172,12 +172,9 @@ cat <<EOF EOF grep '^[a-z]' "$1" | while read name meta args; do - gen_proto "${meta}" "${name}" "atomic64" "s64" ${args} + gen_proto "${meta}" "${name}" "${ARCH}" "atomic64" "s64" ${args} done cat <<EOF -#define atomic64_cond_read_acquire(v, c) smp_cond_load_acquire(&(v)->counter, (c)) -#define atomic64_cond_read_relaxed(v, c) smp_cond_load_relaxed(&(v)->counter, (c)) - #endif /* _LINUX_ATOMIC_FALLBACK_H */ EOF
scripts/atomic/gen-atomics.sh +3 -2
@@ -10,10 +10,11 @@ LINUXDIR=${ATOMICDIR}/../.. cat <<EOF | gen-atomic-instrumented.sh asm-generic/atomic-instrumented.h gen-atomic-long.sh asm-generic/atomic-long.h +gen-atomic-fallback.sh linux/atomic-arch-fallback.h arch_ gen-atomic-fallback.sh linux/atomic-fallback.h EOF -while read script header; do - /bin/sh ${ATOMICDIR}/${script} ${ATOMICTBL} > ${LINUXDIR}/include/${header} +while read script header args; do + /bin/sh ${ATOMICDIR}/${script} ${ATOMICTBL} ${args} > ${LINUXDIR}/include/${header} HASH="$(sha1sum ${LINUXDIR}/include/${header})" HASH="${HASH%% *}" printf "// %s\n" "${HASH}" >> ${LINUXDIR}/include/${header}
Peter Zijlstra
maintainerPATCH v4 24/27 x86/int3: Avoid atomic instrumentation
In reply to Peter ZijlstraUse arch_atomic_*() and READ_ONCE_NOCHECK() to ensure nothing untoward creeps in and ruins things.
That is; this is the INT3 text poke handler, strictly limit the code that runs in it, lest we inadvertenly hit yet another INT3.
--- arch/x86/kernel/alternative.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
arch/x86/kernel/alternative.c +3 -3
@@ -960,9 +960,9 @@ static struct bp_patching_desc *bp_desc;static __always_inline struct bp_patching_desc *try_get_desc(struct bp_patching_desc **descp) { -struct bp_patching_desc *desc =READ_ONCE (*descp);/* rcu_dereference */ +struct bp_patching_desc *desc =READ_ONCE_NOCHECK (*descp);/* rcu_dereference */ -if (!desc || !atomic_inc_not_zero (&desc->refs)) +if (!desc || !arch_atomic_inc_not_zero (&desc->refs))return NULL ;return desc;
@@ -971,7 +971,7 @@ struct bp_patching_desc *try_get_desc(st static __always_inline void put_desc(struct bp_patching_desc *desc) {smp_mb__before_atomic (); -atomic_dec (&desc->refs); +arch_atomic_dec (&desc->refs); } static __always_inline void *text_poke_addr(struct text_poke_loc *tp)
Peter Zijlstra
maintainerPATCH v4 25/27 lib/bsearch: Provide __always_inline variant
In reply to Peter ZijlstraFor code that needs the ultimate performance (it can inline the @cmp function too) or simply needs to avoid calling external functions for whatever reason, provide an __always_inline variant of bsearch().
--- arch/x86/kernel/alternative.c | 9 ++++----- include/linux/bsearch.h | 26 ++++++++++++++++++++++++-- lib/bsearch.c | 22 ++-------------------- 3 files changed, 30 insertions(+), 27 deletions(-)
include/linux/bsearch.h +24 -2
@@ -4,7 +4,29 @@#include <linux/types.h> -void *bsearch (const void *key,const void *base,size_t num,size_t size, -cmp_func_t cmp); +static __always_inline +void *__bsearch(const void *key, const void *base, size_t num, size_t size, cmp_func_t cmp) +{ +const char *pivot; +int result; + +while (num >0 ) { + pivot = base + (num >>1 ) * size; + result =cmp (key, pivot); + +if (result ==0 ) +return (void *)pivot; + +if (result >0 ) { + base = pivot + size; + num--; + } + num >>=1 ; + } + +return NULL ; +} + +extern void *bsearch (const void *key,const void *base,size_t num,size_t size,cmp_func_t cmp);#endif /* _LINUX_BSEARCH_H */
lib/bsearch.c +2 -20
@@ -28,27 +28,9 @@* the key and elements in the array are of the same type, you can use * the same comparison function for both sort() and bsearch(). */ -void *bsearch (const void *key,const void *base,size_t num,size_t size, -cmp_func_t cmp) +void *bsearch (const void *key,const void *base,size_t num,size_t size,cmp_func_t cmp) { -const char *pivot; -int result; - -while (num >0 ) { - pivot = base + (num >>1 ) * size; - result =cmp (key, pivot); - -if (result ==0 ) -return (void *)pivot; - -if (result >0 ) { - base = pivot + size; - num--; - } - num >>=1 ; - } - -return NULL ; +return __bsearch (key, base, num, size, cmp); }EXPORT_SYMBOL (bsearch);NOKPROBE_SYMBOL (bsearch);
Peter Zijlstra
maintainerPATCH v4 26/27 x86/int3: Inline bsearch()
In reply to Peter ZijlstraAvoid calling out to bsearch() by inlining it, for normal kernel configs this was the last external call and poke_int3_handler() is now fully self sufficient -- no calls to external code.
--- arch/x86/kernel/alternative.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
arch/x86/kernel/alternative.c +4 -5
@@ -979,7 +979,7 @@ static __always_inline void *text_poke_areturn _stext + tp->rel_addr; } -static int notrace patch_cmp(const void *key, const void *elt) +static __always_inline int patch_cmp(const void *key, const void *elt) {struct text_poke_loc *tp = (struct text_poke_loc *) elt;
@@ -989,7 +989,6 @@ static int notrace patch_cmp(const voidreturn 1 ;return 0 ; } -NOKPROBE_SYMBOL (patch_cmp); int notrace poke_int3_handler(struct pt_regs *regs) {
@@ -1024,9 +1023,9 @@ int notrace poke_int3_handler(struct pt_* Skip the binary search if there is a single member in the vector. */ if (unlikely (desc->nr_entries >1 )) { - tp =bsearch (ip, desc->vec, desc->nr_entries, -sizeof (struct text_poke_loc ), - patch_cmp); + tp =__bsearch (ip, desc->vec, desc->nr_entries, +sizeof (struct text_poke_loc ), + patch_cmp);if (!tp) goto out_put; }else {
Peter Zijlstra
maintainerPATCH v4 27/27 x86/int3: Ensure that poke_int3_handler() is not sanitized
In reply to Peter ZijlstraIn order to ensure poke_int3_handler() is completely self contained -- we call this while we're modifying other text, imagine the fun of hitting another INT3 -- ensure that everything is without sanitize instrumentation.
--- arch/x86/kernel/alternative.c | 2 +- arch/x86/kernel/traps.c | 2 +- include/linux/compiler-clang.h | 7 +++++++ include/linux/compiler-gcc.h | 6 ++++++ include/linux/compiler.h | 5 +++++ include/linux/compiler_attributes.h | 1 + 6 files changed, 21 insertions(+), 2 deletions(-)
arch/x86/kernel/alternative.c +1 -1
@@ -990,7 +990,7 @@ static __always_inline int patch_cmp(conreturn 0 ; } -int notrace poke_int3_handler(struct pt_regs *regs) +notrace __no_sanitize int poke_int3_handler(struct pt_regs *regs) {struct bp_patching_desc *desc;struct text_poke_loc *tp;
arch/x86/kernel/traps.c +1 -1
@@ -502,7 +502,7 @@ dotraplinkage void do_general_protection }NOKPROBE_SYMBOL (do_general_protection); -dotraplinkage notrace void do_int3(struct pt_regs *regs, long error_code) +dotraplinkage notrace __no_sanitize void do_int3(struct pt_regs *regs, long error_code) {if (poke_int3_handler (regs))return ;
include/linux/compiler-clang.h +7 -0
@@ -24,6 +24,13 @@#define __no_sanitize_address#endif +#if __has_feature (undefined_sanitizer) +#define __no_sanitize_undefined \ + __atribute__((no_sanitize("undefined"))) +#else +#define __no_sanitize_undefined +#endif +/* * Not all versions of clang implement the the type-generic versions * of the builtin overflow checkers. Fortunately, clang implements
include/linux/compiler-gcc.h +6 -0
@@ -145,6 +145,12 @@#define __no_sanitize_address#endif +#if __has_attribute (__no_sanitize_undefined__) +#define __no_sanitize_undefined __attribute__((no_sanitize_undefined)) +#else +#define __no_sanitize_undefined +#endif +#if GCC_VERSION >=50100 #define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1#endif
include/linux/compiler.h +5 -0
@@ -199,6 +199,7 @@ void __read_once_size(const volatile voi __READ_ONCE_SIZE; } +#define __no_kasan __no_sanitize_address#ifdef CONFIG_KASAN /* * We can't declare function 'inline' because __no_sanitize_address confilcts
@@ -274,6 +275,10 @@ static __always_inline void __write_once*/ #define READ_ONCE_NOCHECK (x) __READ_ONCE(x, 0) +#define __no_ubsan __no_sanitize_undefined + +#define __no_sanitize __no_kasan __no_ubsan +static __no_kasan_or_inline unsigned long read_word_at_a_time (const void *addr) {
include/linux/compiler_attributes.h +1 -0
@@ -41,6 +41,7 @@# define __GCC4_has_attribute___nonstring__ 0# define __GCC4_has_attribute___no_sanitize_address__ (__GNUC_MINOR__ >= 8)# define __GCC4_has_attribute___fallthrough__ 0 +# define __GCC4_has_attribute___no_sanitize_undefined__ (__GNUC_MINOR__ >= 9)#endif /*
kbuild test robot
build botRe: [PATCH v4 27/27] x86/int3: Ensure that poke_int3_handler() is not sanitized
I love your patch! Yet something to improve:
Hi Peter,
I love your patch! Yet something to improve:
[auto build test ERROR on tip/perf/core]
[also build test ERROR on linus/master v5.6-rc2]
[cannot apply to tip/x86/core rcu/dev next-20200221]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system. BTW, we also suggest to use '--base' option to specify the base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
url: https://github.com/0day-ci/linux/commits/Peter-Zijlstra/tracing-vs-world/20200223-012357 base: https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git fdb64822443ec9fb8c3a74b598a74790ae8d2e22 config: x86_64-randconfig-s2-20200223 (attached as .config) compiler: gcc-4.9 (Debian 4.9.2-10+deb8u1) 4.9.2 reproduce: # save the attached .config to linux build tree make ARCH=x86_64
If you fix the issue, kindly add following tag
All errors (new ones prefixed by >>):
In file included from arch/x86/include/asm/math_emu.h:5:0,
from arch/x86/include/asm/processor.h:13,
from arch/x86/include/asm/cpufeature.h:5,
from arch/x86/include/asm/thread_info.h:53,
from include/linux/thread_info.h:38,
from arch/x86/include/asm/preempt.h:7,
from include/linux/preempt.h:78,
from include/linux/spinlock.h:51,
from include/linux/seqlock.h:36,
from include/linux/time.h:6,
from include/linux/stat.h:19,
from include/linux/module.h:13,
from arch/x86/kernel/alternative.c:4:
arch/x86/kernel/alternative.c: In function 'poke_int3_handler':
arch/x86/include/asm/ptrace.h:126:28: error: inlining failed in call to always_inline 'user_mode.isra.1': function attribute mismatch
static __always_inline int user_mode(struct pt_regs *regs)
^
arch/x86/kernel/alternative.c:1000:6: error: called from here
if (user_mode(regs))
^
>> arch/x86/kernel/alternative.c:961:26: error: inlining failed in call to always_inline 'try_get_desc.constprop': function attribute mismatch
struct bp_patching_desc *try_get_desc(struct bp_patching_desc **descp)
^
arch/x86/kernel/alternative.c:1013:7: error: called from here
desc = try_get_desc(&bp_desc);
^
In file included from arch/x86/kernel/alternative.c:17:0:
include/linux/bsearch.h:8:7: error: inlining failed in call to always_inline '__bsearch.constprop': function attribute mismatch
void *__bsearch(const void *key, const void *base, size_t num, size_t size, cmp_func_t cmp)
^
arch/x86/kernel/alternative.c:1026:6: error: called from here
tp = __bsearch(ip, desc->vec, desc->nr_entries,
^
arch/x86/kernel/alternative.c:977:30: error: inlining failed in call to always_inline 'text_poke_addr.isra.6': function attribute mismatch
static __always_inline void *text_poke_addr(struct text_poke_loc *tp)
^
arch/x86/kernel/alternative.c:1033:7: error: called from here
if (text_poke_addr(tp) != ip)
^
In file included from arch/x86/include/asm/kprobes.h:18:0,
from include/linux/kprobes.h:30,
from arch/x86/kernel/alternative.c:15:
arch/x86/include/asm/text-patching.h:67:28: error: inlining failed in call to always_inline 'text_opcode_size': function attribute mismatch
static __always_inline int text_opcode_size(u8 opcode)
^
arch/x86/kernel/alternative.c:1037:6: error: called from here
len = text_opcode_size(tp->opcode);
^
In file included from arch/x86/include/asm/kprobes.h:18:0,
from include/linux/kprobes.h:30,
from arch/x86/kernel/alternative.c:15:
arch/x86/include/asm/text-patching.h:144:6: error: inlining failed in call to always_inline 'int3_emulate_call': function attribute mismatch
void int3_emulate_call(struct pt_regs *regs, unsigned long func)
^
arch/x86/kernel/alternative.c:1049:3: error: called from here
int3_emulate_call(regs, (long)ip + tp->rel32);
^
In file included from arch/x86/include/asm/kprobes.h:18:0,
from include/linux/kprobes.h:30,
from arch/x86/kernel/alternative.c:15:
arch/x86/include/asm/text-patching.h:122:6: error: inlining failed in call to always_inline 'int3_emulate_jmp.isra.4': function attribute mismatch
void int3_emulate_jmp(struct pt_regs *regs, unsigned long ip)
^
arch/x86/kernel/alternative.c:1054:3: error: called from here
int3_emulate_jmp(regs, (long)ip + tp->rel32);
^
arch/x86/kernel/alternative.c:971:29: error: inlining failed in call to always_inline 'put_desc': function attribute mismatch
static __always_inline void put_desc(struct bp_patching_desc *desc)
^
arch/x86/kernel/alternative.c:1064:2: error: called from here
put_desc(desc);
^vim +961 arch/x86/kernel/alternative.c
1f676247f36a4b Peter Zijlstra 2019-12-11 959
fd85274efb2876 Thomas Gleixner 2020-02-21 960 static __always_inline
fd85274efb2876 Thomas Gleixner 2020-02-21 @961 struct bp_patching_desc *try_get_desc(struct bp_patching_desc **descp)
1f676247f36a4b Peter Zijlstra 2019-12-11 962 {
2a78c27ec07053 Peter Zijlstra 2020-02-21 963 struct bp_patching_desc *desc = READ_ONCE_NOCHECK(*descp); /* rcu_dereference */
1f676247f36a4b Peter Zijlstra 2019-12-11 964
2a78c27ec07053 Peter Zijlstra 2020-02-21 965 if (!desc || !arch_atomic_inc_not_zero(&desc->refs))
1f676247f36a4b Peter Zijlstra 2019-12-11 966 return NULL;
1f676247f36a4b Peter Zijlstra 2019-12-11 967
1f676247f36a4b Peter Zijlstra 2019-12-11 968 return desc;
1f676247f36a4b Peter Zijlstra 2019-12-11 969 }
1f676247f36a4b Peter Zijlstra 2019-12-11 970 :::::: The code at line 961 was first introduced by commit
:::::: fd85274efb2876ccb2c8f8c5a413910ac0edc08d x86/int3: Ensure that poke_int3_handler() is not traced
:::::: TO: Thomas Gleixner <[email protected]>
:::::: CC: 0day robot <[email protected]>
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org