Repository navigation
Conversation
tomastola
left a comment
There was a problem hiding this comment.
Thanks for this, @Woody-Hu, and for the clear write-up with before/after numbers from real hardware. The diagnosis is right: the failed name lookup was being treated as a verdict about the part, and classifying from the kernel target is the correct fix. A few things need attention before it can land. The first one is the important one, and it's a one-line change.
Review: needs work
This is a review of the whole change at 0b542d58 against main at 1c33248c.
It fixes the is_apu classification symptom from #449 and adds the 1586 row that #507 asks for. The description says it doesn't try to close the rest of either issue.
Blocking
-
examine-29 never uses the host it plants, so it fails on lanes without a real APU and passes on a real one whether or not the fix is present.
tests/e2e-cucumber/features/examine.feature:447,tests/e2e-cucumber/tests/e2e/examine_steps.rs:523,:1510-1541- The Given step puts the fake
lspci/rocminfoPATH andROCM_CLI_TEST_HOST_ROOTintoworld.command_env. - The When step it uses, "the user inspects the system in machine-readable form", calls
crate::run_rocm, and that function never appliescommand_env. Onlyrun_rocm_with_scenario_envdoes, and that is used by "the user inspects that machine in machine-readable form" (examine_steps.rs:1543). - What I saw:
- At this head on a Linux host with no GPU, the scenario failed with "lspci not found; cannot enumerate PCI GPUs",
"gpus": []andhas_apu: false. The planted env was never used. - With the step text switched to "inspects that machine", it passes at head and fails with the
examine.rschange reverted. So the fixture itself is good; only the step wiring is off. - On a real Strix Halo with ROCm installed, the host's own
lspci, KFD androcminfoanswer instead, so the scenario passes whether or not the fix is present.
- At this head on a Linux host with no GPU, the scenario failed with "lspci not found; cannot enumerate PCI GPUs",
- Suggested fix: use the "inspects that machine in machine-readable form" step. It also skips framework probing, which this scenario doesn't need. The feature comment ("every Linux lane can drive it") and the description's "3/3 steps pass" will then be accurate.
- The Given step puts the fake
-
Nothing tests the new
if gpu.is_apu != Some(true)guard.crates/rocm-core/src/examine.rs:1725- I replaced the guard with
if true. All 756rocm-corelib tests still passed, and so did examine-29 with its When step corrected. - Every test that reaches the empty-target branch starts from
is_apu: Some(false). - The guard only changes the result in one case: the name matched an APU keyword but resolved no target, and KFD then reports a target that
gfx_is_apu_familydoesn't list. The PCI scan never leaves an AMD entry atNone, so in practice the guard means== Some(false). - Suggested fix: add a unit test that starts from
Some(true), an empty target and a KFD target outside the family list, and asserts the verdict staysSome(true). Or, if "never downgrade" isn't intended here, drop the guard.
- I replaced the guard with
-
The kernel-only path has user-visible behaviour but no scenario.
crates/rocm-core/src/examine.rs:1707AGENTS.mdasks for a scenario as well as a unit test when user-observable behaviour changes: "User-observable behavior needs a scenario, not only a unit test."- On a host without
lspci, this change setshas_apuandhas_discrete_amdthrough the kernel-only branch. Onlya_kernel_only_apu_node_is_classified_from_its_targetcovers that. - Even with the When step corrected, examine-29 always has a PCI match, so it never reaches this branch. When I broke the branch, the scenario stayed green.
- Suggested fix: add a variant of examine-29 whose fake
lspciprints nothing, asplant_gpu_fixturesalready does. Alternatively, state the gap in the PR text, whichAGENTS.mdallows.
Non-blocking
-
The sysfs fallback still leaves
is_apuunset, and its comments now contradict the reasoning here.examine.rs:1477,:1500-1508,:5627-5632- The comment this PR removes tied the two paths together ("for the same reason
probe_gpus_sysfs_fallbackleaves it unset"). probe_gpus_sysfs_fallbackstill says "Claiming either would be inventing a fact". The test comment at:5629still says "the topology says which target, not whether it is integrated". As a result, a gfx1151 found only through DRM ip-discovery still reportshas_apu: false.- Your reasoning should be the one that stands, because the rocminfo path (
:1447) and the hipInfo path (:3189) already classify from the target. Either classify in the sysfs fallback too and update both comments, or note it as a follow-up.
- The comment this PR removes tied the two paths together ("for the same reason
-
A kernel-only node with an empty or unlisted target now reads as discrete.
examine.rs:1707KfdGpuNode.gfx_targetis empty when the version doesn't decode (host_gpu.rs:1003), andgfx_is_apu_family("")is false. That node used to beNoneand is nowSome(false), sohas_discrete_amd: truegets set with no evidence behind it.- APU targets missing from the list (Raven, gfx902) are affected the same way.
- The rocminfo path already behaves like this. Still, keeping
Nonewhengfx_targetis empty would be a cheap guard.
-
The comments say
pci.idshas no name for 1002:1586, but current upstreampci.idsdoes.host_gpu.rs:717-718,examine.rs:5101,examine.feature:432, and the commit message of 0b542d5- Upstream now has:
1586 Strix Halo [Radeon Graphics / Radeon 8050S Graphics / Radeon 8060S Graphics]. The bug is still real on hosts with an older packaged copy, so "older distro copies ofpci.ids" would be accurate. - That upstream entry would also be a good source to cite for the new row, as the gfx90c rows cite theirs.
- The row's comment justifies it with Linux evidence (KFD,
pci.ids), but this table is only read on the Windows paths. - 1586 isn't in
pnp_device_id_table_agrees_about_apus(examine.rs:5893) yet.
- Upstream now has:
Decisions for the author
- This PR bundles #449 and #507.
AGENTS.mdasks for one logical change per PR. The 1586 row only matters on Windows and doesn't affect the #449 scenario. Both are about Strix Halo and the description is upfront about the split, so keeping them together is defensible. Splitting them would let the table row land on its own. - It overlaps with #521. The description says the two don't overlap because
GfxPackagingis untouched. However, #521 ("classify integrated AMD GPUs by target, and never downgrade a verdict") reworks the same classification inexamine.rsand already includes a("Device", "1586", "gfx1151", true)case for #449. Whichever lands second will conflict or duplicate. It may be worth agreeing an order with the #521 author.
nowycondro
left a comment
There was a problem hiding this comment.
Automated review (recall-biased, high effort): found one likely correctness regression and one altitude/consistency gap. Details inline / below.
| // carve-out) still needs a name; `has_apu` only needs the | ||
| // family, so leaving this unset hid kernel-visible APUs on | ||
| // hosts without `lspci`. | ||
| is_apu: Some(gfx_is_apu_family(&node.gfx_target)), |
There was a problem hiding this comment.
Unresolved KFD target is stamped as a confident "discrete" verdict instead of "unknown".
node.gfx_target can legitimately be an empty string: kfd_gpu_nodes_in builds it via parse_linux_kfd_gfx_target(version.trim()).unwrap_or_default(), and parse_linux_kfd_gfx_target deliberately returns None (not a guess) for a 5/6-digit gfx_target_version it cannot map through gfx_target_from_gc_version — the comment there even says the intent is to "report the target as unknown" for exactly this case (a future/unrecognized chip).
gfx_is_apu_family("") returns false (see the existing test assert!(!gfx_is_apu_family(""))), so this line turns that "unknown" signal into is_apu: Some(false), i.e. a confident discrete verdict. Before this PR, this same kernel-only branch always set is_apu: None, which summarise_gpu_categories correctly treats as "don't count it either way."
Concretely: a future AMD APU whose gfx_target_version isn't yet in gfx_target_from_gc_version, on a host with no lspci match and no rocminfo (the exact "ROCm not installed yet" scenario rocm examine exists for), now reports has_discrete_amd: true / has_apu: false for an actual APU — the very symptom class this PR fixes for the PCI-name path, reintroduced one layer down for the KFD-target-decode path.
Suggest guarding on node.gfx_target.is_empty() the same way the matched branch guards on a resolved name, e.g. is_apu: (!node.gfx_target.is_empty()).then(|| gfx_is_apu_family(&node.gfx_target)).
There was a problem hiding this comment.
Fixed in f5f435e. gfx_target empty now stays None in both membership branches -- the kernel-only one through (!node.gfx_target.is_empty()).then(...), and the matched one by only reclassifying when the node actually named a target. Added an_unparseable_kernel_target_leaves_the_family_unknown, which asserts is_apu: None and that summarise_gpu_categories leaves has_discrete_amd false.
|
Finding (could not anchor inline — on an unchanged line outside this diff's hunks): The sysfs-fallback path has the identical bug this PR fixes, and is left unfixed.
That directly contradicts this PR's own stated principle a few hundred lines away ("the target is enough to answer the family question... Since this PR is already establishing " |
|
🤖 Automated review (Claude Code) · 0b542d5 Reviewed by reading the PR diff and the full contents of Findings (posted individually as inline/PR comments above):
No other blocking issues found beyond what's noted above; reuse/simplification/efficiency angles and cross-file caller checks did not surface anything that survived verification. 🤖 Generated with Claude Code |
…known Review follow-up on ROCm#726. The examine-29 When step was "inspects the system", which runs the CLI against the runner itself: `world.command_env` (the stub `lspci`/`rocminfo` and `ROCM_CLI_TEST_HOST_ROOT`) is applied only by the planted-machine step. Every lane therefore inspected the host instead of the fixture -- green on a real Strix Halo whether or not the fix is present, and `gpus: []` with a failed assertion on a lane without a GPU. Switch it to the planted-machine step, which is also the one that skips framework probing. Also: * an empty `gfx_target` is unknown, not discrete. KFD leaves it empty when its `gfx_target_version` does not decode and `gfx_is_apu_family("")` answers false, so both membership branches now keep `None` instead of stamping a "discrete" verdict from a failed decode -- the same mistake this PR fixes for the PCI name, one layer down; * unit tests for what the existing ones never reached: the `is_apu != Some(true)` guard (a resolved APU verdict is never downgraded by a kernel target) and an undecoded target staying unknown; * examine-30 drives the kernel-only branch end to end (stub `lspci` reporting an empty bus), which examine-29 cannot reach because it always has a PCI match; * the 1586 comments no longer claim `pci.ids` has no name for the id -- upstream carries it, older packaged copies do not -- and the row joins `pnp_device_id_table_agrees_about_apus`. Refs ROCm#449, ROCm#507 Signed-off-by: Hu Di <812791840@qq.com>
|
Pushed f5f435e for the review. What changed, item by item: Blocking 1 -- examine-29 never used the host it plants. Fixed by switching the When to "the user inspects that machine in machine-readable form". You were right about the mechanism: Blocking 2 -- nothing tested the Blocking 3 -- the kernel-only path had no scenario. Added examine-30 ( Non-blocking, taken:
Non-blocking, deferred: the sysfs fallback still leaves Decisions: keeping #449 and #507 in one PR as you allowed -- say the word if you would rather have the 1586 row split out, it is two files and one test row. On #521: it reworks the same classification and already carries a 1586 row, so whichever lands second should drop its duplicate rather than merge both. I have no preference on the order; happy to rebase on top of it, and I will drop both the row and the reclassification here if #521 lands first. Local verification: |
|
Note for whoever has write access: the workflows for f5f435e are sitting in |
nowycondro
left a comment
There was a problem hiding this comment.
🔴 Automated review · pr-review-watcher · f5f435e
Review — needs work
Full review of the whole change (examine.rs, host_gpu.rs, examine.feature, examine_steps.rs) between base efb9bc37 and head f5f435ed.
Implements the is_apu classification fix for the Strix Halo symptom in issue #449 (explicitly scoped to the classification question only — the issue's other two asks, resolving a target from the marketing name and reporting UMA/VRAM-carveout, are stated out of scope), and adds the host_gpu.rs 1586 → gfx1151 PCI-id table row requested in #507 (the description itself notes this only exercises the Windows/PNP path for now; the Linux lspci device-id reader #507 also asks for is still unbuilt). Neither issue is claimed closed.
Blocking
- The PR description is stale relative to the current head
The live description (and its "Verification on hardware" / checklist sections) documents only the first two commits (72e4848a,0b542d58) and scenarioexamine-29. It says nothing about the third commit (f5f435ed), which: rewiresexamine-29'sWhenstep to actually drive the planted host (the scenario previously ran against the real test runner and passed regardless of the fix), adds a new scenarioexamine-30for the kernel-only-node branch, changes an undecoded/empty kernel target from "discrete" to "unknown" (None), and corrects thepci.idsclaim in the comments. A reader relying on the description to decide what's covered would not know any of this happened.
Confidence 85 · architectural · Fix: update the PR description to cover the latest commit (new scenario, theWhen-step correction, the unknown-vs-discrete semantics, the comment correction), or at minimum link to the commit's own message, which already explains it well.
Non-blocking
-
A sibling function's rationale now contradicts this change's own reasoning —
crates/rocm-core/src/examine.rs:1493-1508(probe_gpus_sysfs_fallback) vs.crates/rocm-core/src/examine.rs:1671-1737(apply_kernel_gpu_membership)
probe_gpus_sysfs_fallbackstill leavesis_apu: Nonewith the comment "is_apuis left unset rather than guessed... Claiming either would be inventing a fact," even when it has a knowngfx_target. This change's new code, given the exact same shape of evidence (a baregfx_target, no marketing name), now argues the opposite and classifies family from it viagfx_is_apu_family. A gfx1151 part found only through DRM ip-discovery (sysfs fallback's documented use case) still reportshas_apu: falseafter this PR.
Confidence 85 · architectural · Fix: apply the same target-derived classification inprobe_gpus_sysfs_fallback, or add a comment there explaining why it is deliberately excluded. -
One new test only discriminates a guard mutation, not a full revert —
crates/rocm-core/src/examine.rs:5203(a_resolved_apu_verdict_is_not_downgraded_by_a_kernel_target)
If the whole diff were reverted (theif gpu.is_apu != Some(true) && ...block removed outright, not just weakened),is_apuwould also trivially staySome(true)here, since pre-PR code never touchedis_apuin this branch at all — this test only fails if the guard condition itself is mutated (e.g. toif true), which it does correctly catch. Full-revert coverage for the fix is actually carried by the sibling test atexamine.rs:5110(a_kernel_target_classifies_an_unnamed_apu).
Confidence 75 · logic · Fix: none required; optionally note in the test's comment that it is a guard-regression test rather than a feature-presence test. -
No cross-reference between the two unrelated "1586" fixes —
crates/rocm-core/src/host_gpu.rs:722,tests/e2e-cucumber/tests/e2e/examine_steps.rs:1541,1591,tests/e2e-cucumber/features/examine.feature:450,462
The new"1586" => Some("gfx1151")row inhost_gpu.rsis reached only through the Windows/PNP path (gfx_target_from_pnp_device_idand its three call sites, all underWindowsDisplayAdapter/parse_windows_display_gfx_target) — the Linuxlspci-name path (probe_gpus_lspci→classify_amd_marketing_name) never consults it, and the device-id reader #507 asks for to make that possible (extract_lspci_device_idor similar) does not exist in this codebase yet. The two new Linux e2e scenarios correctly exercise the real Linux fix (apply_kernel_gpu_membership's target-based reclassification), not this table row, but neither the feature file's scenario comments nor the fixture doc comments say so — a reader skimming both diffs together could assume the e2e scenarios validate the new table row.
Confidence 70 · architectural · Fix: a one-line note in either file disambiguating the two "1586" fixes (Windows PNP table vs. Linux kernel-target reclassification).
Decisions for the author
None
Positive signals
- The non-downgrade guard (
gpu.is_apu != Some(true)atexamine.rs:1735) is minimal and strictly additive — it only ever strengthens an unresolved or failed verdict, never overwrites one the PCI name already resolved. - The four new unit tests (
examine.rs:5110,5146,5171,5203) each isolate a different branch of the fix (unnamed-but-matched, kernel-only, undecoded target, already-resolved) — together they close exactly the mutation gaps an earlier review round identified as untested. - The two new e2e scenarios (
examine-29/examine-30) correctly use the scenario-environmentWhenstep and were verified end-to-end against the KFDlocation_id/gfx_target_versiondecode arithmetic (0xc500→0000:c5:00.0;110501→gfx1151). - Code comments throughout are unusually precise about why, and that reasoning is actually encoded in the guard logic rather than only asserted in prose (e.g., the
.then(...)guard genuinely is what keeps an empty target from becomingSome(false)). - Commit messages are thorough and well-structured: each of the three commits explains what changed and why, cites concrete before/after JSON, and is signed off.
Deployment notes
This is a cross-repository (fork) pull request, and the only status check that has run against the reviewed commit is a docs build (docs/readthedocs.com) — no Rust test, clippy, formatting, or commit-signature check has executed yet, likely pending workflow approval for a fork contribution. The author reports (unverified here) cargo test -p rocm-core --lib: 756 passed, clean clippy/fmt. This repo's sandbox had no cargo toolchain, so these claims were not independently re-run.
What this covered
All four changed files in full (crates/rocm-core/src/examine.rs, crates/rocm-core/src/host_gpu.rs, tests/e2e-cucumber/features/examine.feature, tests/e2e-cucumber/tests/e2e/examine_steps.rs) between efb9bc37672e9ca57966be7e30cd064061909348 and f5f435ed80128d4b707f8bb5527267e2ad5e5d07, plus the full surrounding context: gfx_is_apu_family, classify_amd_marketing_name, probe_gpus_sysfs_fallback, summarise_gpu_categories, apply_rocminfo_gpu_agents, the Windows PNP-id path, and diagnose.rs's consumers of is_apu. Reviewed via two independent fan-out passes (production code; e2e tests) plus driver-level verification and cross-checks. History pass covered all three commit messages. Agent-instruction pass checked against this repo's AGENTS.md.
Did not run: cargo test / cargo clippy (no Rust toolchain available in this review sandbox) — verification was by static tracing instead. No CI build/test/lint check has executed against this commit (only a docs build), so that class of verification is not handled by anything external either.
This PR's own review/discussion state was visible during the mandatory live-state check that precedes this review (to decide whether a re-review was warranted); none of that prior discussion's wording or conclusions were used to produce the findings above — each was independently re-derived and verified directly against the code, and several (the e2e wiring fix, the four new unit tests, the pci.ids comment correction) were confirmed to already be resolved on the current head. Not otherwise reconciled against any discussion on this PR.
f5f435e to
2a21f7c
Compare
…known Review follow-up on ROCm#726. The examine-29 When step was "inspects the system", which runs the CLI against the runner itself: `world.command_env` (the stub `lspci`/`rocminfo` and `ROCM_CLI_TEST_HOST_ROOT`) is applied only by the planted-machine step. Every lane therefore inspected the host instead of the fixture -- green on a real Strix Halo whether or not the fix is present, and `gpus: []` with a failed assertion on a lane without a GPU. Switch it to the planted-machine step, which is also the one that skips framework probing. Also: * an empty `gfx_target` is unknown, not discrete. KFD leaves it empty when its `gfx_target_version` does not decode and `gfx_is_apu_family("")` answers false, so both membership branches now keep `None` instead of stamping a "discrete" verdict from a failed decode -- the same mistake this PR fixes for the PCI name, one layer down; * unit tests for what the existing ones never reached: the `is_apu != Some(true)` guard (a resolved APU verdict is never downgraded by a kernel target) and an undecoded target staying unknown; * examine-30 drives the kernel-only branch end to end (stub `lspci` reporting an empty bus), which examine-29 cannot reach because it always has a PCI match; * the 1586 comments no longer claim `pci.ids` has no name for the id -- upstream carries it, older packaged copies do not -- and the row joins `pnp_device_id_table_agrees_about_apus`. Refs ROCm#449, ROCm#507 Signed-off-by: Hu Di <812791840@qq.com>
…test pins Review follow-up on ROCm#726, comments only. The `1586 => gfx1151` row is reached only through the Windows/PNP path; the Linux `lspci` reader that would consume device ids is the other half of ROCm#507 and does not exist yet, so the Linux scenarios for ROCm#449 exercise the kernel-target reclassification instead. Saying that at the row stops the two "1586" fixes from reading as one covered by the e2e scenarios. The non-downgrade test fails only when the guard is weakened, not when the whole reclassification is reverted, because the pre-change code never touched `is_apu` in that branch. Naming it a guard-regression test, and pointing at the sibling that does carry revert coverage, keeps the next reader from reading more into a green run than it proves. Refs ROCm#449, ROCm#507 Signed-off-by: Hu Di <812791840@qq.com> Signed-off-by: trae-solo-agent <solo-agent@trae.ai>
…name it
On a Strix Halo host `pci.ids` has no entry for 1002:1586, so `lspci` prints the
bare word "Device". The PCI scan resolves no target from that name but still
records `is_apu: false` -- the failed lookup, not a verdict about the part. The
KFD topology then supplies `gfx_target: gfx1151` in `apply_kernel_gpu_membership`
without revisiting the flag, so `examine --json` reported
"gfx_target": "gfx1151", "is_apu": false, "has_apu": false,
"has_discrete_amd": true
on a unified-memory APU. Consumers that branch on `has_apu` (APU diagnostics,
GTT tuning) therefore skipped exactly the machine they exist for.
The node's target is the first real evidence about the device, and
`gfx_is_apu_family` answers the family question from it -- the same answer the
`rocminfo` path already derives from its agent name. Use it to reclassify when
the PCI scan could not resolve a target, and to classify a kernel-only node
instead of leaving it `None`. A discrete target still classifies as discrete.
Refs ROCm#449
Signed-off-by: Hu Di <812791840@qq.com>
`pci.ids` does not name 1002:1586, so any probe that resolves a target from the device id instead of the marketing name has nothing to match. On the Strix Halo machine this was verified on, `lspci -nn` reports the id and the KFD node reports `gfx_target_version 110501` (gfx1151) for the same address, which is the confirmation ROCm#507 asked for before adding the row. Refs ROCm#507 Signed-off-by: Hu Di <812791840@qq.com>
…known Review follow-up on ROCm#726. The examine-29 When step was "inspects the system", which runs the CLI against the runner itself: `world.command_env` (the stub `lspci`/`rocminfo` and `ROCM_CLI_TEST_HOST_ROOT`) is applied only by the planted-machine step. Every lane therefore inspected the host instead of the fixture -- green on a real Strix Halo whether or not the fix is present, and `gpus: []` with a failed assertion on a lane without a GPU. Switch it to the planted-machine step, which is also the one that skips framework probing. Also: * an empty `gfx_target` is unknown, not discrete. KFD leaves it empty when its `gfx_target_version` does not decode and `gfx_is_apu_family("")` answers false, so both membership branches now keep `None` instead of stamping a "discrete" verdict from a failed decode -- the same mistake this PR fixes for the PCI name, one layer down; * unit tests for what the existing ones never reached: the `is_apu != Some(true)` guard (a resolved APU verdict is never downgraded by a kernel target) and an undecoded target staying unknown; * examine-30 drives the kernel-only branch end to end (stub `lspci` reporting an empty bus), which examine-29 cannot reach because it always has a PCI match; * the 1586 comments no longer claim `pci.ids` has no name for the id -- upstream carries it, older packaged copies do not -- and the row joins `pnp_device_id_table_agrees_about_apus`. Refs ROCm#449, ROCm#507 Signed-off-by: Hu Di <812791840@qq.com>
…test pins Review follow-up on ROCm#726, comments only. The `1586 => gfx1151` row is reached only through the Windows/PNP path; the Linux `lspci` reader that would consume device ids is the other half of ROCm#507 and does not exist yet, so the Linux scenarios for ROCm#449 exercise the kernel-target reclassification instead. Saying that at the row stops the two "1586" fixes from reading as one covered by the e2e scenarios. The non-downgrade test fails only when the guard is weakened, not when the whole reclassification is reverted, because the pre-change code never touched `is_apu` in that branch. Naming it a guard-regression test, and pointing at the sibling that does carry revert coverage, keeps the next reader from reading more into a green run than it proves. Refs ROCm#449, ROCm#507 Signed-off-by: Hu Di <812791840@qq.com> Signed-off-by: trae-solo-agent <solo-agent@trae.ai>
2a21f7c to
6e982fc
Compare
|
Rebased onto
Local gates on the rebased tree: Not run: the cucumber scenarios. They are @tomastola the three blocking items from your review are addressed in the third commit; could you take another look when you have a moment? |
nowycondro
left a comment
There was a problem hiding this comment.
🔴 Automated review · pr-review-watcher · 6e982fc
Review — needs work
Full review of the whole change (4 files, merge-base 79f6e08c42b9…head 6e982fcd8b72).
Fixes the classification symptom reported in #449 (not the Linux-lspci-device-id half of
#507, which the description says is deliberately out of scope and is instead addressed by
the separate, still-open PR #521).
Blocking
- Branch is not mergeable against current
main— a real conflict, not a stale-UI
artifact —tests/e2e-cucumber/features/examine.feature:465(this PR's new
examine-30),tests/e2e-cucumber/features/examine.feature:464(main's existing,
collidingexamine-30)
gh pr view 726 --json mergeable,mergeStateStatusreports"mergeable":"CONFLICTING",
"mergeStateStatus":"DIRTY". Reproduced locally with
git merge-tree origin/main pr726head, which reports
CONFLICT (content): Merge conflict in tests/e2e-cucumber/features/examine.feature.
Root cause: this branch's merge-base (79f6e08c) predates amaincommit (ea86403c,
"Remove amdgpu-install as an install method") that appended its own new scenario —
also self-titledScenario: examine-30 - System inspection reports a current install-method name...— to the same feature file, at essentially the same anchor
point (right afterexamine-29) that this PR's two new scenarios
(examine-30/examine-31) are appended to. A naive "accept both sides" conflict
resolution leaves two different scenarios both namedexamine-30, which violates this
repo's own uniqueness/sequential-numbering invariants enforced by
tests/e2e-cucumber/tests/feature_naming.rs(scenario_indexes_are_unique_across_the_suite,
scenario_names_are_indexed_sequentially_per_feature) — a drift guard written for exactly
this class of mistake.
Confidence 100 · architectural · Fix: rebase onto currentmain, renumber this PR's two
new scenarios past whatever is now the lastexamine-NN, and update the stale
cross-reference in the next finding to match.
Non-blocking
- Stale scenario cross-reference in a doc comment —
tests/e2e-cucumber/tests/e2e/examine_steps.rs:1588
plant_kernel_only_apu_fixtures's doc comment says "Therocminfostub is load-bearing
for the same reason as in examine-29" — butexamine-29is the unrelated Windows
driver-version/age scenario, which has norocminfostub at all. The matching reasoning
actually lives in the scenario immediately above it,examine-30("A GPU whose PCI name
is unrecognised..."). Almost certainly a leftover from the renumbering this PR's third
commit performed (29/30 → 30/31 per its own commit message), where this one
cross-reference was missed.
Confidence 100 · mechanical · Fix: change "examine-29" to "examine-30" (and again to
whatever it becomes after the rebase above).
Decisions for the author
probe_gpus_sysfs_fallbackstill returnsis_apu: Nonefor the same
target-only-evidence situation this PR just resolved for the kernel-membership and
PCI-name-lookup paths — answered-by-intent
PR description: "Follow-up, not fixed here:probe_gpus_sysfs_fallbackstill leaves
is_apu: Noneand its comment still argues that claiming either verdict would invent a
fact. It is the last pass in the sequence (KFD → rocminfo → sysfs), so it only runs when
neither KFD norlspciis available... Changing it belongs with the classification rework
rather than this fix." Would otherwise read as an inconsistency this PR introduces (two
code paths reasoning about the same "target is the only evidence" situation now disagree
on what to do with it). The description owns this as a deliberate, scoped-out follow-up —
confirm that's still the intended boundary before merging.
Positive signals
- The new
host_gpu.rs"1586" table-row comment precisely scopes which platform path reads
it today (Windows/PNP) versus the still-open Linux half of #507, so a reader can't mistake
this row alone for closing the Linux case. a_resolved_apu_verdict_is_not_downgraded_by_a_kernel_target's comment explicitly flags
itself as a guard-regression test rather than revert coverage, and names the sibling test
that actually carries the revert coverage — more precise test-intent documentation than
this kind of change usually gets.- The two new e2e fixtures' planted KFD
location_id/gfx_target_versionvalues are
arithmetically correct for the PCI address and gfx target they claim to encode
(50432 == 0xc500, matchingpci_id "0000:c5:00.0";110501decodes via this repo's own
major/minor/revision packing togfx1151) — verified by hand, not just plausible-looking
magic numbers.
Deployment notes
No Rust/clippy/e2e CI has executed against this head commit — the only check that has run
is the docs build (pass). The description attributes this to the fork's workflow run
awaiting maintainer approval. Combined with the confirmed merge conflict above, this PR is
not yet in a CI-verified, mergeable state; approve the workflow run and get a green
Rust/clippy/e2e lane — which, post-rebase, will also need to pass
tests/e2e-cucumber/tests/feature_naming.rs — before merging.
What this covered
DEGRADED REVIEW. Fan-out was attempted (two parallel code-review workers, one for
examine.rs/host_gpu.rs, one for the .feature/step-definition pair) but every spawn
failed on a concurrency limit shared across this host (20 subagents already running,
none of them mine) and the harness directed not to retry; the review proceeded
single-context instead. Recommend re-running with fan-out available, per this skill's own
guidance that a single-context pass catches a minority of what an independent-worker pass
finds.
What was actually read: all 4 changed files in full
(crates/rocm-core/src/examine.rs, crates/rocm-core/src/host_gpu.rs,
tests/e2e-cucumber/features/examine.feature,
tests/e2e-cucumber/tests/e2e/examine_steps.rs) between merge-base 79f6e08c42b9 and head
6e982fcd8b72, plus surrounding call paths: classify_amd_marketing_name,
probe_gpus_lspci, gfx_target_from_pnp_device_id/amd_pci_device_id_from_pnp_id, the KFD
gfx_target_version decode chain (parse_linux_kfd_gfx_target,
gfx_target_from_gc_version), gfx_target_has_no_rocm_build, and
tests/e2e-cucumber/tests/feature_naming.rs's scenario-numbering guard. Also read, at
Step 9: this PR's own description, and issues #449, #507, and PR #521 by identifier via
gh issue view/gh pr view.
Did not run: cargo test/cargo check/cargo clippy — no Rust toolchain is available in
this review environment, so the code-logic reasoning above is argued from tracing the
source, not from execution, and is scored accordingly. The merge-conflict finding above
was verified by actually running git merge-tree and querying GitHub's own mergeable
field. History and prior-changes passes: no prior review of this PR was consulted (by
design); git log over the touched files shows no relevant history beyond the linked
issues. Not reconciled against any discussion thread on this PR.
What this changes
rocm examineon a Strix Halo APU (gfx1151) reports the machine as a discrete AMD GPU:Older packaged copies of
pci.idspredate1002:1586, solspciprints the bare word "Device".classify_amd_marketing_namecannot resolve a target from that name and stampsis_apu: false— the failed lookup, not a verdict about the part.apply_kernel_gpu_membershiplater fillsgfx_targetfrom KFD (only when the field is empty) but never revisitsis_apu.The fix
Four commits, in order:
fix(examine): classify from the kernel target. When KFD supplies the target, reclassify withgfx_is_apu_family— the same function therocminfopath already uses to answer the family question. Kernel-only nodes (nolspcimatch) are classified from their target instead of being leftNone. A discrete target (gfx1100,gfx942, …) still classifies as discrete.fix(host_gpu): the1586 => gfx1151row requested in examine: lspci cannot name a GPU that pci.ids does not know, though the device id is on the line #507, for hosts that have neither KFD norrocminfo.fix(examine): review follow-up. Theexamine-29Whenstep was "inspects the system", which runs the CLI against the runner itself —world.command_env(the stublspci/rocminfoandROCM_CLI_TEST_HOST_ROOT) is applied only by the planted-machine step. Every lane therefore inspected the host instead of the fixture: green on a real Strix Halo whether or not the fix is present, andgpus: []on a lane without a GPU. It now uses the planted-machine step, which also skips framework probing. The same commit adds:gfx_targetis unknown, not discrete. KFD leaves it empty whengfx_target_versiondoes not decode andgfx_is_apu_family("")answersfalse, so both membership branches now keepNoneinstead of stamping "discrete" from a failed decode — the same mistake this PR fixes for the PCI name, one layer down;is_apu != Some(true)guard, and an undecoded target staying unknown;1586comments no longer claimpci.idshas no name for the id (upstream carries it; older copies do not), and the row joinspnp_device_id_table_agrees_about_apus.docs(examine): comments only. Which path reads the1586row today (Windows/PNP), and that the non-downgrade test pins the guard rather than the fix.Scenarios
Two new Linux scenarios, both simulated hosts so every Linux lane can drive them:
@id:examine-classifies-an-apu-the-pci-name-cannot(examine-30): unrecognisedlspciname, a KFD gfx1151 node, emptyrocminfo.@id:examine-classifies-a-kernel-only-apu(examine-31): stublspcireports an empty bus, so only the kernel topology sees the GPU.The empty
rocminfostub is deliberate in both: on a runner with ROCm installed the real probe resolves the APU on its own (it already classifies by target) and would mask the defect.They were
examine-29/examine-30before this branch was rebased onto79f6e08c;maintookexamine-29for the Windows driver-version scenario in the meantime, so both were renumbered.Verification
Ryzen AI MAX 395 (gfx1151,
1002:1586), same machine, same probe inputs, nightly1c33248cvs the patched binary:gpus[0].gfx_targetgfx1151gfx1151gpus[0].is_apufalsetruehas_apufalsetruehas_discrete_amdtruefalseRebased tree (head
6e982fcd, on79f6e08c), macOS dev machine:cargo test -p rocm-core --lib: 794 passed, 3 failed, 3 ignored. The three failures are pre-existing and macOS-only (proc_lifecycle's two signal tests andfix::tests::print_only_fix_returns_zero); they fail identically at the base commit.a_kernel_target_classifies_an_unnamed_apu,a_kernel_only_apu_node_is_classified_from_its_target,a_resolved_apu_verdict_is_not_downgraded_by_a_kernel_target,an_unparseable_kernel_target_leaves_the_family_unknown, plusa_kernel_visible_gpu_the_pci_scan_missed_is_still_listed.cargo fmt --all -- --checkclean;cargo clippy -p rocm-core --all-targets -- -D warningsclean on 1.96.Not run here: the cucumber e2e scenarios. They are Linux-only and this machine is macOS, so
examine-30/examine-31need the CI Linux lane — which is still awaiting workflow approval on this fork PR, so no Rust, e2e or clippy check has executed against the head yet (only the docs build).Scope and follow-ups
is_apuclassification only.GfxPackagingis untouched.1586row only affects the Windows/PNP path for now; on Linux, reading device ids fromlspciis the other half of examine: lspci cannot name a GPU that pci.ids does not know, though the device id is on the line #507 and is not part of this PR.probe_gpus_sysfs_fallbackstill leavesis_apu: Noneand its comment still argues that claiming either verdict would invent a fact. It is the last pass in the sequence (KFD →rocminfo→ sysfs), so it only runs when neither KFD norlspciis available, and it faces the same target-only evidence as the kernel-only branch. Changing it belongs with the classification rework rather than this fix; the comment there is now the only place the old reasoning stands.gfx_apu_verdict. It does not touchapply_kernel_gpu_membershipand does not add a1586row, so on a host with norocminfoand an oldpci.idsit does not fix examine: Strix Halo APU (gfx1151, Ryzen AI Max+ 395) misclassified as discrete GPU (has_apu=false) #449 on its own. The two are complementary; whichever lands second needs the other's row or reclassification removed.Checklist
tests/e2e-cucumber/expectations.tomlfor examine: Strix Halo APU (gfx1151, Ryzen AI Max+ 395) misclassified as discrete GPU (has_apu=false) #449 and examine: lspci cannot name a GPU that pci.ids does not know, though the device id is on the line #507 — there are no rows to narrow.examine.rs/host_gpu.rsmodules.has_apu,is_apu,has_discrete_amd) is asserted as the resultingexamine --jsondocument inexamine-30andexamine-31, not as message wording.AI assistance
This change was developed with an AI coding agent; every measurement, unit test and e2e run quoted above was executed on the hardware/environment described.