<feed xmlns='http://www.w3.org/2005/Atom'>
<title>open-iov.git/kernel/main.c, branch archive/pre-squash</title>
<subtitle>Open-IOV vGPU-IO: host-side GSP emulation for unmodified NVIDIA guest drivers
</subtitle>
<id>https://git.vgpu.io/open-iov.git/atom?h=archive%2Fpre-squash</id>
<link rel='self' href='https://git.vgpu.io/open-iov.git/atom?h=archive%2Fpre-squash'/>
<link rel='alternate' type='text/html' href='https://git.vgpu.io/open-iov.git/'/>
<updated>2026-09-23T04:09:13+00:00</updated>
<entry>
<title>kernel: drop PCFG poison experiment and config-write spam, keep bus-info detail log</title>
<updated>2026-09-23T04:09:13+00:00</updated>
<author>
<name>Arthur Hanson Rasmusson</name>
<email>arthur@vgpu.io</email>
</author>
<published>2026-09-23T04:09:13+00:00</published>
<link rel='alternate' type='text/html' href='https://git.vgpu.io/open-iov.git/commit/?id=d28e5bb94752ba523b826945409e5ad3206dad5a'/>
<id>urn:sha1:d28e5bb94752ba523b826945409e5ad3206dad5a</id>
<content type='text'>
The poison test (fill every dword of BAR0 0x88000-0x88FFF, 0xB80000-
0xB80EFF, 0xC08000-0xC08EFF with 0x103) did not change the CUDA "Unknown
PCIe speed" failure, proving the failing BUS_GET_INFO_V2 index-3 data does
not come from any BAR0 mirror read. Combined with the QEMU config-space
behavior (link registers zeroed, type=0x92, 0x84 never read from us) the
value must come from the VGPU_STATIC_INFO branch in getBusInfos (pVSI-&gt;
pcieGpuLinkCaps), i.e. the guest needs the host vGPU static-info payload.

Cleanup: remove the poison loops and the per-write CFGWR log; keep the
once-per-init PCIe cap print and add per-entry BUS_GET_INFO_V2 logging
(index+data) for the ongoing CUDA/UVM work.
</content>
</entry>
<entry>
<title>kernel: real TU104 config-space layout (PCIe cap at 0x78) + CUDA/UVM tracing</title>
<updated>2026-09-23T04:04:14+00:00</updated>
<author>
<name>Arthur Hanson Rasmusson</name>
<email>arthur@vgpu.io</email>
</author>
<published>2026-09-23T04:04:14+00:00</published>
<link rel='alternate' type='text/html' href='https://git.vgpu.io/open-iov.git/commit/?id=7d6c789a469de154ee6d26a7fb9161ef7279a34a'/>
<id>urn:sha1:7d6c789a469de154ee6d26a7fb9161ef7279a34a</id>
<content type='text'>
Move the emulated PCIe capability to config offset 0x78 and shift MSI to
0x48 / MSI-X to 0x68, matching the real TU104 (host lspci: PM 0x60, MSI
0x68, Express 0x78). This matters because the driver's NV_PCFG mirror
(BAR0+0x88000, size 0x1000) is read as PCI config space:
osDevReadReg032 -&gt; vgpuDevReadReg032 intercepts [NV_PCFG, +0x30) (or the
full 0x1000 for SRIOV) and forwards to osPciReadDword, so
NV_XVE_LINK_CAPABILITIES (0x84) must be the PCIe Link Capabilities
register, i.e. cap+0x0C with the cap at 0x78. Link Caps = Gen3 x16
(0x103), Link Status = 0x0103.

Also set MCFG-visible caps: the guest now reports MSI [48], MSI-X [68],
Express [78] exactly like the host GPU. Fixing the capability chain: the
first attempt set the PCIe cap's NEXT to 0x0C, which broke enumeration
(device 00:06.0 disappeared from the guest) - NEXT must terminate at 0.

