[PATCH v1 0/9] arm64: Automatic system register definition generation
Mark Brown
broonie at kernel.org
Tue Mar 15 06:14:44 PDT 2022
The arm64 kernel requires some metadata for each system register it may
need to access. Currently we have:
* A SYS_<regname> 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_<op1>_C<crn>_C<crm>_<op2> 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 <regname>_<fieldname>_SHIFT and <regname>_<fieldname>_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 <linux/bitfield.h>, 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 <regname>_<fieldname>_<valname> 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 series introduces a
script which describes registers and the fields within them in a format
that is easy to cross reference with the architecture reference manual
and uses them to generate the constants we use in a standard format:
| #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 ARM64_SYSREG_BITMASK(63, 60)
| #define ID_AA64ISAR0_EL1_RNDR_MASK ARM64_SYSREG_BITMASK(63, 60)
| #define ID_AA64ISAR0_EL1_RNDR_SHIFT 60
| #define ID_AA64ISAR0_EL1_RNDR_WIDTH 4
| #define ID_AA64ISAR0_EL1_RNDR_NI ULL(0b0000)
| #define ID_AA64ISAR0_EL1_RNDR_IMP ULL(0b0001)
This should be particularly useful for the ID registers where we will be
able to specify just the register and field for more of the bitfield
information, simplifying ARM64_FTR_BITS() and providing helpers for use
in struct arm64_cpu_capabilities or for hwcaps.
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 could also be extended to cover more
information such as the FTR_SIGNED/FTR_UNSIGNED distinction. There is
also currently no support for registers which change layout at runtime,
for example based on virtualisation settings - these could be manually
handled for the time being, or the script extended.
At the present time (especially given how near we are to the merge
window) this is as much about getting feedback on the general approach
and how to move forward if we want to move forward. Rather than
attempting to convert every register at once the current series converts
a few sample registers to provide some concrete examples but allow for
easier updating during review of the file format and the script.
Handling a register at a time should also make review less taxing so it
seems like a sensible approach in general.
The generation script was originally written by Mark Rutland and
subsequently improved and integrated into the kernel build by me.
Mark Brown (8):
arm64/mte: Move shift from definition of TCF0 enumeration values
arm64/sysreg: Standardise ID_AA64ISAR0_EL1 macro names
arm64/sysreg: Rename SCTLR_EL1_NTWE/TWI to SCTLR_EL1_nTWE/TWI
arm64/sysreg: Provide a helper macro for defining sysreg bitmasks
arm64/sysreg: Enable automatic generation of system register
definitions
arm64/sysreg: Generate definitions for ID_AA64ISAR0_EL1
arm64/sysreg: Generate definitions for TTBRn_EL1
arm64/sysreg: Generate definitions for SCTLR_EL1
Mark Rutland (1):
arm64: Add sysreg header generation scripting
arch/arm64/include/asm/Kbuild | 1 +
arch/arm64/include/asm/archrandom.h | 2 +-
arch/arm64/include/asm/sysreg.h | 63 +-----
arch/arm64/kernel/cpufeature.c | 70 +++---
arch/arm64/kernel/mte.c | 6 +-
.../arm64/kvm/hyp/include/nvhe/fixed_config.h | 28 +--
arch/arm64/tools/Makefile | 8 +-
arch/arm64/tools/gen-sysreg.awk | 213 ++++++++++++++++++
arch/arm64/tools/sysreg | 183 +++++++++++++++
9 files changed, 468 insertions(+), 106 deletions(-)
create mode 100755 arch/arm64/tools/gen-sysreg.awk
create mode 100644 arch/arm64/tools/sysreg
base-commit: 7903522790f477201e0bd1556c23ca6ac534e247
--
2.30.2
More information about the linux-arm-kernel
mailing list