Repository navigation
drm/asahi: g17: add the T6040 (M4 Pro) GPU as a Neo-style target - #408
Conversation
A single-instance G17 firmware (the M4 Pro runs both roles on one coprocessor) has no secondary kernel root. Make secondary_root_offset an Option<u64>: the pagetables region then only needs the primary root, mirror_secondary_root() does nothing, and the TTBAT context-1 kernel alias is installed for every PublishedRoots firmware, since activate_render_context needs it. T8140 keeps Some(0x40000) and behaves as before. Signed-off-by: Jonathan Goyvaerts <jonathan.goyvaerts@gmail.com> Assisted-by: LLM
The M4 Pro firmware runs both G17 roles on one coprocessor. Prepare the runtime for such a target; T8140 keeps two instances and behaves as before. - Firmware.secondary is an Option<Coprocessor>, created only when the configuration names a secondary root; boot, init, POWER_ON_DONE, the opening-retire wait, stop and drop skip it when absent. - event::Transport::roles(): event, trace and statistics service and the idle recheck cover only the instances that exist. - Config::recovery_slot_keys (T8140: SLOT_KEYS) replaces the hard-coded physical address; None leaves recovery to the firmware's own blame. - Config::gpu_generation is reported to userspace (T8140: G17). - The pm_metrics client VA comes from the target's configuration instead of hw::t8140::CONFIG in user_aliases and render preparation. Signed-off-by: Jonathan Goyvaerts <jonathan.goyvaerts@gmail.com> Assisted-by: LLM
G17 firmware builds that share the interface version still differ in a few queue rules. Name them in a fw::Variant that each SoC's Config points at, instead of hard-coding the A18 Pro firmware's (26A428) choices: - qid_floor: the first QID the host may use; queue admission and the UAPI queue limit follow the render pairs it leaves; - pointers: where the item-ring producer and the recovery target live in a queue's pointer block; - mmio_pair_registration: whether render pairs are registered through the MMIO queue ports; - mcache: whether render kick entries may name an MCache table; - few_primitives and ray_traversal: whether those render and compute features are offered and accepted. The variant reaches the queue-ID table, the compute and render graphs, command validation and the feature report through the structures that already carry per-device state. T8140 uses V26A428, which keeps every value it had, so its behaviour does not change. Signed-off-by: Jonathan Goyvaerts <jonathan.goyvaerts@gmail.com> Assisted-by: LLM
The initialization builder names hw::t8140 for the register windows, the reserved register-map slots, the performance-table configuration and the operating-point count. Move these references into Config so a second G17 SoC can supply its own tables, and make the crash log placement an enum (CrashBuffers::Fixed) that a SoC whose firmware places its own crash log can extend. T8140 passes its existing tables; nothing changes for it. Signed-off-by: Jonathan Goyvaerts <jonathan.goyvaerts@gmail.com> Assisted-by: LLM
The performance tables of the hardware data have sixteen voltage lanes per state. The A18 Pro lists one voltage per operating point, which the host broadcasts to every lane of table A and stores in lane 0 of table B. GPUs with several clusters have one voltage per cluster, listed as one opp-microvolt cell per cluster (as the T6031 device tree already does). Read every cell, and store cluster n's voltage in lane n of both tables, leaving the other lanes zero. A single cell keeps the current broadcast, so the T8140 tables are unchanged. All operating points must have the same number of cells. Signed-off-by: Jonathan Goyvaerts <jonathan.goyvaerts@gmail.com> Assisted-by: LLM
A register-map slot of the hardware data can describe several instances of a block: the firmware finds instance n at va + n * size, and the entry's total size covers all of them while its element size is that of one instance. On SoCs with several memory controllers or AFR blocks the instances are not contiguous in physical memory. Give RegisterWindow an instance count and a physical stride, map each instance separately, and fill total_size and element_size from them. Every T8140 window has one instance, so its register map and mappings are unchanged. Signed-off-by: Jonathan Goyvaerts <jonathan.goyvaerts@gmail.com> Assisted-by: LLM
The A18 Pro firmware acknowledges the initialization root with an INITDATA_ACK message and expects POWER_ON_DONE once both coprocessors are initialized. Other firmware builds acknowledge by setting word +0x14 of the primary status A to 1 and send no message. Add fw::variant::InitAck and Variant::power_on_done. With InitAck::Status the host polls status A for up to 3 s after handing over the primary root, failing early if the firmware crashes; the opening-record wait that follows is unchanged. POWER_ON_DONE is sent only where the variant asks for it. V26A428 keeps the message and POWER_ON_DONE, so T8140 is unchanged. Signed-off-by: Jonathan Goyvaerts <jonathan.goyvaerts@gmail.com> Assisted-by: LLM
The UAT code reaches the firmware's root and kernel-window tables
through struct page, so it requires the pagetables region to be part
of the kernel's memory map; it refuses a root in no-map memory ("DT
using no-map?"). On the M4 Pro the boot loader reserves the UAT ranges
as no-map regions outside /memory, and the firmware also builds tables
in the l2-pagetables region.
Add mmu::UatQuirks::reserved_tables: the pagetables and l2-pagetables
regions are mapped write-back once (pgtable::ReservedTables), and every
table access goes through with_table(), which uses that mapping for a
page in either region and struct page otherwise. The CPU's cached lines
of both regions are cleaned and invalidated after the firmware booted,
so the host reads what the firmware wrote.
This is a temporary path: once the boot loader adds the UAT ranges to
/memory, as m1n1 does, the regions lose no-map and this commit can be
reverted. T8140 and the older GPUs use UatQuirks::DEFAULT and are
unchanged.
Signed-off-by: Jonathan Goyvaerts <jonathan.goyvaerts@gmail.com>
Assisted-by: LLM
The M4 Pro GPU has only ever run with the UAT policy the Gravity Linux G16 driver uses for it: every page-table and context-table change is written back (dc cvac), TLB ranges are invalidated one page at a time, the handoff page carries only the host header (current slot 0xffff_ffff, the lock never taken) and GPU-only client mappings are stored as AP 0 with the access in PXN/UXN. Whether the M4 Pro needs any of this has not been tested; the A18 Pro needs none of it. Add one UatQuirks field per setting, so a SoC can stay on the policy it was tested with and each setting can be moved to the A18 Pro's value on its own after a test: - clean_tables: clean every page-table change to the point of coherency, with the page-table cleaning the G16 backend already uses (clean_poc, no longer limited to G16), and also the handoff page and each context-table slot after it changes; - page_tlbi: invalidate page by page (vae1os), or the whole ASID above 2048 pages, instead of rvae1os; - handoff_lock and handoff_slot: whether the legacy handoff lock is taken and the current slot written at initialization; - native_gpu_permissions: the AP 0 form for GPU-only mappings of client and kernel-lower tables, on map and on reprotect. The root clean of clean_poc goes through the reserved-table mapping, so it also covers a firmware root in no-map memory. UatQuirks::DEFAULT keeps the A18 Pro policy, so T8140, the older GPUs and the adopted G15/G16 UAT are unchanged. Based on findings by Gravity Linux (Cody Ho, Niklas Sheth). Signed-off-by: Jonathan Goyvaerts <jonathan.goyvaerts@gmail.com> Assisted-by: LLM
The M4 Pro (T6040) GPU coprocessor is an ASCWrap v6 like the A18 Pro's: the ADT node /arm-io/gfx-asc is compatible with iop,ascwrap-v6, its wrapper is 0x88000 bytes with the ASC mailbox at +0x8000, and its vector-base register follows the same layout. Unlike the A18 Pro it runs a single firmware instance, with the GFX role. Signed-off-by: Jonathan Goyvaerts <jonathan.goyvaerts@gmail.com> Assisted-by: LLM
The ASCWrap v6 provider accepts only the T8140's GPU coprocessor windows. The M4 Pro (T6040) GPU coprocessor is the same block with one firmware role, GFX, at wrapper 0x28a600000 and vector base 0x28a050000 (ADT /arm-io/gfx-asc). Replace the hard-coded T8140 checks with a role table per compatible: each role has its name, its firmware role and its fixed CPU-physical windows, which the probe validates as before. Add the apple,t6040-ascwrap-v6 compatible with its single role. T8140 keeps its two roles at the same addresses. Signed-off-by: Jonathan Goyvaerts <jonathan.goyvaerts@gmail.com> Assisted-by: LLM
The M4 Pro (T6040) GPU is described like the A18 Pro's: an asc and an sgx register range, its GPU power domain and an operating-point table with one voltage per cluster. It has a single GFX coprocessor mailbox, operating-point tables for its CS and AFR clock domains (apple,cs-opp and apple,afr-opp, the names the older Apple GPUs' device trees use), and two more memory regions than the A18 Pro: fw-data, the loaded firmware's data segment, where the firmware places its crash log, and l2-pagetables, where the firmware builds the page tables of its kernel window. The boot loader may report the macOS version whose boot firmware loaded the GPU firmware in apple,firmware-version, which identifies the firmware build. The memory-region lists differ per compatible, so move them into the per-compatible branches; the existing compatibles keep the same regions and names. Signed-off-by: Jonathan Goyvaerts <jonathan.goyvaerts@gmail.com> Assisted-by: LLM
The M4 Pro runs the macOS 26.6 GPU firmware (25G83, mBoot-18000.161.10). It has the A18 Pro firmware's interface version and the same initialization objects, with these differences: - One coprocessor carries both roles: one main configuration with the secondary-only words (0x300 = 4, the power-configuration pointer), a zeroed page at unk_18, 0x32c and 0x344 zero, and one merged root naming status B, the power state and the configuration. - The cluster is 0xd4000 bytes: status B at 0x10000 is 0xf180 bytes long, status A follows it, and the power state is its own page, of which only the fast-die target and release temperatures are set. - The hardware data (HwData25G83) is the A18 Pro's up to 0x2554 with 8 bytes inserted before 0x2570 and 4 more before 0x2614, so the completion rings move to 0x2620 and the QoS pointer to 0x26b8. It has the CS and AFR performance tables at 0x1a48 and 0x1b90 and carries one voltage lane per cluster. - The power configuration (PowerConfig25G83) is at bundle +0x5380 and has two blocks fewer than the A18 Pro's; the auxiliary data and an AON temperature-source table follow it. - Region C has other values, now RegionCConfig in Config (T8140 keeps its values). - The five views and the firmware area are separate pages. fw::variant::InitGraph selects the graph. The 25G83 contents are constants except for the operating points (the device tree's GPU, CS and AFR tables), the core count, three pointers and a random word. They were derived by evaluating, for the J616s, the hardware-data, region C and power encoders that Gravity Linux (Niklas Sheth, Cody Ho) wrote for this firmware, which the M4 Pro has run with since; no code of theirs is carried. At boot the built hardware data, power configuration and region C are hashed (FNV-1a, without the runtime words) and compared with the hashes of the encoders' output, and the GPU is not started if they differ. The leakage coefficients in the power configuration are this unit's values. They are not in the ADT, and whether they are per SoC or per device is not known; they stay a driver constant until that is. Where the 25G83 graph deviates from the A18 Pro's is only known from that setup; every value is the one that runs today. Based on findings by Gravity Linux (Cody Ho, Niklas Sheth). Signed-off-by: Jonathan Goyvaerts <jonathan.goyvaerts@gmail.com> Assisted-by: LLM
The 25G83 firmware expects two commands in a render pair's item rings that the A18 Pro firmware does not take: - InitBufferManager (tag 5) before the first tiling descriptor that uses a buffer manager, naming its UAT context, buffer slot, PB state and tiling stamp; - FragmentBarrier (tag 4) before every fragment descriptor, waiting for the paired tiling stamp in addition to the kick-entry dependency. Add Variant::lead_commands. With it, render publication writes these commands after each stage's QueueConfig record in its configuration slot and publishes them as the first item of the stage, and the buffer manager remembers that it was initialized once a tiling pass with InitBufferManager was published. V26A428 has no lead commands. Based on findings by Gravity Linux (Cody Ho, Niklas Sheth). Signed-off-by: Jonathan Goyvaerts <jonathan.goyvaerts@gmail.com> Assisted-by: LLM
The 25G83 firmware takes render descriptors with other register programs, and the M4 Pro's two clusters of ten cores change the buffers whose layout follows the core layout. Firmware-build data (Variant::programs, RegisterPrograms::V25G83): - Tiling array of 83 entries (checkpoints 81/83/83, free-list slot index 79): the A18 Pro's without 0x1748 and 0x1740, with the twelve tiler parameter sub-buffer registers and 0x10131 = 0x88. - Main fragment array of 91 entries (checkpoints 87/88/88, slot index 84): with 0x160b8 = 0 after the tile state and 0x160a8 = 0x20 before the closing 0x16068. - Both drop the SCS enable 0x017d9 unless the stage has shader-context scratch; a stage with it carries 0x017d9 = 1 as on the A18 Pro, and the counts and indices after it move by one. - Tile-state base 0x36011 instead of 0x3717f: with the A18 Pro's bits a fragment pass more than 80 tiles wide and with more than 4096 tiles never completes, which includes every full-screen pass on the 3456x2234 panel. - The TPC object also holds the seven tiler parameter sub-buffers the tiling registers name. Core-layout data: - The deflake buffer's sub-buffers follow each cluster's control words: +0x20/+0x2a0 with one cluster, +0xa0/+0x820 with two, where the viewport words at +0x900 would land in the third sub-buffer and are not written (render::Deflake). - The compute operand-state buffer holds two banks of three records per core and one tail per cluster: 0x44000 bytes with banks of 0x1e000 at a stride of 0x1e400 for two clusters of ten cores (compute::OperandState). Only the measured layouts are accepted. V26A428 and one cluster keep the A18 Pro's programs and buffers. The 25G83 register lists come from the register programs that the Gravity Linux G16 driver (Niklas Sheth, Cody Ho) runs on the M4 Pro; the code is new. Based on findings by Gravity Linux (Cody Ho, Niklas Sheth). Signed-off-by: Jonathan Goyvaerts <jonathan.goyvaerts@gmail.com> Assisted-by: LLM
Add the M4 Pro GPU to the G17 runtime. Its firmware (25G83) runs on one ASCWrap v6 coprocessor with the GFX role, which the mailbox provider starts and stops; the GPU power domains are ordinary PMGR domains. The ID registers report one die of two clusters with ten cores each, family 0xa, variant 3, revision B1. - hw/t6040.rs: the configuration, the 25 register windows (the memory controller and AFR slots with four instances each), the performance table configuration and region C. - fw::variant::V25G83: QIDs from 32, the producer at pointer block +0x50 without a recovery target, no MMIO render-pair registration, no MCache, lead commands, the 25G83 register programs and initialization graph, acknowledgment in status A and no POWER_ON_DONE. Few-primitives renders hang this firmware and a stalled ray traversal wedges the GPU without a recovery, so neither is offered nor accepted. - CrashBuffers::FirmwareData: the firmware asks for its crash log at a physical address inside its data segment (the fw-data reserved region); the driver maps that range and RTKit echoes the request. - Config::adopt_root_entries and Config::fabric_bridge: the M4 Pro borrows the firmware root as the firmware left it and writes neither the fabric bridge nor the gating register, as it has always run. - The UABI reports the GPU as G16, which userspace drives it as. - The firmware build is identified, not inferred from the SoC: Config::firmware (fw::variant::Firmware) lists the builds a SoC supports by the macOS version whose boot firmware loaded them, which the boot loader reports in apple,firmware-version on the GPU node (as m1n1 writes it). The T6040 accepts macOS 26.6.2 (iBoot mBoot-18000.161.10, the 25G83 firmware) and refuses anything else before touching the GPU, naming what it found; the build it accepts is logged. The T8140 keeps its single unidentified build. Where the values differ from the A18 Pro's they are the ones the M4 Pro runs with today. The UAT quirks other than the no-map tables, the root adoption, the bridge and gating, the MMIO registration and POWER_ON_DONE were never tested the A18 Pro's way on this chip, and each stays a separate setting until it is. Based on findings by Gravity Linux (Cody Ho, Niklas Sheth). Signed-off-by: Jonathan Goyvaerts <jonathan.goyvaerts@gmail.com> Assisted-by: LLM
Describe the M4 Pro GPU as the A18 Pro's is described: - pmgr_gfx: the PMGR block of the GPU power domains (ADT pmgr devices AFR 0x181 at +0x100 and GFX 0x182 at +0x110 with parent AFR), laid out as on the T6031. Both are always on: the GPU firmware keeps running and does not survive GFX going off. GPX (0x180 at +0x0) is left alone, as the boot loader leaves it on and nothing uses it. - gfx_mbox: the ASCWrap v6 coprocessor mailbox with the GFX role (ADT gfx-asc), its send-empty and receive-not-empty interrupts. - gpu: the asc and sgx ranges, the mailbox and the GFX power domain. - The PMP's GPU report entry (pmp_gfx) gets the GFX domain as its parent, as on the T8140. On the J616s the GPU firmware runs from boot on, with GFX always on, so the board claims pmp_gfx always-on: the PMP sees the GPU on whenever it is powered. Without the GPU node the entry stays unclaimed (the PMP crash of a claim with nothing powering the GPU, fixed by commit c4722f3). On the J616s, add its sixteen operating points in performance-state order with one opp-microvolt cell per cluster (ADT /arm-io/sgx perf-states and perf-states1), the eight of its CS and AFR clock domains (cs-perf-states, afr-perf-states), and the memory the boot loader reserves for the GPU firmware: its data segment (fw-data), where it places its crash log, and the UAT ranges (ttbs, pagetables, l2-pagetables, handoff). The operating points are binned per device: these are this unit's values until the boot loader fills them in. The UAT ranges are no-map until the boot loader adds them to /memory. Binding: apple,agx-t6040 and apple,t6040-ascwrap-v6, earlier in this series. Signed-off-by: Jonathan Goyvaerts <jonathan.goyvaerts@gmail.com> Assisted-by: LLM
Bring in the J616s USB-C ports (aurora-silicon#403). Its Type-C nodes and this series' GPU nodes were added at the same place in t6040-j616s.dts; both are kept. Signed-off-by: Jonathan Goyvaerts <jonathan.goyvaerts@gmail.com> Assisted-by: LLM
The boot loader finds the GPU node through the gpu alias, as m1n1's dt_set_gpu() does on every other Apple SoC (t600x, t602x, t603x, t8103, t8112, t8122, t8132, t8140 all have it). Without it a loader cannot fill in apple,firmware-version on the T6040 GPU node, and the driver refuses the GPU unless the device tree carries the property itself. Fixes: 92d0217 ("arm64: dts: apple: t6040: Add the GPU") Signed-off-by: Jonathan Goyvaerts <jonathan.goyvaerts@gmail.com> Assisted-by: LLM
|
Pushed one fix on top: 🤖 Generated with Claude Code |
|
Data from a second J616s (MacBook Pro 16" M4 Pro, 48 GB) for the per-unit values in the J616s GPU node. It comes from this unit's ADT, captured through m1n1 proxy and read offline. Read-only: I haven't booted this branch on it yet. GPU operating points are binned per unit.
At 338-1312 MHz this unit's values are mostly 5-15 mV higher. A few states are lower, and states 2 and 3 differ in opposite directions between the two cells. So this DT as merged would run this unit's GPU below its own voltages in most states. It's a concrete case for the loader filling in the OPPs (m1n1 Reserved memory: same addresses on this unit. In the ADT, Firmware version string. This unit's macOS 26.6.2 was installed through Recovery, and its |
|
Ran the KUnit tests of this PR at Result: kunitconfig |
RyanTheTide
left a comment
There was a problem hiding this comment.
Thanks for this. It's a big, careful series, and most of it is fine to take. We're holding it for now because of two blockers, one about attribution and one about the J616s device tree. Details below, with file:line references to the series merged onto integration/aurora 1aa2857.
Blockers
- Gravity attribution in the crash log mapping (commit 16, "drm/asahi: g17: add the T6040 (M4 Pro)"). In
g17/mod.rs(about lines 380-393), thefw-datacrash log path follows Gravity Linux'sCrashBuffer::shmem_mapindrivers/gpu/drm/asahi/g16.rs(gravity-m4) step for step. It takes the same reserved region by name, uses the samechecked_sub/checked_addbounds againstres.size(), the sameMem::try_new(res, MemFlag::WB)and the same field set, and has a reworded copy of the SAFETY comment.g16.rsis GPL-2.0-only, and our file isGPL-2.0-only OR MIT, while the PR says there is no Gravity code in the series. It's small, but our rule on Gravity code is strict. Either credit it properly (Originally-by Cody Ho / Niklas Sheth, as appropriate, with a Link, and keep it out of the dual-licensed file), or replace it with an independent design. Mappingfw-dataonce at boot and handing out subranges would also stop the driver remapping 0x138000 bytes on every crash log request. - The J616s GPU node ships one unit's values with
status = "okay"(t6040-j616s.dts, the gpu node, its OPP tables and reserved-memory). The driver refuses safely when noapple,firmware-versionis present:firmware_variant()runs before the first GPU register read. But a loader that writes the version without filling in the per-unit data makes the driver run with your unit's voltages. fbalazsy's numbers show a second unit needs 5-15 mV more in most states. Ryan's J616s is on a different firmware (26.6.1) and has different reserved-memory addresses, and the regions sit at about base + 48 GiB, so a lower-memory configuration would not have them in DRAM at all. Please keep&gpudisabled in the board file, or leave the regions and OPPs out until a loader fills them from the ADT and enables the node, as m1n1 does on the other SoCs. The version property alone shouldn't count as proof that the per-unit data was filled in.
Major
- Firmware identity (
g17/mod.rsaround 1080-1110). The init-data hash only covers the driver's own constants (not OPPs or the core count), so it catches drift in the code, not a different firmware build or a different unit. The.701.1question fbalazsy raised can't be answered by it. The G16 backend already checks the SHA-256 of the loaded 25G83 TEXT (g16/hw.rs,g16/boot.rs). Reusing that check here would make this solid. - Leakage coefficients (
fw/initdata/v25g83.rs,LEAKAGE). The commit says it isn't known whether they're per SoC or per device, and the hash then passes silently on another unit. Either take them from the DT, filled by the loader (m1n1 computes them from the ADT on other SoCs), or show that they're per SoC. - T8140 buffer layouts now depend on the cluster count (
fw/compute.rsOperandState::new(clusters, cores),fw/render.rsDeflake::new(clusters)). The A18 Pro keeps its old layout only if it reports one cluster. Please select these throughConfig/Variant, so the T8140 gets its layout explicitly rather than through a hardware count read at probe. - No-map table path (commit 8,
pgtable.rswith_table). For a table outside the two reserved regions it falls back toPage::borrow_phys_unchecked, which is undefined behaviour on a no-map system. Whenreservedis set, use the checked borrow and return an error. Coherency is also assumed for firmware writes tol2-pagetablesafter the one clean and invalidate at boot; please document why that holds. As you say, this commit should go once the loader puts the ranges in/memory. - A second 25G83 implementation. The G16 backend already drives 25G83 for T8132. Building the T6040 on G17's queue and render code makes sense, but the firmware identity check and the region names (
shared-l2vs the newl2-pagetables) should be shared, not duplicated.
Minor
mem.rsPAGE_TLBIis a global static set fromUat::new. Make it a field of the UAT, or document that it assumes one GPU.apple,agx.yaml:apple,firmware-versionneedsminItems: 3as well asmaxItems: 3.fw/initdata.rsPerfGroup::fill: nothing checks that the number of voltage cells is 1 or equals the cluster count. Check it inopps().queue/render/memory.rswrite_leads:fragment_id as u32truncates.fw/queue.rsPointerBlock::word()maps any offset other than 0x50 toword_40. Use an enum or assert the two valid offsets.- A few comments name Apple Metal driver internals (
emitBarrierCommands, "the 25G83 Metal driver's default parameter-buffer sizes"). Please describe the facts instead; this is a public tree.
What's fine. I checked the T8140 path in detail. UatQuirks::DEFAULT leaves the A18 Pro policy as it was, clean_poc doesn't run on the T8140, the QID floor is 0 and max_queues stays 58, the boot order and the mailbox are unchanged, and the region C, register windows and OPP cells keep their values, apart from the cluster-count point above. The UAT policy, v25g83 layouts, region C, lead commands and register arrays read as independently written from facts, and the "Based on findings by Gravity Linux" credit covers them. I ran an exact-line match and a constant match against gravity-m4, niklassheth/linux integration/m4-7.3, gpu/g16-dev, bits/210-gpu and Gravity's PUBLIC_neo_agx_rust_driver. Only trivial lines matched, and only 2-5 of the 155 new constants appear anywhere in Gravity.
Suggested way forward. Split the series. Commits 1-7 and 10-15, plus the cluster-count and with_table fixes, can go in on their own once they've had a Neo GPU run. Commit 16 follows once the crash log attribution is resolved (ideally with the TEXT hash). Keep 17-18 back until the GPU node is loader-filled or disabled by default. Once that's done, we'll boot the J616s without the version property, check there's no SError after "PMP started", and then merge.
drm/asahi: g17: T6040 (M4 Pro) GPU, #408 with review follow-ups (GPU disabled on J616s)
|
Merged through #420 (137462e), with your commits unchanged plus our follow-ups from the review: the fw-data crash-log mapping moved to a GPL-2.0-only g17/data_segment.rs crediting Cody Ho and Niklas Sheth, the J616s GPU node kept disabled in-tree until a loader fills in the per-unit values, the core-layout buffers taken from Config, and the smaller items. Tested on the Neo (no regressions, fault test passes) and on our J616s with the GPU disabled (clean PMP start, no SError). Thanks. |
…rved regions With reserved table regions (no-map systems such as the T6040), a page-table page outside them went through Page::borrow_phys_unchecked(), which is undefined behaviour when the page is other no-map memory without a struct page. Use the checked borrow there and refuse such a page with -EIO; systems without reserved regions keep the unchecked borrow of an allocated page-table page. Document the single cache invalidate of the reserved regions at boot. It runs after the host has already written table entries, which is safe because the T6040 cleans every host table store to the PoC (UatQuirks::clean_tables), so the invalidate drops only clean lines. Not invalidating again assumes the firmware stops writing the tables the host walks once it has booted; say that this is an assumption. The wrapper's comment claimed the invalidate came before the first host edit, which it doesn't. Link: #408 Signed-off-by: Jonathan Goyvaerts <jonathan.goyvaerts@gmail.com> Assisted-by: LLM
Retain the public model provenance in the implementation. The numeric tables came through Jonathan Goyvaerts from Gravity Linux work by Cody Ho and Niklas Sheth. The loader calculates them from per-chip data. Preserve the proven generic restore diagnostic now that the GPU uses the helper too. Originally-by: Jonathan Goyvaerts <jonathan.goyvaerts@gmail.com> Link: aurora-silicon/linux#408 Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Retain the public model provenance in the implementation. The numeric tables came through Jonathan Goyvaerts from Gravity Linux work by Cody Ho and Niklas Sheth. The loader calculates them from per-chip data. Preserve the proven generic restore diagnostic now that the GPU uses the helper too. Originally-by: Jonathan Goyvaerts <jonathan.goyvaerts@gmail.com> Link: aurora-silicon/linux#408 Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The M4 Pro GPU (T6040) running macOS 26.6.2's GPU firmware (25G83), added to the G17 backend the way the A18 Pro (T8140, Neo) is: per-SoC tables in
hw/t6040.rs, the firmware's initialization data as typed layouts, device-tree power domains, operating-point tables and the ASCWrap v6 mailbox. 25G83 carries the A18 Pro's firmware interface (26A428), so the T6040 runs on the existing G17 code; where the two differ, the difference is a field of the SoC config or of the firmware variant, and the T8140 keeps its values.There is no GravityLinux code in this series. Their M4 Pro bring-up (Cody Ho, Niklas Sheth) is the source of the UAT policy the chip has been running with, credited in that commit.
What the series adds
Config::firmwarelists the firmware builds a SoC supports, identified by the macOS version whose boot firmware loaded them:apple,firmware-versionon the GPU node, as m1n1 provides it for the other GPUs. The T6040 accepts macOS 26.6.2 (iBoot mBoot-18000.161.10, the 25G83 firmware) and refuses anything else before touching the GPU, naming what it found; the build it accepts is logged. The T8140 keeps its single build, not identified.max_queues) 42 logical queues instead of 58: a 43rd queue is refused when it is created instead of waiting for a pair that never comes. The T8140 keeps 58./memory, and the firmware also builds tables in anl2-pagetablesregion. Table accesses go through a write-back mapping of those regions. Temporary: once the loader adds the ranges to/memory, as m1n1 does, this goes.UatQuirks): page-table cleaning to the point of coherency (the G16 backend'sclean_poc, no longer limited to G16), with the context-table slots and the handoff page; page-by-page TLB invalidation; whether the handoff lock is taken and the current slot written at init; and the native AP 0 form for GPU-only mappings. The T6040 keeps the policy it has always run with; each setting can move to the A18 Pro's value on its own once a test shows it is not needed.UatQuirks::DEFAULTis the A18 Pro policy.apple,agx-t6040(merged with the T8132 entries of arm64: apple: T8132/J713 (M4 MacBook Air) support and native graphics (replaces #366, #367) #400: each SoC keeps its own memory-region names), andapple,t6040-ascwrap-v6with its driver support.hw/t6040.rs) and the J616s GPU node:pmgr_gfxwith the AFR and GFX power states (always on: the firmware keeps running and does not survive GFX going off),gfx_mbox, the GPU node, its OPP tables (binned per device: this unit's values until a boot loader fills them in), and the reserved memory (the firmware data segment and the UAT ranges, at the addresses iBoot uses on this unit, until a boot loader fills them in from the ADT as m1n1 does on the T8140). The PMP's GPU report entry (pmp_gfx, j616s: PMP boots and stays up (endpoint 7, pmp-gfx report) #402) gets the GFX state as its parent, and the J616s board claims it always-on next to enabling the GPU, so the PMP sees the GPU on exactly while it is powered; without a GPU node it stays unclaimed.The UAPI reports the GPU as G16, which is what Mesa drives it as.
Defaults kept as tested
Where the T6040's values differ from the A18 Pro's, they are the ones it has run with: the UAT policy above, the firmware root borrowed as the firmware left it, no fabric bridge or gating write, no MMIO render-pair registration, no POWER_ON_DONE, the init accepted in status A, few-primitives off, ray traversal refused, no MCache. Each is a separate field so it can be tried the A18 Pro's way on its own; that is also why the 25G83 register builders keep their SCS (ray query scratch) handling although
ray_traversalis off.Hardware tested on: Apple MacBook Pro (16-inch, M4 Pro, 2024), J616s / T6040, macOS 26.6.2 firmware (25G83), booted by our own loader.
How tested: Our daily kernel 7.3.0-m4.11 (on
integration/aurora6af6603bf85) carries exactly this branch, plus our private device-tree include (withapple,firmware-version = <26 6 2>on the GPU node, since our loader does not write it yet). On it the GPU probes ("GPU firmware: macOS 26.6.2 (25G83, iBoot mBoot-18000.161.10)") and drives the desktop (Hyprland, Mesa as G16). Its predecessor 7.3.0-m4.10 ran this driver before the review fixes in this branch (the init-data hash, the recovery timestamp table, the queue limit, the reserved-table cache maintenance) and has been the desktop's GPU since this morning; the stress run was on it: glmark2 (GLES) 8003 and vkmark 12835 with Mesa's single-queue setting, 8160 and 14967 without it, all runs completing, with no GPU recovery, fault or firmware crash in the kernel log. Our earlier daily kernels drove the same firmware build with an older T6040 driver.Not tested / limits:
apple,firmware-versionon the GPU node nor the GPU's reserved regions and operating points, so this needs a boot loader that does. Ours keeps the regions at iBoot's addresses, which the board file carries, and has the version write in its next revision; the tested build had the version in its device tree. Without the property the driver refuses the GPU, by design.Commits: 17, in order: the MMU and G17 groundwork (1-9), the bindings and mailbox (10-12), the 25G83 layout and commands (13-15), the T6040 config (16), the J616s GPU node (17).
Base:
integration/aurora(6af6603bf85). Built at every commit withCONFIG_DRM_ASAHI=mandCONFIG_DRM_ASAHI_G16=y(G16 and G17 together), W=1, and with KUnit enabled so the tests build: no new warnings (the tip's own 8fetch_updatedeprecations, and with KUnit an unusedMMstatic inmemacct.rs, remain).dt_binding_check(dtschema 2026.9) is clean for apple,agx.yaml and apple,ascwrap-v6.yaml;dtbs_checkpasses for t6040-j616s, t8140-j700 and t8132-j713 against them (the J616s tree's only report is the knownnonposted-mmioon its pmp-report node).Userspace: Mesa needs T6040 support to use the GPU; a Mesa PR follows.
🤖 Generated with Claude Code