Unknown still open: QEMU presents type=0x92 (Root Complex Integrated
Endpoint) and zeroes 0x84-0x8B in its config cache (never read from us,
not refreshed by writes), and poisoning all BAR0 mirror windows with
0x103 does not change the driver's "Unknown PCIe speed" - so the value
comes from the VGPU_STATIC_INFO branch (pVSI-&gt;pcieGpuLinkCaps, IS_VIRTUAL
true via hypervisor detection) rather than any register read.

Debug helpers added (temporary): CFGWR config-write log, PCFG change
watch, PCIe-cap print at init.
</content>
</entry>
<entry>
<title>kernel: FB/BUS info-list controls + PCIe link caps for the UVM path</title>
<updated>2026-09-23T03:32:44+00:00</updated>
<author>
<name>Arthur Hanson Rasmusson</name>
<email>arthur@vgpu.io</email>
</author>
<published>2026-09-23T03:32:44+00:00</published>
<link rel='alternate' type='text/html' href='https://git.vgpu.io/open-iov.git/commit/?id=14283fe73fb5e432a7af45de94961655714910f6'/>
<id>urn:sha1:14283fe73fb5e432a7af45de94961655714910f6</id>
<content type='text'>
CUDA (cuInit) now reaches UVM's device create: libcuda opens nvidia-uvm,
UVM calls nvGpuOpsDeviceCreate/gpuGetGpuInfo, and the driver fails at
getPCIELinkRateMBps -&gt; calculatePCIELinkRateMBps ("Unknown PCIe speed",
NV_ERR_INVALID_STATE) -&gt; nv_open_device aborts -&gt; cuInit returns
CUDA_ERROR_NOT_INITIALIZED (3).

Implemented along the way:
- FB_GET_INFO_V2 (0x20801303): echo the requested FB info indices and
  answer TU104 values (256MB RAM/heap/BAR1, GDDR6, 8 LTCs, 4MB L2, ...).
  Fixes the kern_mem_sys_ctrl.c:911 asserts and gives CUDA/UVM real
  memory sizes.
- BUS_GET_INFO_V2 (0x20801823): echo indices; PCIe Gen3 x16 link caps /
  GEN info / link status, SYSMEM_CONNECTION_TYPE=PCIE. UVM's
  gpuGetSysmemLinkInfo reads SYSMEM_CONNECTION_TYPE and the nominal link
  bandwidth from here.
- PCIe Link Capabilities in the emulated config space (0x8C/0x92) and in
  the BAR0 PCFG mirror (gpuReadBusConfigReg -&gt; NV_PCFG+0x84 = BAR0+
  0x88084): MAX_SPEED=3 (8GT/s Gen3), MAX_WIDTH=0x10 (x16); link status
  mirror at 0x88088. Also mirrored under the VF-window/low aliases.
- Temporary change-watch on PCFG[0x88084] to see if the guest overwrites
  it (it does not - stays 0x103).

Verified: guest nvidia-smi -L still works and reports PCIe Generation
Max/Current = 3. cuInit still fails; the remaining question is which
address the driver's kbifGetGpuLinkCapabilities read sees as zero (the
PCFG shadow holds 0x103). Guest-side kprobe tracing of that function
panicked the VM (free_swap_cache page fault on a corrupted pointer) -
possible guest memory corruption to investigate separately.
</content>
</entry>
<entry>
<title>BAR2 verify test fix: remove PRAMIN sync + contiguous ALLOC + vidmem VA allocator</title>
<updated>2026-09-23T01:55:54+00:00</updated>
<author>
<name>Arthur Hanson Rasmusson</name>
<email>arthur@vgpu.io</email>
</author>
<published>2026-09-23T01:55:54+00:00</published>
<link rel='alternate' type='text/html' href='https://git.vgpu.io/open-iov.git/commit/?id=fcd603db457c0fb035df882abc55397bc854a1cd'/>
<id>urn:sha1:fcd603db457c0fb035df882abc55397bc854a1cd</id>
<content type='text'>
Fixes the BAR2 verify test (kbusVerifyBar2_GM107):
1. Removed PRAMIN window sync from emulated BAR1 - the sync was overwriting
   test data written by the driver through the vBar2 aperture. The shadow
   BAR0 is already consistent (guest writes/reads hit the same shadow location).
