Commit Graph
18 Commits
Author SHA1 Message Date
TermiNexus 9745f8832a fix(vkernel): UHCI frame list 步长越界 12KB 砸坏 buddy 堆(堆损坏根因);paging 页表记录指针缩放;清理临时探针
根因:uhci.vp 两处写成 _frame_list + uint64(i) * 4 —— uint32* 的 +n 已按元素(4字节)缩放,
再乘 4 使实际步长变成 16 字节;1024 次循环写到 16KB,而缓冲只有 UHCI_NUM_FRAMES*4 = 4KB
⇒ 越界 12KB 覆盖相邻 buddy 空闲块头(现场:[0E][PF] cr2=0xba4c000 err=0x3 rip=0x10e598
rax=0x3000=12288),把空闲链 next/prev 写坏 ⇒ 随机 [mm] BAD blk、malloc 失败、app 崩溃。
定位手段:把空闲链表头页在内核页表标只读(paging.init 已置 CR0.WP=1),任何写入立即 #PF
并给出 rip/cr2 直接指认写者(该探针定位完已删除)。

paging:save_pt_range / restore_pt_range 里的 save_buf + i*16 在 uint64* 上实际是 128 字节
步长、+8 实际是 +64 字节(IR 取证:getelementptr i64 ⇒ 按 8 字节元素缩放),改为显式字节
地址推进记录 + 元素索引(+1 = +8 字节),两处布局保持一致。

保留的加固(非探针):memory_block.magic 与 allocate_block/free_block/merge_blocks 的块头
校验、free() 的堆范围校验、slab 建页的 total 边界护栏、页表池按真实 buf_size 计页与
pt_pool_magic/pt_pool_limit 哨兵、#GP 分支补打 rax 便于定位非规范地址写。

elf.vp 新增 ELF_LOAD 开关(=1 正常装载;置 0 可整体跳过 app/.so 装载,便于隔离内核问题)。
2026-10-15 13:35:34 +08:00
TermiNexus ec57603bb3 fix(vkernel): 分配器与页表池加固(块头魔数/双链校验、池边界与哨兵),并清理定位用临时探针
mm: memory_block 加 magic(塞进原有 padding,布局仍 32B);allocate/free/merge 前校验块头(magic、size==2^order、state、prev/next 在堆内且 8 字节对齐),坏块只报不改并限流;free() 增加堆范围校验;slab 建页前校验 total 与地址范围自洽(防 uint64 下溢 + uint16 截断导致成片写页外);NO FREE BLOCK 附带 used/free/total。paging: 页表池按调用者给的真实 buf_size 计算可用页数(此前丢掉 buf_size、上限硬编码 PT_POOL_PAGES ⇒ 池会发到缓冲之外,把页表内容盖到 buddy 空闲块头);加 pt_pool_magic/pt_pool_limit 哨兵与 CORRUPT/EXHAUSTED fail-fast。idt: #GP 分支补打 rax(rax+0x10 即触发访存地址),与 #PF 分支同口径。同时移除本轮定位用临时探针(elf.vp/isr.s/main.vp 恢复原状)。
2026-10-15 12:47:39 +08:00
TermiNexus b6cc64a5c9 chore(vkernel): 移除本轮排查加的全部临时诊断探针,并把 fb 为空改为 fail-fast
现象已定位清楚:fb=0 时刷新会把后备缓冲写到物理 0 起,覆盖 IVT/BDA + 低端内存 +
内核镜像自身(边跑边改坏自己正在执行的代码 → 卡死;宿主 QEMU abort 0x40000015)。
本轮实测 fb/pitch 正确时桌面渲染正常、[perf] 数值单调(.bss/中断那条线的修复生效)。

清理内容:
- main.vp:删除 _WhProbe 探针函数与 7 处调用、2 处 mm.DumpBuddy() 调用
- desktop.vp:删除 [rc] 阶段面包屑 7 处、[rc] preflush 转储、[dt] 每秒心跳、[dst] 入口探针
- mm.vp:删除已无调用点的 DumpBuddy()(保留 3 条 malloc 失败诊断——它们是错误信息,非调试噪音)

