Received: by 2002:a6b:500f:0:0:0:0:0 with SMTP id e15csp4691384iob; Sun, 8 May 2022 22:09:57 -0700 (PDT) X-Google-Smtp-Source: ABdhPJytWhLoQrEvygF9Bul5nWv3hWvnCPJHMWjKNk2R1vYqLJSQ6dy9FweYQOWTvofBDw8XUuO8 X-Received: by 2002:a17:90a:1509:b0:1d8:c22b:4d61 with SMTP id l9-20020a17090a150900b001d8c22b4d61mr24193554pja.78.1652072997234; Sun, 08 May 2022 22:09:57 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1652072997; cv=none; d=google.com; s=arc-20160816; b=fIa0ciW9aUuEvNRugZVYTnr5cKNCUGC+ZimKZvNEeYC1o7oRGCm5J50Uef8Fh0e/Vy cZsWlnGu0vz9gFiarHcCwkeUv2qY4l4K654YsSG0V+ZsBGQxJi4FImRnc8w98nbMneFo BaviwS34/WX4d7NEezcdvF1ZT9jymy+PPF/sgKcgFqN6rwdNIcCQOFANoqdwFFBvObNW CJ6stlFRt+Sl19d4Cw2a9+g1Lu1WEIDmo5pxjhdypH+cOmqZntLZASt/R1HZkLwKL4hC aISzFmDkU6PtA6hsbww4UTk3p3CmxGiehQ0fKgP+f5BHuM/5JcEQOe3pZ7sTzCIHevXy HKZw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=kWiAzL1XgB8kEqmHEgehjoPHHFRxXOEWNZk0fRIUWmw=; b=Hrp/cwS7KmAONScFPxN78s0onOAuJRu+VWAsrHBF69O+4fIkNY5Hdhihdu8xeDvkZM 9NpFO0pXe18FQyEMaveszXoyGniMa1d1YXuciB/7248gsmH38T57JpjjWH39yDDPhmJ5 1WXNm5gq8FWK7nmF2SJM8QP8TfEoIwFVTaHUavv2ZSfHV5RW/wUI6dzio4k7zX2kLb7o Ucc2bb/G+Gs6LTU4Cdlnoqwb1Hga/BaVYo40UdZtYcLpxlPYGpAzieqi74zuOcw3kD0x qwPCS9S7qWI+HqL/CvN+KBt+gXJQ7SYaBkLTN/jgUuTVFN4cG4Pu0snimQmqwNDg/tYx GvWg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=Bkxkj8L1; spf=softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net. [23.128.96.19]) by mx.google.com with ESMTPS id i16-20020a17090332d000b00158d1f2d451si11664011plr.45.2022.05.08.22.09.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 08 May 2022 22:09:57 -0700 (PDT) Received-SPF: softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) client-ip=23.128.96.19; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=Bkxkj8L1; spf=softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 39D95140850; Sun, 8 May 2022 22:05:20 -0700 (PDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235546AbiEHQUc (ORCPT + 99 others); Sun, 8 May 2022 12:20:32 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39084 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235519AbiEHQU3 (ORCPT ); Sun, 8 May 2022 12:20:29 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 085CBB7E3 for ; Sun, 8 May 2022 09:16:38 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id B3CD3B80DBE for ; Sun, 8 May 2022 16:16:36 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1CDC1C385C0; Sun, 8 May 2022 16:16:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1652026595; bh=1D217r1rSI/uUeSIUljN5J553Ajo8zPgW0SHZ2rk+io=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Bkxkj8L1JiFS7MiCImm50YEZA/y0LoDC6dK+ZhYwc59l2AdRol9CFhGrkpuAUDYjy Wdv7f9x4kCNhOQdPCB4cKzmvR8VRc1tJchGSEuv5jGbQ2/8WhXcS3CBxGK07H1P2S0 feZH21gUL3s8D9XG0WkxWHeDVH2G5SlXZkg8nE1O+Wl5lAFCBfEhtsmKSCyMtarMww Y6MF9P2PeoJi937nqmfY8bazzEtLdNZ8/3bLh/+Wd2I2D0zhnaFhx6DQG/fF7KUW0y hK2FqBj+6hTibsMrhxPSE8UthdSkITPTWpFTtX8MJBE1il89sfJrAeHsnWFfBmWWLE zCQK2m8bJ9Xkw== From: Jisheng Zhang To: Paul Walmsley , Palmer Dabbelt , Albert Ou , Andrey Ryabinin , Alexander Potapenko , Andrey Konovalov , Dmitry Vyukov , Vincenzo Frascino , Alexandre Ghiti Cc: linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org, kasan-dev@googlegroups.com Subject: [PATCH v2 2/4] riscv: introduce unified static key mechanism for CPU features Date: Mon, 9 May 2022 00:07:47 +0800 Message-Id: <20220508160749.984-3-jszhang@kernel.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220508160749.984-1-jszhang@kernel.org> References: <20220508160749.984-1-jszhang@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.9 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,MAILING_LIST_MULTI, RDNS_NONE,SPF_HELO_NONE,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Currently, riscv has several features why may not be supported on all riscv platforms, for example, FPU, SV48 and so on. To support unified kernel Image style, we need to check whether the feature is suportted or not. If the check sits at hot code path, then performance will be impacted a lot. static key can be used to solve the issue. In the past FPU support has been converted to use static key mechanism. I believe we will have similar cases in the future. Similar as arm64 does(in fact, some code is borrowed from arm64), this patch tries to add an unified mechanism to use static keys for all the cpu features by implementing an array of default-false static keys and enabling them when detected. The cpus_have_*_cap() check uses the static keys if riscv_const_caps_ready is finalized, otherwise the compiler generates the bitmap test. Signed-off-by: Jisheng Zhang --- arch/riscv/Makefile | 3 + arch/riscv/include/asm/cpufeature.h | 94 +++++++++++++++++++++++++++++ arch/riscv/kernel/cpufeature.c | 23 +++++++ arch/riscv/tools/Makefile | 22 +++++++ arch/riscv/tools/cpucaps | 5 ++ arch/riscv/tools/gen-cpucaps.awk | 40 ++++++++++++ 6 files changed, 187 insertions(+) create mode 100644 arch/riscv/include/asm/cpufeature.h create mode 100644 arch/riscv/tools/Makefile create mode 100644 arch/riscv/tools/cpucaps create mode 100755 arch/riscv/tools/gen-cpucaps.awk diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile index 7d81102cffd4..f4df67369d84 100644 --- a/arch/riscv/Makefile +++ b/arch/riscv/Makefile @@ -154,3 +154,6 @@ PHONY += rv64_randconfig rv64_randconfig: $(Q)$(MAKE) KCONFIG_ALLCONFIG=$(srctree)/arch/riscv/configs/64-bit.config \ -f $(srctree)/Makefile randconfig + +archprepare: + $(Q)$(MAKE) $(build)=arch/riscv/tools kapi diff --git a/arch/riscv/include/asm/cpufeature.h b/arch/riscv/include/asm/cpufeature.h new file mode 100644 index 000000000000..d80ddd2f3b49 --- /dev/null +++ b/arch/riscv/include/asm/cpufeature.h @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2014 Linaro Ltd. + * Copyright (C) 2022 Jisheng Zhang + */ + +#ifndef __ASM_CPUFEATURE_H +#define __ASM_CPUFEATURE_H + +#include + +#include +#include +#include + +extern DECLARE_BITMAP(cpu_hwcaps, RISCV_NCAPS); +extern struct static_key_false cpu_hwcap_keys[RISCV_NCAPS]; +extern struct static_key_false riscv_const_caps_ready; + +static __always_inline bool system_capabilities_finalized(void) +{ + return static_branch_likely(&riscv_const_caps_ready); +} + +/* + * Test for a capability with a runtime check. + * + * Before the capability is detected, this returns false. + */ +static inline bool cpus_have_cap(unsigned int num) +{ + if (num >= RISCV_NCAPS) + return false; + return test_bit(num, cpu_hwcaps); +} + +/* + * Test for a capability without a runtime check. + * + * Before capabilities are finalized, this returns false. + * After capabilities are finalized, this is patched to avoid a runtime check. + * + * @num must be a compile-time constant. + */ +static __always_inline bool __cpus_have_const_cap(int num) +{ + if (num >= RISCV_NCAPS) + return false; + return static_branch_unlikely(&cpu_hwcap_keys[num]); +} + +/* + * Test for a capability without a runtime check. + * + * Before capabilities are finalized, this will BUG(). + * After capabilities are finalized, this is patched to avoid a runtime check. + * + * @num must be a compile-time constant. + */ +static __always_inline bool cpus_have_final_cap(int num) +{ + if (system_capabilities_finalized()) + return __cpus_have_const_cap(num); + else + BUG(); +} + +/* + * Test for a capability, possibly with a runtime check. + * + * Before capabilities are finalized, this behaves as cpus_have_cap(). + * After capabilities are finalized, this is patched to avoid a runtime check. + * + * @num must be a compile-time constant. + */ +static __always_inline bool cpus_have_const_cap(int num) +{ + if (system_capabilities_finalized()) + return __cpus_have_const_cap(num); + else + return cpus_have_cap(num); +} + +static inline void cpus_set_cap(unsigned int num) +{ + if (num >= RISCV_NCAPS) { + pr_warn("Attempt to set an illegal CPU capability (%d >= %d)\n", + num, RISCV_NCAPS); + } else { + __set_bit(num, cpu_hwcaps); + } +} + +#endif diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c index 1b2d42d7f589..e6c72cad0c1c 100644 --- a/arch/riscv/kernel/cpufeature.c +++ b/arch/riscv/kernel/cpufeature.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -25,6 +26,15 @@ static DECLARE_BITMAP(riscv_isa, RISCV_ISA_EXT_MAX) __read_mostly; __ro_after_init DEFINE_STATIC_KEY_FALSE(cpu_hwcap_fpu); #endif +DECLARE_BITMAP(cpu_hwcaps, RISCV_NCAPS); +EXPORT_SYMBOL(cpu_hwcaps); + +DEFINE_STATIC_KEY_ARRAY_FALSE(cpu_hwcap_keys, RISCV_NCAPS); +EXPORT_SYMBOL(cpu_hwcap_keys); + +DEFINE_STATIC_KEY_FALSE(riscv_const_caps_ready); +EXPORT_SYMBOL(riscv_const_caps_ready); + /** * riscv_isa_extension_base() - Get base extension word * @@ -62,6 +72,17 @@ bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, int bit) } EXPORT_SYMBOL_GPL(__riscv_isa_extension_available); +static void __init enable_cpu_capabilities(void) +{ + int i; + + for (i = 0; i < RISCV_NCAPS; i++) { + if (!cpus_have_cap(i)) + continue; + static_branch_enable(&cpu_hwcap_keys[i]); + } +} + void __init riscv_fill_hwcap(void) { struct device_node *node; @@ -236,4 +257,6 @@ void __init riscv_fill_hwcap(void) if (elf_hwcap & (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D)) static_branch_enable(&cpu_hwcap_fpu); #endif + enable_cpu_capabilities(); + static_branch_enable(&riscv_const_caps_ready); } diff --git a/arch/riscv/tools/Makefile b/arch/riscv/tools/Makefile new file mode 100644 index 000000000000..932b4fe5c768 --- /dev/null +++ b/arch/riscv/tools/Makefile @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0 + +gen := arch/$(ARCH)/include/generated +kapi := $(gen)/asm + +kapi-hdrs-y := $(kapi)/cpucaps.h + +targets += $(addprefix ../../../,$(gen-y) $(kapi-hdrs-y)) + +PHONY += kapi + +kapi: $(kapi-hdrs-y) $(gen-y) + +# Create output directory if not already present +_dummy := $(shell [ -d '$(kapi)' ] || mkdir -p '$(kapi)') + +quiet_cmd_gen_cpucaps = GEN $@ + cmd_gen_cpucaps = mkdir -p $(dir $@) && \ + $(AWK) -f $(filter-out $(PHONY),$^) > $@ + +$(kapi)/cpucaps.h: $(src)/gen-cpucaps.awk $(src)/cpucaps FORCE + $(call if_changed,gen_cpucaps) diff --git a/arch/riscv/tools/cpucaps b/arch/riscv/tools/cpucaps new file mode 100644 index 000000000000..cb1ff2747859 --- /dev/null +++ b/arch/riscv/tools/cpucaps @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Internal CPU capabilities constants, keep this list sorted + +HAS_NO_FPU diff --git a/arch/riscv/tools/gen-cpucaps.awk b/arch/riscv/tools/gen-cpucaps.awk new file mode 100755 index 000000000000..52a1e1b064ad --- /dev/null +++ b/arch/riscv/tools/gen-cpucaps.awk @@ -0,0 +1,40 @@ +#!/bin/awk -f +# SPDX-License-Identifier: GPL-2.0 +# gen-cpucaps.awk: riscv cpucaps header generator +# +# Usage: awk -f gen-cpucaps.awk cpucaps.txt + +# Log an error and terminate +function fatal(msg) { + print "Error at line " NR ": " msg > "/dev/stderr" + exit 1 +} + +# skip blank lines and comment lines +/^$/ { next } +/^#/ { next } + +BEGIN { + print "#ifndef __ASM_CPUCAPS_H" + print "#define __ASM_CPUCAPS_H" + print "" + print "/* Generated file - do not edit */" + cap_num = 0 + print "" +} + +/^[vA-Z0-9_]+$/ { + printf("#define RISCV_%-30s\t%d\n", $0, cap_num++) + next +} + +END { + printf("#define RISCV_NCAPS\t\t\t\t%d\n", cap_num) + print "" + print "#endif /* __ASM_CPUCAPS_H */" +} + +# Any lines not handled by previous rules are unexpected +{ + fatal("unhandled statement") +} -- 2.34.1