2. Added contiguous page allocation for golden image (alloc_pages with order
   for large allocations, falling back to individual pages).
3. Added vidmem VA allocator - ALLOC now returns GPU VAs within the emulated
   GPU's vidmem range (0x100000 - fb_size) instead of default 4GB, so the
   memmgr accepts them.

Verified: driver probes past RmInitNvDevice bus init, reaches golden image
channel allocation (progress from fn-10 FREE timeout).
</content>
</entry>
<entry>
<title>host stability: BAR3 shadow + skip submodule nvidia + teardown-safe garbage handler</title>
<updated>2026-09-22T13:43:22+00:00</updated>
<author>
<name>Arthur Hanson Rasmusson</name>
<email>arthur@vgpu.io</email>
</author>
<published>2026-09-22T13:43:22+00:00</published>
<link rel='alternate' type='text/html' href='https://git.vgpu.io/open-iov.git/commit/?id=60da11fe771968bbc0cc65b8f629cc5e6b3f44a1'/>
<id>urn:sha1:60da11fe771968bbc0cc65b8f629cc5e6b3f44a1</id>
<content type='text'>
Root causes of host GSP crash (WPR2 stuck, 'unexpected WPR2 already up'):
1. stack_manager load-nvidia tried to load our submodule nvidia.ko (610.57.04-base)
   alongside/over apt nvidia 570.211.01 -&gt; GSP crash during driver conflict.
   Fix: skip submodule when apt nvidia is already loaded (not needed for QEMU).
2. BAR3 (32MB instance memory window) was mapped to the physical GPU's real BAR3,
   so guest BAR3 writes could corrupt the host GPU's instance memory.
   Fix: vzalloc'd shadow buffer (like BAR1 emulated vidmem), per-page mmap.
3. GSP-RM garbage element handler declared GSP death on teardown queue garbage,
   preventing driver cleanup frees from completing.
   Fix: stop polling quietly, let Booter-unload kick handle reset.

Verified: full lifecycle (load, mdev create, QEMU guest boot, guest probe,
mdev remove, unload, reload) with host nvidia-smi (apt 570.211.01) stable
throughout. No GSP crash, no WPR2 stuck, no module unload hang.
</content>
</entry>
<entry>
<title>kernel: dedicated host-RAM vidmem buffer for BAR1 (not host GPU's real VRAM)</title>
<updated>2026-09-22T09:16:37+00:00</updated>
<author>
<name>Arthur Hanson Rasmusson</name>
<email>arthur@vgpu.io</email>
</author>
<published>2026-09-22T09:16:37+00:00</published>
<link rel='alternate' type='text/html' href='https://git.vgpu.io/open-iov.git/commit/?id=9b891254b05e9e46f27b8ff53decfbbb429d1cc4'/>
<id>urn:sha1:9b891254b05e9e46f27b8ff53decfbbb429d1cc4</id>
<content type='text'>
Guest VRAM (BAR1) was mapped to the host GPU's real BAR1 (managed by
nvidia.ko) - guest VRAM accesses hit the broken host GPU. Now a
dedicated 256MB vzalloc buffer backs guest VRAM; BAR1 mmap uses
per-page vmalloc_to_pfn (like BAR0 shadow). vfree on cleanup.
</content>
</entry>
<entry>
<title>kernel: Present physical TU104 to guest + emulate GSP boot (FWSEC/Booter) + VBIOS serving</title>
<updated>2026-09-21T18:11:45+00:00</updated>
<author>
<name>Arthur Hanson Rasmusson</name>
<email>arthur@vgpu.io</email>
</author>
<published>2026-09-21T18:10:43+00:00</published>
<link rel='alternate' type='text/html' href='https://git.vgpu.io/open-iov.git/commit/?id=c8249854284c3e8181587b96e3c5b4177d705e0c'/>
<id>urn:sha1:c8249854284c3e8181587b96e3c5b4177d705e0c</id>
<content type='text'>
Guest driver probe fixes (unmodified 570.144 open driver on physical path):

