Date: Mon, 24 Aug 2020 12:59:55 +0000 (UTC) From: Emmanuel Vadot <manu@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r364671 - in stable/12/sys: compat/linuxkpi/common/include/linux compat/linuxkpi/common/src conf libkern sys Message-ID: <202008241259.07OCxt1i042570@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: manu Date: Mon Aug 24 12:59:55 2020 New Revision: 364671 URL: https://svnweb.freebsd.org/changeset/base/364671 Log: MFC r361247, r361343, r361418-r361419, r361422, r361449 r361247: linuxkpi: Add irq_work.h Since handlers are call in a thread context we can simply use a workqueue to emulate those functions. The DRM code was patched to do that already, having it in linuxkpi allows us to not patch the upstream code. Sponsored-by: The FreeBSD Foundation Reviewed by: hselasky Differential Revision: https://reviews.freebsd.org/D24859 r361343: linuxkpi: Add rcu_work functions The rcu_work function helps to queue some work after waiting for a grace period. This is needed by DRM drivers. Sponsored-by: The FreeBSD Foundation Reviewed by: hselasky Differential Revision: https://reviews.freebsd.org/D24942 r361418: libkern: Add arc4random_uniform This variant get a random number up to the limit passed as the argument. This is simply a copy of the libc version. Sponsored-by: The FreeBSD Foundation Reviewed by: cem, hselasky (previous version) Differential Revision: https://reviews.freebsd.org/D24962 r361419: linuxkpi: Add prandom_u32_max This is just a wrapper around arc4random_uniform Needed by DRM v5.3 Sponsored-by: The FreeBSD Foundation Reviewed by: cem, hselasky Differential Revision: https://reviews.freebsd.org/D24961 r361422: bbr: Use arc4random_uniform from libkern. This unbreak LINT build Reported by: jenkins, melifaro r361449: linuxkpi: Add __same_type and __must_be_array macros The same_type macro simply wraps around builtin_types_compatible_p which exist for both GCC and CLANG, which returns 1 if both types are the same. The __must_be_array macros returns 1 if the argument is an array. This is needed for DRM v5.3 Sponsored-by: The FreeBSD Foundation Reviewed by: hselasky Differential Revision: https://reviews.freebsd.org/D24953 Added: stable/12/sys/compat/linuxkpi/common/include/linux/irq_work.h - copied unchanged from r361247, head/sys/compat/linuxkpi/common/include/linux/irq_work.h stable/12/sys/libkern/arc4random_uniform.c - copied unchanged from r361419, head/sys/libkern/arc4random_uniform.c Modified: stable/12/sys/compat/linuxkpi/common/include/linux/compiler.h stable/12/sys/compat/linuxkpi/common/include/linux/random.h stable/12/sys/compat/linuxkpi/common/include/linux/workqueue.h stable/12/sys/compat/linuxkpi/common/src/linux_work.c stable/12/sys/conf/files stable/12/sys/sys/libkern.h Directory Properties: stable/12/ (props changed) Modified: stable/12/sys/compat/linuxkpi/common/include/linux/compiler.h ============================================================================== --- stable/12/sys/compat/linuxkpi/common/include/linux/compiler.h Mon Aug 24 12:59:15 2020 (r364670) +++ stable/12/sys/compat/linuxkpi/common/include/linux/compiler.h Mon Aug 24 12:59:55 2020 (r364671) @@ -111,4 +111,7 @@ #define _AT(T,X) ((T)(X)) +#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) +#define __must_be_array(a) __same_type(a, &(a)[0]) + #endif /* _LINUX_COMPILER_H_ */ Copied: stable/12/sys/compat/linuxkpi/common/include/linux/irq_work.h (from r361247, head/sys/compat/linuxkpi/common/include/linux/irq_work.h) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ stable/12/sys/compat/linuxkpi/common/include/linux/irq_work.h Mon Aug 24 12:59:55 2020 (r364671, copy of r361247, head/sys/compat/linuxkpi/common/include/linux/irq_work.h) @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 2020 The FreeBSD Foundation + * + * This software was developed by Emmanuel Vadot under sponsorship + * from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef __LINUX_IRQ_WORK_H__ +#define __LINUX_IRQ_WORK_H__ + +#include <linux/workqueue.h> + +struct irq_work { + struct work_struct work; +}; + +static inline void +init_irq_work(struct irq_work *irqw, void (*func)(struct irq_work *)) +{ + INIT_WORK(&irqw->work, (work_func_t)func); +} + +static inline void +irq_work_queue(struct irq_work *irqw) +{ + schedule_work(&irqw->work); +} + +#endif /* __LINUX_IRQ_WORK_H__ */ Modified: stable/12/sys/compat/linuxkpi/common/include/linux/random.h ============================================================================== --- stable/12/sys/compat/linuxkpi/common/include/linux/random.h Mon Aug 24 12:59:15 2020 (r364670) +++ stable/12/sys/compat/linuxkpi/common/include/linux/random.h Mon Aug 24 12:59:55 2020 (r364671) @@ -63,4 +63,10 @@ get_random_long(void) return (val); } +static inline u32 +prandom_u32_max(u32 max) +{ + return (arc4random_uniform(max)); +} + #endif /* _LINUX_RANDOM_H_ */ Modified: stable/12/sys/compat/linuxkpi/common/include/linux/workqueue.h ============================================================================== --- stable/12/sys/compat/linuxkpi/common/include/linux/workqueue.h Mon Aug 24 12:59:15 2020 (r364670) +++ stable/12/sys/compat/linuxkpi/common/include/linux/workqueue.h Mon Aug 24 12:59:55 2020 (r364671) @@ -72,6 +72,13 @@ struct work_struct { atomic_t state; }; +struct rcu_work { + struct work_struct work; + struct rcu_head rcu; + + struct workqueue_struct *wq; +}; + #define DECLARE_WORK(name, fn) \ struct work_struct name; \ static void name##_init(void *arg) \ @@ -111,6 +118,9 @@ do { \ TASK_INIT(&(work)->work_task, 0, linux_work_fn, (work)); \ } while (0) +#define INIT_RCU_WORK(_work, _fn) \ + INIT_WORK(&(_work)->work, (_fn)) + #define INIT_WORK_ONSTACK(work, fn) \ INIT_WORK(work, fn) @@ -191,6 +201,12 @@ do { \ #define flush_work(work) \ linux_flush_work(work) +#define queue_rcu_work(wq, rwork) \ + linux_queue_rcu_work(wq, rwork) + +#define flush_rcu_work(rwork) \ + linux_flush_rcu_work(rwork) + #define flush_delayed_work(dwork) \ linux_flush_delayed_work(dwork) @@ -236,5 +252,7 @@ extern bool linux_flush_delayed_work(struct delayed_wo extern bool linux_work_pending(struct work_struct *); extern bool linux_work_busy(struct work_struct *); extern struct work_struct *linux_current_work(void); +extern bool linux_queue_rcu_work(struct workqueue_struct *wq, struct rcu_work *rwork); +extern bool linux_flush_rcu_work(struct rcu_work *rwork); #endif /* _LINUX_WORKQUEUE_H_ */ Modified: stable/12/sys/compat/linuxkpi/common/src/linux_work.c ============================================================================== --- stable/12/sys/compat/linuxkpi/common/src/linux_work.c Mon Aug 24 12:59:15 2020 (r364670) +++ stable/12/sys/compat/linuxkpi/common/src/linux_work.c Mon Aug 24 12:59:55 2020 (r364671) @@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$"); #include <linux/wait.h> #include <linux/compat.h> #include <linux/spinlock.h> +#include <linux/rcupdate.h> #include <sys/kernel.h> @@ -153,6 +154,53 @@ linux_queue_work_on(int cpu __unused, struct workqueue default: return (false); /* already on a queue */ } +} + +/* + * Callback func for linux_queue_rcu_work + */ +static void +rcu_work_func(struct rcu_head *rcu) +{ + struct rcu_work *rwork; + + rwork = container_of(rcu, struct rcu_work, rcu); + linux_queue_work_on(WORK_CPU_UNBOUND, rwork->wq, &rwork->work); +} + +/* + * This function queue a work after a grace period + * If the work was already pending it returns false, + * if not it calls call_rcu and returns true. + */ +bool +linux_queue_rcu_work(struct workqueue_struct *wq, struct rcu_work *rwork) +{ + + if (!linux_work_pending(&rwork->work)) { + rwork->wq = wq; + linux_call_rcu(RCU_TYPE_REGULAR, &rwork->rcu, rcu_work_func); + return (true); + } + return (false); +} + +/* + * This function waits for the last execution of a work and then + * flush the work. + * It returns true if the work was pending and we waited, it returns + * false otherwise. + */ +bool +linux_flush_rcu_work(struct rcu_work *rwork) +{ + + if (linux_work_pending(&rwork->work)) { + linux_rcu_barrier(RCU_TYPE_REGULAR); + linux_flush_work(&rwork->work); + return (true); + } + return (linux_flush_work(&rwork->work)); } /* Modified: stable/12/sys/conf/files ============================================================================== --- stable/12/sys/conf/files Mon Aug 24 12:59:15 2020 (r364670) +++ stable/12/sys/conf/files Mon Aug 24 12:59:55 2020 (r364671) @@ -4071,6 +4071,7 @@ kgssapi/gsstest.c optional kgssapi_debug # the file should be moved to conf/files.<arch> from here. # libkern/arc4random.c standard +libkern/arc4random_uniform.c standard crypto/chacha20/chacha.c standard libkern/asprintf.c standard libkern/bcd.c standard Copied: stable/12/sys/libkern/arc4random_uniform.c (from r361419, head/sys/libkern/arc4random_uniform.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ stable/12/sys/libkern/arc4random_uniform.c Mon Aug 24 12:59:55 2020 (r364671, copy of r361419, head/sys/libkern/arc4random_uniform.c) @@ -0,0 +1,58 @@ +/* $OpenBSD: arc4random_uniform.c,v 1.3 2019/01/20 02:59:07 bcook Exp $ */ + +/* + * Copyright (c) 2008, Damien Miller <djm@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#include <sys/types.h> +#include <sys/libkern.h> + +/* + * Calculate a uniformly distributed random number less than upper_bound + * avoiding "modulo bias". + * + * Uniformity is achieved by generating new random numbers until the one + * returned is outside the range [0, 2**32 % upper_bound). This + * guarantees the selected random number will be inside + * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound) + * after reduction modulo upper_bound. + */ +uint32_t +arc4random_uniform(uint32_t upper_bound) +{ + uint32_t r, min; + + if (upper_bound < 2) + return 0; + + /* 2**32 % x == (2**32 - x) % x */ + min = -upper_bound % upper_bound; + + /* + * This could theoretically loop forever but each retry has + * p > 0.5 (worst case, usually far better) of selecting a + * number inside the range we need, so it should rarely need + * to re-roll. + */ + for (;;) { + r = arc4random(); + if (r >= min) + break; + } + + return r % upper_bound; +} Modified: stable/12/sys/sys/libkern.h ============================================================================== --- stable/12/sys/sys/libkern.h Mon Aug 24 12:59:15 2020 (r364670) +++ stable/12/sys/sys/libkern.h Mon Aug 24 12:59:55 2020 (r364671) @@ -127,6 +127,7 @@ extern int arc4rand_iniseed_state; struct malloc_type; uint32_t arc4random(void); void arc4random_buf(void *, size_t); +uint32_t arc4random_uniform(uint32_t); void arc4rand(void *, u_int, int); int timingsafe_bcmp(const void *, const void *, size_t); void *bsearch(const void *, const void *, size_t,
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202008241259.07OCxt1i042570>