Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
212 changes: 104 additions & 108 deletions docs/ABI.md

Large diffs are not rendered by default.

16 changes: 8 additions & 8 deletions docs/ABI_MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ libc,但新应用不得增加对私有硬件入口的依赖。Linux 兼容范

| 现有接口/实现 | 目标接口 | 当前状态 | 说明 |
| --- | --- | --- | --- |
| 文件读写、目录和进程 | POSIX libc + Linux syscall | 进行中 | 标准 `stat/fstat/lstat` 已返回完整 POSIX `struct stat`;第一方内部查询暂用显式命名的 `leonos_*_legacy`;`openat(AT_FDCWD)` 已接入,目录 fd 相对解析仍待完成 |
| 文件读写、目录和进程 | POSIX libc + Linux syscall | 进行中 | 标准 `stat/fstat/lstat` 已返回完整 POSIX `struct stat`;第一方内部查询暂用显式命名的 `leonos_*_legacy`;`openat(AT_FDCWD)` 已接入,目录 fd 相对解析已实现(非绝对路径经 `dirfd` 解析) |
| `leonos_pty_*` 和私有 PTY ioctl | Unix98 PTY + `termios`/`TIOCGWINSZ` | 进行中 | libc 已提供 `posix_openpt/openpty/forkpty`;新的程序应使用 `/dev/ptmx`、`/dev/pts/<id>`、`/dev/tty`,旧入口仅作过渡 |
| `leonos_socket_*` 网络包装 | POSIX socket fd | 进行中 | `AF_UNIX/SOCK_STREAM` 已接入 socket syscall、FD 生命周期和 poll;IPv4 网络仍由过渡层驱动 |
| `LEONOS_GUI_IOCTL_*` | 版本化 GUI IPC + SDK GUI 库 | 设计完成,迁移中 | GUI 不属于 POSIX,内核 ioctl 仅作为过渡实现 |
| `leonos_socket_*` 网络包装 | POSIX socket fd | 基础完成 | `AF_UNIX/SOCK_STREAM` 与 `AF_INET` TCP/UDP 均已接入 socket syscall、FD 生命周期和 poll;`leonos_socket_*` 兼容包装直接使用真实 socket fd |
| `LEONOS_GUI_IOCTL_*` | 版本化 GUI IPC + SDK GUI 库 | 已完成 | 私有 GUI ioctl 已全部删除;应用经 libc `wind.c` 走 windowd AF_UNIX 协议(含外观、窗口、事件),帧缓冲合成使用 `/dev/fb0` 的 `LEONOS_FBIOBLIT` |
| `leonos_gpu_*`/`LEONOS_IOCTL_GPU_*`(fd 3) | 版本化 GPU SDK + 设备/服务通道 | 迁移中 | 采用方案 A:`leonos_gpu_*` 仅为 fd 3 过渡入口;新 SDK 使用版本化 GPU 客户端 API,删除里程碑见阶段状态 |
| 帧缓冲私有 ioctl | Linux fbdev UAPI (`/dev/fb0`) | 基础完成 | `/dev/fb0` 支持 mmap 以及 `FBIOGET_VSCREENINFO`、`FBIOGET_FSCREENINFO`、`FBIOPUT_VSCREENINFO`;绘制扩展仍由 GUI 服务负责 |
| 原始键盘和鼠标输入 | evdev (`/dev/input/event*`) | 基础完成 | `/dev/input/event0` 是键盘、`event1` 是鼠标;独立 FD 游标支持 `read`、`O_NONBLOCK`、`poll` 和常用 `EVIOC*` 查询 |
| 输入法管理私有 ioctl | 版本化 GUI 文本输入服务 | 迁移中 | 输入法不是硬件事件设备;过渡期改走 `/dev/input-method`,不再借用 `event0`,后续移入 GUI Unix socket 协议 |
| 输入法管理私有 ioctl | 版本化 GUI 文本输入服务 | 基础完成 | 输入法不是硬件事件设备;私有 ioctl 与过渡节点 `/dev/input-method` 均已删除,libc 改走 imd 守护进程的 `/run/leonos/input-method.sock` Unix socket |
| 音频私有 ioctl | OSS `/dev/dsp` | 基础完成 | 16-bit little-endian stereo playback,首版不引入 ALSA ABI |
| 磁盘/分区私有 ioctl | `/dev/*` 块设备 + Linux 风格 ioctl | 基础完成 | BusyBox、installer、gptinit 和 diskmgr 使用 `/dev/diskN[pN]`、`BLK*`、原始对齐 I/O 与 `mount(2)`;旧公开 ioctl 已移除 |
| `leonos_device_list` | `/dev` 枚举、`stat`、设备服务 IPC | 进行中 | `/dev` devfs 已提供稳定节点,设备列表 ioctl 待淘汰 |
| 私有 signal ioctl | `rt_sigaction`/`rt_sigprocmask` | 进行中 | 当前只完整支持默认/忽略处置,用户 handler frame 仍待实现 |
| `leonos_device_list` | `/dev` 枚举、`stat`、设备服务 IPC | 已完成 | `/dev` devfs 提供稳定节点;设备列表 ioctl 已删除,`leonos_device_list()` 走 devmand AF_UNIX 协议(device-agent 服务) |
| 私有 signal ioctl | `rt_sigaction`/`rt_sigprocmask` | 基础完成 | 用户 handler frame 已实现(`signal_setup_frame` 构造 `linux_rt_sigframe`,`rt_sigreturn` 恢复现场,返回用户态前投递 pending signal) |