- kernel/main.c: add show_description to the mdev driver. Userspace mdev
  management tools parse 'framebuffer=&lt;n&gt;M' from every mdev type's
  description sysfs file before creating an mdev; the missing file made
  such tools fail to create the vGPU. Also fix create_mdev.sh for the real
  type dir name pci-nvidia-vgpu-* (mdev core names dirs
  dev_driver_string(parent)-&lt;sysfs_name&gt;; the parent registers before
  nvidia.ko binds so dev_driver_string == 'pci').

- kernel/bar_emulation.c: seed BAR0 shadow so guest sees a REAL, PHYSICAL,
  non-virtual TU104 (user directive: no PV/VF vGPU paths, unmodified driver):
  * PMC_BOOT_0/1/42 = physical TU104 values captured from host hardware
    (0x164000a1 / 0x0 / 0x164a1000). Without these, halmgrGetHalForGpu()
    fails and probe aborts with 'does not include the required GSP'.
  * Serve a valid VBIOS at the PROM window (BAR0+0x300000) loaded from
    /lib/firmware/tu104_vbios.bin (dump of host TU104 ROM). Guest's
    kgspExtractVbiosFromRom_TU102 needs it for the mandatory FWSEC ucode
    (kgspGetFrtsSize is hardwired to 1MB on Turing).
  * Pre-set GSP secure-boot (GFW) completion state: PGC6 PLM (0x118128)=1,
    GFW_BOOT progress (0x118234)=0xFF, GSP falcon CPUCTL HALTED (0x110100).
    The driver's post-FLR GFW wait only *waits* (never kicks), so the
    pre-set state satisfies it immediately.

- kernel/gsp_emulation.c/h: physical GSP boot emulation.
  * Falcon boot-watch: poll GSP falcon/PGC6/WPR2/scratch registers and log
    changes (guest BAR0 is mmap-based, otherwise invisible to host).
  * gsp_emu_poll_boot: STARTCPU auto-complete state machine. Guest kicks
    FWSEC then Booter Load via GSP falcon CPUCTL; detect each kick and
    complete the stage (HALTED + FRTS err NONE + WPR2 + mailbox +
    RISCV-active) so the guest believes its ucodes ran.

Diagnosis that led here (documented in Handoff-vGPU-IO.md):
- Open nvidia.ko can never be an SR-IOV VF vGPU guest: os_is_grid_supported()
  is a stub returning FALSE in the open build (disassembled). PV path also
  rejected per user directive. Only the physical path with a fully emulated
  local GSP boot remains.
