Skip to content

honeykrisp: map placed memory at the allocation size - #8

Open
joshuaswarren wants to merge 20 commits into
omacom:integration/aurorafrom
joshuaswarren:map-placed-length
Open

joshuaswarren wants to merge 20 commits into
omacom:integration/aurorafrom
joshuaswarren:map-placed-length

Conversation

@joshuaswarren

@joshuaswarren joshuaswarren commented Oct 12, 2026 •

Copy link
Copy Markdown

Current status: not ready to merge

Head d4fd1a4cb06f2f1cfbec79c07afa4b681e492988. Target: integration/aurora at a19691114759e2c0507f3502cf6166ef2c6e2e33.

Evidence binding (3 Nov 2026): the native, CTS and fixture results recorded on 1 Nov are for commit 093714aec24529ae3b127f3b0439b4f3126923c3. The head above is that commit plus one commit, d4fd1a4cb06f, which trims the review history from the header of tests/test-placed-map.c as the maintainer asked. It changes comments and one failure message in that CPU test; no driver source file changed. With comments stripped, the file differs from 093714aec245 only in that message. hk_placed_map_lifetime passes at the new head in a local x86 build. No new device or CTS run was made for d4fd1a4cb06f, so the 1 Nov device evidence stays bound to 093714aec245.

Two behaviors the review noted: an ordinary vkMapMemory now makes its own whole-BO mapping even when the BO's internal map exists, and the agx_bo statistics (mapped_B, from account_bo) count only the internal map, so application mappings are no longer in it.

Each app map belongs to one memory object. It no longer moves or drops the BO map used by an image or the trace code. This uses Aurora's map helpers. The heap rules do not change.

The virtio map now honors the requested length. A zero length still maps the whole BO. A failed host map still clears the pointer and size. The regression calls the real map function with a recording host stub. It checks placed length, ordinary mapping and failure cleanup. All nine CPU cases pass. The test includes the production header.

The fix owner observed the new case fail with the old length logic: the map covered 0x104000 bytes instead of the requested 0x100000. That control kept the function linkable. An earlier link failure is not regression evidence. These are CPU checks, not a VM or GPU run.

The real virtgpu host mapper returns NULL on failure. The BO map now clears its size for NULL as well as MAP_FAILED. The added regression failed before the fix: a NULL map kept a size of 0x104000. All nine CPU cases pass after the fix. This checks the real map function with a recording host stub, not a VM.

The original eight-case ownership control failed seven cases and passed the no-op case. It used an adapted shim, not the old tree as shipped. The ownership port's independent source review predates this virtio correction. It is not an exact-head review or merge GREEN for this update.

History is preserved by a forward update. No force push is used. PR10 is closed as already included, not merged. PR8 remains next; PR9 remains held. Current-head CI, exact-head review and GPU or real virtio checks remain required. Old device results below do not qualify this port.

Historical main-based description and results

Current status: READY after #10 (30 October)

Head 8eec298f16b5ec7e8aa116e12dc83e78950d2159.

The device check passed on an M1 Apple GPU on 30 October at 13:26 UTC. The exact driver passed all 13 native placed-map CTS cases. The loader trace confirms it loaded the candidate driver.

Four Vulkan checks passed on this head and failed on the control at 7cda7850edd103ace21aac37d416d2fdf7a282e1. Two imported memory objects kept distinct, coherent maps. Freeing one left the other readable and writable. Host copies worked before and after plain unmap, reserve unmap and ordinary unmap of an unaligned allocation. The reserve address could also be mapped again.

The control reused the other importer's mapping. Its three host-copy checks each faulted after release, after a working baseline. These were failures inside the cases, not missing features or setup errors.

Placed maps used aligned allocation sizes. The unaligned check used an ordinary map. See VUID-VkMemoryMapInfo-flags-09651.

The eight CPU cases and full local driver build also passed. An independent source review found no defect at this head.

At 14:37 UTC, a separate device check passed the sequence from Chris's finding: image bind, placed map, host copy, plain unmap, then host copy again. A working host-copy baseline was established before the placed map. All four sequence checks passed. The control aborted during the placed map, with the mapping-address assertion in hk_MapMemory2KHR. Both runs loaded their bound drivers. The packet checks remained clean.

Limits: virtio partial-length mapping remains a stated gap for a separate VM test. This is not full CTS.

Landing order stays #10, then #8, then #9. No merge is claimed.

Earlier description and evidence

Status on 29 October (withdrawn, superseded by the status above)

Head ddfb4cf114a6e72b690581ff6fb2fe8447d11ffa: READY status withdrawn following Chris's source-review finding. A placed application mapping can unmap the BO mapping still retained in a bound image's host-copy pointer; mem->map == NULL and a single BO reference do not exclude this lifetime.

Required next steps: reproduce the image-bind → placed-map → host-copy → unmap sequence, preserve the internal mapping independently or repair every retained pointer, and rerun the relevant regressions and exact-head review. The finding is source evidence, not a measured device crash. Earlier targeted results below do not cover this sequence.

Landing order remains #10 first, then corrected/qualified #8, then #9. #9 must wait for #8's correction and qualification.

Historical evidence and original PR description

READY TO MERGE after #10.

Head: ddfb4cf114a6e72b690581ff6fb2fe8447d11ffa.

GitHub reports MERGEABLE against main: no text conflicts. This is not a test pass.

The exact-head tests and GREEN source review below cover this commit. They are targeted checks, not full CTS. Merge it after #10 lands. Preserve this unchanged head; no new run or rebase is needed just to update its status. An authorized maintainer can land it next in the agreed order.

Earlier review, source and test notes are kept below with their original bindings. They do not change this status.


What this fixes

The conformance test dEQP-VK.memory.map_placed.unmap_reserve.size_1048576 crashes the process when it runs after many other memory tests. Four cases in the neighbouring exact_size group fail in that run. omacom/mesa main at 7cda7850ed has this crash.

The cause is in the placed map path of VK_EXT_map_memory_placed:

  1. A placed mapping covered the whole BO, not the allocation. The BO cache can return a BO that is larger than the request. A 0x100000 byte allocation got a 0x104000 byte mapping. The extra page lay in application memory. The test writes guard bytes there and reads them back, and the read hit an inaccessible page.
  2. A BO can go back to the BO cache with a mapping still on it, plain or placed. The next placed map of that BO returned the old address and made no new mapping. A placed mapping that was never unmapped also stayed in the application address range after vkFreeMemory.
  3. The reserve remap and the unmap used the BO size, so they covered the same extra page.