## 统一 UAPI

Expand Down Expand Up @@ -56,7 +56,7 @@ libc,但新应用不得增加对私有硬件入口的依赖。Linux 兼容范
- [x] Unix98 PTY 基础 master/slave fd、标准 winsize/termios ioctl
- [x] POSIX `stat/fstat/lstat` 结构和错误语义,保留显式 legacy 查询入口
- [x] `/dev/fb0` 基础 Linux fbdev UAPI 和 framebuffer mmap
- [ ] `rt_sig*` 用户 handler frame 和完整 Unix98 PTY hangup 语义
- [x] `rt_sig*` 用户 handler frame、`rt_sigreturn` 恢复和 Unix98 PTY hangup(master 关闭挂断、drain 后 EOF、`TIOCSCTTY` 会话规则)
- [x] evdev `/dev/input/event*` 原始读写、非阻塞、`poll` 和基础 `EVIOC*` 查询
- [ ] evdev 独占抓取、热插拔和完整能力/状态位图
- [x] OSS `/dev/dsp` 音频设备接口:`SNDCTL_DSP_SETFMT`、`CHANNELS`、`SPEED`、能力/缓冲区查询、非阻塞写入和 `poll(POLLOUT)`
Expand Down Expand Up @@ -92,5 +92,5 @@ IPv4 网络仍使用现有网络服务过渡接口,待后续迁移。
`SNDCTL_DSP_GETODELAY` 和 `SNDCTL_DSP_NONBLOCK` 已实现。应用应通过
`write` 提交 PCM,并用 `poll(POLLOUT)` 或 `EAGAIN` 处理队列饱和。

`/dev/audio` 与 `/dev/audio0` 仅用于仍使用旧私有音频 ioctl 的二进制兼容,
`/dev/audio` 仅用于二进制兼容,
新应用和 SDK 示例必须使用 `<linux/soundcard.h>` 与 `/dev/dsp`。
14 changes: 7 additions & 7 deletions docs/APK_PREPARATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,17 +114,17 @@ command help; this does not change transaction semantics.
The default local signing key is generated once at
`~/.local/share/leonos/apk-signing/key.pem`, mode 0600, outside the repository.
Only its public key enters the image. Preserve this private key for subsequent
updates of images built with it. `LEONOS_APK_SIGNING_KEY` can select a maintained
updates of images built with it. `APK_SIGNING_KEY` can select a maintained
release key. A new key is not automatically trusted by an installed system.
Changing the selected key intentionally requires a separate authenticated key
rotation or a fresh install; the updater never imports the media's key into
the target trust store.

## Build and installation

`python3 build.py run apk-root` builds the normal staging payload, makes signed
`make apk-repo` builds the normal staging payload, makes signed
APKv3 packages/index with upstream `apk mkpkg/mkndx`, and installs them into
`build/apk/root` using upstream `apk add`. When available, host user namespaces
`$(O)/rootfs/managed` using upstream `apk add`. When available, host user namespaces
map ownership to root without modifying the host root or requiring sudo. On
runners that prohibit user namespaces, the build uses the installed `fakeroot`
compatibility path instead. Normal image targets depend on this managed root.
Expand Down Expand Up @@ -265,16 +265,16 @@ program. These are local-fixture results, not promises about public mirror or
VMware speeds. See `docs/NETWORK_STATUS_2026-09-13.md` for evidence and scope.

```sh
python3 build.py run test-apk-distribution
make test-apk
python3 tools/test_apk_qemu.py
python3 tools/test_apk_qemu.py --testing-only
python3 tools/test_terminal.py
python3 tools/test_linux_ioctl_cloexec.py
# Requires current kernel, app:terminal and apk-root build outputs.
# Requires current kernel, terminal app and apk-repo build outputs.
python3 tools/test_hyfetch_qemu.py
python3 tools/test_alpine_runtime_qemu.py
python3 tools/test_apk_qemu.py --package-cache build/alpine-runtime/cache
python3 build.py run images-iso
python3 tools/test_apk_qemu.py --package-cache out/x86_64/release/packages/apk/cache
make iso
python3 tools/test_apk_layout.py --images
```

Expand Down
1 change: 1 addition & 0 deletions docs/APP_REGISTRY.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ exec=notepad.elf
icon=notepad.bmp
entry=1
terminal=0
system=1
hidden=0
open_with=1
extensions=.txt,.md,.log
Expand Down
2 changes: 1 addition & 1 deletion docs/BOOT_AND_INTEGRITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ The installer payload is built from the same matched runtime staging tree:
- `build/esp` contains the loader, kernel, resources, config, and
userland applications for the installed system.
- `tools/make_installer_root.py` splits `build/esp` into `install/esp` (the
FAT32 ESP boot subset) and `install/root` (the exFAT runtime root) inside
FAT32 ESP boot subset) and `install/root` (the ext2 runtime root) inside
`build/install/root.fat`.
- `tools/make_installer_iso.py` stages top-level installer copies of
`boot/loader.elf`, `system/kernel.sys`, and
Expand Down
5 changes: 3 additions & 2 deletions docs/BROWSER.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ Upstream litehtml is checked out as:

- submodule path: `third_party/litehtml`
- upstream URL: `https://github.com/litehtml/litehtml.git`
- current recorded commit: `932439c91afb04dbce30903673292e3bf2da01dc`
- current recorded commit: `b9e89f0b9494ff9a5f008800af35503efabddf59`

The current upstream tree is C++ and depends heavily on STL types and library
facilities such as strings, vectors, maps, smart pointers, variants, algorithms,
Expand All @@ -84,7 +84,8 @@ should remain useful when the full C++ litehtml container becomes available.

To integrate real litehtml, do these in order:

1. Add a userland C++ build mode in `tools/gen_ninja.py`.
1. Add a userland C++ build mode to the GNU Make build system
(`mk/userland.mk` and the component graph).
2. Provide a minimal C++ runtime surface for constructors, destructors,
allocation, exceptions-disabled builds, and required ABI helpers.
3. Port or provide an STL subset/libc++ profile that satisfies litehtml.
Expand Down
8 changes: 4 additions & 4 deletions docs/BUILDSYSTEM.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ ext2fs 头文件/库和镜像工具。fetch 校验锁定摘要,是唯一联网
默认 `O=out/x86_64/release`;`ARCH=x86_64 PROFILE=debug|release` 选择配置隔离。
`make O=out/custom menuconfig` 编辑该树 `config/.config`;olddefconfig 保留设置并补充新项,
defconfig 重置为 configs/default.conf。可以复制 `.config` 保存配置,再 olddefconfig。
Kconfig 与 configs/components.toml 区分 BUILD、IMAGE、ENTRY、SDK、API;required 组件强制开启。
Kconfig 菜单(Build、Image defaults 等)决定默认配置,configs/components.toml 用 stage/entry/sdk/api 字段区分组件归属;required 组件强制开启。

生成文件只写 O。`SOURCE_DATE_EPOCH` 默认为提交时间,仅用于时间元数据与可复现打包;
版本为 `major.minor.patch`,没有构建号覆盖或计数器,提交身份另存 LEONOS_SOURCE_ID。

| 目标 | 输出 |
| --- | --- |
| kernel / loader / drivers | generated/system、generated/drivers、loader |
| kernel / loader / drivers | generated/system、generated/boot、generated/drivers |
| runtime / userland / leonos-pam / leonos-upstream | 运行库、应用、独立上游安装树 |
| sdk / musl-sdk | packages/LeonOS4-Developer-SDK.zip、leonos-musl-sdk.tar.gz |
| rootfs-raw / rootfs / apk-repo | rootfs/raw、managed、manifest.json;packages/apk/repository |
Expand Down Expand Up @@ -61,7 +61,7 @@ SDK 的可选头/库由 SDK 选择控制,不从旧 devtools 生成物偷取。

APK 使用上游 apk 的真实 mkpkg/mkndx/add,包含数据库和签名。
默认密钥为 `~/.local/share/leonos/apk-signing/key.pem`(0600),可用 APK_SIGNING_KEY 指定。
新版本 `1.<SOURCE_DATE_EPOCH>.<content-id>-r0` 排在旧 `0.<time_ns>-r0` 之后。
默认版本号 `2.<SOURCE_DATE_EPOCH>-r0` 排在旧 gen-1/gen-0 媒体之后。
正式发行需要递增 epoch 或显式递增 APK_BUILD_VERSION;同一提交的脏工作区不保证内容哈希排序。
本地 world 请求保持未锁定,升级可替换系统包;外部包与受保护配置保留。

Expand All @@ -74,7 +74,7 @@ APK 使用上游 apk 的真实 mkpkg/mkndx/add,包含数据库和签名。
- test:C 单元测试及 ASan/UBSan、Shell 构建契约。
- test-long:生产 execve、并行/中断恢复、缺失 stage 恢复;需要较多磁盘临时空间。
- test-legacy:明确选择的既有 Python OS 主机回归,不参与生产构建。
- test-smoke:三种介质的真实 QEMU 启动;必须出现 kernel boot complete 与 PID 1 标记。
- test-smoke:三种介质的真实 QEMU 启动;必须出现 `[ntclks] boot complete:` 与 `[ntclks] PID 1 path=` 标记。

可用 `TMPDIR=$PWD/out/test-tmp` 避免 tmpfs 太小。结果以 verification.md 最新记录为准;
生成镜像或通过主机测试均不能替代来宾安装/升级验收。历史参考 Python 的保留边界见 legacy-removal.md。
23 changes: 12 additions & 11 deletions docs/BUILD_AND_INSTALLER.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,27 +135,28 @@ runtime `/etc/leonos/license.conf` server override.

## Main outputs

Common build outputs:
Common build outputs (under `$(O)`, default `out/x86_64/release`):

- `build/images/leonos4.vmdk`
- `build/images/leonos4.iso`
- `build/images/leonos4-installer.iso`
- `build/install/root.fat`
- `build/images/esp.fat`
- `build/images/root.ext2` (default; FAT/exFAT cannot represent the current real symlinks)
- `images/leonos4.vmdk` / `images/leonos4.raw`
- `images/leonos4-live.iso`
- `images/leonos4-installer.iso`
- `images/installer-root.ext2` (historically `install/root.fat`)
- `images/root.ext2` (Live / disk root; default ext2 because FAT/exFAT cannot represent the current real symlinks)
- `stage/esp` (ESP staging directory; esp.fat is generated from it during ISO/VMDK assembly)

The common system staging tree is:

- `build/esp`
- `stage/esp`

It contains the Alpine-shaped root tree (`bin/`, `sbin/`, `lib/`, `usr/`,
`etc/leonos/`, `var/lib/leonos/`, `opt/`) plus the ESP-only loader and kernel
under `leonos/`. Help documents live in
`usr/share/doc/leonos/`; all application packages live in
`usr/lib/leonos/apps/`.
Vim and ncurses are enabled by default. `python3 build.py run vim` builds the
unmodified static Linux musl Vim and its ncurses dependency from pinned
submodules. Both `image-vmdk` and `installer` package Vim's runtime and the
Vim and ncurses are enabled by default. Vim now arrives as the unmodified
Alpine `vim` APK (pinned in `configs/dependencies.lock.json`), and ncurses is
built from the pinned submodule via `make upstream-ncurses`. Both `image-vmdk` and
`installer` package Vim's runtime and the
ncurses terminfo database. The ncurses tools also embed fallback descriptions
for LeonOS terminal types (`xterm`, `xterm-256color`, `linux`, `vt100`, `ansi`,
`screen`, and `screen-256color`), so `clear`, `tput`, and Vim remain usable if
Expand Down
21 changes: 21 additions & 0 deletions docs/DESKTOP_PERFORMANCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,27 @@ host scheduling, the selected virtual GPU, and application rendering still
determine the observed rate. `glxgears`' counter measures submitted frames and
must not be used alone as scanout evidence.

## 2026-09-24: asynchronous present

The legacy `framebuffer_present_region` fallback path always finished by
calling `framebuffer_vmware_sync`, which rings the `VMWARE_SVGA_REG_SYNC`
doorbell **and** spins reading `SVGA_REG_BUSY` until the host has drained the
FIFO. Because `LEONOS_FBIOBLIT` executes inside the kernel's global execution
transaction with local interrupts masked, that busy-wait pinned one core per
frame and serialised every other core's syscall behind the same ticket lock.
Under multi-core desktop load the loop was the dominant cost of a compositor
present and the visible cause of CPU-0 saturation when running Doom or a
Terminal repaint burst.

`framebuffer_present_region` now publishes the update and only rings the
doorbell (a new `framebuffer_vmware_kick` helper, non-blocking). The full
synchronous drain runs exclusively when `framebuffer_vmware_fifo_update`
reports FIFO backpressure, at which point waiting is required before retrying
the exact damage region. The newer SVGA backend already rings its own doorbell
inside `svga_fifo_packet_locked`, so the change strictly reduces the work done
under the execution lock on that path too. The global execution lock itself is
unchanged; reducing its scope across subsystems remains separate work.

For a compositor sample, create `/etc/leonos/desktop-profile` in the guest and
restart the desktop. It logs `[desktop-perf] frames=... elapsed_ms=...
paint_ms=... inputm_ms=...` every five seconds. The profile is disabled by
Expand Down
6 changes: 4 additions & 2 deletions docs/DRIVERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ All driver source code lives in the repository-root `drivers/` directory.

- `drivers/bootstrap`: console, framebuffer, VGA, EFI filesystem, storage, and
USB UHCI/HID implementations that are linked into `kernel.sys`.
- `drivers/mouse`, `drivers/serial`, and `drivers/e1000`: loadable driver
implementations built as `mouse.drv`, `serial.drv`, and `e1000.drv`.
- `drivers/mouse`, `drivers/serial`, `drivers/e1000`, `drivers/ac97`, and
`drivers/es1371`: loadable driver implementations built as `mouse.drv`,
`serial.drv`, `e1000.drv`, `ac97.drv`, and `es1371.drv` (see `DRIVER_NAMES`
in `mk/boot.mk`).

The normal image, normal ISO, installer runtime root, and installed ESP place
loadable modules directly in `/drivers`.
Expand Down
16 changes: 11 additions & 5 deletions docs/EEVDF_SCHEDULER.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,17 @@ LeonOS 当前时钟抢占为 100 Hz,所以请求长度选用 10 ms;没有宣
红黑树、PELT、调度组、CPU capacity/NUMA、CFS bandwidth、实时调度类或
`RUN_TO_PARITY` 特性。现有 Linux ABI 对不支持的调度策略继续拒绝。

当前生产代码在 `arch/x86_64/smp.c` 设置 `SMP_USER_SCHEDULER_ENABLED=0`,
原因是此前 AP 用户态并发存在任务所有权和回收崩溃风险。本次保留该限制。
**配置 2/4 个虚拟 CPU 不等于 LeonOS 已启用 2/4 个调度 CPU。**
每 CPU 选择和迁移有确定性的主机测试,但本次来宾测试实际 active CPU 为 1,
不能据此声称 AP 并发已验证;启用 AP 需要单独完成上下文切换/回收同步审计。
当前生产代码在 `arch/x86_64/smp.c` 已启用 AP 用户态调度:`smp_release_aps()` 在 BSP
完成首轮用户态 timer tick 之后置位 `smp_scheduler_started`,此后每个 AP 在
`smp_ap_entry` 的永久循环里调用 `userland_schedule_from_frame(NULL)` 并 `arch_enter_user_frame`
进入 Ring 3。配置 N 个 vCPU 时,N 个 CPU 都可以选取和运行用户任务。

**限制仍然存在**:设备 IRQ 目前全部路由到 BSP,AP 只接收 LAPIC 定时器 vector `0x40`
用于抢占(见 `smp_ap_entry` 里的注释"No device IRQ is routed to an AP");系统调用的
全局执行锁(`lock.c` 中的 `kernel_execution_lock_irqsave`)串行化几乎所有内核态服务,
所以多核有效并行度仍受这把 ticket 锁限制。拆分锁粒度或至少把设备 IRQ 分派到 AP 是
后续独立工作。每 CPU 选择和迁移有确定性的主机测试;启用 AP 前上下文切换/回收同步
审计已在 `smp_release_aps` 的"等待 BSP 完成首轮用户 tick"机制下补做。

## 验证

Expand Down
11 changes: 7 additions & 4 deletions docs/EXECUTION_LOCK.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@ QEMU 测试校验独立进程及共享地址空间线程的内存内容,并记
此前成功构建约 1468 秒,但本次后段同时生成安装 ISO,且旧记录计时范围不同,
所以不将两者视为严格的提速百分比测量。

后续 EEVDF 调度调查补充:上述 QEMU 配置虽为 2 vCPU,但来宾启动日志显示
`SMP topology CPUs=1 ... (AP scheduler disabled)`。因此上述来宾数据是双进程、
单实际调度 CPU 的测量,主要验证缺页路径与取消逐页强制调度的收益;
读侧真正重叠由主机并发锁测试覆盖,不能将该来宾结果称为多核并行收益。
EEVDF 后续调查补充:上述 QEMU 配置为 2 vCPU,且当前 `arch/x86_64/smp.c` 已经启用
AP 用户态调度(`smp_release_aps` 在 BSP 完成首轮用户 tick 后置位 `smp_scheduler_started`,
AP 从 `smp_ap_entry` 循环进入 Ring 3)。但**设备 IRQ 仍全部路由到 BSP,AP 只跑 LAPIC
定时抢占**;系统调用的全局执行锁 `kernel_execution_lock_irqsave` 是 FIFO ticket 锁
并在持锁/等锁期间关本核中断,所以两个"能跑用户任务"的 CPU 在跨核 syscall 上仍被
串行化。上述 8192-页缺页微基准主要在**取消逐页强制调度**这一层生效,读侧并发由
主机并发锁测试覆盖;不要把这些数据当作多核并行加速的量化证明。
Loading
Loading