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