From 2bf6f591c3ad70a4ac39579cb384754577d9798d Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Fri, 3 Nov 2023 11:43:03 +0800 Subject: [PATCH 01/13] arm64: Add sysreg header generation scripting mainline inclusion from mainline-v5.18-rc1 commit 66847e0618d7dcaf34d9626e2b1f699fc05a2fef category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8DFTV CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=66847e0618d7dcaf34d9626e2b1f699fc05a2fef -------------------------------- The arm64 kernel requires some metadata for each system register it may need to access. Currently we have: * A SYS_ definition which sorresponds to a sys_reg() macro. This is used both to look up a sysreg by encoding (e.g. in KVM), and also to generate code to access a sysreg where the assembler is unaware of the specific sysreg encoding. Where assemblers support the S3__C_C_ syntax for system registers, we could use this rather than manually assembling the instructions. However, we don't have consistent definitions for these and we currently still need to handle toolchains that lack this feature. * A set of __SHIFT and __MASK definitions, which can be used to extract fields from the register, or to construct a register from a set of fields. These do not follow the convention used by , and the masks are not shifted into place, preventing their use in FIELD_PREP() and FIELD_GET(). We require the SHIFT definitions for inline assembly (and WIDTH definitions would be helpful for UBFX/SBFX), so we cannot only define a shifted MASK. Defining a SHIFT, WIDTH, shifted MASK and unshifted MASK is tedious and error-prone and life is much easier when they can be relied up to exist when writing code. * A set of __ definitions for each enumerated value a field may hold. These are used when identifying the presence of features. Atop of this, other code has to build up metadata at runtime (e.g. the sets of RES0/RES1 bits in a register). This patch adds scripting so that we can have an easier-to-manage canonical representation of this metadata, from which we can generate all the definitions necessary for various use-cases, e.g. | #define REG_ID_AA64ISAR0_EL1 S3_0_C0_C6_0 | #define SYS_ID_AA64ISAR0_EL1 sys_reg(3, 0, 0, 6, 0) | #define SYS_ID_AA64ISAR0_EL1_Op0 3 | #define SYS_ID_AA64ISAR0_EL1_Op1 0 | #define SYS_ID_AA64ISAR0_EL1_CRn 0 | #define SYS_ID_AA64ISAR0_EL1_CRm 6 | #define SYS_ID_AA64ISAR0_EL1_Op2 0 | #define ID_AA64ISAR0_EL1_RNDR GENMASK(63, 60) | #define ID_AA64ISAR0_EL1_RNDR_MASK GENMASK(63, 60) | #define ID_AA64ISAR0_EL1_RNDR_SHIFT 60 | #define ID_AA64ISAR0_EL1_RNDR_WIDTH 4 | #define ID_AA64ISAR0_EL1_RNDR_NI UL(0b0000) | #define ID_AA64ISAR0_EL1_RNDR_IMP UL(0b0001) The script requires that all bits in the register be specified and that there be no overlapping fields. This helps the script spot errors in the input but means that the few registers which change layout at runtime depending on things like virtualisation settings will need some manual handling. No actual register conversions are done here but a header for the register data with some documention of the format is provided. For cases where multiple registers share a layout (eg, when identical controls are provided at multiple ELs) the register fields can be defined once and referenced from the actual registers, currently we do not generate actual defines for the individual registers. At the moment this is only intended to express metadata from the architecture, and does not handle policy imposed by the kernel, such as values exposed to userspace or VMs. In future this could be extended to express such information. This script was mostly written by Mark Rutland but has been extended by Mark Brown to improve validation of input and better integrate with the kernel. Signed-off-by: Mark Rutland Co-Developed-by: Mark Brown Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20220503170233.507788-9-broonie@kernel.org Signed-off-by: Catalin Marinas Signed-off-by: Junhao He --- arch/arm64/tools/gen-sysreg.awk | 261 ++++++++++++++++++++++++++++++++ arch/arm64/tools/sysreg | 48 ++++++ 2 files changed, 309 insertions(+) create mode 100755 arch/arm64/tools/gen-sysreg.awk create mode 100644 arch/arm64/tools/sysreg diff --git a/arch/arm64/tools/gen-sysreg.awk b/arch/arm64/tools/gen-sysreg.awk new file mode 100755 index 000000000000..3ffd77cbb499 --- /dev/null +++ b/arch/arm64/tools/gen-sysreg.awk @@ -0,0 +1,261 @@ +#!/bin/awk -f +# SPDX-License-Identifier: GPL-2.0 +# gen-sysreg.awk: arm64 sysreg header generator +# +# Usage: awk -f gen-sysreg.awk sysregs.txt + +# Log an error and terminate +function fatal(msg) { + print "Error at " NR ": " msg > "/dev/stderr" + 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 +} + +# Sanity check the number of records for a field makes sense. If not, produce +# an error and terminate. +function expect_fields(nf) { + if (NF != nf) + fatal(NF " fields found where " nf " expected") +} + +# Print a CPP macro definition, padded with spaces so that the macro bodies +# line up in a column +function define(name, val) { + printf "%-48s%s\n", "#define " 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) +} + +# Parse a "[:]" string into the global variables @msb and @lsb +function parse_bitdef(reg, field, bitdef, _bits) +{ + if (bitdef ~ /^[0-9]+$/) { + msb = bitdef + lsb = bitdef + } else if (split(bitdef, _bits, ":") == 2) { + msb = _bits[1] + lsb = _bits[2] + } else { + fatal("invalid bit-range definition '" bitdef "'") + } + + + if (msb != next_bit) + fatal(reg "." field " starts at " msb " not " next_bit) + if (63 < msb || msb < 0) + fatal(reg "." field " invalid high bit in '" bitdef "'") + if (63 < lsb || lsb < 0) + fatal(reg "." field " invalid low bit in '" bitdef "'") + if (msb < lsb) + fatal(reg "." field " invalid bit-range '" bitdef "'") + if (low > high) + fatal(reg "." field " has invalid range " high "-" low) + + next_bit = lsb - 1 +} + +BEGIN { + print "#ifndef __ASM_SYSREG_DEFS_H" + print "#define __ASM_SYSREG_DEFS_H" + print "" + print "/* Generated file - do not edit */" + + block = "None" +} + +END { + print "#endif /* __ASM_SYSREG_DEFS_H */" +} + +# skip blank lines and comment lines +/^$/ { next } +/^#/ { next } + +/^SysregFields/ { + change_block("SysregFields", "None", "SysregFields") + expect_fields(2) + + reg = $2 + + res0 = "UL(0)" + res1 = "UL(0)" + + print "" + + next_bit = 63 + + next +} + +/^EndSysregFields/ { + if (next_bit > 0) + fatal("Unspecified bits in " reg) + + change_block("EndSysregFields", "SysregFields", "None") + + define(reg "_RES0", "(" res0 ")") + define(reg "_RES1", "(" res1 ")") + print "" + + reg = null + res0 = null + res1 = null + + next +} + +/^Sysreg/ { + change_block("Sysreg", "None", "Sysreg") + expect_fields(7) + + reg = $2 + op0 = $3 + op1 = $4 + crn = $5 + crm = $6 + op2 = $7 + + res0 = "UL(0)" + res1 = "UL(0)" + + define("REG_" reg, "S" op0 "_" op1 "_C" crn "_C" crm "_" op2) + define("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) + + print "" + + next_bit = 63 + + next +} + +/^EndSysreg/ { + if (next_bit > 0) + fatal("Unspecified bits in " reg) + + change_block("EndSysreg", "Sysreg", "None") + + if (res0 != null) + define(reg "_RES0", "(" res0 ")") + if (res1 != null) + define(reg "_RES1", "(" res1 ")") + print "" + + reg = null + op0 = null + op1 = null + crn = null + crm = null + op2 = null + res0 = null + res1 = null + + next +} + +# Currently this is effectivey a comment, in future we may want to emit +# defines for the fields. +/^Fields/ && (block == "Sysreg") { + expect_fields(2) + + if (next_bit != 63) + fatal("Some fields already defined for " reg) + + print "/* See " $2 " */" + print "" + + next_bit = 0 + res0 = null + res1 = null + + next +} + + +/^Res0/ && (block == "Sysreg" || block == "SysregFields") { + expect_fields(2) + parse_bitdef(reg, "RES0", $2) + field = "RES0_" msb "_" lsb + + res0 = res0 " | GENMASK_ULL(" msb ", " lsb ")" + + next +} + +/^Res1/ && (block == "Sysreg" || block == "SysregFields") { + expect_fields(2) + parse_bitdef(reg, "RES1", $2) + field = "RES1_" msb "_" lsb + + res1 = res1 " | GENMASK_ULL(" msb ", " lsb ")" + + next +} + +/^Field/ && (block == "Sysreg" || block == "SysregFields") { + expect_fields(3) + field = $3 + parse_bitdef(reg, field, $2) + + define_field(reg, field, msb, lsb) + print "" + + next +} + +/^Enum/ { + change_block("Enum", "Sysreg", "Enum") + expect_fields(3) + field = $3 + parse_bitdef(reg, field, $2) + + define_field(reg, field, msb, lsb) + + next +} + +/^EndEnum/ { + change_block("EndEnum", "Enum", "Sysreg") + field = null + msb = null + lsb = null + print "" + next +} + +/0b[01]+/ && block = "Enum" { + expect_fields(2) + val = $1 + name = $2 + + define(reg "_" field "_" name, "UL(" val ")") + next +} + +# Any lines not handled by previous rules are unexpected +{ + fatal("unhandled statement") +} diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg new file mode 100644 index 000000000000..8e39c718c1b8 --- /dev/null +++ b/arch/arm64/tools/sysreg @@ -0,0 +1,48 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# System register metadata + +# Each System register is described by a Sysreg block: + +# Sysreg +# +# ... +# EndSysreg + +# Within a Sysreg block, each field can be described as one of: + +# Res0 [:] + +# Res1 [:] + +# Field [:] + +# Enum [:] +# +# ... +# EndEnum + +# Alternatively if multiple registers share the same layout then +# a SysregFields block can be used to describe the shared layout + +# SysregFields +# +# ... +# EndSysregFields + +# and referenced from within the Sysreg: + +# Sysreg +# Fields +# EndSysreg + +# For ID registers we adopt a few conventions for translating the +# language in the ARM into defines: +# +# NI - Not implemented +# IMP - Implemented +# +# In general it is recommended that new enumeration items be named for the +# feature that introduces them (eg, FEAT_LS64_ACCDATA introduces enumeration +# item ACCDATA) though it may be more taseful to do something else. + -- Gitee From e6fbeca648b01bbdef5c6369977b5a431ce9a8dd Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 3 Nov 2023 11:43:04 +0800 Subject: [PATCH 02/13] arm64/sysreg: Enable automatic generation of system register definitions mainline inclusion from mainline-v5.18-rc1 commit c07d8017bceb82cbe5fedd129d072c59a53f5513 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8DFTV CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=c07d8017bceb82cbe5fedd129d072c59a53f5513 -------------------------------- Now that we have a script for generating system registers hook it up to the build system similarly to cpucaps. Since we don't currently have any actual register information in the input file this should produce no change in the built kernel. For ease of review the register information will be converted in separate patches. Signed-off-by: Mark Brown Acked-by: Mark Rutland Link: https://lore.kernel.org/r/20220503170233.507788-10-broonie@kernel.org Signed-off-by: Catalin Marinas Signed-off-by: Junhao He --- arch/arm64/Makefile | 3 +++ arch/arm64/include/asm/Kbuild | 2 ++ arch/arm64/include/asm/sysreg.h | 8 ++++++++ arch/arm64/tools/Makefile | 18 ++++++++++++++++++ 4 files changed, 31 insertions(+) create mode 100644 arch/arm64/tools/Makefile diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile index 4a42de35a898..5971ca85a6a1 100644 --- a/arch/arm64/Makefile +++ b/arch/arm64/Makefile @@ -170,6 +170,9 @@ vdso_install: $(if $(CONFIG_COMPAT_VDSO), \ $(Q)$(MAKE) $(build)=arch/arm64/kernel/vdso32 $@) +archprepare: + $(Q)$(MAKE) $(build)=arch/arm64/tools kapi + # We use MRPROPER_FILES and CLEAN_FILES now archclean: $(Q)$(MAKE) $(clean)=$(boot) diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild index a3426b61ff65..cef37f080b05 100644 --- a/arch/arm64/include/asm/Kbuild +++ b/arch/arm64/include/asm/Kbuild @@ -4,3 +4,5 @@ generic-y += mcs_spinlock.h generic-y += qrwlock.h generic-y += set_memory.h generic-y += user.h + +generated-y += sysreg-defs.h diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index 7aded7acdd06..ca9c9b8ca571 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -111,6 +111,14 @@ #define SYS_DC_CSW sys_insn(1, 0, 7, 10, 2) #define SYS_DC_CISW sys_insn(1, 0, 7, 14, 2) +/* + * Automatically generated definitions for system registers, the + * manual encodings below are in the process of being converted to + * come from here. The header relies on the definition of sys_reg() + * earlier in this file. + */ +#include "asm/sysreg-defs.h" + /* * System registers, organised loosely by encoding but grouped together * where the architected name contains an index. e.g. ID_MMFR_EL1. diff --git a/arch/arm64/tools/Makefile b/arch/arm64/tools/Makefile new file mode 100644 index 000000000000..9c3b7edfd720 --- /dev/null +++ b/arch/arm64/tools/Makefile @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0 + +gen := arch/$(ARCH)/include/generated +kapi := $(gen)/asm + +kapi-hdrs-y := $(kapi)/sysreg-defs.h + +targets += $(addprefix ../../../, $(kapi-hdrs-y)) + +PHONY += kapi + +kapi: $(kapi-hdrs-y) + +quiet_cmd_gen_sysreg = GEN $@ + cmd_gen_sysreg = mkdir -p $(dir $@); $(AWK) -f $(real-prereqs) > $@ + +$(kapi)/sysreg-defs.h: $(src)/gen-sysreg.awk $(src)/sysreg FORCE + $(call if_changed,gen_sysreg) -- Gitee From f896de000de1171892318363c0ed3e95fb20cc69 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 3 Nov 2023 11:43:05 +0800 Subject: [PATCH 03/13] arm64/sysreg: Introduce helpers for access to sysreg fields mainline inclusion from mainline-v5.18-rc1 commit e6a6b34f97efe3ded077b31f4370b4c1206c9e56 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8DFTV CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=e6a6b34f97efe3ded077b31f4370b4c1206c9e56 -------------------------------- The macros we define for the bitfields within sysregs have very regular names, especially once we switch to automatic generation of those macros. Take advantage of this to define wrappers around FIELD_PREP() allowing us to simplify setting values in fields either numerically SYS_FIELD_PREP(SCTLR_EL1, TCF0, 0x0) or using the values of enumerations within the fields SYS_FIELD_PREP_ENUM(SCTLR_EL1, TCF0, ASYMM) Suggested-by: Mark Rutland Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20220503170233.507788-2-broonie@kernel.org Signed-off-by: Catalin Marinas Signed-off-by: Junhao He --- arch/arm64/include/asm/sysreg.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index ca9c9b8ca571..80a9dac43479 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -1232,4 +1232,10 @@ #endif +#define SYS_FIELD_PREP(reg, field, val) \ + FIELD_PREP(reg##_##field##_MASK, val) + +#define SYS_FIELD_PREP_ENUM(reg, field, val) \ + FIELD_PREP(reg##_##field##_MASK, reg##_##field##_##val) + #endif /* __ASM_SYSREG_H */ -- Gitee From 413d89c2885521644175ddfe24e160f0a3d663d6 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 3 Nov 2023 11:43:06 +0800 Subject: [PATCH 04/13] arm64/sysreg: Add SYS_FIELD_GET() helper mainline inclusion from mainline-v5.18-rc1 commit 3a87d53853c57c4abea0a2f37cc874c102c2c712 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8DFTV CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=3a87d53853c57c4abea0a2f37cc874c102c2c712 -------------------------------- Add a SYS_FIELD_GET() helper to match SYS_FIELD_PREP(), providing a simplified interface to FIELD_GET() when using the generated defines with standardized naming. Signed-off-by: Mark Brown Acked-by: Mark Rutland Link: https://lore.kernel.org/r/20220704170302.2609529-5-broonie@kernel.org Signed-off-by: Will Deacon Signed-off-by: Junhao He --- arch/arm64/include/asm/sysreg.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index 80a9dac43479..62b81a00ac58 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -1232,6 +1232,9 @@ #endif +#define SYS_FIELD_GET(reg, field, val) \ + FIELD_GET(reg##_##field##_MASK, val) + #define SYS_FIELD_PREP(reg, field, val) \ FIELD_PREP(reg##_##field##_MASK, val) -- Gitee From 94c61bf8af10db6311875c797ee30706bcc4ffcd Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Fri, 3 Nov 2023 11:43:07 +0800 Subject: [PATCH 05/13] arm64/sysreg: improve comment for regs without fields mainline inclusion from mainline-v5.18-rc1 commit 82bf59002e0f84e51c16589080c2feba6e6ec78a category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8DFTV CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=82bf59002e0f84e51c16589080c2feba6e6ec78a -------------------------------- Currently for registers without fields we create a comment pointing at the common definitions, e.g. | #define REG_TTBR0_EL1 S3_0_C2_C0_0 | #define SYS_TTBR0_EL1 sys_reg(3, 0, 2, 0, 0) | #define SYS_TTBR0_EL1_Op0 3 | #define SYS_TTBR0_EL1_Op1 0 | #define SYS_TTBR0_EL1_CRn 2 | #define SYS_TTBR0_EL1_CRm 0 | #define SYS_TTBR0_EL1_Op2 0 | | /* See TTBRx_EL1 */ It would be slightly nicer if the comment said what we should be looking for, e.g. | #define REG_TTBR0_EL1 S3_0_C2_C0_0 | #define SYS_TTBR0_EL1 sys_reg(3, 0, 2, 0, 0) | #define SYS_TTBR0_EL1_Op0 3 | #define SYS_TTBR0_EL1_Op1 0 | #define SYS_TTBR0_EL1_CRn 2 | #define SYS_TTBR0_EL1_CRm 0 | #define SYS_TTBR0_EL1_Op2 0 | | /* For TTBR0_EL1 fields see TTBRx_EL1 */ Update the comment generation accordingly. Signed-off-by: Mark Rutland Cc: Mark Brown Cc: Will Deacon Link: https://lore.kernel.org/r/20220513174118.266966-2-mark.rutland@arm.com Signed-off-by: Catalin Marinas Signed-off-by: Junhao He --- arch/arm64/tools/gen-sysreg.awk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/tools/gen-sysreg.awk b/arch/arm64/tools/gen-sysreg.awk index 3ffd77cbb499..f41feb87d0ca 100755 --- a/arch/arm64/tools/gen-sysreg.awk +++ b/arch/arm64/tools/gen-sysreg.awk @@ -184,7 +184,7 @@ END { if (next_bit != 63) fatal("Some fields already defined for " reg) - print "/* See " $2 " */" + print "/* For " reg " fields see " $2 " */" print "" next_bit = 0 -- Gitee From 7f0761c624531f7c8889cd1234d7866afefd132f Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Fri, 3 Nov 2023 11:43:08 +0800 Subject: [PATCH 06/13] arm64/sysreg: fix odd line spacing mainline inclusion from mainline-v5.18-rc1 commit 5005d1dbbb3828078f32dff24b77866502e45e93 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8DFTV CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=5005d1dbbb3828078f32dff24b77866502e45e93 -------------------------------- Between the header and the definitions, there's no line gap, and in a couple of places a double line gap for no semantic reason, which makes the output look a little odd. Fix this so blocks are consistently separated with a single line gap: * Add a newline after the "Generated file" comment line, so this is clearly split from whatever the first definition in the file is. * At the start of a SysregFields block there's no need for a newline as we haven't output any sysreg encoding details prior to this. * At the end of a Sysreg block there's no need for a newline if we have no RES0 or RES1 fields, as there will be a line gap after the previous element (e.g. a Fields line). There should be no functional change as a result of this patch. Signed-off-by: Mark Rutland Cc: Mark Brown Cc: Will Deacon Link: https://lore.kernel.org/r/20220513174118.266966-3-mark.rutland@arm.com Signed-off-by: Catalin Marinas Signed-off-by: Junhao He --- arch/arm64/tools/gen-sysreg.awk | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/tools/gen-sysreg.awk b/arch/arm64/tools/gen-sysreg.awk index f41feb87d0ca..4aa7ff8ce707 100755 --- a/arch/arm64/tools/gen-sysreg.awk +++ b/arch/arm64/tools/gen-sysreg.awk @@ -77,6 +77,7 @@ BEGIN { print "#define __ASM_SYSREG_DEFS_H" print "" print "/* Generated file - do not edit */" + print "" block = "None" } @@ -98,8 +99,6 @@ END { res0 = "UL(0)" res1 = "UL(0)" - print "" - next_bit = 63 next @@ -162,7 +161,8 @@ END { define(reg "_RES0", "(" res0 ")") if (res1 != null) define(reg "_RES1", "(" res1 ")") - print "" + if (res0 != null || res1 != null) + print "" reg = null op0 = null -- Gitee From 779262d27c750f8c6c84922a9fa87a6761e62bb4 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 3 Nov 2023 11:43:09 +0800 Subject: [PATCH 07/13] arm64/sysreg: Support generation of RAZ fields mainline inclusion from mainline-v5.18-rc1 commit 9e2c0819ac853d94c927d5d2f59e2ca2b48500b4 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8DFTV CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=9e2c0819ac853d94c927d5d2f59e2ca2b48500b4 -------------------------------- Add a statement for RAZ bitfields to the automatic register generation script. Nothing is emitted to the header for these fields. Signed-off-by: Mark Brown Acked-by: Mark Rutland Link: https://lore.kernel.org/r/20220510161208.631259-7-broonie@kernel.org Signed-off-by: Catalin Marinas Signed-off-by: Junhao He --- arch/arm64/tools/gen-sysreg.awk | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/tools/gen-sysreg.awk b/arch/arm64/tools/gen-sysreg.awk index 4aa7ff8ce707..89bfb74e28de 100755 --- a/arch/arm64/tools/gen-sysreg.awk +++ b/arch/arm64/tools/gen-sysreg.awk @@ -226,6 +226,13 @@ END { next } +/^Raz/ && (block == "Sysreg" || block == "SysregFields") { + expect_fields(2) + parse_bitdef(reg, field, $2) + + next +} + /^Enum/ { change_block("Enum", "Sysreg", "Enum") expect_fields(3) -- Gitee From 915bb119432ca4f2debfd17e97f46016ea75b27c Mon Sep 17 00:00:00 2001 From: Alejandro Tafalla Date: Fri, 3 Nov 2023 11:43:10 +0800 Subject: [PATCH 08/13] arm64/sysreg: Fix typo in Enum element regex mainline inclusion from mainline-v5.18-rc1 commit ce253b8573ce3de1278513395f07118650a49e39 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8DFTV CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=ce253b8573ce3de1278513395f07118650a49e39 -------------------------------- In the awk script, there was a typo with the comparison operator when checking if the matched pattern is inside an Enum block. This prevented the generation of the whole sysreg-defs.h header. Fixes: 66847e0618d7 ("arm64: Add sysreg header generation scripting") Signed-off-by: Alejandro Tafalla Reviewed-by: Mark Brown Link: https://lore.kernel.org/r/20220609204220.12112-1-atafalla@dnyon.com Signed-off-by: Catalin Marinas Signed-off-by: Junhao He --- arch/arm64/tools/gen-sysreg.awk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/tools/gen-sysreg.awk b/arch/arm64/tools/gen-sysreg.awk index 89bfb74e28de..5c55509eb43f 100755 --- a/arch/arm64/tools/gen-sysreg.awk +++ b/arch/arm64/tools/gen-sysreg.awk @@ -253,7 +253,7 @@ END { next } -/0b[01]+/ && block = "Enum" { +/0b[01]+/ && block == "Enum" { expect_fields(2) val = $1 name = $2 -- Gitee From b1793ce4a6e0b38e3298d0d90b310c4f8979da02 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 3 Nov 2023 11:43:11 +0800 Subject: [PATCH 09/13] arm64/sysreg: Allow leading blanks on comments in sysreg file mainline inclusion from mainline-v5.18-rc1 commit f43ff286512ec2da2e1038ab76471e9a07e3a951 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8DFTV CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=f43ff286512ec2da2e1038ab76471e9a07e3a951 -------------------------------- Currently we only accept comments where the # is placed at the start of a line, allow leading blanks so we can format comments inside definitions in a more pleasing manner. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20220704170302.2609529-4-broonie@kernel.org Signed-off-by: Will Deacon Signed-off-by: Junhao He --- arch/arm64/tools/gen-sysreg.awk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/tools/gen-sysreg.awk b/arch/arm64/tools/gen-sysreg.awk index 5c55509eb43f..db461921d256 100755 --- a/arch/arm64/tools/gen-sysreg.awk +++ b/arch/arm64/tools/gen-sysreg.awk @@ -88,7 +88,7 @@ END { # skip blank lines and comment lines /^$/ { next } -/^#/ { next } +/^[\t ]*#/ { next } /^SysregFields/ { change_block("SysregFields", "None", "SysregFields") -- Gitee From 17d426f4dd038675db53f8a9afebf1f8622793e4 Mon Sep 17 00:00:00 2001 From: James Morse Date: Fri, 3 Nov 2023 11:43:12 +0800 Subject: [PATCH 10/13] arm64/sysreg: Extend the maximum width of a register and symbol name mainline inclusion from mainline-v6.1-rc1 commit 7587cdef55928ef70d4e945003646711ad39e405 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8DFTV CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=7587cdef55928ef70d4e945003646711ad39e405 -------------------------------- 32bit has multiple values for its id registers, as extra properties were added to the CPUs. Some of these end up having long names, which exceed the fixed 48 character column that the sysreg awk script generates. For example, the ID_MMFR1_EL1.L1Hvd field has an encoding whose natural name would be 'invalidate Iside only'. Using this causes compile errors as the script generates the following: #define ID_MMFR1_EL1_L1Hvd_INVALIDATE_ISIDE_ONLYUL(0b0001) Add a few extra characters. Reviewed-by: Mark Brown Signed-off-by: James Morse Link: https://lore.kernel.org/r/20221130171637.718182-17-james.morse@arm.com Signed-off-by: Will Deacon Signed-off-by: Junhao He --- arch/arm64/tools/gen-sysreg.awk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/tools/gen-sysreg.awk b/arch/arm64/tools/gen-sysreg.awk index db461921d256..c350164a3955 100755 --- a/arch/arm64/tools/gen-sysreg.awk +++ b/arch/arm64/tools/gen-sysreg.awk @@ -33,7 +33,7 @@ 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 "%-48s%s\n", "#define " name, val + printf "%-56s%s\n", "#define " name, val } # Print standard BITMASK/SHIFT/WIDTH CPP definitions for a field -- Gitee From 85dced074e973c09d4a3a10382425ab892590e07 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 3 Nov 2023 11:43:13 +0800 Subject: [PATCH 11/13] arm64/sysreg: Allow enumerations to be declared as signed or unsigned mainline inclusion from mainline-v6.2-rc1 commit a55d1425fb2f4000a415164ba08712de9c1b7755 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8DFTV CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=a55d1425fb2f4000a415164ba08712de9c1b7755 -------------------------------- Many of our enumerations follow a standard scheme where the values can be treated as signed however there are some where the value must be treated as signed and others that are simple enumerations where there is no clear ordering to the values. Provide new field types SignedEnum and UnsignedEnum which allows the signedness to be specified in the sysreg definition and emit a REG_FIELD_SIGNED define for these which is a boolean corresponding to our current FTR_UNSIGNED and FTR_SIGNED macros. Existing Enums will need to be converted, since these do not have a define generated anyone wishing to use the sign of one of these will need to explicitly annotate that field so nothing should start going wrong by default. Acked-by: Mark Rutland Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20221207-arm64-sysreg-helpers-v4-1-25b6b3fb9d18@kernel.org Signed-off-by: Catalin Marinas Signed-off-by: Junhao He --- arch/arm64/tools/gen-sysreg.awk | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/arch/arm64/tools/gen-sysreg.awk b/arch/arm64/tools/gen-sysreg.awk index c350164a3955..7f27d66a17e1 100755 --- a/arch/arm64/tools/gen-sysreg.awk +++ b/arch/arm64/tools/gen-sysreg.awk @@ -44,6 +44,11 @@ function define_field(reg, field, msb, lsb) { define(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) +} + # Parse a "[:]" string into the global variables @msb and @lsb function parse_bitdef(reg, field, bitdef, _bits) { @@ -233,6 +238,30 @@ END { next } +/^SignedEnum/ { + change_block("Enum<", "Sysreg", "Enum") + expect_fields(3) + field = $3 + parse_bitdef(reg, field, $2) + + define_field(reg, field, msb, lsb) + define_field_sign(reg, field, "true") + + next +} + +/^UnsignedEnum/ { + change_block("Enum<", "Sysreg", "Enum") + expect_fields(3) + field = $3 + parse_bitdef(reg, field, $2) + + define_field(reg, field, msb, lsb) + define_field_sign(reg, field, "false") + + next +} + /^Enum/ { change_block("Enum", "Sysreg", "Enum") expect_fields(3) -- Gitee From 6f41418a47aa1129c1434083dabba69f4c6b3d04 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 3 Nov 2023 11:43:14 +0800 Subject: [PATCH 12/13] arm64: Allow the definition of UNKNOWN system register fields mainline inclusion from mainline-v6.2-rc1 commit e2c0b51f1c9dacc68292ce9ebffbfd4204d1ca58 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8DFTV CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=e2c0b51f1c9dacc68292ce9ebffbfd4204d1ca58 -------------------------------- The CCSIDR_EL1 register contains an UNKNOWN field (which replaces fields that were actually defined in previous revisions of the architecture). Define an 'Unkn' field type modeled after the Res0/Res1 types to allow such description. This allows the generation of #define CCSIDR_EL1_UNKN (UL(0) | GENMASK_ULL(31, 28)) which may have its use one day. Hopefully the architecture doesn't add too many of those in the future. Signed-off-by: Marc Zyngier Signed-off-by: Akihiko Odaki Reviewed-by: Mark Brown Link: https://lore.kernel.org/r/20230112023852.42012-2-akihiko.odaki@daynix.com Signed-off-by: Oliver Upton Signed-off-by: Junhao He --- arch/arm64/tools/gen-sysreg.awk | 20 +++++++++++++++++++- arch/arm64/tools/sysreg | 2 ++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/arch/arm64/tools/gen-sysreg.awk b/arch/arm64/tools/gen-sysreg.awk index 7f27d66a17e1..6fa0468caa00 100755 --- a/arch/arm64/tools/gen-sysreg.awk +++ b/arch/arm64/tools/gen-sysreg.awk @@ -103,6 +103,7 @@ END { res0 = "UL(0)" res1 = "UL(0)" + unkn = "UL(0)" next_bit = 63 @@ -117,11 +118,13 @@ END { define(reg "_RES0", "(" res0 ")") define(reg "_RES1", "(" res1 ")") + define(reg "_UNKN", "(" unkn ")") print "" reg = null res0 = null res1 = null + unkn = null next } @@ -139,6 +142,7 @@ END { res0 = "UL(0)" 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 ")") @@ -166,7 +170,9 @@ END { define(reg "_RES0", "(" res0 ")") if (res1 != null) define(reg "_RES1", "(" res1 ")") - if (res0 != null || res1 != null) + if (unkn != null) + define(reg "_UNKN", "(" unkn ")") + if (res0 != null || res1 != null || unkn != null) print "" reg = null @@ -177,6 +183,7 @@ END { op2 = null res0 = null res1 = null + unkn = null next } @@ -195,6 +202,7 @@ END { next_bit = 0 res0 = null res1 = null + unkn = null next } @@ -220,6 +228,16 @@ END { next } +/^Unkn/ && (block == "Sysreg" || block == "SysregFields") { + expect_fields(2) + parse_bitdef(reg, "UNKN", $2) + field = "UNKN_" msb "_" lsb + + unkn = unkn " | GENMASK_ULL(" msb ", " lsb ")" + + next +} + /^Field/ && (block == "Sysreg" || block == "SysregFields") { expect_fields(3) field = $3 diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg index 8e39c718c1b8..936aca8504f9 100644 --- a/arch/arm64/tools/sysreg +++ b/arch/arm64/tools/sysreg @@ -15,6 +15,8 @@ # Res1 [:] +# Unkn [:] + # Field [:] # Enum [:] -- Gitee From 14486ab470704ff26d74c36c384e4a5a4ab6221d Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Fri, 3 Nov 2023 11:43:15 +0800 Subject: [PATCH 13/13] arm64/sysreg: allow *Enum blocks in SysregFields blocks mainline inclusion from mainline-v6.3-rc1 commit 013ecd4439784bc98fe83bfe3413924db97c3b38 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8DFTV CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=013ecd4439784bc98fe83bfe3413924db97c3b38 -------------------------------- 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: Anshuman Khandual Reviewed-by: Mark Brown Link: https://lore.kernel.org/r/20230306114836.2575432-1-mark.rutland@arm.com Signed-off-by: Will Deacon Signed-off-by: Junhao He --- arch/arm64/tools/gen-sysreg.awk | 95 ++++++++++++++++++++------------- 1 file changed, 58 insertions(+), 37 deletions(-) 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 -- Gitee