What this changes

  • The BO records the length of its live mapping.
  • A placed map covers the allocation size. An ordinary map still covers the whole BO, as before.
  • Unmap and the reserve remap use the recorded length.
  • A placed map drops any old mapping first. vkFreeMemory unmaps a placed mapping that its own memory object holds, before the BO goes back to the cache.
  • A failed map returns VK_ERROR_MEMORY_MAP_FAILED. The old assert for this is compiled out in release builds. The same error covers a placed map at a different address than the one requested, a placed map with an offset other than 0 or a size other than the allocation size, and a placed map of a BO that an import shares and that is already mapped. The driver reports memoryMapRangePlaced as false, so VUID-VkMemoryMapInfo-flags-09571 and VUID-VkMemoryMapInfo-flags-09572 make offset 0 and size VK_WHOLE_SIZE or the allocation size the only valid placed map.

Test results

The chunk runs use the library bytes of the built package, one run per arm. Control is the package of main at 7cda7850ed, built with the same recipe as the candidate. Candidate is the package of this branch at ddfb4cf114.

The first 1000 cases of the memory group (chunk 0 of its 7 chunks), the chunk where the control crashes. The 16-inch M1 Max and the 13-inch M1 give the same table.

Control Candidate
Pass 388 393
NotSupported 607 607
Fail 4 0
Crash 1 0

Exactly 5 of the 1000 rows differ on both chips. No other row differs.

Case Control Candidate
map_placed.exact_size.size_4096 Fail Pass
map_placed.exact_size.size_8192 Fail Pass
map_placed.exact_size.size_65536 Fail Pass
map_placed.exact_size.size_1048576 Fail Pass
map_placed.unmap_reserve.size_1048576 Crash Pass

All 13 map_placed cases pass on the candidate.

A small test program, run on the 16-inch M1 Max, one boot, with a native build of this branch, one test per process. It covers an ordinary map, an ordinary map then a reserve unmap, a cached larger BO with a placed map (plain and reserve unmap), a placed map after a free without unmap, and an application page at a freed placed address. The control crashes on the cached-BO case with a 0x104000 byte placed map, returns the wrong pointer after a free without unmap, and leaves the placed range mapped after vkFreeMemory. The branch passes all six tests with placed lengths of 0x100000 and 0x10000.

What this does not show

  • One chunk, 1000 of 3,253,584 cases. This is not a full conformance run.
  • The shared-BO guard has no test.
  • The offset and size error path has no test.
  • The virtio path compiles but did not run.
  • The Gallium driver was not built.
  • The source tree has one unrelated hazard that this change leaves as it is: two imported memory objects that share one BO and both use an ordinary map share one mapping.

The conformance test expects exact page boundaries here (see vktMemoryMapPlacedTests.cpp). I found no sentence in the extension text that requires it.

Observational two-M1 comparison (not approval)

Chris's comparison binds to main 7cda7850ed versus the old control stack d38e7192452 (#10 b87e7456, #8 c70e5372, #9 11ae82d8) plus build-only overlay 645169e3901 adding #9's missing idep_nir. It is not evidence for a future ownership-repair head.

The 13-inch M1 and M1 Air each ran seven common-path workloads, one warm-up and three measured rounds, plus clean/corrupted compute controls: 30 valid runs per arm, all four arms 30/30. Driver attribution, clean environment, no new kernel fault lines and drained process groups were checked per run. Same aarch64 recipes passed 47/47 registered tests on main and 49/49 on the control. Overall lab jobs still failed a separate known provider-attribution check; those failed verdicts are not being relabelled as passes.

Median latency change of control versus baseline (negative is lower):

Workload M1 Air submit/wait M1 Air GPU 13-inch M1 submit/wait 13-inch M1 GPU
raster -0.6% +0.1% -0.4% +0.0%
texture -2.8% -3.1% -0.7% -0.6%
compute +4.6% +5.9% +0.3% +0.4%
copy -0.6% -0.5% +1.6% +0.3%
submit-single +5.5% +4.5% -1.4% -1.4%
submit-batched +4.2% -1.7% -0.2% -1.2%
bo-lifetime +0.2% -1.9% -0.4% +2.9%

These are descriptive n=3 measurements without CPU frequency/affinity control, not statistical significance or equivalence. The source comment identifies which min/max ranges did not overlap. No placed maps, host image copies, capture/replay buffers or transform feedback were exercised, so this qualifies none of the three fixes and does not close the tracing or imported-object defects. The external-display path was not tested. Both Macs were restored afterward. Post-fix correctness and any new-head observations must retain their own source bindings.

A VK_EXT_map_memory_placed mapping covered the whole BO. The BO cache can
return a BO that is larger than the allocation, for example 0x104000 bytes
for a 0x100000 byte request. The mapping then covered the page after the
allocation in application memory. The conformance test writes guard bytes
there and reads them back, and it failed with a crash.

Record the length of the live mapping in the BO and use it to unmap. Map a
placed mapping with the allocation size, not the BO size. Report
VK_ERROR_MEMORY_MAP_FAILED when the map fails, in place of an assert that is
compiled out in release builds.

A placed mapping can also stay on a BO that goes back to the cache. The next
placed map of that BO then returned the old address and made no new mapping.
Unmap a placed mapping when its memory is freed, and drop any old mapping
before a new placed map.

The virtio path takes the new size argument. It was not run.
Review follow-up for the placed map change.

Return VK_ERROR_MEMORY_MAP_FAILED if a placed map ends at another address
than the one the application asked for, and drop that mapping. The old
assert for this was compiled out in release builds.

A placed map without a range covers the whole allocation from offset 0. Return
an error for any other offset or size.

Refuse a placed map when the BO is shared through an import and already
mapped, so a mapping that another memory object holds is not torn down.

Use one helper for the length of a live mapping in the unmap and the reserve
paths. A reserve unmap of a BO with no mapping does nothing.
The placed length now comes from the allocation size. Return an error if it
ever exceeds the BO, so mmap cannot map past the GEM object.
@joshuaswarren

Copy link
Copy Markdown
Author

GREEN at ddfb4cf, with two small notes. I read the full diff against main at 7cda785. I ran no build.

Checked:

  • Every writer and reader of the BO mapping is covered. That includes both bo_mmap implementations and both ops tables. It also includes agx_bo_unmap in agx_bo_free and in hk_device_memory.c, and the one agx_bo_map_placed caller.
  • agx_bo_map keeps bo->size. The roughly 20 other callers, including the Gallium driver, behave as before.
  • agx_device_virtio.c is in the build list and compiled. It was not run.
  • The BO cache can return a BO up to 2x the request (agx_bo_cache_fetch). Before this change the placed map, the reserve remap, the plain unmap and the BO free all used bo->size.
  • The new checks match the stated rules. A placed map must start at offset 0 with a size equal to the allocation size. That fits the driver reporting memoryMapRangePlaced as false.
  • A wrong address unmaps and returns VK_ERROR_MEMORY_MAP_FAILED.
  • The sharing guard fires only when the BO is already mapped and its refcount is above 1. Nothing in the Vulkan driver takes an extra reference, so it fires only for an import share.
  • Every number in the body matches the raw per-chunk results on both chips. The table is 388/607/4/1 against 393/607/0/0, with the same five rows. All 13 map_placed cases pass, and the full list is 3,253,584 cases.

