summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-29 15:19:34 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-29 15:19:34 -0400
commit1895679334371c5a89dd5cb715c980ade6559c72 (patch)
tree2bc3a8483b5d55c7451476ea7a256ad84261bd79
parent1df5ff4729a6ad2d93bdd8707c0837e3bf9581b6 (diff)
downloadopen-iov-1895679334371c5a89dd5cb715c980ade6559c72.tar.gz
open-iov-1895679334371c5a89dd5cb715c980ade6559c72.zip
sema-svc: never apply swept-page releases with no live channel (guest boot corruption); tooling guards
-rw-r--r--kernel/gsp_sema_service.c23
-rw-r--r--tools/guest-diag/pin_gr_stream.py7
-rwxr-xr-xtools/guest-diag/semfix_uvmt.py10
3 files changed, 36 insertions, 4 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index ae8f7da..b29e833 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -2668,6 +2668,29 @@ static u32 svc_apply_page_data(struct nv_vgpu_device *vgpu, const u8 *buf,
u64 pa_page)
{
u32 off, applied = 0;
+ bool any = false;
+ unsigned long flags;
+ int ci;
+
+ /*
+ * No live channel: no client can be waiting on a release, so a
+ * "release" decoded from an arbitrary swept page can only be a false
+ * positive, and its write lands through whatever translation the VA
+ * happens to have (observed: 2 applied writes while the guest kernel
+ * was booting corrupted a task's CPU field and panicked the guest
+ * scheduler). Only apply swept-page releases while a client exists;
+ * real releases are carried by the channels' readable pushes then.
+ */
+ spin_lock_irqsave(&svc.chan_lock, flags);
+ for (ci = 0; ci < SVC_MAX_CHANNELS; ci++) {
+ if (svc.chan[ci].valid) {
+ any = true;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&svc.chan_lock, flags);
+ if (!any)
+ return 0;
/*
* Decoded execution: walk the page as a method stream and perform the
diff --git a/tools/guest-diag/pin_gr_stream.py b/tools/guest-diag/pin_gr_stream.py
index 22c202b..c1ef7b2 100644
--- a/tools/guest-diag/pin_gr_stream.py
+++ b/tools/guest-diag/pin_gr_stream.py
@@ -45,8 +45,11 @@ def install_and_start():
b64 = subprocess.run(["base64", "-w0"], stdin=f,
capture_output=True, text=True).stdout
cmd = ("echo '%s' | base64 -d > /tmp/guest_pin_stream.py; "
- "[ -f /tmp/guest_pin_stream.pid ] && sudo kill "
- "$(cat /tmp/guest_pin_stream.pid) 2>/dev/null; "
+ "if [ -f /tmp/guest_pin_stream.pid ]; then "
+ "p=$(cat /tmp/guest_pin_stream.pid 2>/dev/null); "
+ "[ -n \"$p\" ] && grep -q guest_pin_stream "
+ "/proc/$p/cmdline 2>/dev/null && sudo kill $p 2>/dev/null; "
+ "fi; "
"sudo rm -f /tmp/guest_pin_stream.pid; "
"sudo setsid nohup python3 /tmp/guest_pin_stream.py %d %d %s %s %s "
">/tmp/guest_pin_stream.log 2>&1 & sleep 2; "
diff --git a/tools/guest-diag/semfix_uvmt.py b/tools/guest-diag/semfix_uvmt.py
index 12577ab..0d31394 100755
--- a/tools/guest-diag/semfix_uvmt.py
+++ b/tools/guest-diag/semfix_uvmt.py
@@ -115,11 +115,17 @@ def state_str(sem, st):
def dmesg_releases(seen):
- """Print/append new host-decoded releases (sema-push lines)."""
+ """Print/append new host-decoded releases (sema-push lines).
+
+ Only lines after the last "sema-svc: thread started" marker count: dmesg
+ keeps the previous module load's lines and the old client's releases.
+ """
try:
r = subprocess.run(
["sudo", "-n", "sh", "-c",
- "dmesg -T | grep 'sema-push' | tail -300"],
+ "dmesg -T | awk '/sema-svc: thread started/{n=NR} "
+ "{l[NR]=$0} END{for(i=n+1;i<=NR;i++) print l[i]}' "
+ "| grep 'sema-push' | tail -300"],
capture_output=True, text=True, timeout=10)
except Exception:
return