summaryrefslogtreecommitdiffstats
path: root/kernel/main.c
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-22 09:43:22 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-22 09:43:22 -0400
commit60da11fe771968bbc0cc65b8f629cc5e6b3f44a1 (patch)
tree99878e4285e9edcab697d4d2569161f70c8642d1 /kernel/main.c
parent9b891254b05e9e46f27b8ff53decfbbb429d1cc4 (diff)
downloadopen-iov-60da11fe771968bbc0cc65b8f629cc5e6b3f44a1.tar.gz
open-iov-60da11fe771968bbc0cc65b8f629cc5e6b3f44a1.zip
host stability: BAR3 shadow + skip submodule nvidia + teardown-safe garbage handler
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 -> 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.
Diffstat (limited to 'kernel/main.c')
-rw-r--r--kernel/main.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/kernel/main.c b/kernel/main.c
index 5e99881..f37be6e 100644
--- a/kernel/main.c
+++ b/kernel/main.c
@@ -1180,17 +1180,28 @@ static int nv_vgpu_vfio_dev_mmap(struct vfio_device *vdev, struct vm_area_struct
return remap_pfn_range(vma, vma->vm_start, pfn, size, vma->vm_page_prot);
}
- /* BAR3 region - ioremap'd host BAR; map backing physical address */
+ /* BAR3 region - emulated shadow buffer (not physical GPU BAR) */
region_base = VFIO_PCI_INDEX_TO_OFFSET(VFIO_PCI_BAR3_REGION_INDEX);
region_size = vgpu->bars[3].size;
if (offset >= region_base && offset < region_base + region_size) {
+ unsigned long bar3_off = offset - region_base;
+ unsigned long pos;
+
if (!vgpu->bars[3].vaddr || region_size == 0)
return -ENODEV;
if (offset + size > region_base + region_size)
return -EINVAL;
- pfn = (vgpu->bars[3].gpa + (offset - region_base)) >> PAGE_SHIFT;
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- return remap_pfn_range(vma, vma->vm_start, pfn, size, vma->vm_page_prot);
+ /* BAR3 shadow is vzalloc'd: per-page vmalloc_to_pfn like BAR0 shadow.
+ * Guest BAR3 accesses hit our clean host-RAM backing, not the
+ * host GPU's real instance memory aperture. */
+ vm_flags_set(vma, VM_DONTEXPAND | VM_DONTDUMP);
+ for (pos = 0; pos < size; pos += PAGE_SIZE) {
+ pfn = vmalloc_to_pfn(vgpu->bars[3].vaddr + bar3_off + pos);
+ if (remap_pfn_range(vma, vma->vm_start + pos, pfn, PAGE_SIZE,
+ vma->vm_page_prot))
+ return -EAGAIN;
+ }
+ return 0;
}
/* BAR4 region - map backing physical address if present */