Notes, neither blocking:

  1. hk_MapMemory2KHR still dereferences placed_info->pPlacedAddress when the placed flag is set and no placed info is chained. That is invalid usage and predates this PR. One check would close it.
  2. The branch has three commits, and the second and third repair the first. Squashing them into one is the maintainers' call.

Not covered, as the body says. The shared-BO guard and the offset and size rejection path have no test. Virtio is not run. The Gallium driver is not built.

@joshuaswarren

Copy link
Copy Markdown
Author

Both notes are open items. I did not change the branch for either.

  1. The null VkMemoryMapPlacedInfoEXT case is invalid usage and was in main before this change. A new commit changes the head, and the driver string in the library carries the head id, so the library bytes would change too. The five-row result above is tied to the library bytes of ddfb4cf114. I can send the one-line check as a separate small change if the maintainers want it.

  2. I did not squash. A squash keeps the tree but changes the commit id, for the same reason as note 1. The maintainers can squash on merge.

@joshuaswarren

Copy link
Copy Markdown
Author

Maintainer routing request for PR 8. This is a request for a merge contact, not a claim that review is finished.

It fixes the crash of dEQP-VK.memory.map_placed.unmap_reserve.size_1048576 that main has. What was run on the head ddfb4cf114a6e72b690581ff6fb2fe8447d11ffa and what was not run is in the description and in the two review comments above; I have not changed it since. PR 8 belongs to a merge order of PR 8, PR 9 and PR 10, then PR 6, then PR 11. A whole-suite run of PR 6 and the PR 11 commit on top of PRs 8, 9 and 10, against PRs 8, 9 and 10 alone, is queued. Its results will be posted on the PR 6 thread.

Question: who can merge into this repository's main branch, and in which of these PRs would you like to start? My account has pull access only.

@joshuaswarren

Copy link
Copy Markdown
Author

Second routing request for PR 8, about 14 hours after the first. It is still a request for a merge contact, not a claim that review is finished.

Nothing on the head has changed since my first note above. The review notes and the list of what was run are in the description and the two review comments.

Question: who can merge into this repository's main branch? If there is a different place to ask, a link is enough. My account has pull access only, so I cannot merge or mark anything ready.

@joshuaswarren

Copy link
Copy Markdown
Author

Status, 25 Oct: no review since I asked for a merge contact. This is the base of the whole-suite run of #6: without it the suite crashes in dEQP-VK.memory.map_placed.unmap_reserve.size_1048576, so I put its three commits unchanged under the #6 test branch and started the paired run on the 16-inch M1 Max. The combined candidate in #12 carries a variant that keeps independent imported mappings; when the two are reconciled, keep ordinary imported mappings independent. I will post the whole-suite result here too.

@joshuaswarren

Copy link
Copy Markdown
Author

Status, 25 Oct, for the landing order (#10 first, then #8, then #9, then #6).

Head ddfb4cf114a6. It merges cleanly after #10 on main 7cda7850ed.

MEASURED: it is in the control arm of the whole-suite CTS of the #6 stack on a 16-inch M1 Max and a 13-inch M1 (main plus #8, #9 and #10 against that plus #6). The memory_model and map_placed groups ran without a Pass to Fail change from the control arm to the candidate arm.

NOT measured: a CTS run with only this change against main.

@joshuaswarren

Copy link
Copy Markdown
Author

Batch 1 for main: #10, then #8, then #9, in that order.

All three apply to main at 7cda7850ed with no conflicts. They touch different code and git applies them in any order. The order is the agreed landing order. The #9 device run below is on top of #10 and #8. The #10 and #8 results below were measured on each branch alone. We checked the three together as a local merge (tip 59c25f62c9d). #19 went into integration/aurora, not main, so this base has not moved.

PR Head Change Device result at that head
#10 b87e7456 accept a NULL array of transform feedback counter buffers three transform_feedback chunks, 2,719 cases, on a 16-inch M1 Max and a 13-inch M1: the 18 former crashes pass, no other change
#8 ddfb4cf1 map placed memory at the allocation size memory chunk 0, 1000 cases, both chips: 4 Fail and 1 Crash become Pass, no other row differs
#9 11ae82d8 give capture and replay buffers their own address range binding_model chunk 0, 1000 cases, 13-inch M1, run at this exact head: 122 ResourceError become Pass, no case gets worse

Stack check, one boot on a 13-inch M1, binding_model chunk 0: main gives 340 Pass, 538 NotSupported and 122 ResourceError. Main with #10, #8 and #9 gives 462 Pass, 538 NotSupported and 0 ResourceError. The 122 changes are all ResourceError to Pass. This shows the three together. It does not isolate #9 from #8 and #10.

These are targeted checks, not the full conformance suite. The CTS binary's source commit is not independently verified.

#6 is not part of this batch. Its run over the touched test groups at its current head has not finished, and three shader_object.performance timing cases still need a decision. We will post that result separately. #3, #4 and #5 are superseded by #6 and will be closed after it merges.

The author account on these PRs has pull-only access, so a maintainer has to merge. Tell us if you want a different order or a different check first.

@joshuaswarren

Copy link
Copy Markdown
Author

@maralcbr could you review this current head for landing after #10? The exact-head test evidence and remaining scope limits are in the PR body. The requested landing order is #10, then #8, then #9. Our account cannot assign formal reviewers or merge here; please route this to a main-branch maintainer if needed.

@chriskearney chriskearney left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A placed map can invalidate a live image's internal host-copy pointer at ddfb4cf.

A non-sparse image bind stores plane->map = agx_bo_map(mem->bo) + offset in hk_image.c:1334. That internal mapping does not set mem->map. A subsequent application vkMapMemory2KHR with VK_MEMORY_MAP_PLACED_BIT_EXT can therefore reach this call while the image is still bound. The new unconditional agx_bo_unmap(bo) removes that internal mapping and replaces bo->_map, but the image keeps its old pointer. The host-image-copy paths later dereference planes[plane].map (for example hk_image.c:1444 and :1523), which can now be unmapped or reused memory.

The refcount check does not cover this case: binding the image keeps the memory object alive through the application's lifetime rules; it does not create another BO reference. This is distinct from main's existing wrong-address behavior when a placed map finds a cached mapping. Replacing the mapping fixes that address result while introducing a dangling pointer for this valid lifetime combination.

Please keep the internal image mapping independent of the application mapping, or otherwise preserve/reestablish every retained pointer, and add host-image-copy coverage with a placed map after image binding and after unmap. The placed-map contract does not invalidate a bound image when an application maps its memory.

This finding is from source review, not a new device crash or a CTS result. Independent runtime reproduction and the shared regression benchmarks are still pending; their results will be kept separate from this source finding.

Comment thread src/asahi/lib/agx_device.h Outdated
agx_bo_map_placed(struct agx_bo *bo, void *fixed_addr, size_t size)
{
if (fixed_addr)
agx_bo_unmap(bo);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This unmap can invalidate hk_image_plane.map, retained when the same allocation was bound to an image. mem->map is still NULL for that internal map and the BO refcount can still be 1, so neither guard above excludes the sequence. Please preserve an independent internal mapping or repair the retained image pointers.

@joshuaswarren

Copy link
Copy Markdown
Author

Confirmed from the source path: the BO mapping can be retained by a bound image even when mem->map is NULL, so the refcount guard is insufficient. I am withdrawing the READY status and adding a regression for image binding followed by placed map, host copy and unmap before changing the shared mapping path. No runtime reproduction or device result is claimed yet.

A bound image retains an internal host-copy mapping
(hk_image_plane_bind, plane->map = agx_bo_map(mem->bo) + offset) with no
mem->map and no BO reference, so a later application placed map reaches
agx_bo_map_placed, drops the BO mapping, and leaves the retained plane
pointers dangling for the host-copy paths.

The new libasahi_placed_map_test drives the real agx_device.h mapping
code with the exact bind, placed-map, unmap and reserve expressions from
hk_image.c and hk_device_memory.c. The only mock is the kernel mmap,
which hands back anonymous pages. Cases: placed map then plain unmap,
placed map then VK_MEMORY_UNMAP_RESERVE_BIT_EXT, and two images aliased
on one memory object. Fails at ddfb4cf; passes once the internal
mapping is independent of the application mapping.
Review follow-up on the CPU fixture: back the BO with one tmpfile
(ftruncate to the BO size) and hand out MAP_SHARED mappings, so the
internal image mapping, the application mapping and the placed mapping
are separate mappings of the same BO contents. The fixture now checks
coherence in both directions (retained vs earlier application mapping,
placed mapping vs bind-offset contents) in addition to lifetime after
unmap.

The placed target keeps its PROT_NONE reservation mapped until the
MAP_FIXED placed map replaces it. Every resource failure now FAILs the
case; the SKIP paths are gone. The shim tracks and cleans up all
mappings and the backing file per case. A map-before-bind control case
covers the application-map-then-bind order that the proposed fix's
stash logic must handle. Case bodies collapse into one data-driven
runner; no new framework.
A bound image retains a BO mapping independently of VkDeviceMemory.map.
Replacing that mapping for a placed application map left host-copy pointers
dangling even with one BO reference.

Give internal and application mappings separate slots. Return mmap results
from the native and virtio primitives instead of swapping shared state;
release both mappings with the BO and preserve placed-map size/error paths.

The four CPU regression cases failed on fixture head
9c3850f and now pass: plain unmap,
reserve unmap, aliased images, and application-map-before-bind. They use
real mapping helpers with shared file-backed kernel mmap emulation.
Vulkan entrypoint/device coverage and full driver compilation remain
separate qualification gates; no hardware readiness claim.
@greptile-apps

greptile-apps Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] No blocking code findings remain from this review; the PR's stated device checks remain separate merge gates.

Summary

Application mappings now belong to each memory object, while images and tracing keep the BO's stable mapping.

  • Each Vulkan memory object keeps its own application map.
  • Virtio placed maps use the requested mapping length.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Memory object A] --> AM[Application mapping A]
  B[Memory object B] --> BM[Application mapping B]
  AM --> BO[Shared BO backing]
  BM --> BO
  I[Images and tracing] --> IM[Stable BO mapping]
  IM --> BO
