summaryrefslogtreecommitdiffstats
path: root/kernel/dynamic_rpc_dispatcher.c
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-29 08:40:19 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-29 08:40:19 -0400
commit64bcfd6fd72546a2758d664bea39354604babcda (patch)
tree0c529f9a03964da6d77887e19ac3a56d8ec45a18 /kernel/dynamic_rpc_dispatcher.c
parentb37cd12a552c7a79a9b965c391fb2f64a8da4912 (diff)
downloadopen-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.c42
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;
}