WIP: arm64: add sysreg header generation scripting
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.
* 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.
* 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 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_AA64ISAR1_EL1 S3_0_C0_C6_1
| #define SYS_ID_AA64ISAR1_EL1 sys_reg(3, 0, 0, 6, 1)
| #define SYS_ID_AA64ISAR1_EL1_Op0 3
| #define SYS_ID_AA64ISAR1_EL1_Op1 0
| #define SYS_ID_AA64ISAR1_EL1_CRn 0
| #define SYS_ID_AA64ISAR1_EL1_CRm 6
| #define SYS_ID_AA64ISAR1_EL1_Op2 1
|
| /* ID_AA64ISAR1_EL1[63:56] RES0 */
|
| #define ID_AA64ISAR1_EL1_I8MM BITMASK(55, 52)
| #define ID_AA64ISAR1_EL1_I8MM_SHIFT 52
| #define ID_AA64ISAR1_EL1_I8MM_WIDTH 4
| #define ID_AA64ISAR1_EL1_I8MM_NI 0b0000
| #define ID_AA64ISAR1_EL1_I8MM_SUPPORTED 0b0001
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.
TODO:
* Decide field format (binary/hex/decimal) and/or add conversion
* Capture field classes (signed/unsigned/enum/debug)
* Error for overlapping fields
* Warn for unhandled bits
* Write up the naming scheme for fieldvals
* Add all system registers
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
2 files changed