Repository navigation
ANE: H16 cold boot and first inference - #750
Conversation
Track pending execution UUIDs before channel-7 publication and retire only matching terminal channel-6 events. Keep one deadline across acknowledgment and completion, order coherent DMA accesses, and quarantine failed or uncertain requests without exposing private output mappings. Validate complete HWX containers, tensor and program descriptors, aperture records, symbols and payload-only kernel relocations. Match execute buffers to kernel-owned process resources and revoke per-file authority on close. Add hardware-free KUnit coverage for validation and pending request paths. Keep H16 registration and section-only loading refused until preload, startup, the original-container ABI and process-resource decoding exist. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Authenticate stable, owned resident firmware snapshots against the pinned normalized digest, checking every patchbay tag and width and masking only the reviewed mutable value cells and exact tunables interval. Keep live page acquisition behind the boot backend ownership gate. Import original HWX bytes once before validation and hashing, retain whole segment geometry, and bound private load plans before DMA allocation. Validate backend mapping geometry and decoded process bindings without accepting userspace resource authority or publishing partial results. Keep H16 registration, section-only loading and process creation refused: the load/process wire bodies, allocation replies and physical boot backend still require reviewed providers. Add hardware-free KUnit coverage for the identity, import, planning and resource paths. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The accepted dependency patch is already applied verbatim as 4700e91, with SHA-256 89bdf5072e468dd750580348679c0caa552ad26a07911ed218ac809495a1e8fd. Record the original PR #681 head as an ancestor so merging it upstream does not create add/add conflicts for the already extended HWX files. Preserve the current source tree unchanged. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Describe the four inclusive DAPF ranges in record order so that the firmware backend can derive both its filters and identity MMIO pages from DT. Require them for T6041 and exercise the preload properties in a T6041 example. The preload DVAs are fixed; only physical reservations need to be supplied by the bootloader. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Describe the four DAPF ranges and preload device addresses without fixing boot-specific physical addresses. Hook the J616s ANE to disabled no-map TEXT and DATA placeholders for the bootloader to fill from segment-ranges. Widen the three DART windows down to zero, preserving their upper bound at 0x3ffffffffff. apple-dart uses the window for forced domain geometry, including private paging domains. Raw iommu_map() currently permits low mappings outside that geometry, but relying on that leaves the domain's advertised aperture inconsistent with the firmware's identity MMIO pages. The widened window covers both those pages and the high firmware DVAs. Add a tether-only test DTS that enables the existing ANE and three DART nodes. The shipping board tree keeps them disabled. Preload reservations remain disabled in both trees until a loader completes the handoff. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Enable the ANE and its three DARTs only for the tether-loaded test DTB. Keep the shipping board tree disabled and require the loader to fill the preload reservations before the driver can pass preflight. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Validate the dynamic channel table before arming host rings, publish pool-backed commands, check replies and consume owned reports. Provide bounded SHAREDMALLOC allocations and match-data IRQ helpers with absolute command deadlines and retained failure state. Exercise malformed descriptors, ring ordering, reply corruption, report ownership, allocation ceilings and deadline expiry using synthetic KUnit accessors. Keep probe and hardware ownership unchanged. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Include the existing tether DTS so the ANE test boot keeps its debug console and the host-owned ATC0 path. Layer only the four ANE and DART status enables on top of that established tether configuration. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Clarify that the backend resolves bindings from validated program metadata. CREATE_PROCESS reply IDs do not describe a resource map. Keep wire serialization and process installation separate from geometry validation, with the existing default refusal unchanged. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Record the wrapped replacement description for commit 0a3bdfc. Keep the published history intact. Validate the dynamic channel table before arming host rings, publish pool-backed commands, check replies and consume owned reports. Provide bounded SHAREDMALLOC allocations and match-data IRQ helpers with absolute command deadlines and retained failure state. Exercise malformed descriptors, ring ordering, reply corruption, report ownership, allocation ceilings and deadline expiry using synthetic KUnit accessors. Keep probe and hardware ownership unchanged. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Use the shared DAPF and preload property names for staged boot. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Reuse the accepted normalized preload checker for the pinned 26A428 image. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Keep default registration refused and add explicit preflight, map, boot and startup stages for the pinned H16 27.0 26A428 preload. Reuse the shared transport and immutable preload checker, keep genpd transitions separate from read-only power checks, and run the CE and ordered tunables before scratch publication. Keep all firmware-visible state and a module reference after RUN, including every uncertain failure. Exercise the sequence with a simulated engine and document each tether rung. Require a SID-0-only test description rather than silently claiming SID 11 with the generic IOMMU attachment API. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Simulate offered RTKit traffic, absent heaps, power and RVBAR refusals, post-RUN DART faults and mapping failures. Keep pool pointer arithmetic inside its allocation and handle a failed domain allocation explicitly. Require coherent clients for the private surfaces. Architecture cache preparation helpers are not exported for a module, so refuse an unsupported memory model rather than leave a cached alias without synchronization. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Opt the pinned H16 build into the native FREE tuple established by the round-5 facts. Resolve only live provider-owned DVAs, publish the zero reply, and retire report authority while retaining backing mappings and quota. Keep other firmware profiles on the conservative default and refuse control requests whose lookup fields have no proved wire layout. Cover locked matching filters, heap/shared overlap, native and foreign FREE, and control refusal in the simulated engine. Complete the polled interrupt acknowledgment before ring reads and keep the coherent-client refusal at pool allocation so the map rung remains available. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Expose CE acknowledgment, tunable group completion and locked mismatches before scratch release, and log a validated nonzero firmware acknowledgment. Clarify that native FREE is enabled only by the pinned H16 profile while the generic transport retains its conservative default. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The task-stream gate now requires the fixed H16 prologue, u32 1 followed by twelve zero bytes, but the synthetic HWX fixture still started its stream with sixteen zero bytes. Every suite case that validates the fixture therefore failed, including the load-plan and resource cases. Write the prologue word and move the fixture builder into a shared test header so the program suite can build the same containers. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
EXECUTE descriptor indices are local to the descriptor class, matching the separate input and output request arrays. The add-128 program has an input and the output that both use index 0. The resource check refused any repeated index, so such a program could never be described. Refuse a repeated index only within one class. Cover the add-128 shape of input, output and input with indices 0, 0 and 1. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Add the program lifecycle on the shared firmware transport, following the H16 cold-boot facts (program load and lifecycle, round 5 slot sources) and the SPEC-r4 EXECUTE layout. LOAD_PROGRAM is 0x1c0 bytes with nine 0x30 slots from one table. Slot 0 is the host-built generic section (index 1002), slot 1 the HWX kernel section when present (1007, class 3), slot 2 the task stream (1006), slots 3, 4 and 6 the operation, procedure and text-property sections (1003 to 1005). The request carries 0xffffffff at +0x1b8 and the reply must echo every slot and replace that word. CREATE_PROCESS is 0x258 bytes with a zero body, which the reply must keep. Program and process ID 0 are valid. TERMINATE (0x10) and UNLOAD (0xc) close a program. EXECUTE resources come from a kernel-owned map, with the class from the resource usage mapping and an index local to that class. The linear program descriptor's mcache tuple adds one custom-BAR record. Each request sends 0x002d with 0, keeps its UUID pending before publishing on channel 7, completes only on a state-1 0x0300 report that matches the UUID and the program, process and procedure IDs, then sends 0x002d with 1 and issues a DMA read barrier. Failure reports, mismatched IDs, malformed reports and timeouts quarantine the session with every mapping retained. A firmware session accepts one program lifetime. On this firmware family the first EXECUTE of a newly loaded program writes into the previous program's output buffer, so a second LOAD fails with -EBUSY, also after UNLOAD. The transport now refuses to publish secure-mode commands 0x27, 0x28, 0x34 and exclave commands 0x30, 0x31. Sequences that cannot fit the monotonic command arena are refused before the first command. KUnit drives a synthetic firmware through two executions and teardown, and covers add-128 and kernel-section slot packing, reply refusals, the deny list, the custom-BAR record, the second-LOAD refusal, mismatched UUIDs and IDs, state-2 quarantine and arena exhaustion. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Extend the staged H16 opt-in with h16_stage=program. After the startup commands it opens one program session and registers an accel node with ABI version 3 and the GET_CAPS, H16_LOAD and H16_EXEC ioctls. Without that stage there is no node, so the default refusal and the H17 refusal are unchanged. H16_LOAD imports the original HWX once, validates it, places each region and each host-built section in its own private mapping in a 1 GiB window above the SHAREDMALLOC range, then loads the program and creates its process. Only the output surface and scratch are device-writable. The program belongs to the file and is torn down when the file closes. H16_EXEC copies inputs in, poisons the output mapping, runs one request and copies the output out. Userspace never passes DVAs, firmware IDs, resource indices or commands, and a second load in one firmware boot is refused with a log line that asks for a reboot. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Add h16-run.py. It checks the add-128 HWX identity, finds the ABI 3 H16 accel node, loads the program with its four host-built sections, and runs it twice. The output is poisoned before each run and must equal expected.bin afterwards. Without the program stage it reports a skip. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
…d preloads The H16 bring-up stages were selected with the h16_stage module parameter. Module parameters are not allowed on shipping paths, and a parameter fixed at load time forced a reboot between the boot, startup and program rungs. Bind a valid H16 device idle, with no power or MMIO access, and drive the stages from <debugfs>/ane-h16/<device>/stage instead. A write runs every stage that has not run yet up to the one written, so one firmware session can go from preflight to the program stage one rung at a time. A pre-RUN failure rolls back as before. A stage at or below the completed one is refused. The preload check looked the TEXT and DATA nodes up in the boot-time reserved memory table, which covers only nodes present at early boot. Take the range from the node itself and refuse it when any part is Linux System RAM. That holds for a no-map reservation made at boot and for a range the loader left outside the memory map, and it is a direct check that Linux never owns the firmware memory. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
EXECUTE descriptors name each buffer by its ID in the generic section that LOAD installs. The driver used an index local to the class instead, so a firmware that resolves the ID against the loaded program would not find the add-128 buffers. Take the IDs from the generic section. Entry k describes surface k in HWX surface order, and the kernel refuses a section whose count, direction, type or size disagrees with the program, that repeats an ID or that uses the reserved IDs 2 and 3. Every captured macOS load populated LOAD slot 1 with at least 0x4000 bytes at a sub-page DVA, which is the __TEXT,__const section of a program without a kernel section. Send the constants there when the program has no __KERN_0 section instead of leaving the slot empty. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
A /bits/ 64 prefix applies only to the cell list that follows it, so the second to fourth apple,dapf-ranges pairs were stored as 32-bit cells and lost their upper bits. The driver reads eight 64-bit values and would refuse the property. Prefix every pair. The staged H16 backend maps SID 0 only and refuses a node that lists more streams, so the J616s ANE test tree now lists SID 0 on the three DARTs. The shipping node keeps both streams and stays disabled. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The H16 backend knew one firmware build, 27.0 (26A428). Its preload identity rule (the patchbay records, the range the bootloader rewrites and the pinned digest) was code in ane_h16_preload.c, and the platform pointed straight at that build. Supporting another iBoot preload, such as the 26.6.2 firmware the J616s Linux volume boots with, would have meant another code path. Describe each supported build as data instead: a profile names the build, gives its preload rule and the boot values to use. The preload module now hashes a snapshot by whatever rule it is given and checks the rule shape first, so a malformed table entry is -EINVAL and never a mismatch. The backend tries every profile in turn, selects the build whose rule matches, and only then takes the firmware DVA layout from it. When a layout matches but its digest is not pinned, it logs the digest so a new build can be added from one boot log. Adding a build is a new table entry. KUnit covers rule shape, selection between two patchbay layouts and the shape of every shipped profile. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The HWX validator matched the n-th tensor descriptor to the n-th surface segment and required the only output to be the last segment. The pinned add-128 program does not look like that: its segments are x (input), y (output) and z (input), in buffer-reference order, while its tensors list x, z and y, inputs first. The validator refused it with -ENOEXEC, so H16_LOAD could never accept the program the J616s first inference uses. Keep the surfaces in segment order, which is the order the program descriptor binds BAR slots in, and pair each one with the single tensor whose short name is the name its buffer reference gives. Require inputs and exactly one output in any order. Checked against the real add-128 HWX (SHA-256 231f54c2...), which now validates with surfaces x, y, z. KUnit adds tensors out of segment order, an output segment first, a reference naming no tensor and a program with no output. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
H16_LOAD takes four host-built sections next to the HWX, and h16-run.py expected them as files with no tool to make them. Add h16-sections.py, which derives them from the HWX alone: a generic section naming every surface (output ID 4, inputs 5 and up, in segment order), one operation record binding each BAR slot the task stream references to the surface or kernel at the program descriptor base for that slot, the fixed procedure form, and text properties with one block per task. The layouts follow libane (omarchy-ane, MIT, by Joshua Warren) and the H16/H17 program facts. For add-128 it gives IDs x=5, y=4, z=6 and BAR refs 6->5, 7->4, 8->6, the binding the H17 add ran exact with. h16-run.py now builds the sections itself unless --sections is given. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The program KUnit suite only loaded synthetic HWX images that the test builds itself. Add the pinned add-128 program and the four sections h16-sections.py builds for it, stored as runs of nonzero bytes, and load them through ane_h16_session_load() against the fake firmware. The test checks the HWX digest, the nine LOAD slots (constants in slot 1 as class 3, the 0x130-byte task stream in slot 2), that only the output is device-writable, and that two EXECUTEs name x, y and z by IDs 5, 4 and 6 with classes 0, 1 and 0 at their mapped DVAs. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Every command was copied into a monotonic 256 KiB pool arena that was never recycled before reset. With an EXECUTE sequence of about 3.3 KiB (two gates and the request), a firmware boot ran out after roughly 75 requests, enough for a first inference but not for benchmarks. Add ane_fw_transport_mark() and ane_fw_transport_release(). Release gives back the arena above a mark, and refuses while any channel still has a command in flight. The H16 session marks the arena before each EXECUTE sequence and releases it once the completion report and the closing gate reply have both arrived, when the firmware no longer reads those commands. LOAD and CREATE keep their space, and a failed request keeps its space too. KUnit runs 1000 requests on one program with the arena back at the same mark after each, and checks the refusals. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The binding required six iommus entries on T6041: stream 0 of the three ANE DARTs, then stream 11 of each, which the ANE MPM uses. The firmware drives the MPM stream itself and the host never maps through it, and listing it puts it in the host's IOMMU group, so the H16 driver refuses a node that lists it. Describe stream 0 of each DART on every SoC, three entries. Also give every pair in the T6041 example apple,dapf-ranges its own /bits/ 64, as the property is a 64-bit matrix. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The ANE DARTs and the ANE could not probe even when enabled: their power domains (ane_sys, and under it ane_mpm, ane_cpu, ane_td and ane_base) and the two fabric domains above ane_sys (fab4_soc, fab5_soc) were left disabled, because no Linux consumer existed. The H16 backend is that consumer now, and the J616s bring-up showed the DARTs bind once the seven providers are registered. fab4_soc and fab5_soc stay always-on. Enable the seven power-state providers, give the ANE stream 0 of each DART only, and drop the now redundant iommus override from the test DTS. The DARTs keep apple,dma-range <0 0 0x400 0> so the firmware identity MMIO pages fit the aperture, and the DAPF ranges and firmware IOVAs stay as SoC data. The ANE and its DARTs stay disabled until the H16 path is proven on hardware. aura fills the preload reservations and firmware IOVAs at boot, so enabling them then is a status change. dt_binding_check and dtbs_check are clean for t6040-j616s, t6040-j616s-tether and t6040-j616s-ane-test. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The J616s Linux volume boots with the 26.6.2 (25G83) ANE firmware,
RTKit-3255.160.4. Its iBoot preload has the same 42 patchbay records and
the same boot-rewritten tunables range as 26A428, each 0x3f80 bytes later
in DATA, and the same cold boot values, so the profile shares the 26A428
build data and only adds the preload rule.
The digest is the normalized SHA-256 of the live J616s preload. With it
the driver accepts the preload on the J616s ("H16 preload identity H16
26.6.2 25G83 accepted").
Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The J616s ANE DART node has one DAPF bank, the reg entry the ADT tags FPAD at DART0 + 0x10000. The driver assumed a bank above each of the three translation instances and read records at DART1 + 0x10000 and DART2 + 0x10000 too. Those addresses are outside every ADT reg entry, and once the DART revision check let preflight get that far, the read above DART1 reset the machine with an SError. Describe every DART and DAPF offset the stages touch in a table keyed by the DART revision (PARAMS3 bits 15:0), with one entry for the T6041 revision 0x0202, and give the platform the location of the single bank. Preflight reads PARAMS3 of the three instances first and refuses a revision without a table before anything else in the DARTs or the bank is touched. Only the bank's own window is mapped. The protect and lock words are read on the owning instance only, record bounds are read as 64-bit words, and an end is compared without its low two bits, which a t8110 bank does not read back. On this revision the loader programs the bank from the ADT, so the driver only reads it. Preflight reports how many records match, and map refuses before any write unless all four match apple,dapf-ranges. The kernel write path stays behind a table field for a revision that needs it, with KUnit coverage. The DART and DAPF offsets leave the firmware build data, since they are not properties of a firmware build. KUnit checks that no DART offset outside the selected table and no DAPF access outside the four records happens, and covers the loader-owned, kernel-owned and unknown-revision cases. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
A preflight on the J616s read the single ANE DAPF bank and found none of its four records programmed. Every r0 is 0, and the bounds and enables hold power-on values. iBoot leaves the bank alone, and since the bank is in the ANE_SYS domain it keeps nothing across a power-down. Linux genpd and the driver's own pre-RUN rollback both power that domain off, so only the driver that powers it up can program the bank in time, as on T8140. Drop the loader-owned mode. At map the driver writes every record that differs from apple,dapf-ranges, in the order the t8110 bank takes them (r4, start, end, r0, r20), with r0, r4 and r20 from the revision table (the ADT dapf-instance values, 0x31, 0 and 1 on T6041), and reads each record back. A record that does not read back fails map before RUN. A bank whose lock word has bit 2 set is still refused before any write. Preflight still only reads. KUnit starts from an unprogrammed bank and checks the write order and values, that only differing records are written, a read-back failure and the locked cases. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The DRM core refuses to open a file whose file_operations lack FOP_UNSIGNED_OFFSET. drm_open_helper() warns and returns -EINVAL. The H16 accel driver lists its fops by hand, without DRM_ACCEL_FOPS because it has no GEM objects and must not route mmap to drm_gem_mmap(), and it missed the flag. On the J616s the program stage registered the node and then every open() of /dev/accel/accel0 failed. Add the flag. Add a KUnit suite that registers the real driver on a mock device and opens the node through its own fops, the way accel_stub_open() hands it over. Without the flag it hits the same drm_open_helper() warning as the J616s did. The suite also checks that the fops have no mmap. h16-run.py treated an accel node it could not open as a missing node and skipped. Report the open() error and fail instead. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
|
First exact inference on the J616s (M4 Pro), from this branch at 992dbda. Kernel 7.3.0-aurora-fleet14c with the ANE modules built from this branch, ANE enabled through a runtime overlay (no boot chain change). Every stage passed in one go:
Still to do before merge: the shipping DT keeps the ANE disabled until the Stage 2 loader carries the preload handoff, and the one-program-per-boot limit gets lifted next. 🤖 Generated with Claude Code |
Tasks in an H16 task stream start 16-byte aligned. The validator also required the last task to be padded out to 16 bytes inside the section. Compiled linked programs end the __text section right after the last task, so a 28-task MobileNetV1 stream of 0x305c bytes was refused. The firmware reads the task count and the stream length from the program descriptor, and the same streams run on the J700. Pad the last task only up to the end of the stream. Any bytes between it and the end must still be zero. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
A linked program keeps its intermediates in DRAM scratch: the HWX has a __DATA,__bss segment, the program descriptor is the 0x8c0 form and every task reaches the scratch through BAR slot 3. The validator already accepted that form and the loader mapped the segment, but nothing told the firmware where the scratch was. The firmware learns it the way it learns a surface. The generic section gets one more entry, last, for the scratch: its own ID, input usage and the segment size. The operation section binds slot 3 to that ID, and every EXECUTE carries one more descriptor with the scratch mapping. Validate that entry against the segment and send the descriptor from the kernel. The scratch stays kernel memory, zeroed and device-writable, and is never a userspace surface. h16-sections.py writes the entry and the slot 3 binding. Programs also no longer need one firmware boot each. A LOAD is refused only while another program is still loaded, and accepted once it closed. Firmware reuses program IDs, so the session numbers its programs itself. The first EXECUTE after the engine last ran a different program sets bit 0 of the request flags word (+0x30). That makes the firmware queue the job, which installs the new program's BAR context, instead of taking the direct path, which reuses the previous program's. On the J700 every program switch with the bit set was exact and every switch without it after a direct-path job was stale. Later requests of the same program keep the direct path. Add h16-mobilenet.py, which loads a linked MobileNetV1 224 package once and runs one EXECUTE per image, checking top-1 against the package's references. KUnit covers the scratch entry (accepted, missing, output-like, short, duplicate ID), the scratch descriptor in EXECUTE, a second program after the first closed, the refusal while one is loaded, and the flag on the first request after a switch only. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Resolve the ANE Kconfig help, Makefile and documentation against the H14 reset and lifetime work: keep both test sets and the H14 restart text, and drop the old note that H14 reset needed its own test. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The H16 firmware span is config_span bytes from the TEXT DVA. The bootloader preload covers TEXT and DATA only, and the firmware keeps runtime heap state in the rest of the span, 0x14000 bytes past the end of DATA on the 26.6.2 build. Larger programs such as MobileNetV1 write there and fault on the DART when nothing is mapped. Allocate that remainder zeroed and map it device-writable in the map stage, right after the preload, and keep it for the life of the boot like the other boot-owned mappings. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The first EXECUTE after boot went down the firmware's direct submission path. That path reuses the reserved direct network context and the per-priority L2-spill mapping, and only the queued EXELOOP path sets them up. add-128 never spills and passed, but the 28-task MobileNetV1 started cold on the direct path and never sent a terminal report: the driver gave up after 3 s with -ETIMEDOUT (logged as "EXECUTE failed 6e"). Every job of the research harness that ran MobileNet, including the first one after boot, set the request flag. Set +0x30 bit 0 whenever the engine did not last run this program, which now includes a cold engine, and keep the direct path for the requests that follow. A failed EXECUTE now also logs the step it stopped at (opening gate, channel-7 ack, report wait, closing gate), the request flags, how many reports arrived for its UUID with the last state, and how many other reports arrived, so the next hang names what the firmware got to. KUnit: the session test expects the first request queued; a new case checks the failure trace for a request that starts and never ends. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
… log on a stall On the J616s the first MobileNet EXECUTE was acknowledged on channel 7 and then nothing came back: no start report, no fault, no crash line. Two changes. Each EXECUTE descriptor now carries the size of the surface's HWX section instead of the tensor span. They differed only for a padded input (MobileNet: 0x49800 of 0x4c000), which the H16 path had never sent. The J700 path that ran MobileNet always described the whole section. Userspace still sees and copies the span. A failed EXECUTE now also prints the non-zero rows of the command it sent and of the channel-7 reply, then every non-empty record of the firmware's text log (the SHAREDMALLOC buffer tagged LOG, 0x80-byte records). The transport keeps each shared allocation's tag so the log can be found. The session is quarantined after a failure, so this runs at most once per program. KUnit: log record decoding, finding allocations by tag, the descriptor size, and a stalled request without a log buffer. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
…f the preload Once the bootloader has filled and enabled the TEXT and DATA preload reservations, run the staged bring-up through the program stage from a work item after probe, so the accel node exists on every boot without a debugfs write. The debugfs stage file stays for reading the state and, before the boot bring-up starts, for diagnosis. While the reservations are still the disabled placeholders of the board DT (an older loader), refuse with -ENODEV and one informational line instead of an error. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
MobileNetV1 runs top-1 16/16 on the J616s through the H16 driver. Enable the ANE and its three DARTs on the board. The engine stays idle until the loader fills and enables the two preload reservations, so an older loader leaves it refused with one informational line. Drop the separate ane-test tree, which only did this, and update the documentation. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
|
Hardware results on the J616s (M4 Pro), 2026-11-02:
What made MobileNet work: the zeroed 0x14000 firmware heap tail mapped after DATA (7040ae9), the first EXECUTE of every program on the queued path (df11bfb), and whole input sections in the EXECUTE descriptor (916532b). The board DT now enables the ANE and its DARTs (a53bbd9). Until the loader fills the two preload reservations the device is refused with one informational line (085586e), so this is safe with the current Stage 2. KUnit 159/159 (x86_64) on the merged tree, arm64 W=1 module build clean, j616s and j616s-tether DTBs build. 🤖 Generated with Claude Code |
The complete H16 (M4 Pro, T6041) ANE feature in one PR: staged cold boot of the iBoot-preloaded firmware, the shared firmware transport, preload identity, program LOAD/CREATE/EXECUTE through the ABI 3 accel node, the host-side LOAD section builder and the T6040/J616s DT. It replaces the per-milestone drafts #720, #705 and #699 (all of their commits are in this branch). The shared transport from #706 is included too, since the H17 work in #714 builds on the same code.
What it does
<debugfs>/ane-h16/<device>/stage(root only):preflight,map,boot,startup,program, each running every stage not yet run. Pre-RUN failures roll back; from RUN on everything is held until reboot.memory-regionnodes and must be no-map and outside System RAM. aura fills them from the ADT at boot (kboot: hand off the ANE firmware preload on the M4 Pro aura#37).tools/testing/selftests/drivers/ane/h16-sections.pyderives the generic, operation, procedure and text-properties sections from the HWX (layouts after libane, MIT, by Joshua Warren).h16-run.pyuses it and runs add-128 twice against the CPU oracle.apple,dma-range <0 0 0x400 0>, DAPF ranges are 64-bit pairs. The ANE and its DARTs stay disabled until the hardware run passes.t6040-j616s-ane-test.dtsenables them for a test boot.Testing
Latest commits
apple,dapf-ranges(r4, start, end, r0, r20, as the t8110 bank takes them), reads it back and fails before RUN on a mismatch. A bank with lock bit 2 set is refused before any write.FOP_UNSIGNED_OFFSET, sodrm_open_helper()refused every open. A new KUnit suite registers the real driver on a mock device and opens the node through its fops (without the flag it reproduces the J616s warning).h16-run.pynow fails with the open() error instead of skipping.🤖 Generated with Claude Code