Linux KVM/arm64 development list
 help / color / mirror / Atom feed
From: Eric Auger <eric.auger@redhat.com>
To: eric.auger.pro@gmail.com, eric.auger@redhat.com,
	qemu-devel@nongnu.org, qemu-arm@nongnu.org,
	kvmarm@lists.linux.dev, peter.maydell@linaro.org,
	shaju.abraham@nutanix.com, khushit.shah@nutanix.com,
	yangjinqian1@huawei.com, cohuck@redhat.com,
	richard.henderson@linaro.org, sebott@redhat.com,
	skolothumtho@nvidia.com, philmd@linaro.org
Cc: maz@kernel.org, oliver.upton@linux.dev, pbonzini@redhat.com,
	armbru@redhat.com, berrange@redhat.com, abologna@redhat.com,
	jdenemar@redhat.com
Subject: [PATCH v5 06/18] scripts: Introduce scripts/update-aarch64-cpu-sysreg-properties.py
Date: Tue, 19 May 2026 15:27:20 +0200	[thread overview]
Message-ID: <20260519132905.145643-7-eric.auger@redhat.com> (raw)
In-Reply-To: <20260519132905.145643-1-eric.auger@redhat.com>

Introduce a script that takes as input the Registers.json file
delivered in the AARCHMRS Features Model downloadable from the
Arm Developer A-Profile Architecture Exploration Tools page:
https://developer.arm.com/Architectures/A-Profile%20Architecture#Downloads
and automates the generation of system register properties definitions.

generates target/arm/cpu-idregs.h.inc containing definitions for
feature ID registers.

We only care about IDregs with opcodes satisfying:
op0 = 3, op1 = {0,1,3}, crn = 0, crm within [0, 7], op2 within [0, 7]

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 .../update-aarch64-cpu-sysreg-properties.py   | 168 ++++++++++++++++++
 1 file changed, 168 insertions(+)
 create mode 100644 scripts/update-aarch64-cpu-sysreg-properties.py

diff --git a/scripts/update-aarch64-cpu-sysreg-properties.py b/scripts/update-aarch64-cpu-sysreg-properties.py
new file mode 100644
index 0000000000..3571e228ee
--- /dev/null
+++ b/scripts/update-aarch64-cpu-sysreg-properties.py
@@ -0,0 +1,168 @@
+#!/usr/bin/env python3
+
+# This script takes as input the Registers.json file delivered in
+# the AARCHMRS Features Model downloadable from the Arm Developer
+# A-Profile Architecture Exploration Tools page:
+# https://developer.arm.com/Architectures/A-Profile%20Architecture#Downloads
+# and outputs target/arm/cpu-sysreg-properties.c content.
+# There, initialize_cpu_sysreg_properties() populates arm64_id_regs array
+# with the name of each ID register and definition of all its fields
+# including their name and min/max bit under the form of the below pattern:
+#
+# /* CCSIDR2_EL1 */
+# ARM64SysReg *CCSIDR2_EL1 = arm64_sysreg_get(CCSIDR2_EL1_IDX);
+# CCSIDR2_EL1->name = "CCSIDR2_EL1";
+# arm64_sysreg_add_field(CCSIDR2_EL1, "NumSets", 0, 23);
+#
+# Copyright (C) 2026 Red Hat, Inc.
+#
+# Authors: Eric Auger <eric.auger@redhat.com>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+
+import json
+import os
+import sys
+from aarch64_sysreg_helpers import extract_idregs_from_registers_json
+
+def collect_fields(item, bit_offset=0):
+    """
+    Recursively finds all field-like objects, handling Fields.Array,
+    Fields.ArrayField, and ConditionalField structures.
+    Applies bit_offset from containers to child fields.
+    """
+    fields = []
+    if not isinstance(item, dict):
+        return fields
+
+    _type = item.get('_type', '')
+
+    # Array types (for example CLIDR_EL1 Ctype<n>, Ttype<n>)
+    if _type == 'Fields.Array':
+        name_template = item.get('name') or item.get('label', '')
+        index_info = item.get('indexes', [{}])[0]
+        start_idx = index_info.get('start', 0)
+        count = index_info.get('width', 0)
+
+        full_range = item.get('rangeset', [{}])[0]
+        bit_start = full_range.get('start', 0) + bit_offset
+        elem_width = full_range.get('width', 0) // count if count else 0
+
+        for i in range(count):
+            idx = start_idx + i
+            # Correctly handle indexed names like Ctype1, Ctype2
+            field_name = name_template.replace('<n>', str(idx))
+            fields.append({
+                'name': field_name,
+                'rangeset': [{
+                    'start': bit_start + (i * elem_width),
+                    'width': elem_width
+                }],
+                '_type': 'Fields.Field'
+            })
+        return fields
+
+    # ConditionalFields
+    elif _type == 'Fields.ConditionalField':
+        inner_offset = bit_offset
+        if item.get('rangeset'):
+            # Parent container defines the absolute start bit
+            inner_offset = item['rangeset'][0].get('start', bit_offset)
+
+        for entry in item.get('fields', []):
+            inner = entry.get('field')
+            if inner:
+                fields.extend(collect_fields(inner, inner_offset))
+        return fields
+
+    # Normal Field Types
+    leaf_types = ['Fields.Field', 'Fields.ConstantField',
+                  'Fields.EnumeratedField', 'Fields.Bitfield']
+    if _type in leaf_types:
+        field_copy = item.copy()
+        if field_copy.get('rangeset'):
+            new_ranges = []
+            for r in field_copy['rangeset']:
+                nr = r.copy()
+                # Apply the cumulative offset to the field's start bit
+                nr['start'] = r.get('start', 0) + bit_offset
+                new_ranges.append(nr)
+            field_copy['rangeset'] = new_ranges
+        fields.append(field_copy)
+        return fields
+
+    # Traverse the hierarchy for other cases
+    for key in ['fields', 'values', 'fieldsets']:
+        for nested in item.get(key, []):
+            fields.extend(collect_fields(nested, bit_offset))
+
+    return fields
+
+
+def generate_sysreg_properties_from_registers_json(id_reg_names, raw_json_path):
+    with open(raw_json_path, 'r') as f:
+        register_data = json.load(f)
+
+    regs = {r.get('name'): r for r in register_data if r.get('_type') == 'Register'}
+
+    final_output = ""
+
+    for reg_name in id_reg_names:
+        register = regs.get(reg_name)
+        if not register:
+            continue
+
+        final_output += f"    IDREG_START({reg_name})\n"
+
+        unique_fields = {}
+        for fieldset in register.get('fieldsets', []):
+            candidates = collect_fields(fieldset)
+            for val in candidates:
+                name = (val.get('name') or val.get('label', '')).strip()
+                if not name or "RESERVED" in name.upper():
+                    continue
+                for r in val.get('rangeset', []):
+                    lsb = int(r.get('start'))
+                    width = r.get('width')
+                    msb = lsb + int(width) - 1
+
+                    # Only keep the fields with the highest MSB
+                    # needed fir CCSIDR_EL1
+                    if name not in unique_fields or msb > unique_fields[name]['msb']:
+                        unique_fields[name] = {'lsb': lsb, 'msb': msb, 'width': width}
+
+        # Sort decreasing lsbs
+        sorted_fields = sorted(unique_fields.items(),
+                               key=lambda x: x[1]['lsb'], reverse=True)
+
+        for name, bits in sorted_fields:
+            line = (f"    IDREG_FIELD({reg_name}, "
+                    f"{name}, {bits['lsb']}, {bits['width']})\n")
+            final_output += line
+        final_output += f"    IDREG_END({reg_name})\n"
+        final_output += "\n"
+
+    os.makedirs("target/arm", exist_ok=True)
+    with open("target/arm/cpu-idregs.h.inc", 'w') as f:
+        f.write("/* AUTOMATICALLY GENERATED, DO NOT MODIFY */\n\n")
+        f.write("/* SPDX-License-Identifier: GPL-2.0-or-later */\n\n")
+        f.write("/* IDREG_START(REG) */\n")
+        f.write("/* IDREG_FIELD(REG, FIELD, SHIFT, LENGTH) */\n")
+        f.write("/* ... */\n")
+        f.write("/* IDREG_END(REG) */\n\n")
+        f.write(final_output)
+
+if __name__ == "__main__":
+    if len(sys.argv) < 2:
+        print("Usage: python scripts/update-aarch64-cpu-sysreg-properties.py "
+              "<path_to_registers_json>")
+    else:
+        json_path = sys.argv[1]
+
+        id_regs_dict = extract_idregs_from_registers_json(json_path)
+        sorted_names = sorted(id_regs_dict.keys())
+
+        if sorted_names:
+            generate_sysreg_properties_from_registers_json(sorted_names, json_path)
+            print("Generated target/arm/cpu-idregs.h.inc")
-- 
2.53.0


  parent reply	other threads:[~2026-05-19 13:30 UTC|newest]