</content>
</entry>
<entry>
<title>kernel: Fix GSP emulation shadow binding, eventfd wiring, RPC livelocks + docs suite + repo reorg</title>
<updated>2026-09-21T17:06:51+00:00</updated>
<author>
<name>Arthur Hanson Rasmusson</name>
<email>arthur@vgpu.io</email>
</author>
<published>2026-09-21T17:06:51+00:00</published>
<link rel='alternate' type='text/html' href='https://git.vgpu.io/open-iov.git/commit/?id=c3a295efd1b1132bbaa5d422cd05b3fa8e89a8bf'/>
<id>urn:sha1:c3a295efd1b1132bbaa5d422cd05b3fa8e89a8bf</id>
<content type='text'>
CRITICAL FIXES (guest driver bring-up):
- gsp_emulation.c: emulation engine bound to the WRONG BAR0 - it polled the
  host physical BAR0 (bars[0].vaddr ioremap) for the doorbell and read RPCs
  from a local dma_alloc_wc buffer, while the guest writes land in the
  vzalloc'd bar0_shadow. The RPC path could never work; PBA writes even
  corrupted the host GPU's physical BAR0+0x3000. gsp_emu_init now binds
  exclusively to bar0_shadow (doorbell/mailbox/PBA aliases;
  shared_mem_dma==0 marks the alias so cleanup never dma_free's it).
- main.c SET_IRQS: DATA_EVENTFD eventfds were DISCARDED ('TODO' + kfree) -
  the guest never received MSI-X completions. Full wiring now:
  eventfd_ctx_fdget per vector, fd -1 clears, dev_close releases refs.
  gsp_emu_inject_completion_interrupt looks up vgpu-&gt;irqs[0].trigger LIVE
  (init-time copy was permanently NULL since QEMU wires after gsp_emu_init).
- gsp_rpc_client.c: BAR_TRAP/MIGRATE in emulation mode called
  gsp_rpc_submit_raw which rings the SAME doorbell the thread polls -
  self-triggered RPC livelock + multi-second stalls. Now fail fast with
  -ENOTSUPP + pr_warn_ratelimited (guest BAR access is direct MMIO).

MORE FIXES:
- main.c: nv_vgpu_config_write returned SIZE_MAX (while(count--) wrap) and
  was dead code while the VFIO write handler did unfiltered byte copies
  (guest could rewrite vendor ID/BARs). Return fixed; VFIO write handler
  now routes through the per-register filter.
- kernel/Makefile: M=$(PWD) used the env var which is stale when invoked
  via the top-level make (pointed at repo root -&gt; kbuild silently built
  NOTHING; explains every 'stale .ko' incident). Now M=$(CURDIR).
- Warnings sweep: header prototypes for mdev/type functions, format casts
  in gsp_comm.c DRY-RUN logs, unused variable.

ROBUSTNESS (harness/tooling):
- vgpu_vm.py: run had no timeout (start could block forever);
  guest_shell recv could block forever on a wedged guest. Both now bounded;
  guest_shell pre-flights guest-ping and reports wedge diagnostics.
- stack_manager.sh: qemu/qemu-debug now launch via the vgpu_vm.py harness
  (workflow rule: never raw QEMU).

REPO REORGANIZATION:
- driver/ (legacy guest-side gsp-vgpu.ko) moved to legacy-driver-guest/
  (reference only, not built; README explains). 3 legacy un-buildable test
  files moved to legacy-driver-guest/kernel-tests/. Top-level Makefile
  cleaned of the dead DRIVER_DIR reference.

DOCUMENTATION SUITE (new):
- docs/GSP_EMULATION_ARCHITECTURE.md - emulator deep-dive: shadow BAR0
  model, doorbell protocol, dispatch table, MSI-X path, lifecycle, memory-
  model caveats
- docs/DEBUGGING.md - QEMU GDB stub workflow, serial console, QMP NMI,
  failure taxonomy, full bring-up validation checklist, EPT-livelock case
  study, version-matrix discipline
- docs/ONBOARDING.md - repo tour, coding standards (incl. virt_to_phys /
  dma_addr_t / get-put rules), first build &amp; test
- docs/VERSION_UPGRADE.md - end-to-end new-driver-version procedure
  (firmware fetch, Ghidra analysis, configs, signatures, validation)
- docs/PERFORMANCE.md - bare-metal A/B methodology + targets
- README.md doc index; STATE.md refreshed; DEVELOPMENT_WORKFLOW.md corrected
  (load order: open-iov-vfio BEFORE nvidia; stock-driver blacklist note)
</content>
</entry>
<entry>
<title>kernel: Fix guest-hang root cause (VFIO mmap garbage PFN) + rebuild mdev remove path</title>
<updated>2026-09-21T16:37:46+00:00</updated>
<author>
<name>Arthur Hanson Rasmusson</name>
<email>arthur@vgpu.io</email>
</author>
<published>2026-09-21T16:37:46+00:00</published>
<link rel='alternate' type='text/html' href='https://git.vgpu.io/open-iov.git/commit/?id=5d4d26f8e773f2871c1b5c9266b82495d390970e'/>
<id>urn:sha1:5d4d26f8e773f2871c1b5c9266b82495d390970e</id>
<content type='text'>
VFIO mmap (main.c): virt_to_phys() was used on vmalloc-family addresses
(vzalloc'd BAR0 shadow, ioremap'd BAR2/3), producing garbage PFNs. Guest
BAR0 access then hit a KVM make_spte reserved-bits WARN and an
EPT-violation livelock, hard-wedging the guest on every nvidia driver
probe (confirmed via QEMU GDB stub). BAR0 now maps per-page via
vmalloc_to_pfn(); BAR2/3/4/5 map bars[N].gpa directly (like BAR1);
config space uses new nv_vgpu_mmap_virt_to_pfn() helper.

mdev remove path (main.c): old path never list_del'd the device
(available_instances leaked), never ran cleanup (leaked gsp_emu kthread),
never unregistered VFIO (leaked /dev/vfio/N + iommu group), never put
pdev, never freed the struct. New kvmgt-style path: cancel init_work -&gt;
wait fds -&gt; vfio_unregister_group_dev -&gt; cleanup work -&gt; list_del -&gt;
pci_dev_put -&gt; vfio_put_device.

gsp_rpc_client.c: fix dma_map_page dma_addr_t-&gt;int truncation in
gsp_rpc_alloc_emul (corrupts &gt;=4GB IOVAs); export gsp_client_init_emulation.

gsp_emulation.c: export gsp_emu_process_rpc and gsp_emu_get_stats.

main.c: remove wrong MODULE_SOFTDEP("pre: nvidia") - module has zero
nvidia imports, loads standalone, and must load BEFORE nvidia.ko
(it exports nvidia_vgpu_vfio_* for nvidia.ko to import).

nvidia-vgpu-vfio.h: NULL-safe nv_vgpu_{dbg,info,warn,err} macros.

tests/gsp_emulation_test.c: rewritten against current API - drives
gsp_emu_process_rpc() with crafted shared-memory messages (protocol
validation, SCHEDULE/YIELD/NOTIFY/DEBUG dispatch, stress). Builds with
KBUILD_EXTRA_SYMBOLS; depends: open-iov-vfio.

stack_manager.sh: vfio_mdev doesn't exist on &gt;=6.4 (probe per-module);
load-nvidia detects foreign nvidia via /sys/module/nvidia/version and
errors with guidance instead of silently skipping.
</content>
</entry>
<entry>
<title>kernel: Add get_available mdev callback (fix leaked available_instances)</title>
<updated>2026-09-21T15:30:46+00:00</updated>
<author>
<name>Arthur Hanson Rasmusson</name>
<email>arthur@vgpu.io</email>
</author>
<published>2026-09-21T15:30:46+00:00</published>
<link rel='alternate' type='text/html' href='https://git.vgpu.io/open-iov.git/commit/?id=79d86fe350eaa520cda91b3832d30b085d9bcd6f'/>
<id>urn:sha1:79d86fe350eaa520cda91b3832d30b085d9bcd6f</id>
<content type='text'>
The mdev core's shared parent-&gt;available_instances counter leaks whenever
an mdev remove path fails to complete (as happened during the now-fixed
remove crash): creates then fail with -EUSERS while sysfs reports 0
available instances with zero mdevs present.

Implement mdev_driver.get_available to compute availability from the
driver's own authoritative device list instead of the core counter.
Handles the 'nvidia-' prefixed sysfs type names when looking up per-type
max_instances (falls back to 1).
</content>
</entry>
</feed>
