From 4b745a1c2c0534a1850b6efe6710536b2225c3f4 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Sun, 13 Sep 2026 19:07:41 -0400 Subject: Phase 1: Add GSP Emulation Engine (host-side) - New kernel/gsp_emulation.h: GSP emulation context and API - New kernel/gsp_emulation.c: Per-mdev emulation thread with: - Adaptive polling of doorbell at BAR0+0x110C00 - Shared memory RPC processing (4KB at BAR0+0x1000) - Dispatch for all 12 RPC types via firmware-decompiled handlers - MSI-X completion interrupt injection via eventfd - Statistics tracking (processed/failed RPCs, latency) - Modified kernel/main.c: Integrate gsp_emu_init/cleanup in device lifecycle - Modified kernel/Makefile: Add gsp_emulation.o to build - Modified kernel/gsp_rpc_client.h: Export gsp_rpc_emulation_set/is_enabled --- kernel/main.c | 129 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 70 insertions(+), 59 deletions(-) (limited to 'kernel/main.c') diff --git a/kernel/main.c b/kernel/main.c index 7d12203..efe5082 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -17,6 +17,7 @@ #include "nvidia-vgpu-vfio.h" #include "bar_emulation.h" #include "gsp_comm.h" +#include "gsp_emulation.h" #include "memory.h" #include "irq.h" #include "migration.h" @@ -450,76 +451,86 @@ static void __exit nv_vgpu_exit(void) static void nv_vgpu_device_init_work(struct work_struct *work) { - struct nv_vgpu_device *vgpu = container_of(work, struct nv_vgpu_device, init_work); - int ret; - - mutex_lock(&vgpu->lock); - vgpu->state = NV_VGPU_STATE_INITIALIZING; - mutex_unlock(&vgpu->lock); - - ret = nv_vgpu_bar_init(vgpu); - if (ret) { - nv_vgpu_err(vgpu, "BAR init failed: %d", ret); - goto err_state; - } - - ret = nv_vgpu_irq_init(vgpu); - if (ret) { - nv_vgpu_err(vgpu, "IRQ init failed: %d", ret); - goto err_bar; - } - - ret = nv_vgpu_memory_init(vgpu); - if (ret) { - nv_vgpu_err(vgpu, "Memory init failed: %d", ret); - goto err_irq; - } - - ret = nv_vgpu_gsp_init(vgpu); - if (ret) { - nv_vgpu_err(vgpu, "GSP init failed: %d", ret); - goto err_memory; - } - - ret = nv_vgpu_migration_init(vgpu); - if (ret) { - nv_vgpu_warn(vgpu, "Migration init failed: %d", ret); - } - - mutex_lock(&vgpu->lock); - vgpu->state = NV_VGPU_STATE_READY; - mutex_unlock(&vgpu->lock); - - nv_vgpu_info(vgpu, "vGPU device initialized successfully"); - return; - + struct nv_vgpu_device *vgpu = container_of(work, struct nv_vgpu_device, init_work); + int ret; + + mutex_lock(&vgpu->lock); + vgpu->state = NV_VGPU_STATE_INITIALIZING; + mutex_unlock(&vgpu->lock); + + ret = nv_vgpu_bar_init(vgpu); + if (ret) { + nv_vgpu_err(vgpu, "BAR init failed: %d", ret); + goto err_state; + } + + ret = nv_vgpu_irq_init(vgpu); + if (ret) { + nv_vgpu_err(vgpu, "IRQ init failed: %d", ret); + goto err_bar; + } + + ret = nv_vgpu_memory_init(vgpu); + if (ret) { + nv_vgpu_err(vgpu, "Memory init failed: %d", ret); + goto err_irq; + } + + ret = nv_vgpu_gsp_init(vgpu); + if (ret) { + nv_vgpu_err(vgpu, "GSP init failed: %d", ret); + goto err_memory; + } + + /* Initialize GSP emulation engine (host-side) */ + ret = gsp_emu_init(vgpu); + if (ret) { + nv_vgpu_err(vgpu, "GSP emulation init failed: %d", ret); + goto err_gsp; + } + + ret = nv_vgpu_migration_init(vgpu); + if (ret) { + nv_vgpu_warn(vgpu, "Migration init failed: %d", ret); + } + + mutex_lock(&vgpu->lock); + vgpu->state = NV_VGPU_STATE_READY; + mutex_unlock(&vgpu->lock); + + nv_vgpu_info(vgpu, "vGPU device initialized successfully"); + return; + +err_gsp: + nv_vgpu_gsp_cleanup(vgpu); err_memory: - nv_vgpu_memory_cleanup(vgpu); + nv_vgpu_memory_cleanup(vgpu); err_irq: - nv_vgpu_irq_cleanup(vgpu); + nv_vgpu_irq_cleanup(vgpu); err_bar: - nv_vgpu_bar_cleanup(vgpu); + nv_vgpu_bar_cleanup(vgpu); err_state: - mutex_lock(&vgpu->lock); - vgpu->state = NV_VGPU_STATE_ERROR; - mutex_unlock(&vgpu->lock); + mutex_lock(&vgpu->lock); + vgpu->state = NV_VGPU_STATE_ERROR; + mutex_unlock(&vgpu->lock); } static void nv_vgpu_device_cleanup_work(struct work_struct *work) { - struct nv_vgpu_device *vgpu = container_of(work, struct nv_vgpu_device, cleanup_work); + struct nv_vgpu_device *vgpu = container_of(work, struct nv_vgpu_device, cleanup_work); - nv_vgpu_migration_cleanup(vgpu); - nv_vgpu_gsp_cleanup(vgpu); - nv_vgpu_memory_cleanup(vgpu); - nv_vgpu_irq_cleanup(vgpu); - nv_vgpu_bar_cleanup(vgpu); + nv_vgpu_migration_cleanup(vgpu); + gsp_emu_cleanup(vgpu); + nv_vgpu_gsp_cleanup(vgpu); + nv_vgpu_memory_cleanup(vgpu); + nv_vgpu_irq_cleanup(vgpu); + nv_vgpu_bar_cleanup(vgpu); - mutex_lock(&vgpu->lock); - vgpu->state = NV_VGPU_STATE_UNINITIALIZED; - mutex_unlock(&vgpu->lock); + mutex_lock(&vgpu->lock); + vgpu->state = NV_VGPU_STATE_UNINITIALIZED; + mutex_unlock(&vgpu->lock); - nv_vgpu_info(vgpu, "vGPU device cleaned up"); + nv_vgpu_info(vgpu, "vGPU device cleaned up"); } static NV_STATUS nv_vgpu_vfio_probe(struct pci_dev *pdev, NvU32 vgpu_type_id, NvU32 *vgpu_id) -- cgit v1.2.3