mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Sascha Bischoff <Sascha.Bischoff@arm.com>
To: "linux-arm-kernel@lists.infradead.org"
	<linux-arm-kernel@lists.infradead.org>,
	"kvmarm@lists.linux.dev" <kvmarm@lists.linux.dev>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	"kvm@vger.kernel.org" <kvm@vger.kernel.org>
Cc: nd <nd@arm.com>, Mark Rutland <Mark.Rutland@arm.com>,
	Mark Brown <broonie@kernel.org>,
	Catalin Marinas <Catalin.Marinas@arm.com>,
	"maz@kernel.org" <maz@kernel.org>,
	"oliver.upton@linux.dev" <oliver.upton@linux.dev>,
	Joey Gouly <Joey.Gouly@arm.com>,
	Suzuki Poulose <Suzuki.Poulose@arm.com>,
	"yuzenghui@huawei.com" <yuzenghui@huawei.com>,
	"will@kernel.org" <will@kernel.org>,
	"lpieralisi@kernel.org" <lpieralisi@kernel.org>
Subject: [PATCH 1/3] arm64/sysreg: Support feature-specific fields with 'Feat' descriptor
Date: Tue, 7 Oct 2025 15:35:14 +0000	[thread overview]
Message-ID: <20251007153505.1606208-2-sascha.bischoff@arm.com> (raw)
In-Reply-To: <20251007153505.1606208-1-sascha.bischoff@arm.com>

Some system register field encodings change based on the available and
in-use architecture features. In order to support these different
field encodings, introduce the Feat descriptor (Feat, ElseFeat,
EndFeat) for describing such sysregs.

The Feat descriptor can be used in the following way (Feat acts as
both an if and an else-if):

        Sysreg  EXAMPLE 0    1    2    3    4
        Feat    FEAT_A
	Field   63:0    Foo
	Feat    FEAT_B
	Field   63:1    Bar
 	Res0    0
        ElseFeat
        Field   63:0    Baz
        EndFeat
        EndSysreg

This will generate a single set of system register encodings (REG_,
SYS_, ...), and then generate three sets of field definitions for the
system register called EXAMPLE. The first set is prefixed by FEAT_A,
e.g. FEAT_A_EXAMPLE_Foo. The second set is prefixed by FEAT_B, e.g.,
FEAT_B_EXAMPLE_Bar. The third set is not given a prefix at all,
e.g. EXAMPLE_BAZ. For each set, a corresponding set of defines for
Res0, Res1, and Unkn is generated.

The intent for the final prefix-less ElseFeat is for describing
default or legacy field encodings. This ensure that new
feature-conditional encodings can be added to already-present sysregs
without affecting existing legacy code.

The Feat descriptor can be used within Sysreg or SysregFields
blocks. Field, Res0, Res1, Unkn, Rax, SignedEnum, Enum can all be used
within a Feat block. Fields and Mapping can not. Fields that vary with
features must be described as part of a SysregFields block,
instead. Mappings, which are just a code comment, make little sense in
this context, and have hence not been included.

There are no changes to the generated system register definitions as
part of this change.

Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
---
 arch/arm64/tools/gen-sysreg.awk | 148 ++++++++++++++++++++++----------
 1 file changed, 104 insertions(+), 44 deletions(-)

diff --git a/arch/arm64/tools/gen-sysreg.awk b/arch/arm64/tools/gen-sysreg.awk
index f2a1732cb1f63..c1bb6d5087a99 100755
--- a/arch/arm64/tools/gen-sysreg.awk
+++ b/arch/arm64/tools/gen-sysreg.awk
@@ -44,23 +44,35 @@ function expect_fields(nf) {
 
 # Print a CPP macro definition, padded with spaces so that the macro bodies
 # line up in a column
-function define(name, val) {
-	printf "%-56s%s\n", "#define " name, val
+function define(feat, name, val) {
+	printf "%-56s%s\n", "#define " feat name, val
 }
 
 # Print standard BITMASK/SHIFT/WIDTH CPP definitions for a field
-function define_field(reg, field, msb, lsb) {
-	define(reg "_" field, "GENMASK(" msb ", " lsb ")")
-	define(reg "_" field "_MASK", "GENMASK(" msb ", " lsb ")")
-	define(reg "_" field "_SHIFT", lsb)
-	define(reg "_" field "_WIDTH", msb - lsb + 1)
+function define_field(feat, reg, field, msb, lsb) {
+	define(feat, reg "_" field, "GENMASK(" msb ", " lsb ")")
+	define(feat, reg "_" field "_MASK", "GENMASK(" msb ", " lsb ")")
+	define(feat, reg "_" field "_SHIFT", lsb)
+	define(feat, reg "_" field "_WIDTH", msb - lsb + 1)
 }
 
 # Print a field _SIGNED definition for a field
-function define_field_sign(reg, field, sign) {
-	define(reg "_" field "_SIGNED", sign)
+function define_field_sign(feat, reg, field, sign) {
+	define(feat, reg "_" field "_SIGNED", sign)
 }
 
+# Print the Res0, Res1, Unkn masks
+function define_resx_unkn(feat, reg, res0, res1, unkn) {
+	if (res0 != null)
+		define(feat, reg "_RES0", "(" res0 ")")
+	if (res1 != null)
+		define(feat, reg "_RES1", "(" res1 ")")
+	if (unkn != null)
+		define(feat, reg "_UNKN", "(" unkn ")")
+	if (res0 != null || res1 != null || unkn != null)
+		print ""
+	}
+
 # Parse a "<msb>[:<lsb>]" string into the global variables @msb and @lsb
 function parse_bitdef(reg, field, bitdef, _bits)
 {
@@ -132,10 +144,7 @@ $1 == "EndSysregFields" && block_current() == "SysregFields" {
 	if (next_bit > 0)
 		fatal("Unspecified bits in " reg)
 
-	define(reg "_RES0", "(" res0 ")")
-	define(reg "_RES1", "(" res1 ")")
-	define(reg "_UNKN", "(" unkn ")")
-	print ""
+	define_resx_unkn(feat, reg, res0, res1, unkn)
 
 	reg = null
 	res0 = null
@@ -162,14 +171,16 @@ $1 == "Sysreg" && block_current() == "Root" {
 	res1 = "UL(0)"
 	unkn = "UL(0)"
 
-	define("REG_" reg, "S" op0 "_" op1 "_C" crn "_C" crm "_" op2)
-	define("SYS_" reg, "sys_reg(" op0 ", " op1 ", " crn ", " crm ", " op2 ")")
+	feat = null
+
+	define(feat, "REG_" reg, "S" op0 "_" op1 "_C" crn "_C" crm "_" op2)
+	define(feat, "SYS_" reg, "sys_reg(" op0 ", " op1 ", " crn ", " crm ", " op2 ")")
 
-	define("SYS_" reg "_Op0", op0)
-	define("SYS_" reg "_Op1", op1)
-	define("SYS_" reg "_CRn", crn)
-	define("SYS_" reg "_CRm", crm)
-	define("SYS_" reg "_Op2", op2)
+	define(feat, "SYS_" reg "_Op0", op0)
+	define(feat, "SYS_" reg "_Op1", op1)
+	define(feat, "SYS_" reg "_CRn", crn)
+	define(feat, "SYS_" reg "_CRm", crm)
+	define(feat, "SYS_" reg "_Op2", op2)
 
 	print ""
 
@@ -183,14 +194,7 @@ $1 == "EndSysreg" && block_current() == "Sysreg" {
 	if (next_bit > 0)
 		fatal("Unspecified bits in " reg)
 
-	if (res0 != null)
-		define(reg "_RES0", "(" res0 ")")
-	if (res1 != null)
-		define(reg "_RES1", "(" res1 ")")
-	if (unkn != null)
-		define(reg "_UNKN", "(" unkn ")")
-	if (res0 != null || res1 != null || unkn != null)
-		print ""
+	define_resx_unkn(feat, reg, res0, res1, unkn)
 
 	reg = null
 	op0 = null
@@ -201,6 +205,7 @@ $1 == "EndSysreg" && block_current() == "Sysreg" {
 	res0 = null
 	res1 = null
 	unkn = null
+	feat = null
 
 	block_pop()
 	next
@@ -225,8 +230,7 @@ $1 == "EndSysreg" && block_current() == "Sysreg" {
 	next
 }
 
-
-$1 == "Res0" && (block_current() == "Sysreg" || block_current() == "SysregFields") {
+$1 == "Res0" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Feat") {
 	expect_fields(2)
 	parse_bitdef(reg, "RES0", $2)
 	field = "RES0_" msb "_" lsb
@@ -236,7 +240,7 @@ $1 == "Res0" && (block_current() == "Sysreg" || block_current() == "SysregFields
 	next
 }
 
-$1 == "Res1" && (block_current() == "Sysreg" || block_current() == "SysregFields") {
+$1 == "Res1" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Feat") {
 	expect_fields(2)
 	parse_bitdef(reg, "RES1", $2)
 	field = "RES1_" msb "_" lsb
@@ -246,7 +250,7 @@ $1 == "Res1" && (block_current() == "Sysreg" || block_current() == "SysregFields
 	next
 }
 
-$1 == "Unkn" && (block_current() == "Sysreg" || block_current() == "SysregFields") {
+$1 == "Unkn" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Feat") {
 	expect_fields(2)
 	parse_bitdef(reg, "UNKN", $2)
 	field = "UNKN_" msb "_" lsb
@@ -256,58 +260,58 @@ $1 == "Unkn" && (block_current() == "Sysreg" || block_current() == "SysregFields
 	next
 }
 
-$1 == "Field" && (block_current() == "Sysreg" || block_current() == "SysregFields") {
+$1 == "Field" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Feat") {
 	expect_fields(3)
 	field = $3
 	parse_bitdef(reg, field, $2)
 
-	define_field(reg, field, msb, lsb)
+	define_field(feat, reg, field, msb, lsb)
 	print ""
 
 	next
 }
 
-$1 == "Raz" && (block_current() == "Sysreg" || block_current() == "SysregFields") {
+$1 == "Raz" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Feat") {
 	expect_fields(2)
 	parse_bitdef(reg, field, $2)
 
 	next
 }
 
-$1 == "SignedEnum" && (block_current() == "Sysreg" || block_current() == "SysregFields") {
+$1 == "SignedEnum" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Feat") {
 	block_push("Enum")
 
 	expect_fields(3)
 	field = $3
 	parse_bitdef(reg, field, $2)
 
-	define_field(reg, field, msb, lsb)
-	define_field_sign(reg, field, "true")
+	define_field(feat, reg, field, msb, lsb)
+	define_field_sign(feat, reg, field, "true")
 
 	next
 }
 
-$1 == "UnsignedEnum" && (block_current() == "Sysreg" || block_current() == "SysregFields") {
+$1 == "UnsignedEnum" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Feat") {
 	block_push("Enum")
 
 	expect_fields(3)
 	field = $3
 	parse_bitdef(reg, field, $2)
 
-	define_field(reg, field, msb, lsb)
-	define_field_sign(reg, field, "false")
+	define_field(feat, reg, field, msb, lsb)
+	define_field_sign(feat, reg, field, "false")
 
 	next
 }
 
-$1 == "Enum" && (block_current() == "Sysreg" || block_current() == "SysregFields") {
+$1 == "Enum" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Feat") {
 	block_push("Enum")
 
 	expect_fields(3)
 	field = $3
 	parse_bitdef(reg, field, $2)
 
-	define_field(reg, field, msb, lsb)
+	define_field(feat, reg, field, msb, lsb)
 
 	next
 }
@@ -329,7 +333,63 @@ $1 == "EndEnum" && block_current() == "Enum" {
 	val = $1
 	name = $2
 
-	define(reg "_" field "_" name, "UL(" val ")")
+	define(feat, reg "_" field "_" name, "UL(" val ")")
+	next
+}
+
+$1 == "Feat" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Feat") {
+	# Don't push a new block if we're already in a Feat
+	# block. This is to support constructs such as:
+	#	Feat FEAT_A
+	#	...
+	#	Feat FEAT_B
+	#	...
+	#	ElseFeat
+	#	...
+	#	EndFeat
+	if (block_current() != "Feat")
+		block_push("Feat")
+	else
+		define_resx_unkn(feat, reg, res0, res1, unkn)
+
+	expect_fields(2)
+	feat = $2 "_"
+
+	next_bit = 63
+
+	res0 = "UL(0)"
+	res1 = "UL(0)"
+	unkn = "UL(0)"
+
+	next
+}
+
+$1 == "ElseFeat" && block_current() == "Feat" {
+	expect_fields(1)
+
+	define_resx_unkn(feat, reg, res0, res1, unkn)
+
+	res0 = "UL(0)"
+	res1 = "UL(0)"
+	unkn = "UL(0)"
+	feat = null
+	next_bit = 63
+
+	next
+}
+
+$1 == "EndFeat" && block_current() == "Feat" {
+	expect_fields(1)
+
+	define_resx_unkn(feat, reg, res0, res1, unkn)
+
+	res0 = null
+	res1 = null
+	unkn = null
+	feat = null
+
+	block_pop()
+
 	next
 }
 
-- 
2.34.1

  reply	other threads:[~2025-10-07 15:35 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-07 15:35 [PATCH 0/3] arm64/sysreg: Introduce Feat descriptor and generated ICH_VMCR_EL2 support Sascha Bischoff
2025-10-07 15:35 ` Sascha Bischoff [this message]
2025-10-07 16:28   ` [PATCH 1/3] arm64/sysreg: Support feature-specific fields with 'Feat' descriptor Mark Brown
2025-10-09  9:48     ` Sascha Bischoff
2025-10-09 12:42       ` Mark Brown
2025-10-07 15:35 ` [PATCH 3/3] KVM: arm64: gic-v3: Switch vGIC-v3 to use generated ICH_VMCR_EL2 Sascha Bischoff
2025-10-07 15:35 ` [PATCH 2/3] arm64/sysreg: Add ICH_VMCR_EL2 Sascha Bischoff

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251007153505.1606208-2-sascha.bischoff@arm.com \
    --to=sascha.bischoff@arm.com \
    --cc=Catalin.Marinas@arm.com \
    --cc=Joey.Gouly@arm.com \
    --cc=Mark.Rutland@arm.com \
    --cc=Suzuki.Poulose@arm.com \
    --cc=broonie@kernel.org \
    --cc=kvm@vger.kernel.org \
    --cc=kvmarm@lists.linux.dev \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lpieralisi@kernel.org \
    --cc=maz@kernel.org \
    --cc=nd@arm.com \
    --cc=oliver.upton@linux.dev \
    --cc=will@kernel.org \
    --cc=yuzenghui@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®