From 6588981b619814b9c2b26130165e440f0556bdec Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Tue, 29 Sep 2026 08:40:19 -0400 Subject: 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. --- kernel/dynamic_rpc_dispatcher.c | 42 ++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) (limited to 'kernel/dynamic_rpc_dispatcher.c') 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; } -- cgit v1.2.3