Loading

Reviews (7) · Last reviewed commit: "test: trim the review history from the p..." · Reviewed by Greptile

Comment thread src/asahi/lib/agx_device.h Resolved
Comment thread src/asahi/vulkan/hk_device_memory.c Outdated
Comment on lines +283 to +284
if (mem->map && mem->placed_map)
agx_bo_unmap(mem->bo);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Freeing one object unmaps another

hk_FreeMemory can now unmap memory still used by another imported memory object. Export and reimport a BO, placed-map the first object while _map is empty, then normally map the second object. The shared-BO check allows this order, and the normal map returns the same _map.

Freeing the first object now unmaps that address even though the second object remains mapped and holds a BO reference. Later reads or writes through the second object's pointer can crash. Give each memory object its own application mapping, or prevent this sharing before returning the pointer.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed in the source: after A creates a placed application map, B can normally map the same BO and receive A's cached pointer; freeing A then unmaps B's live mapping. This head remains NOT READY. I am adding a failing-first two-object/free-one regression and removing BO ownership of application mappings: each VkDeviceMemory will own its app pointer and length, while the BO keeps its stable driver/decoder mapping. No device reproduction is claimed, and no re-review request is being sent before the regression and fix are verified.

@joshuaswarren

Copy link
Copy Markdown
Author

The follow-up tracing and imported-memory findings expose a remaining ownership error in this head: a BO can be shared by multiple VkDeviceMemory objects, so it cannot own their replaceable application mapping. I am keeping this NOT READY and moving application pointer/length ownership to each memory object, while restoring the stable BO mapping used by driver and decoder callers. New trace and two-importer lifetime regressions will run failing-first. The earlier four CPU cases pass and the full local driver compiles, but neither covers these follow-up cases or replaces device qualification.

@chriskearney chriskearney left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At c70e537, trace mode crashes at the first queue submission. This confirms at runtime the tracing finding above, which your 23:25 note already plans to fix.

How it was run: an x86_64 host with Mesa's asahi drm-shim (G13G profile; no kernel, no GPU), and Honeykrisp built from this exact head (release, NDEBUG). A small Vulkan program records a transform feedback draw and calls vkQueueSubmit with ASAHI_MESA_DEBUG=trace.

Driver Result
main 7cda7850ed decode completes; 25,311-byte agxdecode dump
previous head ddfb4cf114 decode completes; same dump size
this head c70e5372 SIGSEGV in the first vkQueueSubmit; the dump stops at 78 bytes

Backtrace: __agxdecode_fetch_gpu_mem (decode.c:136) ← agxdecode_stateful ← agxdecode_drm_cmdbuf ← queue_submit ← vkQueueSubmit.

Cause:

  • With tracing on, agx_bo_create calls agx_bo_map(), then agxdecode_track_alloc() stores a copy of the BO (agx_bo.c:397-399).
  • agx_bo_map() now fills only _imap, so the stored copy has _map == NULL.
  • decode.c:102, :136 and :976 still read mem->_map / cmdbuf->_map.

Control: a local scratch change that reads _imap before _map at those three lines removes the crash, and the dump is byte-identical to main's. The scratch change only tests the cause; it is not a proposed final shape. The program's transform feedback data check fails under drm-shim on every driver, because nothing executes without a GPU; that check is not part of this result.

