diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-09-29 08:40:19 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-09-29 08:40:19 -0400 |
| commit | 64bcfd6fd72546a2758d664bea39354604babcda (patch) | |
| tree | 0c529f9a03964da6d77887e19ac3a56d8ec45a18 /kernel/dynamic_rpc_dispatcher.c | |
| parent | b37cd12a552c7a79a9b965c391fb2f64a8da4912 (diff) | |
| download | open-iov-64bcfd6fd72546a2758d664bea39354604babcda.tar.gz open-iov-64bcfd6fd72546a2758d664bea39354604babcda.zip | |
sema: fix host stack-overflow hang; robust VA resolution; dispatcher lock fix
- svc_handle_chan_dump()/svc_decode_stream(): static snapshot buffers. The
128-channel local array made an ~18 KB frame, which overflows the 16 KB
kernel stack in the function prologue and panicked the host 2-3 s after a
VM attached the vGPU (proven from EFI pstore: guard page hit at
svc_handle_chan_dump+0x20, sub rsp,0x4850).
- svc_pump_channels(): write-back now also persists expected_sem_payload,
rescue_last and rescue_fail. The pump works on a snapshot copy, so
without this the stale-entry skip and the rescue rate limit could never
fire and the payload expectation was reinitialized every pass.
- svc_targeted_resolve(): sliced scan (128 MB per call, one VA at a time,
failed-VA cache) instead of a full-RAM scan per miss; no longer appends
to the sorted map out of order.
- svc_rebuild(): merges new scan results into the previous map (fresh
translation wins in place, new VAs appended) instead of replacing it
wholesale, so live translations survive a scan-yield collapse.
- Warning fixes: misleading indentation, unused variable, jiffies
typecheck. Frame audit: largest frame now 872 B.
- Includes the previous session's uncommitted work: sema_counter /
shadow_scan / shadow_dump debug params, exit stage markers, pdev ref
fix, and the dynamic dispatcher request_firmware-out-of-spinlock fix.
Diffstat (limited to 'kernel/dynamic_rpc_dispatcher.c')
| -rw-r--r-- | kernel/dynamic_rpc_dispatcher.c | 42 |
1 files changed, 25 insertions, 17 deletions
diff --git a/kernel/dynamic_rpc_dispatcher.c b/kernel/dynamic_rpc_dispatcher.c index ca4268d..3853604 100644 --- a/kernel/dynamic_rpc_dispatcher.c +++ b/kernel/dynamic_rpc_dispatcher.c @@ -221,41 +221,49 @@ static struct rpc_interface interface_emu = { int dynamic_dispatcher_init(const char *fw_path) { struct fw_analysis_result result; + struct rpc_interface *iface; + bool use_native = false; int ret; spin_lock(&g_dispatcher.lock); - if (g_dispatcher.initialized) { spin_unlock(&g_dispatcher.lock); return 0; } + spin_unlock(&g_dispatcher.lock); - /* Analyze firmware */ + /* + * Firmware analysis must run outside the lock: request_firmware() + * waits for userspace and sleeps, so holding g_dispatcher.lock + * (a spinlock) across it is a scheduling-while-atomic bug. + */ ret = fw_analyzer_load_and_analyze(fw_path, &result); if (ret) { pr_warn("DYN_DISPATCH: Firmware analysis failed, using emulation: %d\n", ret); - g_dispatcher.current_interface = &interface_emu; - g_dispatcher.initialized = true; - spin_unlock(&g_dispatcher.lock); - return 0; - } - - g_dispatcher.fw_analysis = result; - - /* Select interface based on firmware version */ - if (result.matched && strcmp(result.version, "570.144W") == 0) { - interface_570.fw_addrs = result.addresses; - g_dispatcher.current_interface = &interface_570; + iface = &interface_emu; + } else if (result.matched && strcmp(result.version, "570.144W") == 0) { + iface = &interface_570; + use_native = true; pr_info("DYN_DISPATCH: Using native 570.144W interface\n"); } else { - g_dispatcher.current_interface = &interface_emu; + iface = &interface_emu; pr_info("DYN_DISPATCH: Using emulation interface (version: %s)\n", result.version); } - g_dispatcher.initialized = true; + spin_lock(&g_dispatcher.lock); + if (!g_dispatcher.initialized) { + if (!ret) { + g_dispatcher.fw_analysis = result; + if (use_native) + interface_570.fw_addrs = result.addresses; + } + g_dispatcher.current_interface = iface; + g_dispatcher.initialized = true; + } spin_unlock(&g_dispatcher.lock); - fw_analyzer_print_result(&result); + if (!ret) + fw_analyzer_print_result(&result); return 0; } |