Thread overview: 76+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-19 13:27 [PATCH v5 00/18] kvm/arm: Introduce a customizable aarch64 KVM host model Eric Auger
2026-05-19 13:27 ` [PATCH v5 01/18] scripts: introduce scripts/update-aarch64-cpu-sysregs-header.py Eric Auger
2026-05-19 13:27 ` [PATCH v5 02/18] target/arm/cpu-sysregs.h.inc: Sort by name alphabetical order Eric Auger
2026-06-01 14:07   ` Shameer Kolothum Thodi
2026-05-19 13:27 ` [PATCH v5 03/18] target/arm/cpu-sysregs.h.inc: Update with automatic generation Eric Auger
2026-06-01 14:09   ` Shameer Kolothum Thodi
2026-05-19 13:27 ` [PATCH v5 04/18] arm/cpu: Add infra to handle generated ID register definitions Eric Auger
2026-05-21 13:23   ` Sebastian Ott
2026-06-01 14:28   ` Shameer Kolothum Thodi
2026-06-12  7:38     ` Eric Auger
2026-06-15 13:20       ` Shameer Kolothum Thodi
2026-05-19 13:27 ` [PATCH v5 05/18] scripts: Introduce scripts/aarch64_sysreg_helpers module Eric Auger
2026-05-19 13:27 ` Eric Auger [this message]
2026-05-27 14:35   ` [PATCH v5 06/18] scripts: Introduce scripts/update-aarch64-cpu-sysreg-properties.py Khushit Shah
2026-05-27 15:11     ` Eric Auger
2026-05-19 13:27 ` [PATCH v5 07/18] target/arm/cpu-idregs.h.inc: generate with script Eric Auger
2026-05-19 13:27 ` [PATCH v5 08/18] target/arm/cpu_idregs: generate tables for Arm64 ID registers and fields Eric Auger
2026-05-21 13:27   ` Sebastian Ott
2026-05-27 14:52   ` Khushit Shah
2026-05-27 15:14     ` Eric Auger
2026-05-19 13:27 ` [PATCH v5 09/18] target/arm/kvm: Introduce kvm_get_writable_id_regs Eric Auger
2026-05-21 13:43   ` Sebastian Ott
2026-06-01 15:26   ` Shameer Kolothum Thodi
2026-05-19 13:27 ` [PATCH v5 10/18] target/arm/cpu64: Retrieve writable ID reg map in aarch64_host_initfn() Eric Auger
2026-05-21 13:47   ` Sebastian Ott
2026-05-27 14:54   ` Khushit Shah
2026-05-27 15:17     ` Eric Auger
2026-05-19 13:27 ` [PATCH v5 11/18] arm/kvm: Initialize all writable ID registers from host Eric Auger
2026-05-21 14:22   ` Sebastian Ott
2026-05-27 15:02   ` Khushit Shah
2026-05-27 15:25     ` Eric Auger
2026-05-27 15:30     ` Eric Auger
2026-05-19 13:27 ` [PATCH v5 12/18] arm/kvm: write back modified ID regs to KVM Eric Auger
2026-05-27 14:42   ` Khushit Shah
2026-05-27 15:28     ` Khushit Shah
2026-05-27 15:33       ` Khushit Shah
2026-05-28 17:35     ` Eric Auger
2026-05-19 13:27 ` [PATCH v5 13/18] target/arm/kvm: Introduce kvm_arm_expose_idreg_properties Eric Auger
2026-05-26 14:42   ` Sebastian Ott
2026-05-27 15:08   ` Khushit Shah
2026-05-27 15:32     ` Eric Auger
2026-05-27 15:44       ` Khushit Shah
2026-05-27 16:19         ` Eric Auger
2026-05-28  5:07           ` Khushit Shah
2026-05-28 15:22             ` Eric Auger
2026-05-19 13:27 ` [PATCH v5 14/18] target/arm/kvm: Special case REVIDR_EL1 and AIDR_EL1 Eric Auger
2026-05-26 15:08   ` Sebastian Ott
2026-05-19 13:27 ` [PATCH v5 15/18] target/arm/kvm: Ignore some writable bits that shouldn't be Eric Auger
2026-05-27 14:46   ` Khushit Shah
2026-05-27 15:45     ` Eric Auger
2026-05-27 15:54       ` Khushit Shah
2026-05-27 16:01         ` Eric Auger
2026-05-27 16:16           ` Khushit Shah
2026-05-27 16:30             ` Eric Auger
2026-05-19 13:27 ` [PATCH v5 16/18] target/arm/cpu: Expose writable ID reg field properties on the kvm host vcpu model Eric Auger
2026-05-26 14:51   ` Sebastian Ott
2026-05-27 15:16   ` Khushit Shah
2026-05-27 15:51     ` Eric Auger
2026-05-27 15:56       ` Khushit Shah
2026-05-27 16:04         ` Eric Auger
2026-05-27 16:11           ` Khushit Shah
2026-05-27 17:20             ` Eric Auger
2026-05-28  5:29               ` Khushit Shah
2026-05-28 17:31                 ` Eric Auger
2026-05-28 15:14             ` Eric Auger
2026-05-19 13:27 ` [PATCH v5 17/18] arm-qmp-cmds: introspection for ID register props Eric Auger
2026-05-27  6:29   ` Sebastian Ott
2026-06-16  8:02     ` Eric Auger
2026-05-27 15:17   ` Khushit Shah
2026-05-27 15:55     ` Eric Auger
2026-05-19 13:27 ` [PATCH v5 18/18] arm/cpu-features: document ID reg properties Eric Auger
2026-05-27  6:37   ` Sebastian Ott
2026-06-04  6:08 ` [PATCH v5 00/18] kvm/arm: Introduce a customizable aarch64 KVM host model Jinqian Yang
2026-06-04  6:32   ` Jinqian Yang
2026-06-04  8:31     ` Eric Auger
2026-06-04 12:00       ` Jinqian Yang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260519132905.145643-7-eric.auger@redhat.com \
    --to=eric.auger@redhat.com \
    --cc=abologna@redhat.com \
    --cc=armbru@redhat.com \
    --cc=berrange@redhat.com \
    --cc=cohuck@redhat.com \
    --cc=eric.auger.pro@gmail.com \
    --cc=jdenemar@redhat.com \
    --cc=khushit.shah@nutanix.com \
    --cc=kvmarm@lists.linux.dev \
    --cc=maz@kernel.org \
    --cc=oliver.upton@linux.dev \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=philmd@linaro.org \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=richard.henderson@linaro.org \
    --cc=sebott@redhat.com \
    --cc=shaju.abraham@nutanix.com \
    --cc=skolothumtho@nvidia.com \
    --cc=yangjinqian1@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox