summaryrefslogtreecommitdiffstats
path: root/tools/guest-diag/semfix_watch.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/guest-diag/semfix_watch.py')
-rw-r--r--tools/guest-diag/semfix_watch.py15
1 files changed, 11 insertions, 4 deletions
diff --git a/tools/guest-diag/semfix_watch.py b/tools/guest-diag/semfix_watch.py
index 1c33de6..fa435ea 100644
--- a/tools/guest-diag/semfix_watch.py
+++ b/tools/guest-diag/semfix_watch.py
@@ -392,7 +392,14 @@ def resolve_sem_pool(q, sem):
def pin_pushbuffer(q, gpu_vas, cpu, gpa, size=0):
"""Pin the pushbuffer pages (the UVM allocation is 16 x 1 MB chunks =
16 MB = 4096 pages; the page layout is only piecewise contiguous, so
- group ascending-contiguous runs into one bulk injection each)."""
+ group ascending-contiguous runs into one bulk injection each).
+
+ gva2gpa of a kernel vmalloc VA intermittently fails while the sampled
+ vCPU executes in user mode (page-table isolation hides the kernel half),
+ so a pass can miss a run of pages. Do not stop at the first hole: scan
+ the whole range (bailing only when essentially everything misses) and
+ return the pinned count, so the caller can retry the remainder later.
+ """
pages = min(max(size >> 12, 1) if size else PUSHBUF_MAX_PAGES,
PUSHBUF_MAX_PAGES)
pinned = 0
@@ -403,9 +410,9 @@ def pin_pushbuffer(q, gpu_vas, cpu, gpa, size=0):
g = q.gva2gpa(cpu + i * 0x1000)
if not g:
miss += 1
- if miss >= 64:
- print("semfix: pushbuf va=0x%x: %d unmapped pages at %d, stop (%d pinned)"
- % (gv, miss, i, pinned), flush=True)
+ if miss >= pages:
+ print("semfix: pushbuf va=0x%x: no page resolved (%d "
+ "tried), wrong cpu base" % (gv, pages), flush=True)
return pinned
i += 1
continue