<feed xmlns='http://www.w3.org/2005/Atom'>
<title>open-iov.git/kernel/bar_emulation.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:41:46+00:00</updated>
<entry>
<title>kernel: serve GMMU static info + per-VF fault/access-counter sizes for UVM</title>
<updated>2026-09-23T04:41:46+00:00</updated>
<author>
<name>Arthur Hanson Rasmusson</name>
<email>arthur@vgpu.io</email>
</author>
<published>2026-09-23T04:41:46+00:00</published>
<link rel='alternate' type='text/html' href='https://git.vgpu.io/open-iov.git/commit/?id=7aef82a5112ee72ee2fc5a430db072085933e927'/>
<id>urn:sha1:7aef82a5112ee72ee2fc5a430db072085933e927</id>
<content type='text'>
Three fixes that clear all driver-visible errors in UVM's device create
(cuInit still fails later in UVM_REGISTER_GPU):

1. GSP_RM_CONTROL 0x20800a59 INTERNAL_GMMU_GET_STATIC_INFO (new handler):
   kgmmu.pStaticInfo-&gt;replayableFaultBufferSize feeds
   kgmmuFaultBufferReplayableAllocate (called by faultbufConstruct when UVM
   opens the device). The generic zero reply made it a 0-page allocation:
   "faultbufConstruct_IMPL: Failed to setup Replayable Fault buffer
   (status=0x51)". Report 64KB replayable / 4KB legacy, mirroring
   kgmmuSetAndGetDefaultFaultBufferSize_TU102 defaults.

2. VF-window NV_VIRTUAL_FUNCTION_PRIV_MMU_FAULT_BUFFER_SIZE(0/1)
   (BAR0+0xB83010/0xB83030, plus plain aliases) pre-filled with _VAL in
   NVC369_BUF_SIZE units (0x800=64KB, 0x80=4KB) so the local (non-RPC)
   path reads the same values the control handler reports.

3. VF-window NV_VIRTUAL_FUNCTION_PRIV_ACCESS_COUNTER_NOTIFY_BUFFER_SIZE
   (BAR0+0xB83110, plus plain alias) = 0x1000 (the value the host's
   physical TU104 reports; x32B = 128KB). uvmGetAccessCounterBufferSize_
   TU102 multiplied our zero and uvmInitializeAccessCntrBuffer failed with
   NV_ERR_NO_MEMORY at mem_desc.c:1353.

