Message ID | 20250206105435.2159977-23-memxor@gmail.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | Resilient Queued Spin Lock | expand |
Hi Kumar, kernel test robot noticed the following build errors: [auto build test ERROR on 0abff462d802a352c87b7f5e71b442b09bf9cfff] url: https://github.com/intel-lab-lkp/linux/commits/Kumar-Kartikeya-Dwivedi/locking-Move-MCS-struct-definition-to-public-header/20250206-190258 base: 0abff462d802a352c87b7f5e71b442b09bf9cfff patch link: https://lore.kernel.org/r/20250206105435.2159977-23-memxor%40gmail.com patch subject: [PATCH bpf-next v2 22/26] bpf: Introduce rqspinlock kfuncs config: x86_64-buildonly-randconfig-004-20250207 (https://download.01.org/0day-ci/archive/20250207/202502072155.DbOeX8Le-lkp@intel.com/config) compiler: clang version 19.1.3 (https://github.com/llvm/llvm-project ab51eccf88f5321e7c60591c5546b254b6afab99) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250207/202502072155.DbOeX8Le-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202502072155.DbOeX8Le-lkp@intel.com/ All errors (new ones prefixed by >>): In file included from fs/timerfd.c:26: In file included from include/linux/syscalls.h:94: In file included from include/trace/syscall.h:7: In file included from include/linux/trace_events.h:10: In file included from include/linux/perf_event.h:62: In file included from include/linux/security.h:35: In file included from include/linux/bpf.h:33: In file included from arch/x86/include/asm/rqspinlock.h:27: >> include/asm-generic/rqspinlock.h:40:12: error: conflicting types for 'resilient_tas_spin_lock' 40 | extern int resilient_tas_spin_lock(rqspinlock_t *lock, u64 timeout); | ^ arch/x86/include/asm/rqspinlock.h:17:12: note: previous declaration is here 17 | extern int resilient_tas_spin_lock(struct qspinlock *lock, u64 timeout); | ^ 1 error generated. -- In file included from fs/splice.c:27: include/linux/mm_inline.h:47:41: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion] 47 | __mod_lruvec_state(lruvec, NR_LRU_BASE + lru, nr_pages); | ~~~~~~~~~~~ ^ ~~~ include/linux/mm_inline.h:49:22: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum lru_list') [-Wenum-enum-conversion] 49 | NR_ZONE_LRU_BASE + lru, nr_pages); | ~~~~~~~~~~~~~~~~ ^ ~~~ In file included from fs/splice.c:31: In file included from include/linux/syscalls.h:94: In file included from include/trace/syscall.h:7: In file included from include/linux/trace_events.h:10: In file included from include/linux/perf_event.h:62: In file included from include/linux/security.h:35: In file included from include/linux/bpf.h:33: In file included from arch/x86/include/asm/rqspinlock.h:27: >> include/asm-generic/rqspinlock.h:40:12: error: conflicting types for 'resilient_tas_spin_lock' 40 | extern int resilient_tas_spin_lock(rqspinlock_t *lock, u64 timeout); | ^ arch/x86/include/asm/rqspinlock.h:17:12: note: previous declaration is here 17 | extern int resilient_tas_spin_lock(struct qspinlock *lock, u64 timeout); | ^ 2 warnings and 1 error generated. -- In file included from fs/aio.c:20: In file included from include/linux/syscalls.h:94: In file included from include/trace/syscall.h:7: In file included from include/linux/trace_events.h:10: In file included from include/linux/perf_event.h:62: In file included from include/linux/security.h:35: In file included from include/linux/bpf.h:33: In file included from arch/x86/include/asm/rqspinlock.h:27: >> include/asm-generic/rqspinlock.h:40:12: error: conflicting types for 'resilient_tas_spin_lock' 40 | extern int resilient_tas_spin_lock(rqspinlock_t *lock, u64 timeout); | ^ arch/x86/include/asm/rqspinlock.h:17:12: note: previous declaration is here 17 | extern int resilient_tas_spin_lock(struct qspinlock *lock, u64 timeout); | ^ In file included from fs/aio.c:29: include/linux/mman.h:159:9: warning: division by zero is undefined [-Wdivision-by-zero] 159 | _calc_vm_trans(flags, MAP_SYNC, VM_SYNC ) | | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/mman.h:137:21: note: expanded from macro '_calc_vm_trans' 137 | : ((x) & (bit1)) / ((bit1) / (bit2)))) | ^ ~~~~~~~~~~~~~~~~~ include/linux/mman.h:160:9: warning: division by zero is undefined [-Wdivision-by-zero] 160 | _calc_vm_trans(flags, MAP_STACK, VM_NOHUGEPAGE) | | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/mman.h:137:21: note: expanded from macro '_calc_vm_trans' 137 | : ((x) & (bit1)) / ((bit1) / (bit2)))) | ^ ~~~~~~~~~~~~~~~~~ 2 warnings and 1 error generated. vim +/resilient_tas_spin_lock +40 include/asm-generic/rqspinlock.h c34e46edef2a89 Kumar Kartikeya Dwivedi 2025-02-06 39 7a9d3b27f7bf9c Kumar Kartikeya Dwivedi 2025-02-06 @40 extern int resilient_tas_spin_lock(rqspinlock_t *lock, u64 timeout); 7a9d3b27f7bf9c Kumar Kartikeya Dwivedi 2025-02-06 41 #ifdef CONFIG_QUEUED_SPINLOCKS 6516ce00a1482f Kumar Kartikeya Dwivedi 2025-02-06 42 extern int resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val, u64 timeout); 7a9d3b27f7bf9c Kumar Kartikeya Dwivedi 2025-02-06 43 #endif 6516ce00a1482f Kumar Kartikeya Dwivedi 2025-02-06 44
diff --git a/include/asm-generic/rqspinlock.h b/include/asm-generic/rqspinlock.h index 46119fc768b8..8249c2da09ad 100644 --- a/include/asm-generic/rqspinlock.h +++ b/include/asm-generic/rqspinlock.h @@ -23,6 +23,13 @@ struct rqspinlock { }; }; +/* Even though this is same as struct rqspinlock, we need to emit a distinct + * type in BTF for BPF programs. + */ +struct bpf_res_spin_lock { + u32 val; +}; + struct qspinlock; #ifdef CONFIG_QUEUED_SPINLOCKS typedef struct qspinlock rqspinlock_t; diff --git a/include/linux/bpf.h b/include/linux/bpf.h index f3f50e29d639..35af09ee6a2c 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -30,6 +30,7 @@ #include <linux/static_call.h> #include <linux/memcontrol.h> #include <linux/cfi.h> +#include <asm/rqspinlock.h> struct bpf_verifier_env; struct bpf_verifier_log; diff --git a/kernel/locking/rqspinlock.c b/kernel/locking/rqspinlock.c index b4cceeecf29c..d05333203671 100644 --- a/kernel/locking/rqspinlock.c +++ b/kernel/locking/rqspinlock.c @@ -15,6 +15,8 @@ #include <linux/smp.h> #include <linux/bug.h> +#include <linux/bpf.h> +#include <linux/err.h> #include <linux/cpumask.h> #include <linux/percpu.h> #include <linux/hardirq.h> @@ -686,3 +688,79 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val, EXPORT_SYMBOL(resilient_queued_spin_lock_slowpath); #endif /* CONFIG_QUEUED_SPINLOCKS */ + +__bpf_kfunc_start_defs(); + +#define REPORT_STR(ret) ({ ret == -ETIMEDOUT ? "Timeout detected" : "AA or ABBA deadlock detected"; }) + +__bpf_kfunc int bpf_res_spin_lock(struct bpf_res_spin_lock *lock) +{ + int ret; + + BUILD_BUG_ON(sizeof(rqspinlock_t) != sizeof(struct bpf_res_spin_lock)); + BUILD_BUG_ON(__alignof__(rqspinlock_t) != __alignof__(struct bpf_res_spin_lock)); + + preempt_disable(); + ret = res_spin_lock((rqspinlock_t *)lock); + if (unlikely(ret)) { + preempt_enable(); + rqspinlock_report_violation(REPORT_STR(ret), lock); + return ret; + } + return 0; +} + +__bpf_kfunc void bpf_res_spin_unlock(struct bpf_res_spin_lock *lock) +{ + res_spin_unlock((rqspinlock_t *)lock); + preempt_enable(); +} + +__bpf_kfunc int bpf_res_spin_lock_irqsave(struct bpf_res_spin_lock *lock, unsigned long *flags__irq_flag) +{ + u64 *ptr = (u64 *)flags__irq_flag; + unsigned long flags; + int ret; + + preempt_disable(); + local_irq_save(flags); + ret = res_spin_lock((rqspinlock_t *)lock); + if (unlikely(ret)) { + local_irq_restore(flags); + preempt_enable(); + rqspinlock_report_violation(REPORT_STR(ret), lock); + return ret; + } + *ptr = flags; + return 0; +} + +__bpf_kfunc void bpf_res_spin_unlock_irqrestore(struct bpf_res_spin_lock *lock, unsigned long *flags__irq_flag) +{ + u64 *ptr = (u64 *)flags__irq_flag; + unsigned long flags = *ptr; + + res_spin_unlock((rqspinlock_t *)lock); + local_irq_restore(flags); + preempt_enable(); +} + +__bpf_kfunc_end_defs(); + +BTF_KFUNCS_START(rqspinlock_kfunc_ids) +BTF_ID_FLAGS(func, bpf_res_spin_lock, KF_RET_NULL) +BTF_ID_FLAGS(func, bpf_res_spin_unlock) +BTF_ID_FLAGS(func, bpf_res_spin_lock_irqsave, KF_RET_NULL) +BTF_ID_FLAGS(func, bpf_res_spin_unlock_irqrestore) +BTF_KFUNCS_END(rqspinlock_kfunc_ids) + +static const struct btf_kfunc_id_set rqspinlock_kfunc_set = { + .owner = THIS_MODULE, + .set = &rqspinlock_kfunc_ids, +}; + +static __init int rqspinlock_register_kfuncs(void) +{ + return register_btf_kfunc_id_set(BPF_PROG_TYPE_UNSPEC, &rqspinlock_kfunc_set); +} +late_initcall(rqspinlock_register_kfuncs);
Introduce four new kfuncs, bpf_res_spin_lock, and bpf_res_spin_unlock, and their irqsave/irqrestore variants, which wrap the rqspinlock APIs. bpf_res_spin_lock returns a conditional result, depending on whether the lock was acquired (NULL is returned when lock acquisition succeeds, non-NULL upon failure). The memory pointed to by the returned pointer upon failure can be dereferenced after the NULL check to obtain the error code. Instead of using the old bpf_spin_lock type, introduce a new type with the same layout, and the same alignment, but a different name to avoid type confusion. Preemption is disabled upon successful lock acquisition, however IRQs are not. Special kfuncs can be introduced later to allow disabling IRQs when taking a spin lock. Resilient locks are safe against AA deadlocks, hence not disabling IRQs currently does not allow violation of kernel safety. __irq_flag annotation is used to accept IRQ flags for the IRQ-variants, with the same semantics as existing bpf_local_irq_{save, restore}. These kfuncs will require additional verifier-side support in subsequent commits, to allow programs to hold multiple locks at the same time. Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> --- include/asm-generic/rqspinlock.h | 7 +++ include/linux/bpf.h | 1 + kernel/locking/rqspinlock.c | 78 ++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+)