The crash is the same in a local merge of main with #10, this head and #9 (d38e71924527392fca5b09c23b9aa6017c52bc2b).

Separately, in the same host setup this head fixes the image-bind/placed-map case from the earlier review. It also fixes host copy after vkUnmapMemory2 and after VK_MEMORY_UNMAP_RESERVE_BIT_EXT, which main fails too. All 6 cases pass, with the image contents read back. These are host CPU-path results, not device or CTS results. Approval still needs the trace path fixed and the two-importer case the bot raised.

…ced-map regression

Follow-up findings on the independent-slots change: decode.c reads
bo->_map directly (agxdecode_grab_mapped, fetch_gpu_mem, cmdstream) and
wrap.c populates ._map at BO creation, so the stable BO mapping must
keep existing and stay pointer-stable across application maps; and two
memory objects sharing one imported BO must map independently, since an
ordinary map currently returns another importer's placed mapping and
that importer's unmap destroys it.

Two new cases on the same tmpfile-backed shared kernel seam: the
decoder-style stable mapping must match agx_bo_map, stay coherent with
a placed application mapping and survive placed map + unmap with an
unchanged pointer; and two importers (refcnt 2) must get distinct
mappings with mutual coherence, where the first importer's unmap leaves
the second's mapping valid. Application-map call sites of these cases
adapt to the per-memory mapping shape in the production fix commit;
assertions do not change. All resource failures FAIL; no SKIP paths.
@chriskearney

chriskearney commented Oct 30, 2026 •

Copy link
Copy Markdown

Observational benchmark of the current heads on two M1 Macs. This is not an approval. At c70e5372227417c8ebac4f218c013f8a378fc1a1 this PR still has the two open defects above: the trace-mode crash at the first submission, and freeing one of two imported memory objects can unmap the other one's mapping. These runs exercise neither path, and they don't exercise any of the three fixes.

What was compared

Workload: the Vulkan benchmark helper from omarchy-m-test GPU suite 1.

  • It runs 7 workloads, one warm-up round and three measured rounds, plus a clean compute control and a deliberately corrupted one. That is 30 runs per arm.
  • Checked in every run:
    • The only Vulkan driver mapped in the process was the staged libvulkan_asahi.so (baseline e85887bd…, control 0125441f…), loaded through the system loader.
    • The environment was clean.
    • No new kernel fault lines appeared, and the process group drained.
  • All 4 arms: 30/30 runs valid.

Results: median change of the control against the baseline. These are latencies, so lower is better. † marks a case where the min–max ranges of the two arms don't overlap.

workload M1 Air submit+wait M1 Air GPU time M1 submit+wait M1 GPU time
raster −0.6% +0.1% −0.4% +0.0%
texture −2.8% −3.1% −0.7% −0.6%
compute +4.6% +5.9% +0.3% +0.4%
copy −0.6% † −0.5% † +1.6% † +0.3%
submit-single +5.5% +4.5% † −1.4% −1.4%
submit-batched +4.2% −1.7% −0.2% −1.2%
bo-lifetime +0.2% −1.9% −0.4% +2.9%

Limits

  • Descriptive only: n = 3 per workload and arm, one job per arm, and no CPU frequency or affinity control. No statistical significance or equivalence is claimed.
  • Common paths only: the runs exercise honeykrisp: give capture and replay buffers their own address range #9's address-heap change and honeykrisp: map placed memory at the allocation size #8's split of internal and application mappings. There are no placed maps, host image copies, capture/replay buffers or transform feedback, so this qualifies none of the three fixes.
  • M1 external-display path: not tested, because no display was connected.
  • omarchy-m-test: no check status differs between baseline and control on either Mac.
  • Lab harness failure, identical in both arms: every job as a whole reads failed, because the lab's separate provider-attribution check stopped with nonregular live graphics path. The exact rejected path was not logged. The check's source and CPU-only controls reproduce that error for a DRM render-node mapping, a known lab-harness bug. The job verdicts are left as failed. It doesn't affect the per-run driver attribution above.
  • Restore: both Macs were returned to their original kernel, Mesa packages and boot configuration afterwards.

…regression

The user-required free scenario: two memory objects share one imported
BO and one is freed. The new case runs the BO-relevant hk_FreeMemory
sequence for the freed object - the placed-unmap condition of
hk_device_memory.c:283 and the real agx_bo_unreference refcount drop -
and requires the survivor's mapping to stay valid and coherent, with
the shared BO left at refcount 1. The heap accounting, ext-BO tracking
and vk_device_memory_destroy tail of hk_FreeMemory need a live
vk_device and stay behind the admitted device gate.
The free-path case calls the real agx_bo_unreference, which lives in
agx_bo.c in libasahi_lib; the test target never linked the library, so
the parent's red run failed at link with an undefined reference instead
of exercising the refcount. Mirror the libasahi_tests dependency
pattern: link_with libasahi_lib, which propagates its own dependency
closure (dep_libdrm, idep_nir, libvdrm, libasahi_decode, idep_libagx,
idep_libpoly) to the consumer. No test or assertion changed.
Parent-observed red at e14884a59caa (pr8-owner-red3.log): the stable BO
mapping was absent because agx_bo_map populated only _imap, and two
memory objects sharing an imported BO shared one replaceable mapping -
importer B's ordinary map returned importer A's placed mapping, so
freeing or unmapping A destroyed B's pointer.

Restore bo->_map as the single stable driver-internal mapping and delete
the _imap slot: agx_bo_map creates and returns _map (whole BO), decode.c
and wrap.c keep reading and populating it directly, the BO cache keeps
it as before, and agx_bo_free releases it. Application mappings leave
the BO entirely: hk_MapMemory2KHR obtains a fresh mapping per memory
object from the returning bo_mmap primitive (placed maps at the
requested fixed address, ordinary maps whole-BO at a kernel-chosen
address) into the existing mem->map plus a new mem->map_size;
hk_UnmapMemory2KHR plain and reserve paths, the placed-address mismatch
error path and vkFreeMemory release exactly that object's mapping. The
shared-BO guard is removed rather than layered: with no replaceable
mapping on the BO there is nothing left for it to protect, and two
importers now map independently with coherence coming from the shared
pages. Offset/size placed contract, mmap failure handling, the
already-mapped check and error results are unchanged.

The regression keeps its assertions and adapts only the application
call expressions to the per-memory shape. Red lineage cited in the test
header (8af285bd30c, e14884a59ca). No device run: hardware, CTS and
precision gates hold.
The stable BO mapping always covers the whole BO. Its length is already bo->size. Application mapping lengths belong to each memory object, and the old placed-map flag has no readers after the ownership fix.
Comment thread src/asahi/lib/tests/test-placed-map.c Resolved
@chriskearney

Copy link
Copy Markdown

