From c9c507c67dca0f3c0510f964e280261a8819f05c Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Wed, 14 Oct 2026 14:18:21 +0800 Subject: [PATCH] =?UTF-8?q?fix(vkernel):=20=5Frender=20=E7=9A=84=E5=88=B7?= =?UTF-8?q?=E6=96=B0/=E8=83=8C=E6=99=AF=E5=BE=AA=E7=8E=AF=E6=8C=89?= =?UTF-8?q?=E5=B1=8F=E5=B9=95=E9=AB=98=E5=BA=A6=E5=A4=B9=E5=8F=96=E8=A1=8C?= =?UTF-8?q?=E7=95=8C=EF=BC=8C=E9=81=BF=E5=85=8D=E8=84=8F=E8=A1=8C=E5=80=BC?= =?UTF-8?q?=E8=A2=AB=E5=86=99=E5=9D=8F=E6=97=B6=E6=AD=BB=E5=BE=AA=E7=8E=AF?= =?UTF-8?q?=E8=B6=8A=E7=95=8C=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 面包屑定位:卡在 “[rc] vblank done” 与 “[rc] flush done” 之间 —— 即帧缓冲刷新循环。 _dirty_y_max 是 .bss 全局,一旦被写坏成很大的正数: - 循环退化成死循环 → 卡死(故 [dt] 心跳一行都不打印); - run_start*pitch 越写越远,写出 0x80000000 帧缓冲之外 → 落进 MMIO → 宿主 QEMU 被写崩(unknown software exception 0x40000015 = STATUS_FATAL_APP_EXIT), 且屏幕只留下顶部已写的那一小块。 两个循环(背景铺底 + 帧缓冲刷新)的行界现夹到 [0, h-1]。这不是根因修复 (.bss 仍被写坏),但: - 止血:不再死循环、不再把宿主 QEMU 写崩; - 兼作探针:[dt] 心跳里的 dymin/dymax 若明显越界,即可确认 .bss 被写坏的量级。 --- VKernel/Kernel/services/desktop.vp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/VKernel/Kernel/services/desktop.vp b/VKernel/Kernel/services/desktop.vp index f0c0478..50367c3 100644 --- a/VKernel/Kernel/services/desktop.vp +++ b/VKernel/Kernel/services/desktop.vp @@ -1306,9 +1306,15 @@ def _render(): t0: uint64 = timer.timer_get_ticks() row_bytes: int = w * 4 + # 行界夹取:_dirty_y_min/_dirty_y_max 若被写坏成异常值,会退化成死循环并越界写 + # 到帧缓冲之外的 MMIO(实测把宿主 QEMU 写崩)。这里夹到 [0, h-1]。 + _dymin_bg: int = _dirty_y_min + if _dymin_bg < 0: _dymin_bg = 0 + _dymax_bg: int = _dirty_y_max + if _dymax_bg > h - 1: _dymax_bg = h - 1 if _bg_row_buf and _dirty_count > 0: - py_bg: int = _dirty_y_min - while py_bg <= _dirty_y_max: + py_bg: int = _dymin_bg + while py_bg <= _dymax_bg: if _dirty_rows[py_bg]: string.memcpy(rawptr(uint64(back) + py_bg * row_bytes), _bg_row_buf, row_bytes) py_bg += 1 @@ -1351,11 +1357,11 @@ def _render(): _wait_vblank() serial.puts("[rc] vblank done\n") if _dirty_count > 0: - py_fb: int = _dirty_y_min - while py_fb <= _dirty_y_max: + py_fb: int = _dymin_bg + while py_fb <= _dymax_bg: if _dirty_rows[py_fb]: run_start: int = py_fb - while py_fb <= _dirty_y_max and _dirty_rows[py_fb]: + while py_fb <= _dymax_bg and _dirty_rows[py_fb]: py_fb += 1 run_bytes: int = (py_fb - run_start) * row_bytes string.memcpy(rawptr(uint64(_fb) + run_start * pitch), rawptr(uint64(back) + run_start * row_bytes), run_bytes)