TermiNexus
|
6f856992da
|
feat: Linux ABI P0-P6, BMIDE DMA, ImageSee, 4KiB page pool and Explorer hardening
|
2026-10-29 00:42:21 +08:00 |
|
TermiNexus
|
624554df01
|
fix(sched): 通过 rdi 传递用户线程入口参数
用户线程入口的第一个形参在 rdi,但 drop_to_user_mode 这条路径从未设置过 rdi,
thread_create(fn, arg) 的 arg 在用户侧一直是垃圾值。iretq 只恢复
RIP/CS/RFLAGS/RSP/SS,因此在 iretq 前显式 mov rdi 即可。
|
2026-10-26 22:40:10 +08:00 |
|
TermiNexus
|
e9d8024138
|
fix(sched): 压缩 _do_switch 注释,规避内联汇编 2047 字节静默截断
llc 报 <inline asm>:55:13 invalid operand + 孤立 mov 的真因:ViperC 的 _asm_append_cstr 只写入 ASM_TEXT_BUF_SIZE-1=2047 字节且静默丢弃后续内容。_do_switch 的 asm 模板(含 CRLF)为 2245 字节,第 2047 字节正好落在 mov [rsi + 40], rcx 的 mov 之后 ⇒ 生成的汇编串以孤立 mov 结尾,popfq/pop/ret 全部丢失。压缩块内 4 条中文注释(模板降到 1894 字节),指令与 clobber 未动。附:sha1_map 第 57 行 3e23dc8764e4a4dd:sched/sched.vp 与报错哈希一致;全仓 16 个含 asm 的 .vp、189 个模板中仅此一处超过 2047 字节。
|
2026-10-17 17:36:45 +08:00 |
|
TermiNexus
|
89385d1b42
|
fix(sched): 恢复立即数 store 的 qword ptr(去掉后操作数大小有歧义)
上一笔把 sched.vp 里所有 qword ptr 都去掉了,误伤 _thread_entry 构造初始栈帧的 8 条立即数 store:mov [rax - 64], 0x202 这类'内存←立即数'无法由另一侧推断大小,报 ambiguous operand size。寄存器配对的 mov(rcx/[rsi]、[rdx]/rcx 等)保持无 ptr 写法,立即数 store 恢复 qword ptr。
|
2026-10-17 17:21:20 +08:00 |
|
TermiNexus
|
937b51a0c5
|
fix(sched): 内联汇编去掉 qword ptr,操作数大小改由寄存器推断
llc 集成汇编器在 Intel 语法下对 mov rcx, qword ptr [rsi] 报 Expected 'PTR' or 'ptr' token(列号正落在 ptr 处),而生成的 .ll 文本本身是对的。改写为 mov rcx, [rsi] / mov [rdx], rcx / mov [rax], rsp 等形式:内存操作数大小可由另一侧寄存器(rcx/rsp)推断,语义完全等价。
|
2026-10-17 17:19:23 +08:00 |
|
TermiNexus
|
7d8a4ee6ff
|
fix(sched): 内联汇编改用 lea + 间接寻址,绕开 [rip + sym + 偏移] 不被集成汇编器接受
llc 集成汇编器对 mov qword ptr [rip + _isr_scratch + 8], rcx 这种'RIP 相对符号 + 常量偏移'的直接寻址报 invalid operand(把整条指令识别成缺源操作数)。改为先 lea rsi, [rip + _isr_scratch](lea 形式此前已验证可用),再按 [rsi + N] / [rdx + N] 访问,共 12 处(保存 6 + 恢复 6)。rsi/rdx 都在 _do_switch 的 push 列表内,切栈后写入会被随后的 pop 恢复,不影响新线程寄存器。
|
2026-10-17 17:17:28 +08:00 |
|
TermiNexus
|
645e4015ca
|
feat(sched): 线程切换保存/恢复 FPU/SSE(fxsave/fxrstor)
混合抢占后中断帧只保存通用寄存器,异步抢占可能落在 SSE 表达式中间,FP 密集 app(Gargantua/Scene3D)的 XMM 会被其它线程覆盖。① Thread 末尾内嵌 fpu_area[528] + fpu_ptr,用 (base+15)&~15 手工对齐出 512B FXSAVE 区(编译器类装饰器只认 packed,不认 aligned);Thread 由 64B 变为 600B,MAX_THREADS=16 ⇒ 线程表 9600B,Scheduler 约 9624B。② _do_switch:切 rsp 之前 fxsave [old],换栈后 fxrstor [new];仅用 RAX 取地址(其值已压栈),不改动 GPR 与中断状态。③ 新线程 FPU 默认镜像直接写内存(512B 清零、FCW=0x037F、MXCSR=0x1F80、MXCSR_MASK=0xFFFF),不执行 fninit 以免破坏创建者的实时 XMM。④ 内嵌于 Thread,随静态存储存活,无需额外回收。⑤ 协作式 yield 与抢占共用 _do_switch,因此两条路径都正确隔离 SSE。⑥ _thread_entry 的硬编码偏移同步为 +9600/×600,并加 fail-fast 校验(不符立即 FATAL,不静默跑飞)。
|
2026-10-17 17:15:14 +08:00 |
|
TermiNexus
|
f2d8e771c2
|
feat(sched): 协作 + 时间片抢占(IRQ0 返回用户态时切换)
原先 timer_tick 只置 needs_reschedule,唯一消费点是 SPAWN 阻塞循环,纯计算线程永不被切走。① 抢占点:isr32_handler 在 timer_handler(含 pic.eoi(0)/apic.eoi)返回之后、且 from_user != 0(ISR 入口读 CS 低两位)时调用 try_reschedule;栈切换仍在 _do_switch。只对 Ring3 返回路径生效,内核临界区/syscall 中途不切。② 中断帧保留在被切线程内核栈上,靠 rsp 切换自然保存/恢复,不拷贝、不在切换中途 iretq。③ 修正全局 _isr_scratch 跨线程覆盖:ISR_SAVE_CLOBBERED 把 rax/rcx/r8-r11 存在全局 scratch,抢占后跨线程会互相覆盖;_do_switch 现按 tid 保存/恢复(_isr_scratch_tbl[16*6])。④ ISR 走中断门 IF=0,_if_saved=0,切回后不 sti,由 iretq 用用户 RFLAGS 恢复;_yield_lock 防嵌套。⑤ 单核前提(_sched_ptr/tick_count 非 per-CPU)。⑥ yield_now 语义、SCHED_QUANTUM=10、Gargantua 分块均未改。已知缺口:中断帧未保存 XMM/MXCSR,FP 密集 app 在异步抢占下有 XMM 被覆盖风险,待补 fxsave/fxrstor。
|
2026-10-17 17:08:46 +08:00 |
|
TermiNexus
|
a3c1d221e6
|
fix(kbd,sched,scene3d): 键盘报告去重;用户线程 return 跳板修正;关窗时序
① Enter 洪流:usb_kbd._on_int_complete 的按下沿依赖 kbd_prev_keycodes,而状态提交在函数末尾第三趟循环;kbd_report 是常驻 DMA 缓冲,按键保持/NAK/重复完成都会让回调反复看到同一份报告 ⇒ 每次中断都注入一次 Enter,Terminal 刷出 [cmd] enter,explorer 被拖死。新增 kbd_prev_sig(modifier+6 keycode 的标量签名)整份报告去重;同一趟循环里先提交 prev 再判定;全 0 报告只更新状态;抽出 _rearm() 保证所有出口都重排中断 IN 且 DMA 读取先于重排。② explorer 限流:kb_pend[64] + _deliver_kb,单轮最多投递 64 字节,ring_push 返回 -1 时停在当前字节(不再当成功丢弃),pending 清空才补读;鼠标取包同样 64 包/轮上限。③ 关窗卡死根因:process.vp 的 _tramp_code 是 mov eax,34; int 0x80; jmp \$,而 Syscall.THREAD_EXIT=60 ⇒ 用户线程 return 后走 syscall 34(无匹配分支)返回 Ring3 在 jmp \$ 空转,空转不再产生 syscall,而内核只在 syscall 返回路径消费 needs_reschedule ⇒ 协作式调度彻底停摆,整机冻结。sched.create_user_thread 在跳板映射后把立即数低字节改为 60(幂等)。④ 次生:主线程先退会立即回收自己的用户栈,而 Scene3D 渲染线程还引用其栈上对象。Scene3D 渲染线程退出改为显式 process.thread_exit() 并置 _render_done;主线程 mainloop 返回后先 yield 等渲染线程退出(上限 10000 次)再 exit。⑤ window.flush 在槽位 used==0 时直接返回;vpui.Tk.redraw 入口判 win_id 与 is_active,窗口已回收时不碰 arena 不 flush。
|
2026-10-17 16:49:37 +08:00 |
|
TermiNexus
|
453c353e01
|
fix(sched): sched_yield 改为无条件切换,原实现只在时间片到期时才切
现场:app 用 4000 次 yield_cpu() 等 /dev/desk ready(explorer 负责 format 并置 ready=1),却全部超时——三个 app 都打出 [win] desk not ready (attach timeout) / create_window: connect FAILED / geometry win_id=-1,最后静默退出;而 explorer 的 [elf] wrapper pid=5 出现在所有 app 退完之后。根因:YIELD syscall 走 sched.Scheduler.try_reschedule(),而它只在 needs_reschedule(时间片到期,由 tick 置位)时才真正 _yield(),因此 N 次 sched_yield 全落在同一个时间片内一次都不切换 ⇒ 主动等待外设的进程被饿死、初始化者永远轮不上。修法:新增 Scheduler.yield_now() 无条件切换,YIELD 分支改用它;try_reschedule() 仍保留给中断/抢占路径使用。
|
2026-10-16 20:57:55 +08:00 |
|
TermiNexus
|
f4c653958e
|
feat(devfs): S1 —— 暴露 /dev/fb0 并让用户态可达 /dev/*(含 ioctl)
devfs:新增 /dev/fb0(framebuffer_device),提供 ioctl(FB_GET_INFO) 回填几何/格式/物理区间,并新增 devfs_file.mmap_info 虚方法(默认不可映射)把物理区间交给内核 mmap 用;main.vp 在 devfs_init 后登记它。输入设备(/dev/input/keyboard、/dev/input/mouse)此前已存在,本轮起从用户态可达。
用户态可达性:Process 增 fd_kind[](0=FAT32 fileobj*,1=devfs_fd+1),OPEN 对 "/dev/" 前缀改走 devfs,READ/WRITE/CLOSE 按 kind 分派;Process.exit 只对 kind=0 调 fat32.close(把 devfs fd 当 fileobj* 会跑飞)。fd 种类常量放在 process.vp 供 syscall.vp 引用,避免 process 反向 import devfs(devfs→keyboard/mouse→intr.idt→sched→process 会成环)。
新增 IOCTL syscall(Linux 号 16,本轮开始实现):只放给 devfs 设备,SDK 侧 vpsdk/fs.vp 加 ioctl() 助手。
|
2026-10-16 18:38:21 +08:00 |
|
TermiNexus
|
f34fe8a378
|
fix(sched): 用户线程出口改为跳板页,消除「线程函数 return 即 #PF」
alloc_user_thread 原来在用户栈顶下一格写哨兵返回地址 0:线程函数一旦 return,ret 就把 0 弹进 rip,Ring3 在 VA 0 取指。VA 0 在内核 identity map 里是存在但 supervisor-only 的页,于是现场固定为 rip=0x0 cr2=0x0 err=0x15 (P=1 保护违例 | U=1 用户态 | I/D=1 取指) rsp=线程栈 vtop,日志以 exc in tid=N, terminating 收场 —— 一次正常的线程结束被报成异常崩溃。
实测:Scene3D 渲染线程(唯一的 THREAD_CREATE,其栈顶 vtop 恰为 0x7FFFFFDE0000)在窗口被 taskbar 徽标关闭后 while root.winfo_exists() 退出并 return,日志即 serial.log 489-493 行那三行。
改为一页只含 mov eax,34(THREAD_EXIT); int 0x80; jmp $ 的出口跳板,映射在 [vtop, vtop+0x1000)(线程栈顶之上、栈向下增长永不到达的 64KB 间隙),栈顶哨兵改写成它的 VA。线程函数 return → 跳板 → THREAD_EXIT syscall → 内核干净回收本线程。free_user_thread 同步解映射该页并交还物理页,UserThreadCtx 增 tramp 字段记录。
|
2026-10-16 17:02:31 +08:00 |
|
TermiNexus
|
3ee35ad586
|
fix(sched): exit_current_thread 先标记 THREAD_DONE 再回收资源,堵住已退线程被再调度的窗口
原顺序是 free_user_thread 在前、state=THREAD_DONE 在后:在已释放用户栈/上下文但 state 仍为 RUNNING 的窗口里,若发生一次再调度(定时器 IRQ → try_reschedule → _yield 仅按 state 过滤),本线程会被再次选中并带着失效上下文回用户态,在已回收的栈上取指 0(现场 [0E] rip=0x0 err=0x15 cr2=0x0 rsp=0x7fffffde0000,紧跟 [syscall] exit called)。_yield 的选择逻辑(THREAD_READY/RUNNING 才可选)本身已正确,故只需把死亡标记提前。
|
2026-10-16 16:47:00 +08:00 |
|
TermiNexus
|
152c4c5683
|
feat(vkernel/vpsdk): 用户线程生命周期 - THREAD_EXIT 显式退出;异常终止时回收用户栈并释放槽位;返回哨兵可辨识
|
2026-10-15 16:50:58 +08:00 |
|
TermiNexus
|
a7faeed21b
|
fix(vkernel): THREAD_CREATE 改用户态线程 - 独立用户栈与内核栈经 drop_to_user_mode 进 Ring3;调度器按线程切 TSS.RSP0/gs[8];同步 _thread_entry 硬编码偏移并加 fail-fast 自检
|
2026-10-15 16:45:09 +08:00 |
|
TermiNexus
|
f8eed7f300
|
fix(vkernel): GS 归一化的说明改为 asm 外的英文注释(本编译器 asm 模板不接受注释/符号名)
上一版把说明写进 __asm__ 模板里:① 编译器会扫描 asm 模板中的符号名(注释里的 _per_cpu 也被判为需导出而报 TypeError);② 本编译器的 __asm__ 模板本身不接受注释。现把注释全部移出 asm,并改用英文;汇编指令本体不变(cli → mov rsp,ksp → 按 GS_BASE 是否为 0 决定 swapgs → 压 iretq 帧)。
|
2026-10-14 22:15:26 +08:00 |
|
TermiNexus
|
1f2faf0db8
|
fix(vkernel): 进用户态前归一化 GS_BASE,修线程从用户态定时器 ISR 切出后 GS 状态错乱导致的三重故障
根因:线程可能是在**别人的用户态定时器 ISR 里**被 _yield 切过来的(timer 路径不经 isrCommonhandler 的 GS 恢复,且切换后 ISR 出口的 swapgs 永不执行),此时 GS_BASE 仍 = _per_cpu。带着这个状态跑用户代码 ⇒ app 第一条 syscall 再 swapgs 就反了 ⇒ mov rsp,gs:[0x8] 读到地址 0x8 的垃圾 ⇒ rsp 变垃圾 ⇒ push 触发 #PF 时异常帧也压不进去 ⇒ 三重故障(QEMU 消失、零输出、ISR 入口探针都照不到)。现场:pid=1(Terminal) 正常、pid=2 起静默三崩。修复:drop_to_user_mode 在 iretq 前按 GS_BASE 是否为 0 决定是否 swapgs(幂等),保证用户代码一律以 GS_BASE=0 运行。
|
2026-10-14 22:11:19 +08:00 |
|
TermiNexus
|
4289d9b190
|
fix(vkernel/intr): GDT/STAR 根治 —— 用户代码段移到第5项(0x28)、TSS 移 0x30,统一用户 CS=0x2B
- 背景:syscall 返回走 sysretq,硬件按 STAR[63:48]=0x1B 算 CS=+16=0x2B、SS=+8=0x23;而 GDT 原来把用户代码放在第 3 项(0x18)、第 5 项(0x28)放 TSS ⇒ app 实际是“拿 TSS 描述符当代码段”在跑(QEMU 不校验 SYSRET 目标描述符类型才没暴露;严格实现会在 sysretq 处 #GP)
- gdt.vp:GDT 扩到 8 项、limit 0x37→0x3F;新增 gdt[5]=用户代码段(0xFA/0x20,与 gdt[3] 同属性;第 3 项保留为兼容镜像);TSS 改放第 6/7 项(setTSS64(6,…) = 选择子 0x30),ltr 改用 0x30;USER_CODE_SEG→0x28、TSS_SEG→0x30
- process.vp:drop_to_user_mode 首次进用户态的 iretq 也改用 CS=0x2B(与 sysretq 一致,两条入口不再产生不同 CS)
- isr.s:用户返回校验同时接受 0x2B/0x1B(0x1B 仅作兼容镜像兜底);上一个 commit 已修“只认 0x1B 导致用户态一被中断就 cli;hlt 假死”
|
2026-10-14 19:07:54 +08:00 |
|
TermiNexus
|
5b4bab59cc
|
chore(ViperOS): 合并落库内核侧在途改动并移除 vpsdk wiki 拷贝
VKernel / vpsdk / Apps / Libs 共 30 个源文件:内核与 SDK 侧的新语法适配及编译修正(含 bootinfo.vp / main.vp 位宽改 uint64、gfx.vp 前向引用改指针、devfs.vp 指针解引用赋值、elf.vp 跨模块函数取值等)。删除 vpsdk/wiki/*.md(14 文件,约 -8100 行):与仓库根 wiki 重复的拷贝,统一以根 wiki 为唯一来源。
|
2026-10-07 19:04:33 +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
|
6a54373c26
|
fix(vkernel): 补 ISR/调度 call 的 rsi/rdi clobber、rep stosb 内存 clobber,修 mm 别名笔误
N8 paging.vp:AllocPage 的 rep stosb 写 4096B 补 CLOBBER_MEMORY,避免优化器
重排/消除其前后的内存读写
N9 coroutine.vp / sched.vp:_coro_entry/_thread_entry 的 call rax 补
CLOBBER_RSI/CLOBBER_RDI(RSP 由 sub rsp,8 / add rsp,8 配对抵消,无需声明)
N15 process.vp:mm_mm.malloc/free → mm.malloc/free(该文件只有 import mm.mm as mm)
N16 elf.vp:读 RAX 的 c.Asm 补 CLOBBER_RAX([DIAG] 探针)
N20 elf.vp / idt.vp(12 处):外部 ELF 入口 / ISR handler 的 call 补
CLOBBER_RSI/CLOBBER_RDI(被调方破坏全部 caller-saved 寄存器)
|
2026-09-11 17:40:21 +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
|
b887d3d9c2
|
更新,部分功能可用
|
2026-08-27 09:47:47 +08:00 |
|
TermiNexus
|
a621b0d264
|
debug(paging,process,fat32): 定位 BSS 全局内存破坏——clone AllocPage 失败打印 pt_pool_raw/pt_pool_used,create_process malloc 返回实际值(mm 成功但调用方收 None),dir_find 失败 dump win 缓冲内容
|
2026-08-27 01:02:39 +08:00 |
|
TermiNexus
|
a8f7c0b0b3
|
debug(sched): create_thread 打印 tid/func/stack 实际值,定位线程首次调度跳栈 #UD(rip 在栈区域)根因
|
2026-08-26 23:30:28 +08:00 |
|
TermiNexus
|
9d786dd5b1
|
self 传参的相关修复
|
2026-07-30 17:30:47 +08:00 |
|
TermiNexus
|
49d074e487
|
通过插件的静态推导修复了一些错误
|
2026-07-30 17:28:27 +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 |
|