Independent follow-up at 4e269c5. The source correction addresses the mapping-ownership findings: the BO retains its stable internal/decoder mapping, while each VkDeviceMemory owns its application pointer and length. This is a source/host validation update, not device qualification or merge approval.

On an x86_64 address-honouring drm-shim, using the same preserved repro programs and controls:

  • All six real-driver host-copy cases pass, including placed-map-after-image-bind, the crash variant, and host copy after plain unmap or reserve unmap. They also pass with ASAHI_MESA_DEBUG=trace.
  • The old c70e537 first-submit trace SIGSEGV still reproduces. On 4e269c5 it is gone: the 25,311-byte decoded command dump is byte-identical to main. The helper's GPU-data check remains the expected failure without a GPU; that is not counted as a transform-feedback pass.
  • The unchanged main and ddfb4cf controls retain their wrong-address/dangling-pointer results; ddfb4cf still faults in the crash variant.
  • A clean build requesting only libasahi_placed_map_test succeeds from an empty build directory, and all seven cases pass. This includes stable-map, independent-importer and free-one/survivor checks. Those importer cases use real BO reference counting with mock mmap and mirror the hk expressions; they do not execute the complete Vulkan import/free path. drm-shim lacks the GEM PRIME handle/fd operations needed for that live-import test.

Separately, the exact clean author union of #10 b87e745, this #8 head, and #9 a8960b7 (local tip 9460a17b877, tree c0404e39) built natively for aarch64 with all 49 registered Meson tests passing, including both Asahi regression targets. No build overlay was needed: #9 now supplies its own idep_nir dependency. Production and test package payloads are byte-identical, independently checked.

Still untested on this head: actual Mac/GPU execution, CTS, and the complete heap-accounting/external-BO/Vulkan teardown path for shared imported memory. The earlier observational benchmark stays bound to the old stack and does not qualify this successor. The PR's current device-qualification hold remains.

Move the map, unmap and reserve-unmap operations into shared helpers so the regression executes the same ownership paths as the Vulkan callers. Register the test with the Vulkan dependency bundle instead of copying its transitive headers.

Proof: eight CPU mapping-lifetime cases pass and the full local Vulkan driver compiles. The earlier missing libagx header build failure is retained. No device qualification or merge approval is claimed.
@joshuaswarren

Copy link
Copy Markdown
Author

Source review at 8eec298: no source defect found. This is a source verdict only. It is not device qualification and not a merge GREEN; the device and maintainer holds named on this PR stay in force.

What I checked at this exact head:

  • The design is consistent. The BO keeps one stable internal mapping (agx_bo_map, bo->_map, read by the decoder and by the image bind at hk_image.c:1334). Each hk_device_memory owns its application mapping and length (map, map_size). hk_memory_map_from_bo never stores a mapping on the BO, hk_memory_unmap and hk_memory_unmap_reserve touch only the memory object's own mapping, and hk_FreeMemory drops it before the BO reference. That removes the lifetime bug in the review finding (a placed map, unmap or free destroying the pointer an image bind retained).
  • Callers: agx_bo_map_placed is gone and nothing references it. The only bo_mmap implementers are agx_bo_mmap and agx_virtio_bo_mmap, both moved to the new (dev, bo, fixed_addr, size) signature and both return NULL on failure. The remaining direct _map users are agx_bo_unmap, agx_bo_map, decode.c and agx_bo.c, all on the stable mapping.
  • hk_MapMemory2KHR: a placed map must be offset 0, size equal to the allocation, and not larger than the BO; it maps exactly the allocation size; an ordinary map maps the whole BO; a returned address that differs from the requested one is unmapped and refused.
  • I rebuilt libasahi_placed_map_test at this head and ran it: 8 of 8 PASS (stable map, independent importers, free of one importer, unmap without map, placed map after bind then unmap, reserve unmap after bind, aliased images, map before bind). I then changed hk_device_memory.h six ways and rebuilt each time. Five were caught: unmap drops the BO's mapping (crash), reserve uses the BO size, the length is not recorded, the reserve leaves the mapping recorded, unmap keeps the pointer. The header was restored afterwards and matches the head.

Findings, none blocking a source verdict:

  1. Test gap: one change survived. If an application map is stored on the BO when the BO has no stable mapping yet (the map-before-bind order), all 8 cases still pass. The fixed code does not do this, but map_before_bind_control does not pin it. Add an assertion that bo->_map stays NULL after an application map, or that a later agx_bo_map returns a different pointer from the application mapping.
  2. The comment above map_before_bind_control still says "The proposed production fix stashes an existing application mapping around the internal map". That design is gone. Delete the sentence.
  3. Not exercised by any host test, so verified by reading only: the size choice (fixed_addr ? mem->vk.size : mem->bo->size), the placed-map validation, the address check, and the hk_FreeMemory order. The CPU test drives the helpers, not the entrypoints.
  4. Edge to cover at the device gate: a placed map uses mem->vk.size, the unaligned allocation size, while the BO is aligned to 16 KiB. mmap and munmap round the length up to the kernel page, so an allocation whose size is not a multiple of the page would make the placed mapping cover the rest of its last page in application memory. The CTS exact-size case uses 1 MiB, which is aligned. I did not test an unaligned size.
  5. The virtio path now asks vdrm_bo_map for a length smaller than the BO for placed maps. I read it; I did not run it.
  6. The subject of commit 8531e06 ends in libasahi_lib, a literal build target name. If this is squash merged, write the subject without it.

Not checked: any device or CTS run (heap accounting, external BO tracking, the teardown tail, placed map after bind on hardware), a full Vulkan driver build (the driver compile is reported on the PR; I built only the test and its library), and the maintainer holds.

@maralcbr maralcbr left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed at 8eec298f16b5ec7e8aa116e12dc83e78950d2159. Requesting changes: the fix is right, but please retarget it to integration/aurora.

The code looks correct on its base. I found no defects.

  • Each VkDeviceMemory now owns its application mapping (hk_memory_map_from_bo, hk_memory_unmap, hk_memory_unmap_reserve). This fixes aliasing between two imports of one BO.
  • bo->_map becomes a stable internal mapping that only agx_bo_free drops. That keeps two retained pointers valid: the image host-copy plane->map = agx_bo_map(mem->bo) + offset, and the trace decoder's copy of the BO taken in agxdecode_track_alloc.
  • A placed map is sized to the allocation, and vkFreeMemory unmaps it before the BO goes back to the cache.
  • The virtio backends return NULL (virtgpu) or MAP_FAILED (vpipe), and both are handled. A placed map that lands at a different address fails cleanly and no longer hits an assert.

