From patchwork Mon Mar 6 11:48:36 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Rutland X-Patchwork-Id: 13161006 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 03095C678D4 for ; Mon, 6 Mar 2023 11:50:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:Message-Id:Date:Subject:Cc :To:From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: List-Owner; bh=IMaarvewWm2ejtkM9So1HTI+pdkPq69Nk1VsSppNOZU=; b=usMT0ZdrSbjijh EGjxNw5UpSwLfzpQxc6fx0UOkOSDY7yjabeP4rw3mUXl/xahe4Ea2RJdmeAIWPRrrpR7NCyOgf+TU q9qQeAfTE5lrwfW9U91JNCDQPrUURRhYcXykOL+VAL1y/Wv99f4SJ0FmUAVm40Hw7jVGR0+/tlMCC 0qY5GWSBJQG2h5f4lnwHjluL+W3Xv67udLxlO25YY6mszrLI64zTbza211SNzVbYI65FL5m4lJLQG 4X1oJxVGliQhP3g15L+jF5eVfqZzggGKna7PtEpl5i+kwNyqtzHlRJXK2iVtA6yZ3/sB23sovN+8f hbhTYKgRPGIoUSrqszfQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1pZ9L7-00CXgW-OR; Mon, 06 Mar 2023 11:49:14 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1pZ9Kh-00CXXs-DJ for linux-arm-kernel@lists.infradead.org; Mon, 06 Mar 2023 11:48:54 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 63E9412FC; Mon, 6 Mar 2023 03:49:25 -0800 (PST) Received: from lakrids.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.121.207.14]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 087D53F5A1; Mon, 6 Mar 2023 03:48:40 -0800 (PST) From: Mark Rutland To: linux-arm-kernel@lists.infradead.org Cc: anshuman.khandual@arm.com, broonie@kernel.org, catalin.marinas@arm.com, mark.rutland@arm.com, maz@kernel.org, will@kernel.org Subject: [PATCH v2] arm64/sysreg: allow *Enum blocks in SysregFields blocks Date: Mon, 6 Mar 2023 11:48:36 +0000 Message-Id: <20230306114836.2575432-1-mark.rutland@arm.com> X-Mailer: git-send-email 2.30.2 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230306_034847_610361_55A65A97 X-CRM114-Status: GOOD ( 21.88 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org We'd like to support Enum/SignedEnum/UnsignedEnum blocks within SysregFields blocks, so that we can define enumerations for sets of registers. This isn't currently supported by gen-sysreg.awk due to the way we track the active block, which can't handle more than a single layer of nesting, which imposes an awkward requirement that when ending a block we know what the parent block is when calling change_block() Make this nicer by using a stack of active blocks, with block_push() to start a block, and block_pop() to end a block. Doing so means that we only need to check the active block at the start of parsing a line: for the start of a block we can check the parent is valid, and for the end of a block we check that the active block is valid. This structure makes the block parsing simpler and makes it easy to permit a block to live under several potential parents (e.g. by permitting Enum to start when the active block is Sysreg or SysregFields). It also permits further nesting, if we need that in future. To aid debugging, the stack of active blocks is reported for fatal errors, and an error is raised if the file is terminated without ending the active block. For clarity I've renamed the top-level element from "None" to "Root". The Fields element it intended only for use within Sysreg blocks, and does not make sense within SysregFields blocks, and so remains forbidden within a SysregFields block. I've verified using sha1sum that this patch does not change the current generated contents of . Signed-off-by: Mark Rutland Cc: Anshuman Khandual Cc: Catalin Marinas Cc: Marc Zyngier Cc: Mark Brown Cc: Will Deacon Reviewed-by: Mark Brown Reviewed-by: Anshuman Khandual --- arch/arm64/tools/gen-sysreg.awk | 95 ++++++++++++++++++++------------- 1 file changed, 58 insertions(+), 37 deletions(-) This is a preparatory patch for BRBE support, as the BRBE series will add a bunch of SysregFields with Enums. I'm sending this on its own as I think it's a useful improvement/cleanup of the sysreg code regardless. Since v1 [1]: * Rebase to v6.3-rc1 * Cleanup commit message * Expand commit message [1] https://lore.kernel.org/all/Y+P2fSWlJ4+PH5sG@FVFF77S0Q05N.cambridge.arm.com/ Mark. diff --git a/arch/arm64/tools/gen-sysreg.awk b/arch/arm64/tools/gen-sysreg.awk index 6fa0468caa00..d1254a056114 100755 --- a/arch/arm64/tools/gen-sysreg.awk +++ b/arch/arm64/tools/gen-sysreg.awk @@ -4,23 +4,35 @@ # # Usage: awk -f gen-sysreg.awk sysregs.txt +function block_current() { + return __current_block[__current_block_depth]; +} + # Log an error and terminate function fatal(msg) { print "Error at " NR ": " msg > "/dev/stderr" + + printf "Current block nesting:" + + for (i = 0; i <= __current_block_depth; i++) { + printf " " __current_block[i] + } + printf "\n" + exit 1 } -# Sanity check that the start or end of a block makes sense at this point in -# the file. If not, produce an error and terminate. -# -# @this - the $Block or $EndBlock -# @prev - the only valid block to already be in (value of @block) -# @new - the new value of @block -function change_block(this, prev, new) { - if (block != prev) - fatal("unexpected " this " (inside " block ")") - - block = new +# Enter a new block, setting the active block to @block +function block_push(block) { + __current_block[++__current_block_depth] = block +} + +# Exit a block, setting the active block to the parent block +function block_pop() { + if (__current_block_depth == 0) + fatal("error: block_pop() in root block") + + __current_block_depth--; } # Sanity check the number of records for a field makes sense. If not, produce @@ -84,10 +96,14 @@ BEGIN { print "/* Generated file - do not edit */" print "" - block = "None" + __current_block_depth = 0 + __current_block[__current_block_depth] = "Root" } END { + if (__current_block_depth != 0) + fatal("Missing terminator for " block_current() " block") + print "#endif /* __ASM_SYSREG_DEFS_H */" } @@ -95,8 +111,9 @@ END { /^$/ { next } /^[\t ]*#/ { next } -/^SysregFields/ { - change_block("SysregFields", "None", "SysregFields") +/^SysregFields/ && block_current() == "Root" { + block_push("SysregFields") + expect_fields(2) reg = $2 @@ -110,12 +127,10 @@ END { next } -/^EndSysregFields/ { +/^EndSysregFields/ && block_current() == "SysregFields" { if (next_bit > 0) fatal("Unspecified bits in " reg) - change_block("EndSysregFields", "SysregFields", "None") - define(reg "_RES0", "(" res0 ")") define(reg "_RES1", "(" res1 ")") define(reg "_UNKN", "(" unkn ")") @@ -126,11 +141,13 @@ END { res1 = null unkn = null + block_pop() next } -/^Sysreg/ { - change_block("Sysreg", "None", "Sysreg") +/^Sysreg/ && block_current() == "Root" { + block_push("Sysreg") + expect_fields(7) reg = $2 @@ -160,12 +177,10 @@ END { next } -/^EndSysreg/ { +/^EndSysreg/ && block_current() == "Sysreg" { if (next_bit > 0) fatal("Unspecified bits in " reg) - change_block("EndSysreg", "Sysreg", "None") - if (res0 != null) define(reg "_RES0", "(" res0 ")") if (res1 != null) @@ -185,12 +200,13 @@ END { res1 = null unkn = null + block_pop() next } # Currently this is effectivey a comment, in future we may want to emit # defines for the fields. -/^Fields/ && (block == "Sysreg") { +/^Fields/ && block_current() == "Sysreg" { expect_fields(2) if (next_bit != 63) @@ -208,7 +224,7 @@ END { } -/^Res0/ && (block == "Sysreg" || block == "SysregFields") { +/^Res0/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { expect_fields(2) parse_bitdef(reg, "RES0", $2) field = "RES0_" msb "_" lsb @@ -218,7 +234,7 @@ END { next } -/^Res1/ && (block == "Sysreg" || block == "SysregFields") { +/^Res1/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { expect_fields(2) parse_bitdef(reg, "RES1", $2) field = "RES1_" msb "_" lsb @@ -228,7 +244,7 @@ END { next } -/^Unkn/ && (block == "Sysreg" || block == "SysregFields") { +/^Unkn/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { expect_fields(2) parse_bitdef(reg, "UNKN", $2) field = "UNKN_" msb "_" lsb @@ -238,7 +254,7 @@ END { next } -/^Field/ && (block == "Sysreg" || block == "SysregFields") { +/^Field/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { expect_fields(3) field = $3 parse_bitdef(reg, field, $2) @@ -249,15 +265,16 @@ END { next } -/^Raz/ && (block == "Sysreg" || block == "SysregFields") { +/^Raz/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { expect_fields(2) parse_bitdef(reg, field, $2) next } -/^SignedEnum/ { - change_block("Enum<", "Sysreg", "Enum") +/^SignedEnum/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { + block_push("Enum") + expect_fields(3) field = $3 parse_bitdef(reg, field, $2) @@ -268,8 +285,9 @@ END { next } -/^UnsignedEnum/ { - change_block("Enum<", "Sysreg", "Enum") +/^UnsignedEnum/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { + block_push("Enum") + expect_fields(3) field = $3 parse_bitdef(reg, field, $2) @@ -280,8 +298,9 @@ END { next } -/^Enum/ { - change_block("Enum", "Sysreg", "Enum") +/^Enum/ && (block_current() == "Sysreg" || block_current() == "SysregFields") { + block_push("Enum") + expect_fields(3) field = $3 parse_bitdef(reg, field, $2) @@ -291,16 +310,18 @@ END { next } -/^EndEnum/ { - change_block("EndEnum", "Enum", "Sysreg") +/^EndEnum/ && block_current() == "Enum" { + field = null msb = null lsb = null print "" + + block_pop() next } -/0b[01]+/ && block == "Enum" { +/0b[01]+/ && block_current() == "Enum" { expect_fields(2) val = $1 name = $2