Skip to content

feat(bar): serve donor register BAR at its real PCI index (#613)#630

Merged
ramseymcgrath merged 3 commits into
mainfrom
feat/bar-aperture-donor-override
Jun 2, 2026
Merged

feat(bar): serve donor register BAR at its real PCI index (#613)#630
ramseymcgrath merged 3 commits into
mainfrom
feat/bar-aperture-donor-override

Conversation

@ramseymcgrath
Copy link
Copy Markdown
Collaborator

Summary

Improves device-clone fidelity for issue #613 by serving the donor's primary
register BAR at its real PCI BAR index, instead of always assuming BAR0.

Donors whose register window isn't BAR0 (common for NICs — e.g. Realtek
RTL8168 with BAR0=IO, BAR2=MMIO) were previously served on the wrong BAR index,
so the host enumerated a Xilinx-default BAR rather than the donor's. Per PG054
the 7-series hard IP routes BAR hits by physical PCI index, so the host sees what
the IP Bar{N} config advertises — this PR makes that index match the donor.

Commits

  1. fix(bar): describe the served BAR in bar_config — replaces the overloaded,
    never-set primary_bar key (which silently defaulted to 0) with explicit
    served_bar_index (donor index), primary_bar (list position),
    served_is_64bit, and a served-BAR aperture_size. This makes the IP
    aperture, cfgspace shadow, and controller all agree on one served BAR.
  2. feat(bar): serve donor register BAR at its real PCI index ([FEATURE] Improve Device Fidelity Beyond Current Xilinx PCIe Core Limitations #613)
    • IP override emits CONFIG.Bar{N}_* (size via Scale/Size, type/64-bit/
      prefetch) and disables every other BAR so exactly one window enumerates
      (no phantom/hanging BARs).
    • BAR controller wires the device impl to wr_bar[N]/rd_req_bar[N] via an
      index-aware loop; the 64-bit partner slot N+1 is forced to none
      (fixes a latent double-drive for a 64-bit BAR0); loopaddr kept at slot 1
      when free; byte-equivalent wiring when N=0.
    • cfgspace COE renders the served BAR at slot N with the 64-bit upper dword at
      N+1; also fixes the pre-existing hardcoded slot 2 = IO bug.
    • Overlay keys the learned-model lookup by served_bar_index.

Scope / limits

  • 7-series only (matches the existing donor-IP override).
  • Single served register BAR (the primary MMIO). Full multi-BAR reproduction
    and IO-primary handling are deferred follow-ups.
  • 64-bit BAR at index 5 is rejected (its upper half would be the Expansion ROM).

Testing

  • TDD throughout; 3 new test files (aperture encode/emit, controller index
    serving, cfgspace index rendering) plus updated context/impl tests.
  • Full affected suites green (~990 tests); the only failures in the tree are the
    pre-existing, unrelated donor-template / CLI-help e2e tests.
  • ⚠️ Hardware validation pending: a real Vivado build + lspci -vv on a
    non-BAR0 donor (e.g. RTL8168) should confirm the donor BAR geometry enumerates
    and BAR reads are serviced before merge — this can't be verified in CI.

Closes #613 (pending hardware validation).

The controller serves config-space BAR0 == the donor's primary register BAR,
but bar_config exposed only the largest-MMIO metadata and templates read a
never-set 'primary_bar' key (silently defaulting to 0). Emit served_bar_index
(donor PCI index), primary_bar (list position), served_is_64bit and aperture
from the served BAR so the IP aperture, cfgspace and controller agree.
Donor devices whose primary register BAR is not index 0 (e.g. NICs with
BAR0=IO, BAR2=MMIO) were served on the wrong BAR index, lowering fidelity.
Now the donor's primary MMIO BAR is served at its real PCI index N:

- IP override emits CONFIG.Bar{N}_* (size via Scale/Size, type/64-bit/prefetch)
  and disables every other BAR so the host enumerates exactly one window.
- BAR controller wires the device impl to wr_bar[N]/rd_req_bar[N] via an
  index-aware loop; the 64-bit partner slot N+1 is forced to 'none' (fixes a
  latent double-drive for a 64-bit BAR0); loopaddr kept at slot 1 when free.
- cfgspace COE renders the served BAR at slot N with the 64-bit upper dword at
  N+1; fixes the pre-existing hardcoded slot-2=IO bug.
- Overlay keys the learned-model lookup by served_bar_index.

7-series only; single served register BAR. 64-bit at BAR5 rejected (upper half
would be the Expansion ROM). Per PG054 the hard IP routes BAR hits by physical
index, so this matches what enumeration actually reads. Needs Vivado/lspci
hardware validation before merge.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Improves device-clone fidelity (issue #613) by serving the donor's primary register BAR at its real PCI index instead of hard-coding BAR0. The IP override, BAR controller template, cfgspace COE, and learned-model overlay are all updated to agree on a single served_bar_index (donor index N), disabling all other BAR slots so the host enumerates exactly one window matching the donor.

Changes:

  • Introduce served_bar_index / served_is_64bit / aperture_size in bar_config, replacing the overloaded primary_bar semantics, and extract them in the donor-IP override extractor.
  • Emit CONFIG.Bar{N}_* for the served BAR (with size via Scale/Size, 64-bit/prefetch flags) and disable the other 5 standard BARs; reject 64-bit at index 5.
  • Rewrite the BAR controller SV template and cfgspace COE to serve / render the device impl at the donor's real index N (with 64-bit partner forced to none, fixing the latent 64-bit BAR0 double-drive and the hardcoded slot-2-IO bug).

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/device_clone/pcileech_context.py Builds new served_bar_index / served_is_64bit / primary_bar (as list position) keys in bar_config.
src/vivado_handling/pcie_ip_donor_override.py Adds aperture fields to DonorPCIeIPConfig, emits CONFIG.Bar{N}_* and disables the other BARs, with validation.
src/templating/sv_overlay_generator.py Keys learned-model lookup by served_bar_index (fallback to legacy keys).
src/templates/sv/pcileech_tlps128_bar_controller.sv.j2 Index-aware loop wires the device impl to slot N; partner slot forced to none for 64-bit.
src/templates/sv/pcileech_cfgspace.coe.j2 Renders served BAR at donor slot N with 64-bit upper dword at N+1; removes hardcoded IO/positional layout.
tests/test_pcileech_context.py New test that served metadata uses donor index N with primary_bar as list position.
tests/test_pcie_ip_donor_override_bar.py New tests for Scale/Size encoding, index-N emit, 64-bit partner disable, rejections.
tests/test_cfgspace_bar_index.py New tests that COE places the BAR at slot N and 64-bit upper dword at slot N+1.
tests/test_bar_controller_index_serving.py New tests for index-N device gating, partner slot rules, single-driver invariants.
tests/test_bar_implementation_generation.py Updates assertions to match the new "served register window" template header.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +7 to +9
The served BAR is always presented as config-space BAR0 (the only window the
PCILeech BAR controller services via ``i_bar0``), so v1 mirrors a single BAR.
"""
Comment on lines +20 to +22
- A5 scope: only the single served BAR is mirrored, presented as config-space
BAR0 (the one window the PCILeech controller answers). Multi-BAR layout
fidelity and donors whose served window isn't BAR0 are out of scope.
@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 2, 2026

Codecov Report

❌ Patch coverage is 86.30137% with 10 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/vivado_handling/pcie_ip_donor_override.py 85.71% 5 Missing and 5 partials ⚠️

📢 Thoughts on this report? Let us know!

Addresses Copilot review on #630 — the A5 module scope note and the test
docstring still described the served BAR as config-space BAR0; gap C serves it
at the donor's real index N.
@ramseymcgrath ramseymcgrath merged commit 4e80815 into main Jun 2, 2026
30 checks passed
@ramseymcgrath ramseymcgrath deleted the feat/bar-aperture-donor-override branch June 2, 2026 06:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Improve Device Fidelity Beyond Current Xilinx PCIe Core Limitations

2 participants