新增(fail-fast,替代静默兜底):
- desktop.start:fb_ptr == 0 时打印 FATAL 并停机,杜绝“刷新把内核自己写掉”这类灾难
- _render:脏行行界夹取保留(越界会静默写穿帧缓冲),但这是防破坏下限,非修复
2026-10-14 14:52:56 +08:00
TermiNexus 449f2dbc37 fix(mm): 加分配失败分步诊断;build.py 改用 --phase2command 产出 kernel.elf
- mm.vp: 在 malloc(slab 路径)、_create_page、allocate_block 三处失败分支各加一条
  [mm] 诊断打印,用于定位“[desktop] dirty_rows malloc FAILED”
  (768B → ≤SLAB_THRESHOLD → slab size class 5(1024B) → _create_page 需 order≥1 伙伴块;
   DumpBuddy 显示伙伴空闲链健康,故需进一步区分是哪一步返回 NULL)
- build.py: kernel.elf 改为调用 viperc --phase2command 拿到“精确链接命令”再改写产出。
  自行 glob .obj 去链会因对象顺序不同得到与 kernel.bin 不一致的段布局
  (实测前 247KB 里 230KB 不同),无法把日志 rip 映射回函数。
2026-10-14 13:36:01 +08:00
TermiNexus 54e88ce957 feat(build): 额外链接带符号 kernel.elf;mm 增加 DumpBuddy 诊断
- build.py: 用同一批 .obj + 同一 linker.ld 再链一份
  VKernel/__vpcbuild__/output/kernel.elf(仅去掉 --oformat binary/--strip-all),
  段布局与 kernel.bin 一致 → 可把日志里的 rip 用 objdump/nm 映射回函数
- mm.vp: 新增 export DumpBuddy(),打印 arena start/end 与 total/used/free
  及各阶空闲链表首块(上限 8 个),定位分配失败是“链表空”还是“块指针坏”
- main.vp: mm.init 之后、desktop.start 之前各调一次 DumpBuddy(),
  用于排查“[desktop] dirty_rows malloc FAILED”
  (768B → ≤SLAB_THRESHOLD → slab size class 5(1024B) → _create_page 需 order≥1 伙伴块)
2026-10-14 13:27:40 +08:00
TermiNexus 0c6396912b fix(vkernel): ISR 保存/恢复 rax/rcx/r8-r11,修中断破坏被中断代码寄存器
根因:isr.s 的 ISR_NOERR/ISR_ERR 宏把 rax/rcx/r8-r11 当临时寄存器用
(读 RIP/CS/RFLAGS、算 is_user),却从未保存/恢复原值,rcx 更是根本不在
保存列表里。于是任意一次中断(定时器 1000Hz)只要落在“这些寄存器里存有
活跃值”的瞬间,就会破坏被中断代码的活跃值:
  - r8 被写成被中断处的 RIP;rcx 被清 0(xor ecx,ecx / setnz cl 造 is_user)

实测吻合:DumpMapping 把 tag 放 rcx、va 放 r8,中断落点恰在其中 → 打印
“ [PG] (None) va=0x11ab82 ”,其中 0x11ab82 正是 DumpMapping 内部的 RIP;
同一机制把 main.vp 的 width 槽写成 0 → “ [desktop] back_fb malloc FAILED ”。
最初日志里的 [0D][GP] rip=0x130d45(vsnprintf 读 %d 变参)亦由此而来。
旧 TPC 编译的寄存器分配没踩到该窗口故“正常”,新版编译器踩到 → 概率性破坏
(对应 VKERNELERR.md 记录的“新版概率性崩溃”)。

- isr.s: 新增 ISR_SAVE_CLOBBERED / ISR_RESTORE_CLOBBERED 与 _isr_scratch;
  入口第一件事保存 rax/rcx/r8-r11,各返回路径在 push 完 iretq 帧之后恢复
  (iretq 从栈取帧,恢复寄存器不影响返回)
- mm.vp: arena 起点抬高后做 4KB 对齐(KernelEnd 未必页对齐),避免伙伴系统块错位
2026-10-14 13:06:26 +08:00
TermiNexus 0919a058a8 fix(vkernel): 预留内核 .bss 与栈区,修堆 arena 覆盖未预留内核内存
根因:bootloader 只按 kernel 文件大小 AllocatePages(.bss 不占文件),于是 .bss
尾部(ticks/_perf_* 等全局量)与主线程栈区(0x60000~0x80000)在 memmap 里仍是
EfiConventionalMemory,被内核 mm 的堆 arena 当作空闲内存占用 → 内核全局量被写坏、
堆元数据被反向破坏,最终桌面线程栈上的 va_list 被改坏,vsnprintf 读 %d 变参时
#GP(rip=0x130d45, err=0x0)。