Also note (companion finding, no code change): the guest must be placed
behind a pcie-root-port; on the Q35 root bus QEMU rewrites the PCIe cap to
Root Complex Integrated Endpoint and zeroes LNKCAP/LNKCTL/DeviceCaps
(vfio_setup_pcie_cap: "On a Root Complex bus Endpoints become Root Complex
Integrated Endpoints, which changes the type and clears the LNK &amp; LNK2
fields"), which is what made getPCIELinkRateMBps read speed 0.
</content>
</entry>
<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>kernel: GSP-RM msgq emulation + TU104 hardware tables (GET_GSP_STATIC_INFO, GSP_RM_CONTROL)</title>
<updated>2026-09-21T22:01:55+00:00</updated>
<author>
<name>Arthur Hanson Rasmusson</name>
<email>arthur@vgpu.io</email>
</author>
<published>2026-09-21T22:01:55+00:00</published>
<link rel='alternate' type='text/html' href='https://git.vgpu.io/open-iov.git/commit/?id=6aadb593750736f239fd54a0ccef4b3834c08fc4'/>
<id>urn:sha1:6aadb593750736f239fd54a0ccef4b3834c08fc4</id>
<content type='text'>
Implements the GSP-RM reply content layer for the msgq RPC channel:

- kernel/gsp_rm_emulation.c/h: GSP-RM msgq emulation engine
  - Queue chain discovery (libos args → RMARGS → GSP_ARGUMENTS_CACHED)
  - Status queue link + GSP_INIT_DONE emission
  - Command queue polling + RPC dispatch
  - SET_GUEST_SYSTEM_INFO version negotiation (VGX 41.12)
  - GET_GSP_STATIC_INFO(65) with 1656-byte GspStaticConfigInfo
  - GSP_RM_CONTROL(76) sub-command dispatch:
    - FIFO_GET_DEVICE_INFO_TABLE (0x20801112)
    - INTERNAL_INTR_GET_KERNEL_TABLE (0x20800a5c)
    - GPU_GET_CONSTRUCTED_FALCON_INFO (0x208001b0)
    - INTERNAL_GET_DEVICE_INFO_TABLE (0x20800a40)

- kernel/gsp_rm_tu104.h: TU104 hardware tables
  - 12-entry FIFO engine table (GR0, CE0-4, NVDEC0-1, NVENC0, SEC2, NVJPG, SW)
  - 8-entry interrupt table (from intr_phys_tu102.c)
  - 1-entry constructed falcon table (FBFLCN)
  - 11-entry internal device info table
  - GspStaticConfigInfo layout (1656 bytes, ABI-verified offsets)
  - Data from NVIDIA driver material (ext-tree) + hwref/turing/tu104

- tools/rmq/: Userspace RM API client (oracle for ground-truth tables)

KNOWN ISSUE: gsp_rm_send crashes (fortify_panic) on multi-element messages
when reply data exceeds one 4096-byte queue element. Affects cmd 0x20800a41
(paramsSize=8204). Multi-element splitting is the next fix.
</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>Phase 2: PCI Config Space &amp; BAR Enhancements</title>
<updated>2026-09-13T23:11:39+00:00</updated>
<author>
<name>Arthur Hanson Rasmusson</name>
<email>arthur@vgpu.io</email>
</author>
<published>2026-09-13T23:11:39+00:00</published>
<link rel='alternate' type='text/html' href='https://git.vgpu.io/open-iov.git/commit/?id=8e64754d9980d2423f1907ae184ec46e63e5ff7e'/>
<id>urn:sha1:8e64754d9980d2423f1907ae184ec46e63e5ff7e</id>
<content type='text'>
- Enhanced PCI config space write handlers in main.c:
  - Added MSI-X Message Control (0x72-0x73) write support
  - Added MSI-X Table Offset/BIR (0x74-0x77) write support
  - Added MSI-X PBA Offset/BIR (0x78-0x7B) write support

- Enhanced BAR emulation in bar_emulation.c:
  - Added MSI-X Table emulation (32 entries at BAR0+0x2000)
  - Added MSI-X PBA emulation (64-bit at BAR0+0x3000)
  - Added nv_vgpu_msix_set_pending/clear_pending for interrupt injection
  - Integrated with GSP emulation constants from gsp_emulation.h

- Updated bar_emulation.h with MSI-X struct definitions and function declarations
- Added GSP emulation constants to gsp_emulation.h (MSIX offsets, polling params)
</content>
</entry>
<entry>
<title>Initial commit: Open-IOV vGPU-IO complete stack</title>
<updated>2026-09-13T22:36:21+00:00</updated>
<author>
<name>Arthur Hanson Rasmusson</name>
<email>arthur@vgpu.io</email>
</author>
<published>2026-09-13T22:36:21+00:00</published>
<link rel='alternate' type='text/html' href='https://git.vgpu.io/open-iov.git/commit/?id=00e54c13c7c9030c4d5f7151467f2d85a3730e29'/>
<id>urn:sha1:00e54c13c7c9030c4d5f7151467f2d85a3730e29</id>
<content type='text'>
- Firmware decompilation: GSP 570.144W (28.5MB ELF, RV64IMAC), 132 decompiled C files
- Kernel modules: nvidia.ko (34MB, OpenRM), open-iov-vfio.ko (2.8MB, VFIO mdev), gsp-vgpu.ko (1.8MB, guest driver)
- Userspace: libiov.so/libvgpu.so (76KB), example_vgpu (28KB), rpc_emulator.c
- PCI config space emulation (256B with PM, MSI, MSI-X, PCIe caps)
- 12 RPC types fully mapped from firmware decompilation
- BAR trap, WPR, scheduling, notification, migration emulation
- Helper scripts: load_vgpu_stack, create_mdev, launch_qemu_vgpu, test_vgpu_stack, setup_guest_driver, unload_vgpu_stack
- Architecture documentation
- Wiki: 10 technical documents
- Git LFS for large binaries (.ko, .bin, .iso, .img, .o, ghidra repos)
- nvidia-open-gpu-kernel-modules as submodule
</content>
</entry>
</feed>