Blocking: retarget to integration/aurora.

  • main mirrors stock Mesa, per the fork policy in AGENTS.md there.
  • Aurora still has the hazard this PR fixes. For non-shared BOs, its hk_MapMemory2KHR maps through agx_bo_map_placed, which munmaps and relocates bo->_map for a placed map (agx_device.h ~368–375). Its hk_UnmapMemory2KHR munmaps bo->_map (hk_device_memory.c ~541–553). Meanwhile hk_image.c ~2169 keeps plane->map = agx_bo_map(mem->bo) + off. So on the branch we actually ship, image bind followed by any map or unmap, then a host image copy, can use a dangling pointer. Trace mode has the same problem.
  • Aurora already has agx_bo_map_owned / bo_mmap_independent for shared BOs. The port should fold that into this per-memory ownership model and keep Aurora's backend abstractions, not run a second scheme beside it.
  • Upstream Mesa main still has the old agx_bo_map_placed path, so please send this upstream as an MR as well.

Non-blocking:

  • The header comment in tests/test-placed-map.c is review history: GitHub URLs, review-thread ids, file:line references, fixture SHAs. Please cut it to what the test checks. Lines 92–93 describe a "stash" fix that the PR no longer uses.
  • An ordinary vkMapMemory now makes a second whole-BO mmap even when bo->_map exists. That's fine, but worth a line in the commit message.
  • agx_bo stats (mapped_B) no longer count application mappings.

Chris's earlier change requests were against ddfb4cf1 and c70e5372. His 2026-10-30 follow-up says the ownership findings are fixed at 4e269c5, so he may want to update his review state.

@maralcbr

Copy link
Copy Markdown
Member

Correction to my review above: drop the "please send this upstream as an MR as well" point.

Upstream Mesa's AGENTS.md puts src/asahi and src/gallium/drivers/asahi under the Asahi Linux LLM policy, which broadly forbids generative AI for material contributions. This change was AI-assisted, so it can't go upstream. A human resubmission or disclosure trailer doesn't change that.

The rest of the review stands: retarget to integration/aurora and fold it into Aurora's existing ownership code.

Every VkDeviceMemory application map takes the backend-owned mapping path, ordinary as well as placed, even when a stable internal BO map already exists; image/decoder users keep that stable map untouched. Map, unmap, reserve and free operate only on the per-memory mapping. No mapping-count statistics exist in the backends, so app maps cannot skew them; command-execution stats are unaffected.

Add a CPU regression asserting an ordinary app map leaves bo->_map empty before bind and the later internal map has a different address, alongside the placed-map and shared-importer lifetime cases.
hk_MapMemory2KHR's three-argument call is the contract; the regression called the same helper with a stray device pointer. Remove the parameter and its (void) silencer from the header and update all eight test callsites, so the header, driver and test agree on one signature.
Declare the regression after hk_deps exists and link the Asahi layout and compiler libraries required by libasahi_lib. Guard the stable-map coherence read so the pre-fix control reports the dangling retained map as a lifetime failure instead of crashing in memcmp.
The tested Aurora ownership port supersedes the older main-based backend changes. Keep both histories without reapplying the obsolete implementation. This merge intentionally retains the exact tested tree from 2f8ebd0; it does not merge the pull request into the integration branch.
@joshuaswarren
joshuaswarren changed the base branch from main to integration/aurora October 31, 2026 17:52
@greptile-apps

This comment has been minimized.

agx_virtio_bo_mmap ignored the length argument and always asked the host for the whole cached BO. A placed map on a BO larger than the VkDeviceMemory then maps past the address the application reserved and records the wrong _map_size, unlike the native backend's length ?: bo->size. Ask vdrm_bo_map for exactly the requested length and fall back to the BO size only for the length-0 ordinary map; the MAP_FAILED cleanup is unchanged. Expose the primitive so the placed-map regression drives the real function against a recorded vdrm stub: placed must request exactly the allocation, length 0 the whole BO, and MAP_FAILED must leave the BO slot cleared. The case is red against the pre-fix length logic and green with it.
Include the production header instead of maintaining a second prototype. The registered nine-case mapping test passes after rebuilding with that declaration.
@joshuaswarren

Copy link
Copy Markdown
Author

CHANGES at 4ca6985.

The virtio length finding is fixed in the shared map function. It passes the requested length to the host and records that same size. Zero length keeps the whole-BO fallback. Failure cleanup is unchanged.

All nine CPU cases pass. The new case calls the real function with a recording host stub. It checks placed length, zero length and MAP_FAILED cleanup. The fix owner observed a size assertion fail with the old length logic, not merely a build failure.

This does not prove real virtio or GPU behavior. Exact-head review, CI and existing device gates remain open. No merge approval is claimed.

The real virtgpu mapper returns NULL on ioctl or mmap failure. Normalize both failure sentinels so no failed BO retains a map length. The nine-case CPU regression fails on the new NULL case before this fix and passes afterward; no VM or GPU qualification is claimed.
@joshuaswarren

Copy link
Copy Markdown
Author

GREEN at 093714a.

Source review only. This is not merge approval.

An independent review covered the full six-file diff against a19691114759e2c0507f3502cf6166ef2c6e2e33. It found no source defect. The review checked per-memory mapping ownership, unmap and free paths, heap bounds, imported-fd cleanup, virtio mapping length, NULL failure cleanup, callers and test registration.

The native check on 2026-11-01 passed all 13 placed-map CTS cases. The candidate provider trace contains exactly two initialization observations. All five candidate fixture modes passed. Control lifetime was clean; the other four control cases met their original defect checks. The strict image-bind sequence checks passed on those same recorded events. There was no second GPU run of that sequence.

The candidate driver SHA-256 was 09f7b4ab0a0cea9ec3803bb299bd6fd8c6cf5c76a83f53ab87c55d14d57af7a3. Both roles retained their source, library and provider bindings. All 51 copied output files matched their hashes.

This closes the recorded native scope and this source review only. Real virtio execution remains unproved. Broad matrix, heap and timing qualification are not claimed. Existing CI and review requirements remain in force. The prior failed native attempt is preserved.

@joshuaswarren

Copy link
Copy Markdown
Author

Status, 3 Nov 2026 (UTC): no change to head 093714aec24529ae3b127f3b0439b4f3126923c3. This is waiting on a maintainer re-review.

At this head: the base is integration/aurora (retargeted as requested on 31 Oct), the merge state is clean, and CI is green (ci / result, build x86_64 and aarch64, source, plan, Greptile). The three change requests were left on older heads (ddfb4cf1, c70e5372, 8eec298f). The two review threads still open are marked outdated.

Not applied: the non-blocking request to trim the review-history header in tests/test-placed-map.c. I left it alone so this head keeps the evidence recorded on 1 Nov; it will go in with the next push.

As on 1 Nov, this is a source review and the recorded native scope only, not merge approval. Real virtio execution remains unproved.

The header of test-placed-map.c carried review history: a GitHub discussion
URL, a thread id, fixture head ids, and file:line references into the driver.
It now says what the test checks and how, and names the functions instead of
line numbers. The same file:line references in two code comments are gone.

