Skip to content
GitLab
Projects Groups Topics Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in
  • O OSKernel2026-StellarOS
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributor statistics
    • Graph
    • Compare revisions
  • Issues 0
    • Issues 0
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 0
    • Merge requests 0
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Package Registry
    • Terraform modules
  • Monitor
    • Monitor
    • Metrics
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • StellarOS
  • OSKernel2026-StellarOS
  • Merge requests
  • !34

### LTP basic 28/28 全通过

  • Review changes

  • Download
  • Patches
  • Plain diff
Merged StellarOS requested to merge fix/basic into busybox/ltp May 15, 2026
  • Overview 1
  • Commits 2
  • Pipelines 0
  • Changes 17

Created by: hjg0603

将赛事 oscomp/testsuits-for-oskernel 的 sdcard-rv 镜像换上后,basic 套件从「只能跑通第一个 brk,第二个测例必挂」推进到 28/28 全部通过。本次共定位 4 个内核 bug + 1 个 initproc 测试驱动配置问题。

Task::fork 缺失 a0 归零导致第二个测例必挂(task/task.rs、syscall/process.rs):

  • 旧 sys_clone 存在 fast-path:flags=17 且其它 4 个参数全 0 时走 Task::fork;但 Task::fork 漏写 trap_cx.x[10] = 0,子进程 fork() 偶发返回父进程进 ecall 时 a0 残留值(=17)而不是 0
  • 子进程 if pid==0 分支判错,跳过 exec 直接去 wait,父子互等死锁
  • 是否触发取决于用户态调 fork() 时 a3/a4 寄存器残留是否恰好为 0,因此现象表现为「换顺序之后还是第二个挂」
  • 修法:删除 Task::fork 与 sys_clone fast-path,永远走 kernel_clone(已在第 446 行正确写入 trap_cx.x[10] = 0)

timer ISR 盲调 SBI legacy console_getchar 卡死整个 hart(fs/stdio.rs、fs/mod.rs、net/mod.rs):

  • poll_background_work() 在每次时钟中断都调 poll_console_input() → sbi_rt::legacy::console_getchar()
  • 老版 RustSBI-QEMU 0.2.0-alpha.2 在 -nographic 模式无输入时该 SBI 不立即返回,M 模式长时间不退出(QEMU monitor 五次采样 PC 均停在 firmware 0x80002d3a,mepc 指向 li a7,2; ecall,scause STIP 一直挂着)
  • 修法:新增 console_has_waiters(),仅当真有任务阻塞在 stdin 上时 timer ISR 才发起 SBI 补货

PipeRingBuffer 内联 64KB 数组撑爆 8KB 内核栈(fs/pipe.rs):

  • buf: [u8; PIPE_BUF_SIZE](65536 字节)使 PipeRingBuffer::new() 的返回值槽位落在调用方栈上,之后才由 Arc::new memcpy 到堆
  • 内核栈仅 2 页(8KB),sp 减 64KB 直接戳穿到非 canonical SV39 地址区域,触发 __alltraps_k 入口的 sd ra, 8(sp) 页错误 → CPU 重入 __alltraps_k → 再次 addi sp,-272; sd 再次错 → 无限递归 trap,hart 死锁
  • QEMU monitor dump 看到 sp=0xffffffa1ddcaa150(bit 38=0 但 bit 39=1,违反 SV39 canonical 要求)佐证
  • 修法:buf: [u8; N] → buf: Vec<u8>,用 vec![0u8; PIPE_BUF_SIZE] 直接堆分配,绕开栈中转

Pipe read/write lost-wakeup race(fs/pipe.rs):

  • 旧路径 drop(ring); self.waiters.readers.wait();,timer 抢占可在 drop ring 锁和 wait 入队之间切到 writer;writer 写完数据调 wake_one 时等待队列还是空,唤醒被丢,reader 永远等不到
  • 修法:改用 WaitQueue::wait_unless,在持 waiters 锁的同一临界区里重检条件并入队,原子化「检查 + 入队睡眠」(不是这次 hang 的直接原因,但确实修了一个潜在的丢唤醒)

initproc cwd 没切导致 fstat / open / read 三个 fail(user/src/lib.rs、user/src/bin/initproc.rs):

  • 这三个测例都用 ./text.txt 等相对路径取测试数据,实际文件在 /glibc/basic/text.txt
  • initproc 启动时 cwd 是 /,fork+exec 出来的 child 继承,于是 ./text.txt 解析成 /text.txt,open 返回 -2,测例首个 assert(fd > 0) 失败退出 -100
  • 修法:user_lib 新增 chdir() 封装(syscall 49 内核侧早有实现),initproc 进入测试循环前先 chdir("/glibc/basic")
Assignee
Assign to
Reviewers
Request review from
Time tracking
Source branch: fix/basic