{"id":2232159,"url":"http://patchwork.ozlabs.org/api/1.2/patches/2232159/?format=json","web_url":"http://patchwork.ozlabs.org/project/qemu-devel/patch/20260503073541.790215-7-eric.auger@redhat.com/","project":{"id":14,"url":"http://patchwork.ozlabs.org/api/1.2/projects/14/?format=json","name":"QEMU Development","link_name":"qemu-devel","list_id":"qemu-devel.nongnu.org","list_email":"qemu-devel@nongnu.org","web_url":"","scm_url":"","webscm_url":"","list_archive_url":"","list_archive_url_format":"","commit_url_format":""},"msgid":"<20260503073541.790215-7-eric.auger@redhat.com>","list_archive_url":null,"date":"2026-05-03T07:33:26","name":"[v4,06/17] scripts: Introduce scripts/update-aarch64-cpu-sysreg-properties.py","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"d0f99042ddafc40257e3fce1e8c6838e668c12e1","submitter":{"id":69187,"url":"http://patchwork.ozlabs.org/api/1.2/people/69187/?format=json","name":"Eric Auger","email":"eric.auger@redhat.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/qemu-devel/patch/20260503073541.790215-7-eric.auger@redhat.com/mbox/","series":[{"id":502569,"url":"http://patchwork.ozlabs.org/api/1.2/series/502569/?format=json","web_url":"http://patchwork.ozlabs.org/project/qemu-devel/list/?series=502569","date":"2026-05-03T07:33:20","name":"kvm/arm: Introduce a customizable aarch64 KVM host model","version":4,"mbox":"http://patchwork.ozlabs.org/series/502569/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2232159/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2232159/checks/","tags":{},"related":[],"headers":{"Return-Path":"<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=VhhJDYAs;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists1p.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)"],"Received":["from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g7c7v2BKZz1yJV\n\tfor <incoming@patchwork.ozlabs.org>; Sun, 03 May 2026 17:38:03 +1000 (AEST)","from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists1p.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1wJRNr-0008Kw-HL; Sun, 03 May 2026 03:36:59 -0400","from eggs.gnu.org ([2001:470:142:3::10])\n by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <eric.auger@redhat.com>)\n id 1wJRNT-00087Q-An\n for qemu-devel@nongnu.org; Sun, 03 May 2026 03:36:41 -0400","from us-smtp-delivery-124.mimecast.com ([170.10.129.124])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <eric.auger@redhat.com>)\n id 1wJRNR-0003b0-F0\n for qemu-devel@nongnu.org; Sun, 03 May 2026 03:36:35 -0400","from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com\n (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by\n relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n cipher=TLS_AES_256_GCM_SHA384) id us-mta-189-dQLbM5VNNMCVizrvDQbp4w-1; Sun,\n 03 May 2026 03:36:29 -0400","from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com\n (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n (No client certificate requested)\n by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id E10691800352; Sun,  3 May 2026 07:36:27 +0000 (UTC)","from laptop.redhat.com (unknown [10.44.48.25])\n by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP\n id 832D61800480; Sun,  3 May 2026 07:36:22 +0000 (UTC)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1777793792;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:\n content-transfer-encoding:content-transfer-encoding:\n in-reply-to:in-reply-to:references:references;\n bh=IrtxNwMsLGHcglifoSdXz79E9LQx4QjnnRg4VVSyOzw=;\n b=VhhJDYAsLaCVtXpDwa0ZAP+kYhIVce1ukmOfWWZeQHdMLeiJNoGTibqKfkzZt0sk6PCqKO\n 5JbWsfwV8OLg1HORXuLVQUsfm+aM8OMfkmcljbK9KGv5sRBK3NJ1Njj3bSO1vMx3oHLMOu\n dGWXuvV8arLbLlMMqL43K5Zx9Xlj7g0=","X-MC-Unique":"dQLbM5VNNMCVizrvDQbp4w-1","X-Mimecast-MFC-AGG-ID":"dQLbM5VNNMCVizrvDQbp4w_1777793788","From":"Eric Auger <eric.auger@redhat.com>","To":"eric.auger.pro@gmail.com, eric.auger@redhat.com, qemu-devel@nongnu.org,\n qemu-arm@nongnu.org, kvmarm@lists.linux.dev, peter.maydell@linaro.org,\n richard.henderson@linaro.org, cohuck@redhat.com, sebott@redhat.com,\n skolothumtho@nvidia.com, philmd@linaro.org","Cc":"maz@kernel.org, oliver.upton@linux.dev, pbonzini@redhat.com,\n armbru@redhat.com, berrange@redhat.com, abologna@redhat.com,\n jdenemar@redhat.com","Subject":"[PATCH v4 06/17] scripts: Introduce\n scripts/update-aarch64-cpu-sysreg-properties.py","Date":"Sun,  3 May 2026 09:33:26 +0200","Message-ID":"<20260503073541.790215-7-eric.auger@redhat.com>","In-Reply-To":"<20260503073541.790215-1-eric.auger@redhat.com>","References":"<20260503073541.790215-1-eric.auger@redhat.com>","MIME-Version":"1.0","Content-Transfer-Encoding":"8bit","X-Scanned-By":"MIMEDefang 3.4.1 on 10.30.177.93","Received-SPF":"pass client-ip=170.10.129.124;\n envelope-from=eric.auger@redhat.com; helo=us-smtp-delivery-124.mimecast.com","X-Spam_score_int":"-20","X-Spam_score":"-2.1","X-Spam_bar":"--","X-Spam_report":"(-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001,\n DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1,\n RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001,\n SPF_HELO_PASS=-0.001,\n SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no","X-Spam_action":"no action","X-BeenThere":"qemu-devel@nongnu.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"qemu development <qemu-devel.nongnu.org>","List-Unsubscribe":"<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>","List-Archive":"<https://lists.nongnu.org/archive/html/qemu-devel>","List-Post":"<mailto:qemu-devel@nongnu.org>","List-Help":"<mailto:qemu-devel-request@nongnu.org?subject=help>","List-Subscribe":"<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>","Errors-To":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org","Sender":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org"},"content":"Introduce a script that takes as input the Registers.json file\ndelivered in the AARCHMRS Features Model downloadable from the\nArm Developer A-Profile Architecture Exploration Tools page:\nhttps://developer.arm.com/Architectures/A-Profile%20Architecture#Downloads\nand automates the generation of system register properties definitions.\n\ngenerates target/arm/cpu-sysreg-properties.c containing\ndefinitions for feature ID registers.\n\nWe only care about IDregs with opcodes satisfying:\nop0 = 3, op1 = {0,1,3}, crn = 0, crm within [0, 7], op2 within [0, 7]\n\nSigned-off-by: Eric Auger <eric.auger@redhat.com>\n---\n .../update-aarch64-cpu-sysreg-properties.py   | 171 ++++++++++++++++++\n 1 file changed, 171 insertions(+)\n create mode 100644 scripts/update-aarch64-cpu-sysreg-properties.py","diff":"diff --git a/scripts/update-aarch64-cpu-sysreg-properties.py b/scripts/update-aarch64-cpu-sysreg-properties.py\nnew file mode 100644\nindex 0000000000..603faa2c80\n--- /dev/null\n+++ b/scripts/update-aarch64-cpu-sysreg-properties.py\n@@ -0,0 +1,171 @@\n+#!/usr/bin/env python3\n+\n+# This script takes as input the Registers.json file delivered in\n+# the AARCHMRS Features Model downloadable from the Arm Developer\n+# A-Profile Architecture Exploration Tools page:\n+# https://developer.arm.com/Architectures/A-Profile%20Architecture#Downloads\n+# and outputs target/arm/cpu-sysreg-properties.c content.\n+# There, initialize_cpu_sysreg_properties() populates arm64_id_regs array\n+# with the name of each ID register and definition of all its fields\n+# including their name and min/max bit under the form of the below pattern:\n+#\n+# /* CCSIDR2_EL1 */\n+# ARM64SysReg *CCSIDR2_EL1 = arm64_sysreg_get(CCSIDR2_EL1_IDX);\n+# CCSIDR2_EL1->name = \"CCSIDR2_EL1\";\n+# arm64_sysreg_add_field(CCSIDR2_EL1, \"NumSets\", 0, 23);\n+#\n+# Copyright (C) 2026 Red Hat, Inc.\n+#\n+# Authors: Eric Auger <eric.auger@redhat.com>\n+#\n+# SPDX-License-Identifier: GPL-2.0-or-later\n+\n+\n+import json\n+import os\n+import sys\n+from aarch64_sysreg_helpers import extract_idregs_from_registers_json\n+\n+def collect_fields(item, bit_offset=0):\n+    \"\"\"\n+    Recursively finds all field-like objects, handling Fields.Array,\n+    Fields.ArrayField, and ConditionalField structures.\n+    Applies bit_offset from containers to child fields.\n+    \"\"\"\n+    fields = []\n+    if not isinstance(item, dict):\n+        return fields\n+\n+    _type = item.get('_type', '')\n+\n+    # Array types (for example CLIDR_EL1 Ctype<n>, Ttype<n>)\n+    if _type == 'Fields.Array':\n+        name_template = item.get('name') or item.get('label', '')\n+        index_info = item.get('indexes', [{}])[0]\n+        start_idx = index_info.get('start', 0)\n+        count = index_info.get('width', 0)\n+\n+        full_range = item.get('rangeset', [{}])[0]\n+        bit_start = full_range.get('start', 0) + bit_offset\n+        elem_width = full_range.get('width', 0) // count if count else 0\n+\n+        for i in range(count):\n+            idx = start_idx + i\n+            # Correctly handle indexed names like Ctype1, Ctype2\n+            field_name = name_template.replace('<n>', str(idx))\n+            fields.append({\n+                'name': field_name,\n+                'rangeset': [{\n+                    'start': bit_start + (i * elem_width),\n+                    'width': elem_width\n+                }],\n+                '_type': 'Fields.Field'\n+            })\n+        return fields\n+\n+    # ConditionalFields\n+    elif _type == 'Fields.ConditionalField':\n+        inner_offset = bit_offset\n+        if item.get('rangeset'):\n+            # Parent container defines the absolute start bit\n+            inner_offset = item['rangeset'][0].get('start', bit_offset)\n+\n+        for entry in item.get('fields', []):\n+            inner = entry.get('field')\n+            if inner:\n+                fields.extend(collect_fields(inner, inner_offset))\n+        return fields\n+\n+    # Normal Field Types\n+    leaf_types = ['Fields.Field', 'Fields.ConstantField',\n+                  'Fields.EnumeratedField', 'Fields.Bitfield']\n+    if _type in leaf_types:\n+        field_copy = item.copy()\n+        if field_copy.get('rangeset'):\n+            new_ranges = []\n+            for r in field_copy['rangeset']:\n+                nr = r.copy()\n+                # Apply the cumulative offset to the field's start bit\n+                nr['start'] = r.get('start', 0) + bit_offset\n+                new_ranges.append(nr)\n+            field_copy['rangeset'] = new_ranges\n+        fields.append(field_copy)\n+        return fields\n+\n+    # Go down the hierarchy for other cases\n+    for key in ['fields', 'values', 'fieldsets']:\n+        for nested in item.get(key, []):\n+            fields.extend(collect_fields(nested, bit_offset))\n+\n+    return fields\n+\n+\n+def generate_sysreg_properties_from_registers_json(id_reg_names, raw_json_path):\n+    with open(raw_json_path, 'r') as f:\n+        register_data = json.load(f)\n+\n+    regs = {r.get('name'): r for r in register_data if r.get('_type') == 'Register'}\n+\n+    final_output = \"\"\n+\n+    for reg_name in id_reg_names:\n+        register = regs.get(reg_name)\n+        if not register:\n+            continue\n+\n+        final_output += f\"    /* {reg_name} */\\n\"\n+        final_output += (f\"    ARM64SysReg *{reg_name} = \"\n+                         f\"arm64_sysreg_get({reg_name}_IDX);\\n\")\n+        final_output += f\"    {reg_name}->name = \\\"{reg_name}\\\";\\n\"\n+\n+        # Collect all fields\n+        field_entries = []\n+        for fieldset in register.get('fieldsets', []):\n+            candidates = collect_fields(fieldset)\n+            for val in candidates:\n+                name = (val.get('name') or val.get('label', '')).strip()\n+                if not name or \"RESERVED\" in name.upper():\n+                    continue\n+                for r in val.get('rangeset', []):\n+                    lsb = int(r.get('start'))\n+                    msb = lsb + int(r.get('width')) - 1\n+                    field_entries.append({'name': name, 'lsb': lsb, 'msb': msb})\n+\n+        # Sort fields by lsb (decreasing order)\n+        field_entries.sort(key=lambda x: x['lsb'], reverse=True)\n+\n+        seen_fields = set()\n+        for entry in field_entries:\n+            f_id = f\"{entry['name']}_{entry['lsb']}_{entry['msb']}\"\n+            if f_id in seen_fields:\n+                continue\n+            seen_fields.add(f_id)\n+\n+            line = (f\"    arm64_sysreg_add_field({reg_name}, \"\n+                    f\"\\\"{entry['name']}\\\", {entry['lsb']}, {entry['msb']});\\n\")\n+            final_output += line\n+        final_output += \"\\n\"\n+\n+    os.makedirs(\"target/arm\", exist_ok=True)\n+    with open(\"target/arm/cpu-sysreg-properties.c\", 'w') as f:\n+        f.write(\"/* AUTOMATICALLY GENERATED, DO NOT MODIFY */\\n\\n\")\n+        f.write(\"/* SPDX-License-Identifier: GPL-2.0-or-later */\\n\\n\\n\")\n+        f.write(\"#include \\\"cpu-idregs.h\\\"\\n\\n\")\n+        f.write(\"ARM64SysReg arm64_id_regs[NUM_ID_IDX];\\n\\n\")\n+        f.write(\"void initialize_cpu_sysreg_properties(void)\\n{\\n\")\n+        f.write(final_output)\n+        f.write(\"}\\n\")\n+\n+if __name__ == \"__main__\":\n+    if len(sys.argv) < 2:\n+        print(\"Usage: python scripts/update-aarch64-cpu-sysreg-properties.py \"\n+              \"<path_to_registers_json>\")\n+    else:\n+        json_path = sys.argv[1]\n+\n+        id_regs_dict = extract_idregs_from_registers_json(json_path)\n+        sorted_names = sorted(id_regs_dict.keys())\n+\n+        if sorted_names:\n+            generate_sysreg_properties_from_registers_json(sorted_names, json_path)\n+            print(\"Generated target/arm/cpu-sysreg-properties.c\")\n","prefixes":["v4","06/17"]}