[V7,2/6] arm64/perf: Add BRBE registers and fields
Commit Message
This adds BRBE related register definitions and various other related field
macros there in. These will be used subsequently in a BRBE driver which is
being added later on.
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Reviewed-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Anshuman Khandual <anshuman.khandual@arm.com>
---
arch/arm64/include/asm/sysreg.h | 103 ++++++++++++++++++++
arch/arm64/tools/sysreg | 161 ++++++++++++++++++++++++++++++++
2 files changed, 264 insertions(+)
Comments
Hi Anshuman,
On Thu, Jan 05, 2023 at 08:40:35AM +0530, Anshuman Khandual wrote:
> This adds BRBE related register definitions and various other related field
> macros there in. These will be used subsequently in a BRBE driver which is
> being added later on.
I haven't verified the specific values, but this looks good to me aside from
one minor nit below.
[...]
> +# This is just a dummy register declaration to get all common field masks and
> +# shifts for accessing given BRBINF contents.
> +Sysreg BRBINF_EL1 2 1 8 0 0
We don't need a dummy declaration, as we have 'SysregFields' that can be used
for this, e.g.
SysregFields BRBINFx_EL1
...
EndSysregFields
... which will avoid accidental usage of the register encoding. Note that I've
also added an 'x' there in place of the index, which we do for other registers,
e.g. TTBRx_EL1.
Could you please update to that?
With that:
Acked-by: Mark Rutland <mark.rutland@arm.com>
Mark.
On 1/12/23 18:54, Mark Rutland wrote:
> Hi Anshuman,
>
> On Thu, Jan 05, 2023 at 08:40:35AM +0530, Anshuman Khandual wrote:
>> This adds BRBE related register definitions and various other related field
>> macros there in. These will be used subsequently in a BRBE driver which is
>> being added later on.
>
> I haven't verified the specific values, but this looks good to me aside from
> one minor nit below.
>
> [...]
>
>> +# This is just a dummy register declaration to get all common field masks and
>> +# shifts for accessing given BRBINF contents.
>> +Sysreg BRBINF_EL1 2 1 8 0 0
>
> We don't need a dummy declaration, as we have 'SysregFields' that can be used
> for this, e.g.
>
> SysregFields BRBINFx_EL1
> ...
> EndSysregFields
>
> ... which will avoid accidental usage of the register encoding. Note that I've
> also added an 'x' there in place of the index, which we do for other registers,
> e.g. TTBRx_EL1.
>
> Could you please update to that?
There is a problem in defining SysregFields (which I did explore earlier as well).
SysregFields unfortunately does not support enums fields. Following build failure
comes up, while trying to convert BRBINFx_EL1 into a SysregFields definition.
Error at 932: unexpected Enum (inside SysregFields)
===============================================================================
diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg
index a7f9054bd84c..519c4f080898 100644
--- a/arch/arm64/tools/sysreg
+++ b/arch/arm64/tools/sysreg
@@ -921,10 +921,7 @@ Enum 3:0 BT
EndEnum
EndSysreg
-
-# This is just a dummy register declaration to get all common field masks and
-# shifts for accessing given BRBINF contents.
-Sysreg BRBINF_EL1 2 1 8 0 0
+SysregFields BRBINFx_EL1
Res0 63:47
Field 46 CCU
Field 45:32 CC
@@ -967,7 +964,7 @@ Enum 1:0 VALID
0b10 SOURCE
0b11 FULL
EndEnum
-EndSysreg
+EndSysregFields
Sysreg BRBCR_EL1 2 1 9 0 0
Res0 63:24
===============================================================================
There are three enum fields in BRBINFx_EL1 as listed here.
Enum 13:8 TYPE
Enum 7:6 EL
Enum 1:0 VALID
However, BRBINF_EL1 can be changed as BRBINFx_EL1, indicating its more generic
nature with a potential to be used for any index value register thereafter.
>
> With that:
>
> Acked-by: Mark Rutland <mark.rutland@arm.com>
>
> Mark.
On Fri, Jan 13, 2023 at 08:32:47AM +0530, Anshuman Khandual wrote:
> On 1/12/23 18:54, Mark Rutland wrote:
> > Hi Anshuman,
> >
> > On Thu, Jan 05, 2023 at 08:40:35AM +0530, Anshuman Khandual wrote:
> >> This adds BRBE related register definitions and various other related field
> >> macros there in. These will be used subsequently in a BRBE driver which is
> >> being added later on.
> >
> > I haven't verified the specific values, but this looks good to me aside from
> > one minor nit below.
> >
> > [...]
> >
> >> +# This is just a dummy register declaration to get all common field masks and
> >> +# shifts for accessing given BRBINF contents.
> >> +Sysreg BRBINF_EL1 2 1 8 0 0
> >
> > We don't need a dummy declaration, as we have 'SysregFields' that can be used
> > for this, e.g.
> >
> > SysregFields BRBINFx_EL1
> > ...
> > EndSysregFields
> >
> > ... which will avoid accidental usage of the register encoding. Note that I've
> > also added an 'x' there in place of the index, which we do for other registers,
> > e.g. TTBRx_EL1.
> >
> > Could you please update to that?
>
> There is a problem in defining SysregFields (which I did explore earlier as well).
> SysregFields unfortunately does not support enums fields. Following build failure
> comes up, while trying to convert BRBINFx_EL1 into a SysregFields definition.
>
> Error at 932: unexpected Enum (inside SysregFields)
This is a problem, but it's one that we can solve. We're in control of
gen-sysreg.awk and the language it parses, so we can make this an expected and
supported case -- see below.
> ===============================================================================
> diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg
> index a7f9054bd84c..519c4f080898 100644
> --- a/arch/arm64/tools/sysreg
> +++ b/arch/arm64/tools/sysreg
> @@ -921,10 +921,7 @@ Enum 3:0 BT
> EndEnum
> EndSysreg
>
> -
> -# This is just a dummy register declaration to get all common field masks and
> -# shifts for accessing given BRBINF contents.
> -Sysreg BRBINF_EL1 2 1 8 0 0
> +SysregFields BRBINFx_EL1
> Res0 63:47
> Field 46 CCU
> Field 45:32 CC
> @@ -967,7 +964,7 @@ Enum 1:0 VALID
> 0b10 SOURCE
> 0b11 FULL
> EndEnum
> -EndSysreg
> +EndSysregFields
>
> Sysreg BRBCR_EL1 2 1 9 0 0
> Res0 63:24
> ===============================================================================
>
> There are three enum fields in BRBINFx_EL1 as listed here.
>
> Enum 13:8 TYPE
> Enum 7:6 EL
> Enum 1:0 VALID
>
> However, BRBINF_EL1 can be changed as BRBINFx_EL1, indicating its more generic
> nature with a potential to be used for any index value register thereafter.
It's certainly better to use the BRBINFx_EL1 name, but my main concern here is
to avoid the dummy values used above to satisfy the tools, so that those cannot
be accidentally misused.
I'd prefer that we fix gen-sysreg.awk to support Enum blocks within
SysregFields blocks (patch below), then use SysregFields as described above.
Thanks,
Mark.
---->8----
From 0c194d92b0b9ff3b32f666a4610b077fdf1b4b93 Mon Sep 17 00:00:00 2001
From: Mark Rutland <mark.rutland@arm.com>
Date: Wed, 8 Feb 2023 17:55:08 +0000
Subject: [PATCH] arm64/sysreg: allow *Enum blocks in SysregFields blocks
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 hat when
ending a block we don't need to know the parent block type, and checks
of the active block become more consistent. On top of that, it's easy to
permit *Enum blocks within both Sysreg and SysregFields blocks.
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 Systeg blocks, and
does not make sense within SysregFields blocks, and so remains forbidden
within a SysregFields block.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Anshuman Khandual <anshuman.khandual@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: Will Deacon <will@kernel.org>
---
arch/arm64/tools/gen-sysreg.awk | 93 ++++++++++++++++++++-------------
1 file changed, 57 insertions(+), 36 deletions(-)
diff --git a/arch/arm64/tools/gen-sysreg.awk b/arch/arm64/tools/gen-sysreg.awk
index 7f27d66a17e1..066ebf5410fa 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
@@ -109,12 +126,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 ")")
print ""
@@ -123,11 +138,13 @@ END {
res0 = null
res1 = null
+ block_pop()
next
}
-/^Sysreg/ {
- change_block("Sysreg", "None", "Sysreg")
+/^Sysreg/ && block_current() == "Root" {
+ block_push("Sysreg")
+
expect_fields(7)
reg = $2
@@ -156,12 +173,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)
@@ -178,12 +193,13 @@ END {
res0 = null
res1 = 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)
@@ -200,7 +216,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
@@ -210,7 +226,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
@@ -220,7 +236,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)
@@ -231,15 +247,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)
@@ -250,8 +267,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)
@@ -262,8 +280,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)
@@ -273,16 +292,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
On 2/9/23 00:52, Mark Rutland wrote:
> On Fri, Jan 13, 2023 at 08:32:47AM +0530, Anshuman Khandual wrote:
>> On 1/12/23 18:54, Mark Rutland wrote:
>>> Hi Anshuman,
>>>
>>> On Thu, Jan 05, 2023 at 08:40:35AM +0530, Anshuman Khandual wrote:
>>>> This adds BRBE related register definitions and various other related field
>>>> macros there in. These will be used subsequently in a BRBE driver which is
>>>> being added later on.
>>>
>>> I haven't verified the specific values, but this looks good to me aside from
>>> one minor nit below.
>>>
>>> [...]
>>>
>>>> +# This is just a dummy register declaration to get all common field masks and
>>>> +# shifts for accessing given BRBINF contents.
>>>> +Sysreg BRBINF_EL1 2 1 8 0 0
>>>
>>> We don't need a dummy declaration, as we have 'SysregFields' that can be used
>>> for this, e.g.
>>>
>>> SysregFields BRBINFx_EL1
>>> ...
>>> EndSysregFields
>>>
>>> ... which will avoid accidental usage of the register encoding. Note that I've
>>> also added an 'x' there in place of the index, which we do for other registers,
>>> e.g. TTBRx_EL1.
>>>
>>> Could you please update to that?
>>
>> There is a problem in defining SysregFields (which I did explore earlier as well).
>> SysregFields unfortunately does not support enums fields. Following build failure
>> comes up, while trying to convert BRBINFx_EL1 into a SysregFields definition.
>>
>> Error at 932: unexpected Enum (inside SysregFields)
>
> This is a problem, but it's one that we can solve. We're in control of
> gen-sysreg.awk and the language it parses, so we can make this an expected and
> supported case -- see below.
>
>> ===============================================================================
>> diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg
>> index a7f9054bd84c..519c4f080898 100644
>> --- a/arch/arm64/tools/sysreg
>> +++ b/arch/arm64/tools/sysreg
>> @@ -921,10 +921,7 @@ Enum 3:0 BT
>> EndEnum
>> EndSysreg
>>
>> -
>> -# This is just a dummy register declaration to get all common field masks and
>> -# shifts for accessing given BRBINF contents.
>> -Sysreg BRBINF_EL1 2 1 8 0 0
>> +SysregFields BRBINFx_EL1
>> Res0 63:47
>> Field 46 CCU
>> Field 45:32 CC
>> @@ -967,7 +964,7 @@ Enum 1:0 VALID
>> 0b10 SOURCE
>> 0b11 FULL
>> EndEnum
>> -EndSysreg
>> +EndSysregFields
>>
>> Sysreg BRBCR_EL1 2 1 9 0 0
>> Res0 63:24
>> ===============================================================================
>>
>> There are three enum fields in BRBINFx_EL1 as listed here.
>>
>> Enum 13:8 TYPE
>> Enum 7:6 EL
>> Enum 1:0 VALID
>>
>> However, BRBINF_EL1 can be changed as BRBINFx_EL1, indicating its more generic
>> nature with a potential to be used for any index value register thereafter.
>
> It's certainly better to use the BRBINFx_EL1 name, but my main concern here is
> to avoid the dummy values used above to satisfy the tools, so that those cannot
> be accidentally misused.
>
> I'd prefer that we fix gen-sysreg.awk to support Enum blocks within
> SysregFields blocks (patch below), then use SysregFields as described above.
The following patch did not apply cleanly on v6.2-rc7 but eventually did so after
some changes. Is the patch against mainline or arm64-next ? Nonetheless, it does
solve the enum problem for SysregFields. With this patch in place, I was able to
- Change Sysreg BRBINF_EL1 as SysregFields BRBINFx_EL1
- Change BRBINF_EL1_XXX fields usage as BRBINFx_EL1_XXX fields
Should I take this patch with this series as an initial prerequisite patch or you
would like to post this now for current merge window ?
>
> Thanks,
> Mark.
>
> ---->8----
>>From 0c194d92b0b9ff3b32f666a4610b077fdf1b4b93 Mon Sep 17 00:00:00 2001
> From: Mark Rutland <mark.rutland@arm.com>
> Date: Wed, 8 Feb 2023 17:55:08 +0000
> Subject: [PATCH] arm64/sysreg: allow *Enum blocks in SysregFields blocks
>
> 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 hat when
> ending a block we don't need to know the parent block type, and checks
> of the active block become more consistent. On top of that, it's easy to
> permit *Enum blocks within both Sysreg and SysregFields blocks.
>
> 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 Systeg blocks, and
> does not make sense within SysregFields blocks, and so remains forbidden
> within a SysregFields block.
>
> Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> Cc: Anshuman Khandual <anshuman.khandual@arm.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Mark Brown <broonie@kernel.org>
> Cc: Will Deacon <will@kernel.org>
> ---
> arch/arm64/tools/gen-sysreg.awk | 93 ++++++++++++++++++++-------------
> 1 file changed, 57 insertions(+), 36 deletions(-)
>
> diff --git a/arch/arm64/tools/gen-sysreg.awk b/arch/arm64/tools/gen-sysreg.awk
> index 7f27d66a17e1..066ebf5410fa 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
> @@ -109,12 +126,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 ")")
> print ""
> @@ -123,11 +138,13 @@ END {
> res0 = null
> res1 = null
>
> + block_pop()
> next
> }
>
> -/^Sysreg/ {
> - change_block("Sysreg", "None", "Sysreg")
> +/^Sysreg/ && block_current() == "Root" {
> + block_push("Sysreg")
> +
> expect_fields(7)
>
> reg = $2
> @@ -156,12 +173,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)
> @@ -178,12 +193,13 @@ END {
> res0 = null
> res1 = 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)
> @@ -200,7 +216,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
> @@ -210,7 +226,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
> @@ -220,7 +236,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)
> @@ -231,15 +247,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)
> @@ -250,8 +267,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)
> @@ -262,8 +280,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)
> @@ -273,16 +292,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
On Thu, Feb 09, 2023 at 11:19:04AM +0530, Anshuman Khandual wrote:
> On 2/9/23 00:52, Mark Rutland wrote:
> > I'd prefer that we fix gen-sysreg.awk to support Enum blocks within
> > SysregFields blocks (patch below), then use SysregFields as described above.
>
> The following patch did not apply cleanly on v6.2-rc7 but eventually did so after
> some changes. Is the patch against mainline or arm64-next ?
Sorry I forgot to say: that needs the arm64 for-next/sysreg-hwcaps branch
(which is merged into arm64 for-next/core).
> Nonetheless, it does
> solve the enum problem for SysregFields. With this patch in place, I was able to
>
> - Change Sysreg BRBINF_EL1 as SysregFields BRBINFx_EL1
> - Change BRBINF_EL1_XXX fields usage as BRBINFx_EL1_XXX fields
Nice!
> Should I take this patch with this series as an initial prerequisite patch or you
> would like to post this now for current merge window ?
I think for now it's best to add it to this series as a prerequisite.
Thanks,
Mark.
>
> >
> > Thanks,
> > Mark.
> >
> > ---->8----
> >>From 0c194d92b0b9ff3b32f666a4610b077fdf1b4b93 Mon Sep 17 00:00:00 2001
> > From: Mark Rutland <mark.rutland@arm.com>
> > Date: Wed, 8 Feb 2023 17:55:08 +0000
> > Subject: [PATCH] arm64/sysreg: allow *Enum blocks in SysregFields blocks
> >
> > 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 hat when
> > ending a block we don't need to know the parent block type, and checks
> > of the active block become more consistent. On top of that, it's easy to
> > permit *Enum blocks within both Sysreg and SysregFields blocks.
> >
> > 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 Systeg blocks, and
> > does not make sense within SysregFields blocks, and so remains forbidden
> > within a SysregFields block.
> >
> > Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> > Cc: Anshuman Khandual <anshuman.khandual@arm.com>
> > Cc: Catalin Marinas <catalin.marinas@arm.com>
> > Cc: Mark Brown <broonie@kernel.org>
> > Cc: Will Deacon <will@kernel.org>
> > ---
> > arch/arm64/tools/gen-sysreg.awk | 93 ++++++++++++++++++++-------------
> > 1 file changed, 57 insertions(+), 36 deletions(-)
> >
> > diff --git a/arch/arm64/tools/gen-sysreg.awk b/arch/arm64/tools/gen-sysreg.awk
> > index 7f27d66a17e1..066ebf5410fa 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
> > @@ -109,12 +126,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 ")")
> > print ""
> > @@ -123,11 +138,13 @@ END {
> > res0 = null
> > res1 = null
> >
> > + block_pop()
> > next
> > }
> >
> > -/^Sysreg/ {
> > - change_block("Sysreg", "None", "Sysreg")
> > +/^Sysreg/ && block_current() == "Root" {
> > + block_push("Sysreg")
> > +
> > expect_fields(7)
> >
> > reg = $2
> > @@ -156,12 +173,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)
> > @@ -178,12 +193,13 @@ END {
> > res0 = null
> > res1 = 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)
> > @@ -200,7 +216,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
> > @@ -210,7 +226,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
> > @@ -220,7 +236,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)
> > @@ -231,15 +247,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)
> > @@ -250,8 +267,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)
> > @@ -262,8 +280,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)
> > @@ -273,16 +292,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
@@ -165,6 +165,109 @@
#define SYS_DBGDTRTX_EL0 sys_reg(2, 3, 0, 5, 0)
#define SYS_DBGVCR32_EL2 sys_reg(2, 4, 0, 7, 0)
+#define __SYS_BRBINFO(n) sys_reg(2, 1, 8, ((n) & 0xf), ((((n) & 0x10)) >> 2 + 0))
+#define __SYS_BRBSRC(n) sys_reg(2, 1, 8, ((n) & 0xf), ((((n) & 0x10)) >> 2 + 1))
+#define __SYS_BRBTGT(n) sys_reg(2, 1, 8, ((n) & 0xf), ((((n) & 0x10)) >> 2 + 2))
+
+#define SYS_BRBINF0_EL1 __SYS_BRBINFO(0)
+#define SYS_BRBINF1_EL1 __SYS_BRBINFO(1)
+#define SYS_BRBINF2_EL1 __SYS_BRBINFO(2)
+#define SYS_BRBINF3_EL1 __SYS_BRBINFO(3)
+#define SYS_BRBINF4_EL1 __SYS_BRBINFO(4)
+#define SYS_BRBINF5_EL1 __SYS_BRBINFO(5)
+#define SYS_BRBINF6_EL1 __SYS_BRBINFO(6)
+#define SYS_BRBINF7_EL1 __SYS_BRBINFO(7)
+#define SYS_BRBINF8_EL1 __SYS_BRBINFO(8)
+#define SYS_BRBINF9_EL1 __SYS_BRBINFO(9)
+#define SYS_BRBINF10_EL1 __SYS_BRBINFO(10)
+#define SYS_BRBINF11_EL1 __SYS_BRBINFO(11)
+#define SYS_BRBINF12_EL1 __SYS_BRBINFO(12)
+#define SYS_BRBINF13_EL1 __SYS_BRBINFO(13)
+#define SYS_BRBINF14_EL1 __SYS_BRBINFO(14)
+#define SYS_BRBINF15_EL1 __SYS_BRBINFO(15)
+#define SYS_BRBINF16_EL1 __SYS_BRBINFO(16)
+#define SYS_BRBINF17_EL1 __SYS_BRBINFO(17)
+#define SYS_BRBINF18_EL1 __SYS_BRBINFO(18)
+#define SYS_BRBINF19_EL1 __SYS_BRBINFO(19)
+#define SYS_BRBINF20_EL1 __SYS_BRBINFO(20)
+#define SYS_BRBINF21_EL1 __SYS_BRBINFO(21)
+#define SYS_BRBINF22_EL1 __SYS_BRBINFO(22)
+#define SYS_BRBINF23_EL1 __SYS_BRBINFO(23)
+#define SYS_BRBINF24_EL1 __SYS_BRBINFO(24)
+#define SYS_BRBINF25_EL1 __SYS_BRBINFO(25)
+#define SYS_BRBINF26_EL1 __SYS_BRBINFO(26)
+#define SYS_BRBINF27_EL1 __SYS_BRBINFO(27)
+#define SYS_BRBINF28_EL1 __SYS_BRBINFO(28)
+#define SYS_BRBINF29_EL1 __SYS_BRBINFO(29)
+#define SYS_BRBINF30_EL1 __SYS_BRBINFO(30)
+#define SYS_BRBINF31_EL1 __SYS_BRBINFO(31)
+
+#define SYS_BRBSRC0_EL1 __SYS_BRBSRC(0)
+#define SYS_BRBSRC1_EL1 __SYS_BRBSRC(1)
+#define SYS_BRBSRC2_EL1 __SYS_BRBSRC(2)
+#define SYS_BRBSRC3_EL1 __SYS_BRBSRC(3)
+#define SYS_BRBSRC4_EL1 __SYS_BRBSRC(4)
+#define SYS_BRBSRC5_EL1 __SYS_BRBSRC(5)
+#define SYS_BRBSRC6_EL1 __SYS_BRBSRC(6)
+#define SYS_BRBSRC7_EL1 __SYS_BRBSRC(7)
+#define SYS_BRBSRC8_EL1 __SYS_BRBSRC(8)
+#define SYS_BRBSRC9_EL1 __SYS_BRBSRC(9)
+#define SYS_BRBSRC10_EL1 __SYS_BRBSRC(10)
+#define SYS_BRBSRC11_EL1 __SYS_BRBSRC(11)
+#define SYS_BRBSRC12_EL1 __SYS_BRBSRC(12)
+#define SYS_BRBSRC13_EL1 __SYS_BRBSRC(13)
+#define SYS_BRBSRC14_EL1 __SYS_BRBSRC(14)
+#define SYS_BRBSRC15_EL1 __SYS_BRBSRC(15)
+#define SYS_BRBSRC16_EL1 __SYS_BRBSRC(16)
+#define SYS_BRBSRC17_EL1 __SYS_BRBSRC(17)
+#define SYS_BRBSRC18_EL1 __SYS_BRBSRC(18)
+#define SYS_BRBSRC19_EL1 __SYS_BRBSRC(19)
+#define SYS_BRBSRC20_EL1 __SYS_BRBSRC(20)
+#define SYS_BRBSRC21_EL1 __SYS_BRBSRC(21)
+#define SYS_BRBSRC22_EL1 __SYS_BRBSRC(22)
+#define SYS_BRBSRC23_EL1 __SYS_BRBSRC(23)
+#define SYS_BRBSRC24_EL1 __SYS_BRBSRC(24)
+#define SYS_BRBSRC25_EL1 __SYS_BRBSRC(25)
+#define SYS_BRBSRC26_EL1 __SYS_BRBSRC(26)
+#define SYS_BRBSRC27_EL1 __SYS_BRBSRC(27)
+#define SYS_BRBSRC28_EL1 __SYS_BRBSRC(28)
+#define SYS_BRBSRC29_EL1 __SYS_BRBSRC(29)
+#define SYS_BRBSRC30_EL1 __SYS_BRBSRC(30)
+#define SYS_BRBSRC31_EL1 __SYS_BRBSRC(31)
+
+#define SYS_BRBTGT0_EL1 __SYS_BRBTGT(0)
+#define SYS_BRBTGT1_EL1 __SYS_BRBTGT(1)
+#define SYS_BRBTGT2_EL1 __SYS_BRBTGT(2)
+#define SYS_BRBTGT3_EL1 __SYS_BRBTGT(3)
+#define SYS_BRBTGT4_EL1 __SYS_BRBTGT(4)
+#define SYS_BRBTGT5_EL1 __SYS_BRBTGT(5)
+#define SYS_BRBTGT6_EL1 __SYS_BRBTGT(6)
+#define SYS_BRBTGT7_EL1 __SYS_BRBTGT(7)
+#define SYS_BRBTGT8_EL1 __SYS_BRBTGT(8)
+#define SYS_BRBTGT9_EL1 __SYS_BRBTGT(9)
+#define SYS_BRBTGT10_EL1 __SYS_BRBTGT(10)
+#define SYS_BRBTGT11_EL1 __SYS_BRBTGT(11)
+#define SYS_BRBTGT12_EL1 __SYS_BRBTGT(12)
+#define SYS_BRBTGT13_EL1 __SYS_BRBTGT(13)
+#define SYS_BRBTGT14_EL1 __SYS_BRBTGT(14)
+#define SYS_BRBTGT15_EL1 __SYS_BRBTGT(15)
+#define SYS_BRBTGT16_EL1 __SYS_BRBTGT(16)
+#define SYS_BRBTGT17_EL1 __SYS_BRBTGT(17)
+#define SYS_BRBTGT18_EL1 __SYS_BRBTGT(18)
+#define SYS_BRBTGT19_EL1 __SYS_BRBTGT(19)
+#define SYS_BRBTGT20_EL1 __SYS_BRBTGT(20)
+#define SYS_BRBTGT21_EL1 __SYS_BRBTGT(21)
+#define SYS_BRBTGT22_EL1 __SYS_BRBTGT(22)
+#define SYS_BRBTGT23_EL1 __SYS_BRBTGT(23)
+#define SYS_BRBTGT24_EL1 __SYS_BRBTGT(24)
+#define SYS_BRBTGT25_EL1 __SYS_BRBTGT(25)
+#define SYS_BRBTGT26_EL1 __SYS_BRBTGT(26)
+#define SYS_BRBTGT27_EL1 __SYS_BRBTGT(27)
+#define SYS_BRBTGT28_EL1 __SYS_BRBTGT(28)
+#define SYS_BRBTGT29_EL1 __SYS_BRBTGT(29)
+#define SYS_BRBTGT30_EL1 __SYS_BRBTGT(30)
+#define SYS_BRBTGT31_EL1 __SYS_BRBTGT(31)
+
#define SYS_MIDR_EL1 sys_reg(3, 0, 0, 0, 0)
#define SYS_MPIDR_EL1 sys_reg(3, 0, 0, 0, 5)
#define SYS_REVIDR_EL1 sys_reg(3, 0, 0, 0, 6)
@@ -921,6 +921,167 @@ Enum 3:0 BT
EndEnum
EndSysreg
+
+# This is just a dummy register declaration to get all common field masks and
+# shifts for accessing given BRBINF contents.
+Sysreg BRBINF_EL1 2 1 8 0 0
+Res0 63:47
+Field 46 CCU
+Field 45:32 CC
+Res0 31:18
+Field 17 LASTFAILED
+Field 16 T
+Res0 15:14
+Enum 13:8 TYPE
+ 0b000000 UNCOND_DIR
+ 0b000001 INDIR
+ 0b000010 DIR_LINK
+ 0b000011 INDIR_LINK
+ 0b000101 RET_SUB
+ 0b000111 RET_EXCPT
+ 0b001000 COND_DIR
+ 0b100001 DEBUG_HALT
+ 0b100010 CALL
+ 0b100011 TRAP
+ 0b100100 SERROR
+ 0b100110 INST_DEBUG
+ 0b100111 DATA_DEBUG
+ 0b101010 ALGN_FAULT
+ 0b101011 INST_FAULT
+ 0b101100 DATA_FAULT
+ 0b101110 IRQ
+ 0b101111 FIQ
+ 0b111001 DEBUG_EXIT
+EndEnum
+Enum 7:6 EL
+ 0b00 EL0
+ 0b01 EL1
+ 0b10 EL2
+ 0b11 EL3
+EndEnum
+Field 5 MPRED
+Res0 4:2
+Enum 1:0 VALID
+ 0b00 NONE
+ 0b01 TARGET
+ 0b10 SOURCE
+ 0b11 FULL
+EndEnum
+EndSysreg
+
+Sysreg BRBCR_EL1 2 1 9 0 0
+Res0 63:24
+Field 23 EXCEPTION
+Field 22 ERTN
+Res0 21:9
+Field 8 FZP
+Res0 7
+Enum 6:5 TS
+ 0b01 VIRTUAL
+ 0b10 GST_PHYSICAL
+ 0b11 PHYSICAL
+EndEnum
+Field 4 MPRED
+Field 3 CC
+Res0 2
+Field 1 E1BRE
+Field 0 E0BRE
+EndSysreg
+
+Sysreg BRBFCR_EL1 2 1 9 0 1
+Res0 63:30
+Enum 29:28 BANK
+ 0b0 FIRST
+ 0b1 SECOND
+EndEnum
+Res0 27:23
+Field 22 CONDDIR
+Field 21 DIRCALL
+Field 20 INDCALL
+Field 19 RTN
+Field 18 INDIRECT
+Field 17 DIRECT
+Field 16 EnI
+Res0 15:8
+Field 7 PAUSED
+Field 6 LASTFAILED
+Res0 5:0
+EndSysreg
+
+Sysreg BRBTS_EL1 2 1 9 0 2
+Field 63:0 TS
+EndSysreg
+
+Sysreg BRBINFINJ_EL1 2 1 9 1 0
+Res0 63:47
+Field 46 CCU
+Field 45:32 CC
+Res0 31:18
+Field 17 LASTFAILED
+Field 16 T
+Res0 15:14
+Enum 13:8 TYPE
+ 0b000000 UNCOND_DIR
+ 0b000001 INDIR
+ 0b000010 DIR_LINK
+ 0b000011 INDIR_LINK
+ 0b000100 RET_SUB
+ 0b000100 RET_SUB
+ 0b000111 RET_EXCPT
+ 0b001000 COND_DIR
+ 0b100001 DEBUG_HALT
+ 0b100010 CALL
+ 0b100011 TRAP
+ 0b100100 SERROR
+ 0b100110 INST_DEBUG
+ 0b100111 DATA_DEBUG
+ 0b101010 ALGN_FAULT
+ 0b101011 INST_FAULT
+ 0b101100 DATA_FAULT
+ 0b101110 IRQ
+ 0b101111 FIQ
+ 0b111001 DEBUG_EXIT
+EndEnum
+Enum 7:6 EL
+ 0b00 EL0
+ 0b01 EL1
+ 0b10 EL2
+ 0b11 EL3
+EndEnum
+Field 5 MPRED
+Res0 4:2
+Enum 1:0 VALID
+ 0b00 NONE
+ 0b01 TARGET
+ 0b10 SOURCE
+ 0b00 FULL
+EndEnum
+EndSysreg
+
+Sysreg BRBSRCINJ_EL1 2 1 9 1 1
+Field 63:0 ADDRESS
+EndSysreg
+
+Sysreg BRBTGTINJ_EL1 2 1 9 1 2
+Field 63:0 ADDRESS
+EndSysreg
+
+Sysreg BRBIDR0_EL1 2 1 9 2 0
+Res0 63:16
+Enum 15:12 CC
+ 0b101 20_BIT
+EndEnum
+Enum 11:8 FORMAT
+ 0b0 0
+EndEnum
+Enum 7:0 NUMREC
+ 0b1000 8
+ 0b10000 16
+ 0b100000 32
+ 0b1000000 64
+EndEnum
+EndSysreg
+
Sysreg ID_AA64ZFR0_EL1 3 0 0 4 4
Res0 63:60
Enum 59:56 F64MM