- linker.ld: .bss 末尾加 LONG(0) 强制 PROGBITS,使 kernel.bin 的 FileSize 涵盖
  .bss,bootloader 的 PagesNeeded 得以预留整块内核镜像(含 .bss)
- mm.init: 新增 KernelAddr/KernelEnd,挑 arena 时把与内核镜像 [kernel_PhysAddr,
  __bss_end) 重叠的 region 起点抬到镜像末端(不整段丢弃)
- main.vp: 取 __bss_end 并传入 mm.init
- boot.c: ExitBootServices 前用 AllocatePages(AllocateAddress, EfiLoaderData)
  占位内核栈区 0x60000~0x80000,使其在 memmap 中标记已用

另含在途整理:多处补显式收窄转换(uint8()/uint16() 等)、kbd_svc 构造改为
kbd_svc.__init__() 等。
2026-10-14 12:54:43 +08:00
TermiNexus dcb7c5c2c0 chore(ViperOS): 落库内核侧进行中的改动(26 文件,+1573/-1805)
内容由用户产出,本次仅代为提交、未做任何语义修改;含 static 修饰符前置迁移等(新增 static 前缀 16 行)。提交消息为中性描述——如需更精确的说明请 amend。
2026-09-28 15:24:52 +08:00
TermiNexus 2a54e2bafb 清理了 t.CVoid 2026-09-16 16:07:04 +08:00
TermiNexus a518f75b24 chore(vkernel): 重置基线 — 纳入 TPV codegen 修复配合的内核侧调整与既有工作区内容
- devfs.vp: string.split 传 PATH_BUFFER_SIZE(配合 split 新增容量参数)

- fat32_types.vp: lfn_extract 越界钳制(base+i > MAX_LFN 返回 -1)

- sheet.vp: gfx.Renderer 实参修正为 (fb, zb, w, h)(原单参导致 w/h=0 渲染空操作)

- 同批包含 VKernel 其余既有移植改动与 vpsdk/Apps/Libs 工作区内容
2026-09-11 14:27:01 +08:00
TermiNexus cd1cc915c5 修正了build.py,重置基线 2026-09-11 10:34:34 +08:00
TermiNexus 4296d2a19e fix(asm-inline): cmos_read 裸 in/out al 补 CLOBBER_RAX + 显式 mov;rdmsr out 绑定与 clobber 冲突(lo/hi 读不到 EAX/EDX)改显式 mov——同类 EAX 破坏根因,残留间歇性数据损坏源 2026-08-27 01:33:19 +08:00
TermiNexus d4200f1129 debug(mm): 无条件打印 memmap 三参数 + fallback CMOS 原始值
serial.log 显示 memmap 分支(d[..] 转储 / mm: best=)从未打印 → 分支未执行,
size≈4GB 来自 fallback 的 detect_memory_size()(CMOS 读到垃圾)。加两处诊断:
1) init 开头无条件打印 MemmapAddr/MemmapSize/MemmapDescSize;
2) fallback 打印 CMOS 0x15-0x18 与 detect_memory_size 结果。
2026-08-26 19:11:22 +08:00
TermiNexus 1043343b9d fix(mm): get_block_size 移位改 64 位,修复伙伴初始化无限循环
4096<<20 在 i32 下溢出为 0x0 → bs=0x0 → cur_addr/remaining 不变 → 无限循环
([mm] it=1..6 order=20 bs=0x0 addr 不变)。改 t.CUInt64T 移位。另增关键数值
打印(memmap addr/size/desc/entries),配合描述符转储定位 4GB 伪可用区。
2026-08-26 19:04:55 +08:00
TermiNexus f9ec205816 debug(mm): 转储 memmap 描述符 + buddy 初始化循环进度
mm.init 报 start=0x400000 size=4292411392(≈4GB)后挂起——256MB 内存不该有
4GB 可用区,怀疑 memmap 描述符读到垃圾。新增:1) init 内转储全部描述符
(type/start/pages);2) buddy __init__ 循环打印前 6 次迭代与 loop done 标记,
定位挂起点。
2026-08-26 19:02:40 +08:00
TermiNexus 8b40203b63 提交新的建议忽略 2026-08-06 18:08:50 +08:00
TermiNexus 20e7289c61 将 .py 和 .pyi 后缀名改为了 .vp 和 .vpi 后缀名 2026-07-30 16:34:26 +08:00
Viper 6813947181 Initial import of ViperOS 2026-07-19 12:38:20 +08:00