From nobody Wed Apr 15 00:01:10 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3689AC00144 for ; Fri, 29 Jul 2022 07:01:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234376AbiG2HBn (ORCPT ); Fri, 29 Jul 2022 03:01:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48174 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231437AbiG2HBi (ORCPT ); Fri, 29 Jul 2022 03:01:38 -0400 Received: from polaris.svanheule.net (polaris.svanheule.net [84.16.241.116]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9BBC31F2E7 for ; Fri, 29 Jul 2022 00:01:37 -0700 (PDT) Received: from terra.. (unknown [IPv6:2a02:a03f:eaf9:8401:aa9f:5d01:1b2a:e3cd]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: sander@svanheule.net) by polaris.svanheule.net (Postfix) with ESMTPSA id 67461302C2C; Fri, 29 Jul 2022 09:01:32 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=svanheule.net; s=mail1707; t=1659078092; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=AofRFvzX6xW4zBEewbV9wBpxI70PpBinQrOT+pLLHig=; b=sgBGRwmVFj9IOMiSTaYFCZoV2K7sXRT/IaivywWU7b2NQ2GQADLol+aZCQs2vopn0Fk5jP BZMks8Tyamw++HXSdG42HgXAEzkZMAfPtYIM2d6ydNBQI5NCiVL/ozRnEuMSDqCwTFiozo rBEWRmjQQr+wCJC0kwOJXXqOA5a1qv6vqVCLlznXuzVsQXLUgOY06f0g/kNSegGJrtQ264 sWtSY32o9jqlGYkhgQCR4cWfQoXJLaBiQ0cxbDQS+dufV7RYDboxvtt+EzsBxN1WWVGYN0 fD1cUwh/fjACjHU6BfXLIaIscTdAMFbE8lbj4sbtUg4xm+yC9xxR7STVpJOE8g== From: Sander Vanheule To: linux-kernel@vger.kernel.org, Andrew Morton Cc: Andy Shevchenko , Brendan Higgins , Dave Hansen , David Gow , Borislav Petkov , Greg Kroah-Hartman , "H . Peter Anvin" , Ingo Molnar , =?UTF-8?q?Ma=C3=ADra=20Canal?= , Marco Elver , Peter Zijlstra , Thomas Gleixner , Valentin Schneider , Yury Norov , Sander Vanheule Subject: [PATCH v5 1/5] x86/cacheinfo: move shared cache map definitions Date: Fri, 29 Jul 2022 09:01:18 +0200 Message-Id: <3181e52cb86b57f3a98dec4aaab8935f14b683a1.1659077534.git.sander@svanheule.net> X-Mailer: git-send-email 2.37.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The maps to keep track of shared caches between CPUs on SMP systems are declared in asm/smp.h, among them specifically cpu_llc_shared_map. These maps are externally defined in cpu/smpboot.c. The latter is only compiled on CONFIG_SMP=3Dy, which means the declared extern symbols from asm/smp.h do not have a corresponding definition on uniprocessor builds. The inline cpu_llc_shared_mask() function from asm/smp.h refers to the map declaration mentioned above. This function is referenced in cacheinfo.c inside for_each_cpu() loop macros, to provide cpumask for the loop. On uniprocessor builds, the symbol for the cpu_llc_shared_map does not exist. However, the current implementation of for_each_cpu() also (wrongly) ignores the provided mask. By sheer luck, the compiler thus optimises out this unused reference to cpu_llc_shared_map, and the linker therefore does not require the cpu_llc_shared_mask to actually exist on uniprocessor builds. Only on SMP bulids does smpboot.o exist to provide the required symbols. To no longer rely on compiler optimisations for successful uniprocessor builds, move the definitions of cpu_llc_shared_map and cpu_l2c_shared_map from smpboot.c to cacheinfo.c. Signed-off-by: Sander Vanheule Cc: Andy Shevchenko Cc: Marco Elver Cc: Greg Kroah-Hartman Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Valentin Schneider Cc: Yury Norov Cc: Ingo Molnar Cc: Borislav Petkov Cc: Dave Hansen Cc: "H. Peter Anvin" Reviewed-by: Ingo Molnar --- Changes since v3: - New patch arch/x86/kernel/cpu/cacheinfo.c | 6 ++++++ arch/x86/kernel/smpboot.c | 4 ---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinf= o.c index fe98a1465be6..66556833d7af 100644 --- a/arch/x86/kernel/cpu/cacheinfo.c +++ b/arch/x86/kernel/cpu/cacheinfo.c @@ -29,6 +29,12 @@ #define LVL_3 4 #define LVL_TRACE 5 =20 +/* Shared last level cache maps */ +DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_llc_shared_map); + +/* Shared L2 cache maps */ +DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_l2c_shared_map); + struct _cache_table { unsigned char descriptor; char cache_type; diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 5e7f9532a10d..f24227bc3220 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -95,10 +95,6 @@ EXPORT_PER_CPU_SYMBOL(cpu_core_map); DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_die_map); EXPORT_PER_CPU_SYMBOL(cpu_die_map); =20 -DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_llc_shared_map); - -DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_l2c_shared_map); - /* Per CPU bogomips and other parameters */ DEFINE_PER_CPU_READ_MOSTLY(struct cpuinfo_x86, cpu_info); EXPORT_PER_CPU_SYMBOL(cpu_info); --=20 2.37.1 From nobody Wed Apr 15 00:01:10 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 85C69C19F2B for ; Fri, 29 Jul 2022 07:01:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234648AbiG2HBr (ORCPT ); Fri, 29 Jul 2022 03:01:47 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48186 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233965AbiG2HBk (ORCPT ); Fri, 29 Jul 2022 03:01:40 -0400 Received: from polaris.svanheule.net (polaris.svanheule.net [IPv6:2a00:c98:2060:a004:1::200]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 467121F2E7 for ; Fri, 29 Jul 2022 00:01:39 -0700 (PDT) Received: from terra.. (unknown [IPv6:2a02:a03f:eaf9:8401:aa9f:5d01:1b2a:e3cd]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: sander@svanheule.net) by polaris.svanheule.net (Postfix) with ESMTPSA id 2E4B4302C2D; Fri, 29 Jul 2022 09:01:33 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=svanheule.net; s=mail1707; t=1659078093; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=dkZvhTljDkGb52uJmlQoon5W3jFZ8oxGweLeMELnqoE=; b=ZMQkVIoXQOJk8Y93zuFIa0n2qIroQmr+imRwGxGnln0iMh0WotiSDe69Pnhnx9ayWvU5MN aHSsL7VoWEI7IvB6fKO5UrULKGDuESLPUAppfWF28npyux+Epf3em5Wx/u5MX0qDxSO7G/ iW6NWsoXStp/w338zafz7Lz400rR2m6Xs1zRPW2AAdtXdBEfa5RlXJXzlGUSnTs7v2Ou76 9MgTTO1pWHLmldVkKckv7CsVbGTI0T1WMQHfoRdSOLqHZcxisU6cOb1RC5XMWPvVjc3dEV SRRTCXkATH6S/lBgjKGcXNbEk8xmysva30fkXGjJRpgrgn3h6Z0xqveYkk+8fg== From: Sander Vanheule To: linux-kernel@vger.kernel.org, Andrew Morton Cc: Andy Shevchenko , Brendan Higgins , Dave Hansen , David Gow , Borislav Petkov , Greg Kroah-Hartman , "H . Peter Anvin" , Ingo Molnar , =?UTF-8?q?Ma=C3=ADra=20Canal?= , Marco Elver , Peter Zijlstra , Thomas Gleixner , Valentin Schneider , Yury Norov , Sander Vanheule Subject: [PATCH v5 2/5] cpumask: add UP optimised for_each_*_cpu versions Date: Fri, 29 Jul 2022 09:01:19 +0200 Message-Id: X-Mailer: git-send-email 2.37.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" On uniprocessor builds, the following loops will always run over a mask that contains one enabled CPU (cpu0): - for_each_possible_cpu - for_each_online_cpu - for_each_present_cpu Provide uniprocessor-specific macros for these loops, that always run exactly once, instead of just relying on for_each_cpu() to provide this optimisation. Signed-off-by: Sander Vanheule Acked-by: Yury Norov Cc: Andy Shevchenko Cc: Borislav Petkov Cc: Dave Hansen Cc: Greg Kroah-Hartman Cc: "H. Peter Anvin" Cc: Ingo Molnar Cc: Marco Elver Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Valentin Schneider --- Changes since v4: - Move patch forward in series - Add Yury's Acked-by include/linux/cpumask.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h index fe29ac7cc469..533612770bc0 100644 --- a/include/linux/cpumask.h +++ b/include/linux/cpumask.h @@ -811,9 +811,16 @@ extern const DECLARE_BITMAP(cpu_all_bits, NR_CPUS); /* First bits of cpu_bit_bitmap are in fact unset. */ #define cpu_none_mask to_cpumask(cpu_bit_bitmap[0]) =20 +#if NR_CPUS =3D=3D 1 +/* Uniprocessor: the possible/online/present masks are always "1" */ +#define for_each_possible_cpu(cpu) for ((cpu) =3D 0; (cpu) < 1; (cpu)++) +#define for_each_online_cpu(cpu) for ((cpu) =3D 0; (cpu) < 1; (cpu)++) +#define for_each_present_cpu(cpu) for ((cpu) =3D 0; (cpu) < 1; (cpu)++) +#else #define for_each_possible_cpu(cpu) for_each_cpu((cpu), cpu_possible_mask) #define for_each_online_cpu(cpu) for_each_cpu((cpu), cpu_online_mask) #define for_each_present_cpu(cpu) for_each_cpu((cpu), cpu_present_mask) +#endif =20 /* Wrappers for arch boot code to manipulate normally-constant masks */ void init_cpu_present(const struct cpumask *src); --=20 2.37.1 From nobody Wed Apr 15 00:01:10 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 03136C00144 for ; Fri, 29 Jul 2022 07:01:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234649AbiG2HBw (ORCPT ); Fri, 29 Jul 2022 03:01:52 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48228 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234370AbiG2HBm (ORCPT ); Fri, 29 Jul 2022 03:01:42 -0400 Received: from polaris.svanheule.net (polaris.svanheule.net [IPv6:2a00:c98:2060:a004:1::200]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 09AA52F39D for ; Fri, 29 Jul 2022 00:01:40 -0700 (PDT) Received: from terra.. (unknown [IPv6:2a02:a03f:eaf9:8401:aa9f:5d01:1b2a:e3cd]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: sander@svanheule.net) by polaris.svanheule.net (Postfix) with ESMTPSA id C23F8302C2E; Fri, 29 Jul 2022 09:01:33 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=svanheule.net; s=mail1707; t=1659078094; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=B5yEFAJsNzK2P3Idr1Ql1MAP9Q2Tlri6Ym2Ak1ckCII=; b=M+RHsBLs6DOjXSjOxbuyM0Miw/O4D+x95Lh9oLPRe9BSHyLPX+WirX416PbErrIuqAKETQ +S98hXou9XbW531rcG9JRHhUoNUXvpnKQTH3qW6sdH/GDRnEOTBHrCfeq+wD2gdd3ZLMkf bQz0aKpf8RGVoC3SQqJTaW4agc6UaE+FfmoShI2wCDyKplx+x7mVY8Y1buxTJDKMKjxo2i AevOqVdh0Dt9VWDWVw5Ia4+pLOvQVYD7pEN8xS2oE2vcHsWlDq5zdFMoxb8BfUsHzzCavc j+mBOSU4KJeKDOYcIQdQ1d7Lr5G1rpI5N4NP4zJnXtbxrqaGpvrIO8r2a6oUHw== From: Sander Vanheule To: linux-kernel@vger.kernel.org, Andrew Morton Cc: Andy Shevchenko , Brendan Higgins , Dave Hansen , David Gow , Borislav Petkov , Greg Kroah-Hartman , "H . Peter Anvin" , Ingo Molnar , =?UTF-8?q?Ma=C3=ADra=20Canal?= , Marco Elver , Peter Zijlstra , Thomas Gleixner , Valentin Schneider , Yury Norov , Sander Vanheule Subject: [PATCH v5 3/5] cpumask: fix invalid uniprocessor mask assumption Date: Fri, 29 Jul 2022 09:01:20 +0200 Message-Id: X-Mailer: git-send-email 2.37.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" On uniprocessor builds, any CPU mask is assumed to contain exactly one CPU (cpu0). This assumption ignores the existence of empty masks, potentially resulting in incorrect behaviour. For example, for_each_cpu() will run one iteration of the loop even when passed an empty cpumask. cpumask_first_zero(), cpumask_next_zero(), and for_each_cpu_not() don't provide behaviour matching the assumption that a UP mask is always "1", but instead provide behaviour matching the empty mask. Drop the incorrectly optimised code and use the generic implementations in all cases. Signed-off-by: Sander Vanheule Suggested-by: Yury Norov Cc: Andy Shevchenko Cc: Borislav Petkov Cc: Dave Hansen Cc: Greg Kroah-Hartman Cc: "H. Peter Anvin" Cc: Ingo Molnar Cc: Marco Elver Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Valentin Schneider --- Changes since v4: - Reflow commit message =20 Changes since v3: - Add back UP-optimised cpumask_local_spread, cpumask_any_distribute, cpumask_any_and_distribute Changes since v1: - Drop UP implementations instead of trying to fix them include/linux/cpumask.h | 99 ++++++++--------------------------------- lib/Makefile | 3 +- lib/cpumask.c | 2 + 3 files changed, 22 insertions(+), 82 deletions(-) diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h index 533612770bc0..6c5b4ee000f2 100644 --- a/include/linux/cpumask.h +++ b/include/linux/cpumask.h @@ -116,85 +116,6 @@ static __always_inline unsigned int cpumask_check(unsi= gned int cpu) return cpu; } =20 -#if NR_CPUS =3D=3D 1 -/* Uniprocessor. Assume all masks are "1". */ -static inline unsigned int cpumask_first(const struct cpumask *srcp) -{ - return 0; -} - -static inline unsigned int cpumask_first_zero(const struct cpumask *srcp) -{ - return 0; -} - -static inline unsigned int cpumask_first_and(const struct cpumask *srcp1, - const struct cpumask *srcp2) -{ - return 0; -} - -static inline unsigned int cpumask_last(const struct cpumask *srcp) -{ - return 0; -} - -/* Valid inputs for n are -1 and 0. */ -static inline unsigned int cpumask_next(int n, const struct cpumask *srcp) -{ - return n+1; -} - -static inline unsigned int cpumask_next_zero(int n, const struct cpumask *= srcp) -{ - return n+1; -} - -static inline unsigned int cpumask_next_and(int n, - const struct cpumask *srcp, - const struct cpumask *andp) -{ - return n+1; -} - -static inline unsigned int cpumask_next_wrap(int n, const struct cpumask *= mask, - int start, bool wrap) -{ - /* cpu0 unless stop condition, wrap and at cpu0, then nr_cpumask_bits */ - return (wrap && n =3D=3D 0); -} - -/* cpu must be a valid cpu, ie 0, so there's no other choice. */ -static inline unsigned int cpumask_any_but(const struct cpumask *mask, - unsigned int cpu) -{ - return 1; -} - -static inline unsigned int cpumask_local_spread(unsigned int i, int node) -{ - return 0; -} - -static inline int cpumask_any_and_distribute(const struct cpumask *src1p, - const struct cpumask *src2p) { - return cpumask_first_and(src1p, src2p); -} - -static inline int cpumask_any_distribute(const struct cpumask *srcp) -{ - return cpumask_first(srcp); -} - -#define for_each_cpu(cpu, mask) \ - for ((cpu) =3D 0; (cpu) < 1; (cpu)++, (void)mask) -#define for_each_cpu_not(cpu, mask) \ - for ((cpu) =3D 0; (cpu) < 1; (cpu)++, (void)mask) -#define for_each_cpu_wrap(cpu, mask, start) \ - for ((cpu) =3D 0; (cpu) < 1; (cpu)++, (void)mask, (void)(start)) -#define for_each_cpu_and(cpu, mask1, mask2) \ - for ((cpu) =3D 0; (cpu) < 1; (cpu)++, (void)mask1, (void)mask2) -#else /** * cpumask_first - get the first cpu in a cpumask * @srcp: the cpumask pointer @@ -260,10 +181,29 @@ static inline unsigned int cpumask_next_zero(int n, c= onst struct cpumask *srcp) =20 int __pure cpumask_next_and(int n, const struct cpumask *, const struct cp= umask *); int __pure cpumask_any_but(const struct cpumask *mask, unsigned int cpu); + +#if NR_CPUS =3D=3D 1 +/* Uniprocessor: there is only one valid CPU */ +static inline unsigned int cpumask_local_spread(unsigned int i, int node) +{ + return 0; +} + +static inline int cpumask_any_and_distribute(const struct cpumask *src1p, + const struct cpumask *src2p) { + return cpumask_first_and(src1p, src2p); +} + +static inline int cpumask_any_distribute(const struct cpumask *srcp) +{ + return cpumask_first(srcp); +} +#else unsigned int cpumask_local_spread(unsigned int i, int node); int cpumask_any_and_distribute(const struct cpumask *src1p, const struct cpumask *src2p); int cpumask_any_distribute(const struct cpumask *srcp); +#endif /* NR_CPUS */ =20 /** * for_each_cpu - iterate over every cpu in a mask @@ -324,7 +264,6 @@ extern int cpumask_next_wrap(int n, const struct cpumas= k *mask, int start, bool for ((cpu) =3D -1; \ (cpu) =3D cpumask_next_and((cpu), (mask1), (mask2)), \ (cpu) < nr_cpu_ids;) -#endif /* SMP */ =20 #define CPU_BITS_NONE \ { \ diff --git a/lib/Makefile b/lib/Makefile index f99bf61f8bbc..bcc7e8ea0cde 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -34,10 +34,9 @@ lib-y :=3D ctype.o string.o vsprintf.o cmdline.o \ is_single_threaded.o plist.o decompress.o kobject_uevent.o \ earlycpio.o seq_buf.o siphash.o dec_and_lock.o \ nmi_backtrace.o nodemask.o win_minmax.o memcat_p.o \ - buildid.o + buildid.o cpumask.o =20 lib-$(CONFIG_PRINTK) +=3D dump_stack.o -lib-$(CONFIG_SMP) +=3D cpumask.o =20 lib-y +=3D kobject.o klist.o obj-y +=3D lockref.o diff --git a/lib/cpumask.c b/lib/cpumask.c index a971a82d2f43..b9728513a4d4 100644 --- a/lib/cpumask.c +++ b/lib/cpumask.c @@ -192,6 +192,7 @@ void __init free_bootmem_cpumask_var(cpumask_var_t mask) } #endif =20 +#if NR_CPUS > 1 /** * cpumask_local_spread - select the i'th cpu with local numa cpu's first * @i: index number @@ -279,3 +280,4 @@ int cpumask_any_distribute(const struct cpumask *srcp) return next; } EXPORT_SYMBOL(cpumask_any_distribute); +#endif /* NR_CPUS */ --=20 2.37.1 From nobody Wed Apr 15 00:01:10 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8CFEEC00144 for ; Fri, 29 Jul 2022 07:02:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234015AbiG2HCL (ORCPT ); Fri, 29 Jul 2022 03:02:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48264 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234386AbiG2HBn (ORCPT ); Fri, 29 Jul 2022 03:01:43 -0400 Received: from polaris.svanheule.net (polaris.svanheule.net [IPv6:2a00:c98:2060:a004:1::200]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 79D251F2E7 for ; Fri, 29 Jul 2022 00:01:41 -0700 (PDT) Received: from terra.. (unknown [IPv6:2a02:a03f:eaf9:8401:aa9f:5d01:1b2a:e3cd]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: sander@svanheule.net) by polaris.svanheule.net (Postfix) with ESMTPSA id AEC5F302C30; Fri, 29 Jul 2022 09:01:34 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=svanheule.net; s=mail1707; t=1659078096; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=U38/SCcfeOS4YYtk9BamiWe1ZOK+KPSRSMapins/TDY=; b=J67qNbqZBxZRXWfmZKdDOzgJvZ74beVOu1SVrFu4txZ2gvcJplOHzntqRYI+ucQ65D1qcH LACJARL2+LxTnnaSHBTJZKBcF6Pq0uuor+B01AaIZlWjICPjBkzm00DulMtJJwVAIPoh3s IkptGcyuOstNaGcVwVoNdFqyS7C2zGcLQd7ROamLrbuoR6fYRIBVeOHtNEQe1BXWqQs+ib dXvmnJ41T4jkCfNhxmBvpyuuC8UGxl11jKPNvOWYcQNwMy1R6vZVFcCvDqO1cY9Ktj+51v GHtakfFotiyKiUWU4UkzTnydPfDE5R6BsQDKbD3mZwQGpCzwHREz+eS+X8s0yg== From: Sander Vanheule To: linux-kernel@vger.kernel.org, Andrew Morton Cc: Andy Shevchenko , Brendan Higgins , Dave Hansen , David Gow , Borislav Petkov , Greg Kroah-Hartman , "H . Peter Anvin" , Ingo Molnar , =?UTF-8?q?Ma=C3=ADra=20Canal?= , Marco Elver , Peter Zijlstra , Thomas Gleixner , Valentin Schneider , Yury Norov , Sander Vanheule Subject: [PATCH v5 4/5] lib/test: introduce cpumask KUnit test suite Date: Fri, 29 Jul 2022 09:01:21 +0200 Message-Id: <85217b5de6d62257313ad7fde3e1969421acad75.1659077534.git.sander@svanheule.net> X-Mailer: git-send-email 2.37.1 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add a basic suite of tests for cpumask, providing some tests for empty and completely filled cpumasks. Signed-off-by: Sander Vanheule Reviewed-by: Andy Shevchenko Suggested-by: Yury Norov Cc: Borislav Petkov Cc: Dave Hansen Cc: Greg Kroah-Hartman Cc: "H. Peter Anvin" Cc: Ingo Molnar Cc: Marco Elver Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Valentin Schneider Cc: Brendan Higgins Cc: David Gow Cc: Ma=C3=ADra Canal Tested-by: Ma=C3=ADra Canal --- Changes since v4: - Belated addition of Yury's Suggested-by: - Follow KUnit style more closely - Drop full check on cpu_possible_mask - Update last check on cpu_possible_mask - Log masks when starting test - Update commit message=20 =20 Changes since v3: - Test for_each_cpu*() over empty mask and cpu_possible_mask - Add Andy's Reviewed-by - Use num_{online,present,possible}_cpus() for builtin masks - Guard against CPU hotplugging during test for dynamic builtin CPU masks =20 Changes since v2: - Rework for_each_* test macros, as suggested by Yury Changes since v1: - New patch lib/Kconfig.debug | 12 ++++ lib/Makefile | 1 + lib/cpumask_test.c | 147 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+) create mode 100644 lib/cpumask_test.c diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 2e24db4bff19..e85e74646178 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2021,6 +2021,18 @@ config LKDTM Documentation on how to use the module can be found in Documentation/fault-injection/provoke-crashes.rst =20 +config CPUMASK_KUNIT_TEST + tristate "KUnit test for cpumask" if !KUNIT_ALL_TESTS + depends on KUNIT + default KUNIT_ALL_TESTS + help + Enable to turn on cpumask tests, running at boot or module load time. + + For more information on KUnit and unit tests in general, please refer + to the KUnit documentation in Documentation/dev-tools/kunit/. + + If unsure, say N. + config TEST_LIST_SORT tristate "Linked list sorting test" if !KUNIT_ALL_TESTS depends on KUNIT diff --git a/lib/Makefile b/lib/Makefile index bcc7e8ea0cde..9f9db1376538 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -59,6 +59,7 @@ obj-$(CONFIG_TEST_BPF) +=3D test_bpf.o obj-$(CONFIG_TEST_FIRMWARE) +=3D test_firmware.o obj-$(CONFIG_TEST_BITOPS) +=3D test_bitops.o CFLAGS_test_bitops.o +=3D -Werror +obj-$(CONFIG_CPUMASK_KUNIT_TEST) +=3D cpumask_test.o obj-$(CONFIG_TEST_SYSCTL) +=3D test_sysctl.o obj-$(CONFIG_TEST_SIPHASH) +=3D test_siphash.o obj-$(CONFIG_HASH_KUNIT_TEST) +=3D test_hash.o diff --git a/lib/cpumask_test.c b/lib/cpumask_test.c new file mode 100644 index 000000000000..0f8059a5e93b --- /dev/null +++ b/lib/cpumask_test.c @@ -0,0 +1,147 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * KUnit tests for cpumask. + * + * Author: Sander Vanheule + */ + +#include +#include +#include + +#define EXPECT_FOR_EACH_CPU_EQ(test, mask) \ + do { \ + const cpumask_t *m =3D (mask); \ + int mask_weight =3D cpumask_weight(m); \ + int cpu, iter =3D 0; \ + for_each_cpu(cpu, m) \ + iter++; \ + KUNIT_EXPECT_EQ((test), mask_weight, iter); \ + } while (0) + +#define EXPECT_FOR_EACH_CPU_NOT_EQ(test, mask) \ + do { \ + const cpumask_t *m =3D (mask); \ + int mask_weight =3D cpumask_weight(m); \ + int cpu, iter =3D 0; \ + for_each_cpu_not(cpu, m) \ + iter++; \ + KUNIT_EXPECT_EQ((test), nr_cpu_ids - mask_weight, iter); \ + } while (0) + +#define EXPECT_FOR_EACH_CPU_WRAP_EQ(test, mask) \ + do { \ + const cpumask_t *m =3D (mask); \ + int mask_weight =3D cpumask_weight(m); \ + int cpu, iter =3D 0; \ + for_each_cpu_wrap(cpu, m, nr_cpu_ids / 2) \ + iter++; \ + KUNIT_EXPECT_EQ((test), mask_weight, iter); \ + } while (0) + +#define EXPECT_FOR_EACH_CPU_BUILTIN_EQ(test, name) \ + do { \ + int mask_weight =3D num_##name##_cpus(); \ + int cpu, iter =3D 0; \ + for_each_##name##_cpu(cpu) \ + iter++; \ + KUNIT_EXPECT_EQ((test), mask_weight, iter); \ + } while (0) + +static cpumask_t mask_empty; +static cpumask_t mask_all; + +#define STR_MASK(m) #m +#define TEST_CPUMASK_PRINT(test, mask) \ + kunit_info(test, "%s =3D '%*pbl'\n", STR_MASK(mask), nr_cpumask_bits, cpu= mask_bits(mask)) + +static void test_cpumask_weight(struct kunit *test) +{ + KUNIT_EXPECT_TRUE(test, cpumask_empty(&mask_empty)); + KUNIT_EXPECT_TRUE(test, cpumask_full(&mask_all)); + + KUNIT_EXPECT_EQ(test, 0, cpumask_weight(&mask_empty)); + KUNIT_EXPECT_EQ(test, nr_cpu_ids, cpumask_weight(cpu_possible_mask)); + KUNIT_EXPECT_EQ(test, nr_cpumask_bits, cpumask_weight(&mask_all)); +} + +static void test_cpumask_first(struct kunit *test) +{ + KUNIT_EXPECT_LE(test, nr_cpu_ids, cpumask_first(&mask_empty)); + KUNIT_EXPECT_EQ(test, 0, cpumask_first(cpu_possible_mask)); + + KUNIT_EXPECT_EQ(test, 0, cpumask_first_zero(&mask_empty)); + KUNIT_EXPECT_LE(test, nr_cpu_ids, cpumask_first_zero(cpu_possible_mask)); +} + +static void test_cpumask_last(struct kunit *test) +{ + KUNIT_EXPECT_LE(test, nr_cpumask_bits, cpumask_last(&mask_empty)); + KUNIT_EXPECT_EQ(test, nr_cpu_ids - 1, cpumask_last(cpu_possible_mask)); +} + +static void test_cpumask_next(struct kunit *test) +{ + KUNIT_EXPECT_EQ(test, 0, cpumask_next_zero(-1, &mask_empty)); + KUNIT_EXPECT_LE(test, nr_cpu_ids, cpumask_next_zero(-1, cpu_possible_mask= )); + + KUNIT_EXPECT_LE(test, nr_cpu_ids, cpumask_next(-1, &mask_empty)); + KUNIT_EXPECT_EQ(test, 0, cpumask_next(-1, cpu_possible_mask)); +} + +static void test_cpumask_iterators(struct kunit *test) +{ + EXPECT_FOR_EACH_CPU_EQ(test, &mask_empty); + EXPECT_FOR_EACH_CPU_NOT_EQ(test, &mask_empty); + EXPECT_FOR_EACH_CPU_WRAP_EQ(test, &mask_empty); + + EXPECT_FOR_EACH_CPU_EQ(test, cpu_possible_mask); + EXPECT_FOR_EACH_CPU_NOT_EQ(test, cpu_possible_mask); + EXPECT_FOR_EACH_CPU_WRAP_EQ(test, cpu_possible_mask); +} + +static void test_cpumask_iterators_builtin(struct kunit *test) +{ + EXPECT_FOR_EACH_CPU_BUILTIN_EQ(test, possible); + + /* Ensure the dynamic masks are stable while running the tests */ + cpu_hotplug_disable(); + + TEST_CPUMASK_PRINT(test, cpu_online_mask); + TEST_CPUMASK_PRINT(test, cpu_present_mask); + + EXPECT_FOR_EACH_CPU_BUILTIN_EQ(test, online); + EXPECT_FOR_EACH_CPU_BUILTIN_EQ(test, present); + + cpu_hotplug_enable(); +} + +static int test_cpumask_init(struct kunit *test) +{ + cpumask_clear(&mask_empty); + cpumask_setall(&mask_all); + + TEST_CPUMASK_PRINT(test, &mask_all); + TEST_CPUMASK_PRINT(test, cpu_possible_mask); + + return 0; +} + +static struct kunit_case test_cpumask_cases[] =3D { + KUNIT_CASE(test_cpumask_weight), + KUNIT_CASE(test_cpumask_first), + KUNIT_CASE(test_cpumask_last), + KUNIT_CASE(test_cpumask_next), + KUNIT_CASE(test_cpumask_iterators), + KUNIT_CASE(test_cpumask_iterators_builtin), + {} +}; + +static struct kunit_suite test_cpumask_suite =3D { + .name =3D "cpumask", + .init =3D test_cpumask_init, + .test_cases =3D test_cpumask_cases, +}; +kunit_test_suite(test_cpumask_suite); + +MODULE_LICENSE("GPL"); --=20 2.37.1 From nobody Wed Apr 15 00:01:10 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0510DC00144 for ; Fri, 29 Jul 2022 07:02:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234183AbiG2HCG (ORCPT ); Fri, 29 Jul 2022 03:02:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48260 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234541AbiG2HBn (ORCPT ); Fri, 29 Jul 2022 03:01:43 -0400 Received: from polaris.svanheule.net (polaris.svanheule.net [84.16.241.116]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4806079ED7 for ; Fri, 29 Jul 2022 00:01:42 -0700 (PDT) Received: from terra.. (unknown [IPv6:2a02:a03f:eaf9:8401:aa9f:5d01:1b2a:e3cd]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: sander@svanheule.net) by polaris.svanheule.net (Postfix) with ESMTPSA id 73ECF302C32; Fri, 29 Jul 2022 09:01:36 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=svanheule.net; s=mail1707; t=1659078096; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ymMelilHDopyMB4Vs8lIxjQOx68nKb0qwXM9yef9/ww=; b=ns3a1gTPDKH6kODoWPWGAx48VvP20hNsmXZ3MRvhg1SbQYJpch7ut/ZAKjipMiehKof41Y Dh9FzYonqHUPj90GM7vLPbx0WRW+fZtQqH+YxczjMoCqGrm6hQuNOEptivloW1mjG/eyJe m0hzIUQJFuq3cqQpZOydpwG8Dcb6TocbxhwBw7CPg/CFsHrg4ko5g2b7x9j0zbXyMKC9K0 0gfpIPaH7rPzmfhqalVX2rlJAVOhaNZ7uh2IjAvqdpskD5IQs9MYvgtEMSt1CXqeVZlLp7 ZR4pnRZDBIWKiKCqEgfrNTFA5mwhGmZIoDcOd9gYcBg09Dh/IbE9Tx0kydnkYQ== From: Sander Vanheule To: linux-kernel@vger.kernel.org, Andrew Morton Cc: Andy Shevchenko , Brendan Higgins , Dave Hansen , David Gow , Borislav Petkov , Greg Kroah-Hartman , "H . Peter Anvin" , Ingo Molnar , =?UTF-8?q?Ma=C3=ADra=20Canal?= , Marco Elver , Peter Zijlstra , Thomas Gleixner , Valentin Schneider , Yury Norov , Sander Vanheule Subject: [PATCH v5 5/5] cpumask: update cpumask_next_wrap() signature Date: Fri, 29 Jul 2022 09:01:22 +0200 Message-Id: <06eebdc46cfb21eb437755a2a5a56d55c41400f5.1659077534.git.sander@svanheule.net> X-Mailer: git-send-email 2.37.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The extern specifier is not needed for this declaration, so drop it. The function also depends only on the input parameters, and has no side effects, so it can be marked __pure like other functions in cpumask.h. Signed-off-by: Sander Vanheule Reviewed-by: Andy Shevchenko Cc: Borislav Petkov Cc: Dave Hansen Cc: Greg Kroah-Hartman Cc: "H. Peter Anvin" Cc: Ingo Molnar Cc: Marco Elver Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Valentin Schneider Cc: Yury Norov --- Changes since v3: - Add Andy's Reviewed-by Changes since v1: - Split off patch from other changes include/linux/cpumask.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h index 6c5b4ee000f2..523857884ae4 100644 --- a/include/linux/cpumask.h +++ b/include/linux/cpumask.h @@ -229,7 +229,7 @@ int cpumask_any_distribute(const struct cpumask *srcp); (cpu) =3D cpumask_next_zero((cpu), (mask)), \ (cpu) < nr_cpu_ids;) =20 -extern int cpumask_next_wrap(int n, const struct cpumask *mask, int start,= bool wrap); +int __pure cpumask_next_wrap(int n, const struct cpumask *mask, int start,= bool wrap); =20 /** * for_each_cpu_wrap - iterate over every cpu in a mask, starting at a spe= cified location --=20 2.37.1