Files
UniXNU/scripts/derive-a740-hwinit.py
bluseliu50 56352f7391 chore: bump Adreno740 for GPU hang recovery
derive-a740-hwinit.py also emits RBBM_SW_RESET_CMD.
2026-10-28 20:40:55 +08:00

114 lines
6.2 KiB
Python

#!/usr/bin/env python3
"""Derive the A740 hw_init register table (a6xx_gpu.c hw_init, a6xx_set_hwcg, a6xx_set_cp_protect) from pinned sources.
Offsets come from the pinned XMLs with exact A7XX variant selection (a6xx.xml first, then adreno_common.xml); the hwcg and
protect values from the pinned a6xx_catalog.c (a740_hwcg, a730_protect). Writes build/adreno740/include/NativeAdrenoA740HwInit.h;
--check compares instead."""
import re, sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
SRC = ROOT / '.cache/adreno-source/drivers/gpu/drm/msm'
XML = SRC / 'registers/adreno'
ORDER = ['A2XX', 'A3XX', 'A4XX', 'A5XX', 'A6XX', 'A7XX', 'A8XX']
OUT = ROOT / 'build/adreno740/include/NativeAdrenoA740HwInit.h'
REFERENCE = ROOT / 'drivers/Adreno740/NativeAdrenoA740HwInit.h'
def matches(variants):
if variants is None:
return True
for part in variants.split(','):
part = part.strip()
if '-' in part:
left, right = part.split('-', 1)
low = ORDER.index(left) if left else 0
high = ORDER.index(right) if right else len(ORDER) - 1
if low <= ORDER.index('A7XX') <= high:
return True
elif part == 'A7XX':
return True
return False
def resolve(name, files, kind='reg(?:32|64)'):
for f in files:
text = (XML / f).read_text()
hits = set()
for m in re.finditer(r'<(' + kind + r') offset="(0x[0-9a-fA-F]+)" name="' + name + r'"([^>]*)>', text):
v = re.search(r'variants="([^"]+)"', m.group(3))
if matches(v.group(1) if v else None):
hits.add(int(m.group(2), 16))
if len(hits) > 1:
raise SystemExit('ambiguous ' + name + ' in ' + f)
if hits:
return hits.pop()
raise SystemExit('missing ' + name)
GPU = ['GBIF_HALT', 'RBBM_GBIF_HALT', 'RBBM_SECVID_TSB_CNTL', 'RBBM_SECVID_TSB_TRUSTED_BASE',
'RBBM_SECVID_TSB_TRUSTED_SIZE', 'RBBM_GBIF_CLIENT_QOS_CNTL', 'UCHE_GBIF_GX_CONFIG',
'RBBM_PERFCTR_GPU_BUSY_MASKED', 'UCHE_TRAP_BASE', 'UCHE_WRITE_THRU_BASE', 'UCHE_GMEM_RANGE_MIN',
'UCHE_GMEM_RANGE_MAX', 'UCHE_CACHE_WAYS', 'CP_AHB_CNTL', 'RBBM_PERFCTR_CNTL', 'RBBM_INTERFACE_HANG_INT_CNTL',
'UCHE_CLIENT_PF', 'CP_PROTECT_CNTL', 'UCHE_CMDQ_CONFIG', 'CP_APRIV_CNTL', 'CP_BV_APRIV_CNTL',
'CP_LPAC_APRIV_CNTL', 'RB_CMP_DBG_ECO_CNTL', 'RBBM_INT_0_MASK', 'CP_SQE_INSTR_BASE', 'CP_RB_BASE',
'CP_RB_CNTL', 'CP_RB_RPTR_ADDR', 'CP_BV_RB_RPTR_ADDR', 'CP_SQE_CNTL', 'CP_RB_RPTR', 'CP_RB_WPTR',
'RBBM_STATUS', 'RBBM_INT_0_STATUS', 'CP_HW_FAULT', 'CP_INTERRUPT_STATUS', 'RBBM_CLOCK_CNTL',
'RBBM_SECVID_TRUST_CNTL', 'RBBM_STATUS3', 'CP_SQE_STAT_ADDR', 'CP_SQE_STAT_DATA',
'RB_NC_MODE_CNTL', 'TPL1_NC_MODE_CNTL', 'SP_NC_MODE_CNTL', 'CP_APERTURE_CNTL_HOST', 'GRAS_NC_MODE_CNTL',
'UCHE_MODE_CNTL', 'RBBM_NC_MODE_CNTL', 'RBBM_INT_CLEAR_CMD', 'CP_ALWAYS_ON_COUNTER', 'RBBM_SW_RESET_CMD']
GMU = ['GPU_GMU_AO_GMU_CGC_MODE_CNTL', 'GPU_GMU_AO_GMU_CGC_DELAY_CNTL', 'GPU_GMU_AO_GMU_CGC_HYST_CNTL']
def main():
catalog = (SRC / 'adreno/a6xx_catalog.c').read_text()
defines = [(n, resolve(n, ['a6xx.xml', 'adreno_common.xml'])) for n in GPU]
defines += [(n, resolve(n, ['a6xx_gmu.xml'])) for n in GMU]
defines.append(('CP_PROTECT', resolve('CP_PROTECT', ['a6xx.xml'], 'array')))
block = re.search(r'a740_hwcg\[\]\s*=\s*\{(.*?)\{\},\s*\};', catalog, re.S).group(1)
hwcg = []
for name, value in re.findall(r'\{\s*REG_A[67]XX_([A-Z0-9_]+),\s*(0x[0-9a-fA-F]+)\s*\}', block):
hwcg.append((name, resolve(name, ['a6xx.xml', 'adreno_common.xml']), int(value, 16)))
if len(hwcg) != block.count('REG_'):
raise SystemExit('unparsed a740_hwcg entry')
pblock = re.search(r'a730_protect_regs\[\]\s*=\s*\{(.*?)\};', catalog, re.S).group(1)
pblock = re.sub(r'/\*.*?\*/', '', pblock, flags=re.S)
protect = []
for entry in [e.strip() for e in pblock.split(',\n')]:
entry = entry.strip().rstrip(',')
if not entry:
continue
if entry == '0':
protect.append(0)
continue
m = re.fullmatch(r'A6XX_PROTECT_(NORDWR|RDONLY)\((0x[0-9a-fA-F]+),\s*(0x[0-9a-fA-F]+)\)', entry)
if not m:
raise SystemExit('unparsed protect entry ' + entry)
reg, length = int(m.group(2), 16), int(m.group(3), 16)
protect.append(((1 << 31) if m.group(1) == 'NORDWR' else 0) | ((length & 0x3fff) << 18) | (reg & 0x3ffff))
count_max = int(re.search(r'DECLARE_ADRENO_PROTECT\(a730_protect,\s*(\d+)\)', catalog).group(1))
# a6xx_set_cp_protect: entries 0..count-2 at their index (zeros skipped), the last one at count_max-1.
writes = [(i, v) for i, v in enumerate(protect[:-1]) if v] + [(count_max - 1, protect[-1])]
lines = ['/* SPDX-License-Identifier: MIT */', '#ifndef NATIVE_ADRENO_A740_HWINIT_H', '#define NATIVE_ADRENO_A740_HWINIT_H',
'#include <stdint.h>',
'/* Generated by scripts/derive-a740-hwinit.py from the pinned a6xx.xml/adreno_common.xml/a6xx_gmu.xml (A7XX',
' * variants) and a6xx_catalog.c (a740_hwcg, a730_protect). Dword register offsets. Do not edit by hand. */']
for name, offset in defines:
lines.append('#define A740_%s 0x%05x' % (name, offset))
lines.append('static const uint32_t NativeAdrenoA740Hwcg[][2]={')
lines += [' {0x%05x,0x%08x}, /* %s */' % (o, v, n) for n, o, v in hwcg]
lines.append('};')
lines.append('#define NATIVE_ADRENO_A740_HWCG_COUNT %d' % len(hwcg))
lines.append('/* {CP_PROTECT index, value} in a6xx_set_cp_protect order. */')
lines.append('static const uint32_t NativeAdrenoA740Protect[][2]={')
lines += [' {%2d,0x%08x},' % w for w in writes]
lines.append('};')
lines.append('#define NATIVE_ADRENO_A740_PROTECT_COUNT %d' % len(writes))
lines.append('#endif')
text = '\n'.join(lines) + '\n'
if '--check' in sys.argv[1:]:
if REFERENCE.read_text() != text:
raise SystemExit('NativeAdrenoA740HwInit.h is stale')
print('PASS: A740 hw_init table matches the pinned sources')
return
OUT.parent.mkdir(parents=True, exist_ok=True)
OUT.write_text(text)
print('PASS: %d registers, %d hwcg entries, %d protect writes' % (len(defines), len(hwcg), len(writes)))
main()