Commit Graph
84 Commits
Author SHA1 Message Date
Acelogic 3c995cc8d8 compat: convert a swap record's brightness to 16.16 nits
The A16 kext now takes the panel brightness from the swap record
IOMobileFramebufferSwapSetBrightness fills: an IEEE double in nits,
unaligned, straight from a client. edp_bl_double_to_q16 turns its bits
into 16.16 nits in integer arithmetic, rounded to nearest and capped,
refuses NaN, infinities and negative values (which name no
brightness), and maps zero and subnormals to 0 (the darkest request).

The model test checks it bit-exact against the host's double
arithmetic for chosen values and for every exponent with a spread of
mantissas, and four mutations (NaN or negative accepted, truncation,
no cap) must fail it. Header-only and unused by the monitor: the
SNAP_EDP_BACKLIGHT monitors built with run next1b's flags, with and
without the define, are byte-identical to org next's.
2026-10-24 20:19:14 -04:00
Acelogic 7e8bf82b3a cycle: pin the next2 AuxKC for --edp-backlight runs
next2-20261024 (cc07dfd3), built from fbed1ca with KEXT_PROFILE=desktop-next I2C_PROFILE=desktop-fnkeys: AdrenoX2 d88a2620 now publishes force-brightness-control and maps nits proportionally (SnapAdreno 9cc1e92). SnapI2CHID's code sections are identical to next-20261024's. next-20261024 (57965a84) stays as the rollback.
2026-10-24 19:52:33 -04:00
Acelogic fbed1cad82 repo: merge the brightness path (backlight-path)
BrightnessControl writes brightness-nits only to a backlight service that carries force-brightness-control; AdrenoBacklight now publishes it (SnapAdreno 9cc1e92), so CoreBrightness's slider and keys reach the panel instead of dimming in software (next1b: RequestsNits 0). The floor drops from 10% to 2% (level 41 of 2047) and nits map proportionally onto levels.
2026-10-24 19:50:41 -04:00
Acelogic 15336488b9 docs: describe how --edp-backlight brightness reaches the panel
RUNNING.md now gives the 2% floor, how CoreBrightness's nits reach
AdrenoBacklight (WindowServer's BrightnessControl, enabled by the
service's force-brightness-control) and the two boot-args that move
the nits-to-level curve. It no longer names the pinned collection's
folder, which the next pin will change.
2026-10-24 19:47:13 -04:00
Acelogic e273ff6475 tests: check AdrenoBacklight's BrightnessControl path
test-edp-backlight.py gains three checks for the path SnapAdreno's
AdrenoBacklight.h describes:
- Wiring: the service publishes force-brightness-control as data with
  a nonzero first byte, backlight-control and IODisplayParameters,
  takes brightness-nits, and maps every request through the one curve
  with the configured minimum.
- UserspaceContract: on a 26A428 host (the guest's userspace) with
  ipsw, the dyld cache's BrightnessControl and IOMobileFramebuffer
  still carry the names the path relies on; SKIP elsewhere.
- Kext (--kext-reference): desktop-next builds too, both backlight
  profiles carry force-brightness-control, the default kext does not.
2026-10-24 19:47:06 -04:00
Acelogic 8351bc0674 repo: point SnapAdreno at its backlight-path branch
SnapAdreno 9cc1e92 (branch backlight-path, not pushed): AdrenoBacklight
maps nits proportionally onto levels with the compat helpers of the
previous commit, publishes force-brightness-control so WindowServer's
BrightnessControl writes brightness-nits to it, and publishes its
DPCD700 diagnostic as 64 bits. The default kext is section for section
the base commit's.
2026-10-24 19:46:45 -04:00
Acelogic b8e2e042f2 compat: lower the eDP backlight floor and map nits linearly
The monitor's floor was 10% of full scale (level 205 of 2047) and the
kext's helpers mapped [min_nits, max_nits] affinely onto [floor, max].
If the panel's DPCD level is linear in luminance, the darkest macOS
request was ~50 nits: ten times the 5-nit minimum the A16's panel
table gives Windows (BrightnessRangeLevel0 5000..500000 millinits,
BrightnessRangeLowOffset 10000).

EDP_BL_FLOOR_PERMILLE is now 20: level 41, ~10 nits under the linear
model (the table's low offset), very dark but never off if the TCON
applied a 2.2 power law instead. Nothing has measured the panel's
curve; the header says so and the hardware run must check the bottom
of the slider. The helpers now model luminance proportional to level
(edp_bl_nits_to_level/edp_bl_level_to_nits with the top level at
max_nits) and edp_bl_min_nits_q16 raises the darkest request to the
floor's luminance; the slider helpers take 16.16 bounds.

The SNAP_EDP_BACKLIGHT=1 monitor built with run next1b's flags differs
from next1b's qualified one in one byte (same size, 200 bytes of code
budget left); without the define the monitor is byte-identical. The
model test checks the floor and the curve, and four new mutations (no
floor change back to 10%, an affine curve, a top short of max, a
minimum below the floor) must fail it.

The SnapAdreno kext with ADRENO_BACKLIGHT uses the new signatures; it
builds once the submodule pointer moves (next commit). The default
kext does not include this header.
2026-10-24 19:46:34 -04:00
Acelogic ee727e83c3 cycle: add --watchdog and --session for two-hour desktop runs
--watchdog SECONDS sets the run's watchdog from 1800 (the default, unchanged) to 7200 s; above 1800 the boot
preflight requires the A16 on AC. --session (with --console) leaves the guest trigger out of SNAP_EARLY_STOP, so the
kext never requests its first-present stop and a desktop session lasts until the watchdog, the thermal guard or
tools/request-stop.py. --early-stop-delay is checked against the run's watchdog. tools/test-session-watchdog.py
covers the default, the bounds, the delay check and the session's triggers.
2026-10-24 19:22:49 -04:00
Acelogic 80da17a462 repo: merge the kernel view pool reclaim (view-reclaim)
A 256-table kernel view pool with lazy reclaim of copies that no longer hold a protected leaf, behind --view-reclaim (SNAP_VIEW_RECLAIM); CODE_AT moves down 16 KiB so the monitor keeps 15 KiB of headroom with --edp-backlight; the pool's count, high-water mark and reclaims are reported as VIEWRCL1. next1 stopped at 1104 s when the 128-table pool was full (exit 7, ROZONE RETYPE refused).
2026-10-24 19:05:41 -04:00
Acelogic 49ccf6bf9b tests: cover kernel view reclaim and the 256-table pool
tools/test-view-reclaim.c drives a monitor-shaped kernel tree (one root,
one level 1, four level 2, 512 level 3) the way the retypes do: prepare,
detach, commit, refresh, with kernel_views_quiesce's steps as the
quiesce. After every step, independently of the library: each CPU's
walk of all 16,384 leaves gives the canonical descriptor or, for
selector2/4, its translation under that CPU's PPERM; no reachable page
holds an unpublished store; copies are distinct and never sources; no
store reaches a retired page before the TLBI after its unlinking.
Scenarios: fill to 256, a full pool and a one-slot-short path refuse
with no change, release and reclaim (TXM import, the level-2 ancestor),
reuse of the retired pages before any allocation, reclaim down to the
root, the restart of a two-frame change, read failure, nothing to
retire, unconfigured views and a failed quiesce. A quiesce without its
TLBI and a dropped protected table are caught (harness self-checks).

tools/test-view-reclaim.py runs it, nine weakened sprr-view.c copies
(each must fail: all do), test-kernel-pperm-variants.c with and without
the define, the wiring (default off, guarded uses, cycle, report place
and decoder) and, with --build, the monitor identities.
test-kernel-pperm-variants.c gains reclaim steps under the define:
positions move under the reuse snapshot, publication rows and variant
columns while both machines keep agreeing.

Tests that hard-coded the 128-table shape now derive it from
SPRR_VIEW_TABLES / USER_PUBLISH_MAX (test-tpro-view.c's RAM,
test-user-prepare-fused.c, test-user-fused-compare.c,
test-user-publish.c, test-user-tree-memo.c); define-off they check
exactly what they did.

Results on this tree (host, ASan/UBSan):
  python3 tools/test-view-reclaim.py              PASS (model 20,578
      checks; 9/9 mutants caught; consumers; wiring)
  python3 tools/test-view-reclaim.py --build --qualification
      .../installed-fresh-desktop-20261024-next1/qualification.json
                                                  PASS (absent == =0 ==
      86bb02ea9e03...; =1 459,904 bytes, 15,232 headroom)
  the 26 C suites linking sprr-view.c, with and without
      -DSNAP_VIEW_RECLAIM=1                      PASS (define-off check
      counts equal the base commit's)
Hardware: not run.
2026-10-24 18:53:55 -04:00
Acelogic 7b729890ef cycle: add --view-reclaim
installed-fresh --view-reclaim appends -DSNAP_VIEW_RECLAIM=1 after every
other monitor define. It is a monitor define only: no AuxKC, boot-arg
or loader change. docs/RUNNING.md describes it.
tools/test-edp-backlight.py's "appended last" check now lets this newer
define follow its own.

With next1's qualification flags plus the define the monitor is 459,904
bytes, 15,232 under the 464 KiB reservation; without it the monitor is
byte-identical to next1's (458,552 bytes, 16,584 under).
Hardware: not run.
2026-10-24 18:53:24 -04:00
Acelogic 411e17fd1b probes: report the kernel view pool as VIEWRCL1
With SNAP_VIEW_RECLAIM the report carries, behind "VIEWRCL1" and a word
of value bytes << 32, the kernel views' count, its high-water mark, the
reclaims that retired tables and how many, the refusals that found
nothing to retire, and the capacity. The record sits at a fixed place
just below the IB async slot (used or not); every chained record is
asserted to end before it. tools/perf_counters.py decode_view_reclaim
reads it (refusing a record whose counts disagree), decode_report adds
it as view_reclaim, the speed/installed-fresh summary keeps it, and
probes/run.py prints one line. 88 bytes of monitor code.
Hardware: not run.

probes/run.py's reservation note now gives the reclaim's exact cost with
this record: 1,352 bytes.
2026-10-24 18:53:18 -04:00
Acelogic b69884f31a probes: lower CODE_AT for a 464 KiB monitor reservation
With --edp-backlight the next1 monitor left 200 bytes of the 448 KiB
reservation, and SNAP_VIEW_RECLAIM adds about 1.3 KiB.

OUT_AT cannot rise: the report ends exactly at heap+0x480000, where the
stopped-probe scratch begins (tools/probe-a16-cpus.py, code at 0x480000,
output at 0x490000), and tools/secondary-runtime.py collect runs that
probe after the monitor returns and before probes/run.py reads the
report, so a higher report would lose its tail (the thermal and DVFS
records). CODE_AT moves down 16 KiB instead. Nothing in q1n1's heap
below CODE_AT is used during a run; the only other user of that range
is tools/qualify-txm-image4-native.py (heap+0x100000, 3 MiB), which
requires a fresh stage. q1n1 does not know these offsets, every tool
reads run.CODE_AT, and the monitor is position independent.

tools/test-monitor-reservation.py checks the new order (code, report,
stopped-probe scratch, SMP page, work locator), that the two stopped
probes use the scratch after the report, and the fresh-stage tool's
workspace. tools/test-reuse-match-mapped.py's budget follows.
Hardware: not run.
2026-10-24 18:53:06 -04:00
Acelogic e128ca1abe shadow: reclaim kernel view copies in a 256-table pool
installed-fresh-desktop-20261024-next1 stopped after 1,104 s with exit
7: a RETYPE to ROZONE was refused because sprr_views_prepare found the
kernel views at SPRR_VIEW_TABLES (128). Its context.bin shows that 114
of the 118 level-3 copies still held selector2 leaves (122 ROZONE
protects, 3 releases): each RO-zone frame lands in its own 2 MiB table,
so the live set itself reached the pool. In the 86 preserved runs of
6 minutes or more, releases stayed at 2 to 8.

SNAP_VIEW_RECLAIM (opt-in, default 0):

- SPRR_VIEW_TABLES becomes 256. struct sprr_views grows by 8,192 bytes
  and 65 of them precede pauth_bank, so PAUTH_BANK_CONTEXT moves under
  the define (still asserted). The publication rows, the row-empty
  checks (sprr_publish_row_empty) and USER_PUBLISH_MAX follow the
  capacity. Context +1.0 MiB, root_ext +1.5 MiB of the arena.
- sprr_views_reclaim retires every copied table no CPU needs: a level-3
  table without a valid selector2/4/9 leaf, an upper table none of
  whose entries leads to a needed copy, never the root. It reads every
  source before changing anything, compacts the metadata (kept tables
  in order, retired sets parked past count at SPRR_VIEW_RETIRED), then
  calls quiesce. kernel_views_quiesce drops the reuse snapshot and the
  publication rows, and shadow_tlb_sync syncs all six views (a retired
  table's parent entry names its canonical source again, an identical
  translation), publishes them and runs TLBI ALLE1IS. Only after that
  may add() reuse the six pages at that position; after a failed
  quiesce they stay unusable.

The trigger is lazy: kernel_views_prepare_change, used by the ROZONE
and TXM-default retypes, reclaims only when a prepare is refused with
fewer than three free slots, then prepares the whole change again,
because the reclaim also retires paths an earlier leaf of the change
prepared (not protected until the commit). prepare_path refuses a path
that does not fit before adding any of it. Nothing runs before the pool
is full: the refresh, PPERM and sync paths are unchanged.

Off, the monitor is byte-identical: next1's flags give 458,552 bytes,
sha256 86bb02ea9e03...; so does the build without SNAP_EDP_BACKLIGHT
and the define-free one. On, the code grows by about 1.3 KiB, which
needs the code reservation of the next commit. kernel_sync_view's
frame grows from 2,336 to 4,528 bytes (64 KiB EL2 stacks; worst
direct-call chain 13.2 KiB, unchanged).

The mirrored multipage_close in tools/test-multipage-fast.c and the
source check in tools/test-kernel-ops-perf-source.py follow the row
helper. Hardware: not run.
2026-10-24 18:52:53 -04:00
Acelogic 67013604d7 cycle: pin the next AuxKC for --edp-backlight runs
INPUT_AUXKC_DESKTOP_BACKLIGHT, the collection --edp-backlight selects
(the only route the next1 run's flags reach), becomes next-20261024:
KEXT_PROFILE=desktop-next I2C_PROFILE=desktop-fnkeys
tools/build-auxkc-desktop.sh at umbrella 78920c5, SnapAdreno b5bfcb4,
SnapI2CHID f0b7984 (sources.txt, no uncommitted changes).

  adreno-input.kc      57965a84916986eed68988b174d699eba06050207945af742c6dd57f616cbd82
  adreno-input.raw.kc  444b0cd1c732071075ca19668a16ca800cd0b752f6c84d072739251eb7e99f40
  AdrenoX2             3202fd6f (desktop-next)
  SnapI2CHID           4a81f74e (desktop-fnkeys)

The brightness branch named this pin for a PROFILE=desktop-backlight
AdrenoX2, which adds the service to desktop (coherent maintenance
skipping, for --gpu-coherent). The run has no --gpu-coherent, so the
pin holds desktop-next instead: desktop-nocoherent plus the service,
with the head rule, the IOMFB trace and the CS sampler opt-in. The
SnapI2CHID in it carries the Fn-key layer, so --input-fnkeys needs no
pin of its own. Both kexts are section-identical (12 of 12) to
separate builds of those profiles from the same tree.

Runs without --edp-backlight keep the latch collection
org-desktop-nocoherent-20261023 (ccf0c8f4, 353756d), which is also
the rollback. docs/RUNNING.md says which profile the pin holds.
tools/test-edp-backlight.py test_cycle now takes its pinned branch
and passes.
2026-10-24 04:14:34 -04:00
Acelogic 78920c59b6 docs: describe --input-fnkeys with the input flags
The fn-keys branch added installed-fresh --input-fnkeys and the
desktop-fnkeys SnapI2CHID profile but left docs/RUNNING.md without
them. List the flag in the Input row and say what it adds, which
SnapI2CHID build reads it, what its bits do and which test covers it.
2026-10-24 04:10:05 -04:00
Acelogic b78c12e1f2 repo: point the submodules at their next branches
SnapAdreno f54b9ec..b5bfcb4 (next):
  adreno-kext: add the desktop-next build profile
  (desktop-nocoherent plus ADRENO_BACKLIGHT in AdrenoDisplay.o, the
  kext of an --edp-backlight run without --gpu-coherent)
SnapMetal 936d51b..7bc40ef (next): the --no-ff merge of
  feature/settings-icons onto migrate-private 40a1864 (same tree as
  936d51b)
SnapI2CHID 816aad8..f0b7984 (next): the merge of feature/fn-keys
  (abaa501 Fn-key layer, 7c0a059 desktop-fnkeys profile). fn-keys made
  no pointer commit, so this is the first one that carries it; the
  umbrella's tests and build-auxkc-desktop.sh I2C_PROFILE need it.

Default builds stay section-identical to migrate-private
(tools/macho-sections.py, ZERO_AR_DATE=1): AdrenoX2 default 12 of 12,
SnapI2CHID default and desktop 12 of 12 each.
2026-10-24 03:58:07 -04:00
Acelogic fb02fa99c2 tests: check --edp-backlight and --input-fnkeys reach the boot-args
Both options already add their guest boot-args; the tests only called
boot_addition with hand-built namespaces. Parse real command lines
with cycle.py's parser and check the addition:

- test-edp-backlight.py test_cycle: no adreno_backlight=1 without the
  flag, adreno_backlight=1 with --edp-backlight (and no mode word),
  and both words, in order, with --edp-backlight-mode;
- test-input-fnkeys.py: --input-fnkeys 0x3, 3, 0x13 and 0b111 each
  give exactly one snap_i2c_fnkeys=<decimal value>, none without it.

For the next1 run's arguments (org2's plus --single-user,
--edp-backlight, --input-fnkeys 0x3, --adreno-cs-samplers) the
addition carries adreno_cs_samplers=1, adreno_backlight=1 and
snap_i2c_fnkeys=3.
2026-10-24 03:49:44 -04:00
Acelogic cf01e689d7 cycle: add --adreno-cs-samplers for the CS sampler opt-in
installed-fresh --adreno-cs-samplers appends the guest boot-arg
adreno_cs_samplers=1, the run-time half of SnapAdreno's
ADRENO_IB_CS_SAMPLERS: the IB validator admits CS sampler loads of up
to 8 units and AdrenoX2 publishes AdrenoIBComputeSamplers, so the
ADRENO_SETTINGS_ICONS plug-in encodes CoreImage's multi-input kernels.
An AdrenoX2 built without the define ignores the boot-arg. Without the
option the boot-argument addition is unchanged.

tools/test-adreno-cs-samplers.py: the default addition is unchanged,
the flag adds the boot-arg once (also beside --edp-backlight,
--input-fnkeys and --single-user), cycle.py's parser reaches the
namespace, AdrenoX2 reads exactly this name under the define, and the
desktop, desktop-nocoherent, desktop-backlight and desktop-next
profiles build AdrenoX2 and adreno-ib-command with it. A misspelt
boot-arg in installed_fresh.py fails it. docs/RUNNING.md lists the
flag and drops "no option yet".
2026-10-24 03:48:50 -04:00
Acelogic a254f01fc9 repo: merge the Settings pane icons (settings-icons)
Merge feature/settings-icons (b9c12cb..22aad4b). docs/RUNNING.md and
tools/cycle_lib/installed_fresh.py merge without conflict: the
settings-icons trust set (ADDITIONS/TRUST_PAYLOAD, mirror-slab kept as
ADDITIONS_MIRRORSLAB for rollback) sits beside the brightness and
fn-keys options.

gpu/adreno-kext/kext: SnapAdreno next f54b9ec, the merge of all three
SnapAdreno feature branches; gpu/adreno-kext/plugin: SnapMetal 936d51b
(feature/settings-icons).
2026-10-24 03:46:49 -04:00
Acelogic c993f8151f repo: merge the Fn-key layer tools (fn-keys) 2026-10-24 03:46:39 -04:00
Acelogic 5b35148492 repo: merge the eDP panel brightness (brightness)
Merge feature/brightness (7da9adf..f189da7) onto the display-modes
merge.

tools/check-iomfb-vtable.py: both branches added an AdrenoDisplay
define option (display-modes --display-define, applied to
AdrenoDisplay.cpp only; brightness --define, applied to every .cpp).
Keep one implementation: --display-define, with --define as an alias
of the same list, compiles AdrenoDisplay.cpp alone with the defines,
which is what both branches' help text promises and what
test-adreno-display-trace.py passes.

gpu/adreno-kext/kext: SnapAdreno next 53c0054, the merge of
feature/display-modes and feature/brightness.
2026-10-24 03:46:35 -04:00
Acelogic 39a39dba90 repo: merge the head rule and IOMFB trace (display-modes) 2026-10-24 03:45:45 -04:00
Acelogic 22aad4b906 docs: document the settings-icons switches and icon caches
BUILDING.md: the plug-in's ADRENO_PIPELINE and ADRENO_SETTINGS_ICONS
build switches (0 or 1; unset or 0 leaves the build unchanged) and the
suites that test the latter. RUNNING.md: a plug-in that changes icon
rendering needs IconServices' store, the user icon caches and the
Dock's icon cache renamed aside from the single-user shell before the
boot continues, and the order that does it with deploy-guest-plugin.py
and guest-console.py under one owner; ADRENO_IB_CS_SAMPLERS stays off
without the boot-arg adreno_cs_samplers=1, which cycle.py cannot add
yet.
2026-10-24 03:35:46 -04:00
Acelogic 8856849ef7 repo: point SnapMetal and SnapAdreno at the settings-icons work
SnapMetal 40a1864..936d51b (branch feature/settings-icons):
  adreno-metal: let build.sh pass ADRENO_PIPELINE
  adreno-metal: encode the CoreImage kernels of Settings pane icons
  adreno-metal: add the Settings pane icon harnesses
SnapAdreno 79de60e..e7b1d3c (branch feature/settings-icons):
  adreno-kext: opt in to multi-unit CS sampler loads (adreno_cs_samplers)
  adreno-kext: build the desktop profiles with ADRENO_IB_CS_SAMPLERS

Both features stay behind their defines. With ADRENO_SETTINGS_ICONS
unset or 0 the plug-in builds byte for byte as at 40a1864 (strict,
lenient, and with ADRENO_PIPELINE); without ADRENO_IB_CS_SAMPLERS the
default and desktop-profile kexts are byte-identical to 79de60e's. The
profiles now carry ADRENO_IB_CS_SAMPLERS, inert unless the guest boots
with adreno_cs_samplers=1. SnapAdreno's AdrenoX2 calls this
repository's adreno_ib_set_cs_sampler_units (compat, b9c12cb).
2026-10-24 03:35:46 -04:00
Acelogic d44fa698d2 cycle: trust and deploy the settings-icons plug-in set
The next installed run boots with the mirror-slab executable 758535d9
installed and must replace it with SnapMetal's ADRENO_SETTINGS_ICONS
build (lenient, ADRENO_PIPELINE, runtime v7: AdrenoMetal 378ff525,
CDHash c76a4677) from single-user mode.

installed_fresh: the trust additions become the settings-icons set's
(the mirror-slab set's 46 rows plus c76a4677: cdc784df, payload
247598bc); the mirror-slab set stays as ADDITIONS_MIRRORSLAB for
rollback, and every earlier CDHash stays trusted, so --restore still
boots. deploy-guest-plugin: the executable's base is the mirror-slab
758535d9 and its payload the 36,670-byte AdrenoMetal-758535d9.bsdiff;
the runtime and CodeResources are already the installed (wsabort) ones
and are skipped.

The set, build/current-assets/metal-stage-settingsicons-20261024, is a
local (ignored) input: AdrenoMetal, AdrenoMetal-758535d9.bsdiff,
trust-additions.json, trustcache.payload and SET.json.

Evidence: the prepare-time trust check (configure_guest, then
trust_cache_spec(ADDITIONS).load(FIRMWARE) against TRUST_PAYLOAD and
TRUST_SHA) passes for the installed, -input and -input-touchpad
profiles, for this set and the mirror-slab rollback;
tools/test-deploy-guest-plugin.py PASS 21 checks (install, again,
restore, refuse) over the console stand-in with 3% loss.
2026-10-24 03:33:06 -04:00
Acelogic 40556de8cd tools: add the System Settings icon suites
test-adreno-settings-icons.py: 261 cases (52 Settings extension icons,
34 type icons at 20 pt and 4 at 64 pt, 67 app icons, 87 named images
of the extensions' asset catalogs, 3 MonitorPanel previews, 14 SF
Symbols) through iconservicesagent's generation entry, the client's CPU
redraw and a CARenderer, on this Mac's GPU answering like the plug-in
(the reference, with pixels) and on the plug-in device. Per case: a
valid reference image, the same image size, nothing omitted or failed,
the same CoreImage kernels as the reference, and every package admitted
by the kext validator. --expect-before requires the unchanged plug-in
to fail. --cs-samplers N stands in for a kext publishing
AdrenoIBComputeSamplers, --cs-samplers-validator replays through this
tree's validator built with ADRENO_IB_CS_SAMPLERS and opted in,
--allow-kext-gated reports the kernels waiting for the property.
Replays run in parallel (--jobs), --cases selects by name.

test-adreno-settings-ci-encoding.py decodes the CS T#, sampler, TSIZE
and SP_CS_CONFIG state of one CoreImage kernel per sampled format (13)
and of a two-input srcOver, with and without the property, checks a
replaceRegion/getBytes round trip of each format against this Mac's
GPU, and requires the production validator to refuse the 2-unit sampler
load that the opted-in validator admits.

Ported from agents/settings-ui (the scratch tree's --kext-tree and
--validator-tree proposal replaced by --cs-samplers-validator, replays
parallelised). Results on this Mac (26A428) in the handoff: the
unchanged plug-in fails 24 of 2873 icon checks and 27 of 126 encoding
checks; ADRENO_SETTINGS_ICONS passes 4713/4714 and 351.
2026-10-24 03:19:47 -04:00
Acelogic b9c12cb158 compat: let the IB validator admit opted-in CS sampler units
CoreImage's multi-input kernels (the folder, document and Safari icons
inside System Settings panes) load one S# per sampled input. The
validator admits exactly one CS sampler unit per LOAD_STATE.

ADRENO_IB_CS_SAMPLERS (default off) adds adreno_ib_set_cs_sampler_units:
1 (the default, as without the define) up to
ADRENO_IB_CS_SAMPLER_UNITS_MAX (8), any other value meaning 1. An S#
holds no address and the load stays bounded by its package relocation
(NUM_UNIT * 16 bytes), as an FS sampler load is; DST_OFF is still
refused. SnapAdreno's AdrenoX2 calls it once, from configureDevice,
only with the boot-arg adreno_cs_samplers=1.

tools/test-adreno-ib-command.c gains test_ib_cs_samplers: one unit
admitted, two refused (E_PACKET) and DST_OFF refused in every build;
with the define, after the opt-in, 2 and 8 units admitted, 9 refused
(E_PACKET), 3 units over a 2-entry table refused (E_BOUNDS), and the
limit back to one for 0 and 9. -DIB_REPLAY_CS_SAMPLER_UNITS=N makes
--replay validate as an opted-in kext (the settings-icons suites).

Evidence: self test (ASan/UBSan) PASS 47286 IB command checks without
the define (46714 before), 47286 with it 0, 48982 with it 1; three
validator mutants (opt-in ignored, two units without the define, no
clamp) each fail it. Without the define the AdrenoX2 kexts (default,
desktop-nocoherent, desktop) are byte-identical to the unchanged
tree's (ZERO_AR_DATE=1, same OUT path).
2026-10-24 03:19:35 -04:00
Acelogic f189da74f0 repo: move SnapAdreno to the AdrenoBacklight commits
gpu/adreno-kext/kext 79de60e -> 41334e1 (SnapAdreno feature/brightness):
the AdrenoBacklight service (c94a34f) and the desktop-backlight profile
(41334e1) that --edp-backlight's AuxKC is built from. The default and
desktop kexts are section for section unchanged. Not pushed.
2026-10-24 01:57:48 -04:00
Acelogic 8efeebbf87 cycle: add --edp-backlight and --edp-backlight-mode
installed-fresh --edp-backlight (needs --present-latch and its chain)
appends -DSNAP_EDP_BACKLIGHT=1 after every other monitor define, adds
the guest boot-arg adreno_backlight=1, and selects
INPUT_AUXKC_DESKTOP_BACKLIGHT (SnapAdreno PROFILE=desktop-backlight).
That collection is not built or pinned yet, so the flag refuses until
KEXT_PROFILE=desktop-backlight tools/build-auxkc-desktop.sh links it
and its two lines are pinned. --edp-backlight-mode adds
adreno_backlight_mode=1. Boot checks compare the AuxKC as for the
other present-path flags. docs/RUNNING.md describes both.

tools/test-edp-backlight.py: the model (PASS), twelve weakened engines
it must reject (all rejected), the opt-in wiring, and with --build /
--kext-reference the identity proofs. On the final code the org2
monitor is 458,552 bytes with the define (200 bytes of headroom; the
probes commit's 216 predates its event-field change), byte-identical
without it. Hardware: not run.
2026-10-24 01:57:42 -04:00
Acelogic 540db81c1b tools: add a read-only eDP AUX survey
tools/survey-edp-aux.py reads, from q1n1 before an --edp-backlight
boot, the dispcc clocks and power domain the monitor's backlight call
needs (stopping before any DP read if one is off: an unclocked MDSS
read is an SError) and then the eDP controller's HW version, interrupt
status and mask bits, HPD state and AUX enable, timeout, limit and
status registers. It writes nothing, starts no AUX transaction and
reads neither the AUX FIFO nor the PHY interrupt status. --plan and
--check run offline. Not run on hardware.
2026-10-24 01:57:35 -04:00
Acelogic 48568f81c1 tools: let check-iomfb-vtable compile AdrenoDisplay with defines
--define NAME=VALUE (repeatable) compiles AdrenoDisplay.cpp with that
define, so an opt-in override gets the same slot, target and PAC
diversity check as the default build. With --define ADRENO_BACKLIGHT=1
slot 397 binds __ZN13AdrenoDisplay20set_brightness_gatedEi with
diversity 1489 (0x05d1), equal to the J700 kernelcache's, and all 483
slots pass. Both that run and the default one still report the two
failures this tree already had (the local header differs from a fresh
generation; AdrenoEarlyStopPresented is not in the check bundle).
2026-10-24 01:57:35 -04:00
Acelogic 30a815744d probes: serve ADRENO_GUEST_BACKLIGHT in SNAP_EDP_BACKLIGHT monitors
-DSNAP_EDP_BACKLIGHT=1 links compat/edp-backlight.c (probes/run.py
OPTIONAL), keeps its state in one zeroed monitor arena page (setup.c;
excluded from transaction publication like the other monitor-only
pages), and dispatches the call from the 0xad16 HVC path. The call is
admitted like ADRENO_GUEST_STOP: EL1, and the HVC word in the loaded
AuxKC's bytes; otherwise EDP_BL_E_ORIGIN. MMIO goes through q1n1's EL2
identity map with a DSB after each access. Every call is recorded as
EV_EDP_BACKLIGHT (60).

Default off. With the org2 desktop run's 122 flags the monitor is
byte-identical with the define absent or 0 (sha256 0d8b9ec3..., the
qualification's monitor_sha256) and 458,536 bytes with it (216 bytes
under the 448 KiB code budget). Hardware: not run.
2026-10-24 01:56:59 -04:00
Acelogic 7da9adf573 compat: add the eDP DPCD backlight engine for the panel brightness
The A16 panel (DISPLAY\SDC422C, Samsung OLED on eDP mdss_dp3) takes its
brightness through the VESA eDP display control registers over the eDP
controller's AUX channel: the DSDT panel table for 0x834C/0x422C has
BacklightType 8, no PMIC keys and DPCD 0x00D bit 3 set, and the DSDT has
no _BCM/_BCL. The guest never maps the controller, so the monitor owns
the call: ADRENO_GUEST_BACKLIGHT (0x0001000C) QUERY and SET.

The first call probes with reads only (dispcc AHB and DPTX3 AUX clocks,
the MDSS GDSC, the AUX enable bit, then DPCD 0x00D, 0x700..0x703 and
0x721..0x726) and enables nothing. SET clamps the level to
[10% of full scale, the panel's max], writes 0x722 (and 0x723) in one
AUX write and reads it back; a panel left in PWM mode is switched only
with EDP_BL_SET_MODE (level first, mode bits only, read back, restored
on failure). MMIO writes are limited to AUX_DATA, AUX_TRANS_CTRL,
PHY_AUX_INTERRUPT_CLEAR and INTR_STATUS acks with every mask bit kept;
DPCD writes to 0x721..0x723. Three failed SETs, one read-back mismatch,
one incomplete transaction or one refused access stop it for the boot.
Register facts from Linux msm dp_reg.h/dp_aux.c and drm_dp.h; no code
reused.

tools/test-edp-backlight.c runs it against a model of the AUX FIFO and
a DPCD panel that checks every access independently: PASS with
ASan/UBSan. Hardware: not run.
2026-10-24 01:56:52 -04:00
Acelogic 981b1d399e tests: cover the head rule glue and the IOMFB trace
- test-adreno-residency.py HeadOffset:
  - scenario 33 is built with re-pin only (org2's refusal reproduced)
    and with the head rule (admitted and mapped);
  - nine weakened head rules each fail;
  - the kext glue calls the rule, under its define, after the wire;
  - the desktop profiles build the define in every unit.
- test-adreno-display-present.c geometry runs
  adreno_display_swap_geometry over the panel's mode, macOS's scaled
  resolutions of a 2880x1800 panel, placement, cropping, negative
  rectangles and an unknown surface.
- test-adreno-display-trace.py:
  - four weakened geometry rules each fail;
  - every traced IOMFB method forwards its arguments unchanged and
    returns the family's result;
  - every trace identifier is behind its define;
  - check-iomfb-vtable.py with the desktop profile's display defines
    keeps all 483 slots. That check is SKIP without the KDK and the
    J700 kernelcache.
2026-10-24 01:46:09 -04:00
Acelogic 40a150a538 repo: move SnapAdreno to the head rule and IOMFB trace
SnapAdreno feature/display-modes (c1b4ad5):
- moves the re-pin refusal report into an ordered part;
- adds ADRENO_RESIDENT_HEAD_OFFSET: page-unaligned client buffers are
  mapped in whole pages, using compat/adreno-resource-tail.h;
- adds ADRENO_DISPLAY_TRACE_MODES: the IOMFB call and swap geometry
  trace;
- builds both in the desktop profiles.
With the defines off, the default build and both profiles are
section-identical to SnapAdreno 79de60e.
2026-10-24 01:46:09 -04:00
Acelogic 19c38ed641 tools: let check-iomfb-vtable build AdrenoDisplay with defines
--display-define NAME[=VALUE] (repeatable) adds a -D to the
AdrenoDisplay.cpp compile only. The checker can then verify a
profile's display object, including option-only overrides such as
the IOMFB call trace, slot by slot against the kernelcache. Without
the option it builds exactly as before.
2026-10-24 01:46:09 -04:00
Acelogic 6276284067 compat: add the head rule for page-unaligned client buffers
IOGPU sizes a client buffer's memory as round_page(page offset +
length) (IOGPUSysMemory::withClientBuffer). A buffer at a
page-unaligned address gets a map one page past what the tail rule
admits, so it is refused -83. In b12v23 and org2 one such WindowServer
buffer was a 16 KiB descriptor under a 32 KiB map. It was refused at
the onset of the Displays-pane glitch. Every composite that listed it
then failed its preparation (-115), until the run ended.

The rules, header-only beside the tail rule:
- admission: the map is exactly the pages that [head, head + bytes)
  touches;
- segments: the first run starts at its page, and the last one runs to
  its page end;
- cache: only the descriptor's lines, with partial first and last
  lines cleaned and invalidated;
- ranges: a client offset lands at head + offset, inside the
  descriptor's bytes.
With head 0 every function gives the tail rule's answer.

tools/test-adreno-residency.c models the descriptor's head.
- Scenario 33 is org2's buffer at seven heads. With re-pin only it is
  refused cleanly (E_PIN) every round. With the head rule it is
  admitted, the GPU reads each client byte where the CPU wrote it, and
  it survives unwire, eviction and a replaced descriptor.
- Scenario 34 checks what is still refused: a map a page too long or
  too short, and boot-arg adreno_head_offset=0. It also checks head-0
  equivalence with the tail rule over every byte count up to three
  pages, and misplaced segments.
All parts of the model pass in four builds: base, re-pin, re-pin plus
head rule, and that with the arena and VA reclaim.
2026-10-24 01:46:09 -04:00
Acelogic d576b6d18b tools: let build-auxkc-desktop.sh take a SnapI2CHID profile
I2C_PROFILE (default desktop) picks the SnapI2CHID profile the desktop
AuxKC is built with, as KEXT_PROFILE does for AdrenoX2, and
sources.txt records it. I2C_PROFILE=desktop-fnkeys builds the
collection for a --input-fnkeys run. Unset, the script runs exactly
the earlier commands.

bash -n passes. Not run: it needs the J700 kernelcache, the KDK and
sudo (build-auxkc-user.py).
2026-10-24 01:30:24 -04:00
Acelogic 2e0f049e81 tools: pass snap_i2c_fnkeys with cycle --input-fnkeys
installed-fresh --input-fnkeys FLAGS (with --input) appends the guest
boot-arg snap_i2c_fnkeys=FLAGS, which a SnapI2CHID built with
SNAP_I2C_HID_FNKEYS (PROFILE=desktop-fnkeys) reads; other builds
ignore it. The sets the kext would refuse are refused here: 0, bits
above 0x1f, brightness encoding 3, the host Fn-lock (0x4) without
translation (0x1), an encoding alone. Without the option the boot
argument addition is unchanged.

python3 tools/test-input-fnkeys.py: 4 tests OK;
python3 tools/test-zone-log.py: 4 tests OK.
2026-10-24 01:30:24 -04:00
Acelogic dac77dfc7d tools: test the SnapI2CHID keyboard's Fn-key layer
Extend the SnapI2CHID harness for -DSNAP_I2C_HID_FNKEYS=1
(drivers/snap-i2c-hid feature/fn-keys, src/hid-keyboard.h):

- test-snap-i2c-hid.c, built with the define, also runs
  test-snap-i2c-hid/fnkeys.c: flag refusals and the three brightness
  encodings; every report-90 code with a macOS usage and the ones
  without; arrays, 0x00/0xFF, repeats and other lengths; reports 54
  and 55 giving hid_kbd_translate's exact events; the host Fn-lock,
  including a key held across a flip; yielding; the raw log, which
  must name no character key; the rate limit; report 90 end to end
  through the GENI model and transport. Without the define the
  test is unchanged.
- test-snap-i2c-hid-start.cpp: seven fnkeys-* glue scenarios (off
  without the boot-arg, translate, raw log and its flood, yield,
  host lock, refused boot-args, transport-refused inputs).
- test-snap-i2c-hid-kext.py test_9_fnkeys: the above, 15 mutations of
  hid-keyboard.c and 9 of the glue that must each fail, and every
  earlier scenario with the define (alone and with LATENCY).

The expected usages are written in the tests from the evidence, not
read from the driver's tables. Needs drivers/snap-i2c-hid at
feature/fn-keys; the submodule pointer is not moved here.

python3 tools/test-snap-i2c-hid-kext.py: 10 tests OK.
2026-10-24 01:30:17 -04:00
Acelogic 58bc2aee86 cycle: create q1n1's build/a16-gpu before the first GPU step log
A fresh q1n1 checkout has no build/ tree, so the org1 boot was refused when
a16gpu() opened its first step log. The record directory is now created first.
2026-10-24 00:38:34 -04:00
Acelogic 353756d561 cycle: pin the org-built non-coherent desktop AuxKC
Built by tools/build-auxkc-desktop.sh with KEXT_PROFILE=desktop-nocoherent at
SnapAdreno 79de60e, which includes the re-pin log fix. SnapI2CHID is
section-identical to the deployed d90e0199; AdrenoX2 differs from the deployed
981e0b88 only by the removed raw-offset task lookup. --gpu-coherent stays off
until the display path handles coherent surfaces.
2026-10-23 21:12:59 -04:00
Acelogic 030c66596b cycle: pin this tree's launcher and persistence tool hashes
pins.example.json pinned the integration tree's
tools/run-sks-transport-candidate.py (52fe215a) and
tools/capture-apfs-persistence.py (4d59b3df). This repository's copies
differ from those only in the SPDX line the public release added, so
installed_fresh's launcher_steps refused every --prepare from a
pins.json copied from the example ("... changed"), and storage's
pinned_tool refused the persistence capture. Pin this tree's bytes
(c967ab84, f2d49308); the STEPS the launcher yields are unchanged.

The observers pinned under build/ (panel/GUI collectors and captures,
the stopped-run helper, the installed snapshot) are run scripts that
were never exported; those pins stay as examples for a local pins.json.
2026-10-23 21:04:35 -04:00
Acelogic 230f8b3a9b cycle: pin the q1n1 stage pair the org q1n1 builds
pins.example.json pinned q1n1-stage.bin 752b4ab7 and q1n1-stage-alt.bin
e6276e5a, which no current q1n1 build produces, so `cycle.py retire`
(stage_pair) refused every checkout started from the example. `make
uefi` in the Snapintosh q1n1 repository at 7872398 (migrate-private)
builds 56f57510 / 5d6f7df0, the same bytes as the integration tree's
q1n1 build; b12v23 recorded running that q1n1-stage.bin. A
stages_source entry says where the pair comes from. The per-machine
pins.json stays local and untracked.
2026-10-23 21:04:23 -04:00
Acelogic 3a07fba3cb compat: regenerate the recover table against the org q1n1
compat/adreno-recover-table.h recorded the sha256 of sme-batch12's q1n1
a16gpu_stage3.py and adreno_x2.py, so installed_fresh's
recover_table_check refused a --gpu-recover reset prepare against the
Snapintosh q1n1 repository (branch migrate-private, 7872398), whose
files differ (adreno_x2.py moved its GPL-2.0-only tables, among them
X285_NONCTXT that hw_init writes, into adreno_x2_protect.py).

tools/gen-adreno-recover-table.py now also records
adreno_x2_protect.py when the q1n1 checkout has it, since hw_init's
non-context writes come from there. Regenerated from that q1n1, only
ADRENO_RECOVER_TABLE_INPUTS changes: every replayed operation, the
CP_ME_INIT words and the SECVID ops are the same. The macro is read
only by the prepare check, so no monitor binary changes.

tools/test-gen-adreno-recover-table.py passes against that q1n1 (it
failed before). compat/adreno-ib-tables.h already records
adreno_x2_protect.py, and its generator reports it fresh against the
same q1n1 and the pinned Mesa.
2026-10-23 21:03:00 -04:00
Acelogic 5ff9d30407 docs: document the desktop build profiles and coherency flags
BUILDING.md: the SnapAdreno and SnapI2CHID PROFILE builds, how to
compare one with a deployed kext, and tools/build-auxkc-desktop.sh.
RUNNING.md: --gpu-coherent and --resident-mib in the GPU flag group,
what b12v20 and b12v23 add to the listed desktop configuration, what
--gpu-coherent requires (--gpu-va-wide, --root-cache-wide, the
desktop-profile kext and a q1n1 with `a16gpu adopt --coherent`) and
that --gpu-coherent-force is a debug build.
2026-10-23 21:00:53 -04:00
Acelogic be64b7055a cycle: pin the coherent-v3 desktop AuxKC
The --present-latch desktop collection the A16 boots since b12v23:
AdrenoX2 c66edb6b (re-pin, aligned live copies and IO-coherent
maintenance skipping; SnapAdreno PROFILE=desktop at its profiles
commit) and SnapI2CHID d90e0199 (PROFILE=desktop), AuxKC bd057773.
The previous pin, latch2-pipe2-recover-nosparse 2cb7b6cc (b12v17), is
four collections back; the history comment lists each step.

The collection itself stays a local, never-committed input under
build/current-assets/. tools/build-auxkc-desktop.sh rebuilds one from
this checkout and prints the pin lines; its bytes differ from
bd057773 (kext UUIDs, staging paths), so a rebuilt collection needs
its own pin.
2026-10-23 21:00:13 -04:00
Acelogic 284506d407 tools: say what keeps a desktop AuxKC from reproducing byte for byte
The previous commit said a rebuilt collection differs from a deployed
one only in UUID-derived bytes. It also differs in each kext's
_PrelinkBundlePath: build-auxkc-user.py stages the kexts in a randomly
named temporary folder and kmutil records that path in the prelink
info. Comparing bd057773 and 43bed810 with collections rebuilt from
the profiles commit, the differing bytes are exactly: the collection
UUID, both kexts' LC_UUID, the receipt's digests, the OSBundleUUID and
_PrelinkKCID strings, and the two staging paths. Document this in the
script header. Comment only.
2026-10-23 20:59:47 -04:00
Acelogic 80bc1af75a tools: add build-auxkc-desktop.sh
Build the A16 desktop AuxKC from this checkout: AdrenoX2 with
SnapAdreno's PROFILE=desktop (KEXT_PROFILE=desktop-nocoherent for a
monitor without --gpu-coherent) and SnapI2CHID with its desktop
profile, then link them the way the deployed collections were linked:
tools/build-auxkc-user.py, tools/auxkc-autoload.py (both bundles,
packaging.json) and build/build-auxkc.py pin for the installed desktop
guest profile. It writes build/current-assets/NAME/ (refusing an
existing one), records the source revisions and per-unit define sets
beside the collection, prints every output's sha256 and the two
installed_fresh.py lines that pin it, and with REFERENCE compares both
kexts section for section with a deployed collection's.

ZERO_AR_DATE=1 is exported unless set, so two builds in one checkout
give the same kext bytes. A collection built elsewhere still differs
from a deployed one in the kexts' UUIDs and what derives from them
(the collection UUID, the receipt's per-kext hashes and the prelink
info's UUID strings).

Checked in a copy of this branch with the J700 downloads: with
SnapAdreno at its profiles commit, desktop and desktop-nocoherent give
AdrenoX2 12 of 12 sections equal to c66edb6b and 981e0b88 and
SnapI2CHID 12 of 12 equal to d90e0199; the collections are the size of
bd057773 and 43bed810 and differ only in those UUID-derived bytes.
2026-10-23 20:59:19 -04:00