Only comments change, plus one failure message that quoted the thread id.
Compiling the file with comments stripped gives the same code except that
string. hk_placed_map_lifetime passes (1/1).
@joshuaswarren

Copy link
Copy Markdown
Author

Status, 3 Nov 2026 (UTC): pushed d4fd1a4cb06f2f1cfbec79c07afa4b681e492988, one commit on top of 093714aec245, to apply the maintainer's non-blocking request: the review-history header (URL, thread id, fixture ids, file:line references) is trimmed from tests/test-placed-map.c. Comments and one failure message only; no driver source file changed, and hk_placed_map_lifetime passes locally. The 1 Nov native evidence stays bound to 093714aec245 (the PR body now says so). The base is still integration/aurora; the earlier change requests were on older heads. Waiting on maintainer re-review.

@joshuaswarren

Copy link
Copy Markdown
Author

GREEN on d4fd1a4

Source review of the delta only: 093714aec24529ae3b127f3b0439b4f3126923c3..d4fd1a4cb06f2f1cfbec79c07afa4b681e492988 ("test: trim the review history from the placed-map test").

Reviewer identity: routed by Main to Sonnet (Claude); the model id is unverifiable from inside the session, and Main's routing notice is the source. The implementer is a different party; implementer model unverified. I did not edit the PR, and I did not build or run the test.

Checked at the exact head (fetched refs/pull/8/head, which resolved to the sha above, and confirmed again just before posting):

  1. Scope: exactly one commit over 093714a (the parent of the head), one file, src/asahi/vulkan/tests/test-placed-map.c (+42 -51; 783 to 774 lines).
  2. Code unchanged: I stripped comments from both versions with gcc -fpreprocessed -dD -E -P and diffed. The stripped files are both 535 lines, and the only difference is one string literal: "placed map + unmap (omacom/mesa#8 r4418383484)" became "placed map + unmap". No other token changed.
  3. That string is a failure message only: nothing else in the PR tree references r4418383484, and nothing keys on the old text.
  4. The trimmed header now cites functions instead of line numbers. Every name it uses exists at this head: hk_image_plane_bind, agx_bo_map, hk_memory_map_from_bo, hk_memory_unmap, hk_memory_unmap_reserve, agx_bo_unreference, agx_virtio_bo_mmap, hk_FreeMemory, vk_device_memory_destroy, bo_mmap; decode.c reads bo->_map (lines 110, 144) and wrap.c initializes ._map (lines 210, 230), as the header says, and that wording was already in the old header.
  5. The commit message matches what the diff does ("Only comments change, plus one failure message that quoted the thread id").

Not checked: that hk_placed_map_lifetime passes (the commit message says 1/1). That is the implementer's claim; with comments and one string literal changed, I would expect the same result, but I did not run it.

@joshuaswarren

Copy link
Copy Markdown
Author

GREEN at d4fd1a4

Source review of the single commit over 093714a (reviewed by Claude Opus; the commit's author is a different agent). It touches only src/asahi/vulkan/tests/test-placed-map.c. The changes are header and comment trims plus one CASE_FAIL label string ("placed map + unmap" no longer quotes the thread id). No test logic or driver source changed, and the new header lists the map-before-bind case already in the file. CI at this head passes. The 1 Nov device evidence stays bound to 093714a, as the PR comment says.

@joshuaswarren

Copy link
Copy Markdown
Author

@maralcbr: this is ready for your re-review at d4fd1a4cb06f2f1cfbec79c07afa4b681e492988 (3 Nov 2026, UTC).

What changed against your review at 8eec298f: the base is integration/aurora as you asked, and your non-blocking request is applied: the review history is trimmed from the header of tests/test-placed-map.c, with no driver source change. An independent source review of the head is posted above (GREEN at this head; source review only, not merge approval). CI is green and the merge state is clean.

Your change request and Chris's two are on older heads (8eec298f, ddfb4cf1, c70e5372). Please re-review, or dismiss them if the points are covered. The recorded native evidence from 1 Nov is bound to 093714aec245, the commit before the header trim; real virtio execution remains unproved.

@joshuaswarren

Copy link
Copy Markdown
Author

Note

🤖 GPT-6.1 Terra responding on behalf of joshuaswarren

This PR now targets integration/aurora at head d4fd1a4cb06f2f1cfbec79c07afa4b681e492988. Application maps use the existing independent mapping helper. The test header is trimmed, and the body records the mapping and accounting changes. The current CI checks pass on x86_64 and aarch64. The device results remain tied to 093714aec24529ae3b127f3b0439b4f3126923c3. Could you re-review the current head?

@joshuaswarren

Copy link
Copy Markdown
Author

[Joshua's agent] @maralcbr: the retarget you asked for is done. This PR now targets integration/aurora. Current head: d4fd1a4 (merge state CLEAN, 20 commits).

Your CHANGES_REQUESTED is attached to 8eec298, which predates the retarget. Could you re-review at d4fd1a4, or dismiss the old request if the retarget covers it? Your earlier note said the code was correct on its base, so the open point was the base only.

@joshuaswarren

Copy link
Copy Markdown
Author

State response at the current head (9 commits since the 4e269c5 follow-up above), covering what changed against that validation point.

Since 4e269c5 the branch adds, grouped by the open items in that follow-up:

  1. Placed-map contract: honeykrisp now maps placed memory at the allocation size (72c18d4) and checks the placed address, size, and sharing mode (f91b6f4), closing the address/length gap that the reserved-unmap cases probed.
  2. Ownership: app mappings are kept independent of the stable BO map (4bd01db), which is the invariant behind the mapping ownership findings from the first review.
  3. Virtio path: the host map is bounded by the requested length (9f8bc55), the map size is cleared when the host returns NULL (093714a), and the test uses the real virtio map declaration (4ca6985).
  4. Test plumbing: the placed-map regression registers standalone after its dependencies (2f8ebd0), so the clean empty-build-dir check from the follow-up keeps working at this head; 8fad125 and d4fd1a4 keep the review history while trimming superseded test history.

What this comment does not claim: no new Mac/GPU execution, no CTS, and no new runtime numbers. The open items from the follow-up stand unchanged: actual device execution, CTS coverage, and the complete shared-import heap accounting and teardown path, which drm-shim cannot exercise because it lacks the GEM PRIME handle and fd operations. The device qualification hold on this PR stays until those are covered.

On the trace path: the interim shape that produced the first-submit SIGSEGV (a separate internal mapping field that agxdecode copies as NULL) is no longer in the tree at this head; agx_bo_map fills the single stable mapping at allocation, so agxdecode_track_alloc stores a copy with a live mapping. The follow-up's finding that the crash is gone at 4e269c5 is consistent with that design; no separate decode fix is carried on this branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants