Files
Deshab-OS/docs/兼容层设计.md
T
2026-07-31 13:53:49 +08:00

244 lines
9.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Deshab 兼容层设计文档
> Linux程序兼容层(双内核park-and-resume)与PE/EXE兼容层(UTSM内置加载器),以及Pacman生态方案。
---
## 1. 概述
Deshab无Linux syscall/动态链接器/Windows API,兼容走两条路线:
| 兼容层 | 目标 | 路线 | 类比 |
|--------|------|------|------|
| Linux兼容层 | Linux x86-64 ELF | UTSM作VMM运行Linux 6.6 guest,Deshab经IPC委托执行取回结果 | WSL |
| PE/EXE兼容层 | PE32+/PE32 | UTSM内置PE加载器+API shim+x86-32解释器,Ring0直接执行 | 极简Wine |
核心判断:pacman装的软件是Linux动态链接ELF,不可能在Deshab原生跑。正确模式:Linux guest内Arch+pacman→Deshab通过IPC委托Linux执行→结果显示回Deshab。
---
## 2. 双内核架构
### 2.1 park-and-resume模型
UTSM作VMM(VMX root),Linux 6.6 LTS作guest(VMX non-root)常驻内存。
```text
UTSM(Ring0) → linux_compat_service.exec() → 写EXEC_REQUEST到utsm_to_linux ring
→ linux_resume() → vmresume → Linux guest(daemon: RECV_MSG→fork+exec→pipe捕获输出
→ SEND_MSG STDOUT/STDERR/EXIT → ioctl(PARK)→HLT→VM-Exit)
← VM-Exit(HLT) → host推进RIP → 从linux_to_utsm ring读输出
```
- **park**:guest HLT→VM-Exit→host推进RIP+exit-to-host(`g_guest_parked=1`)
- **resume**:`linux_resume()`经vmresume唤醒parked guest
- guest cmdline须含`nohlt idle=poll`:防止内核idle的HLT误触发park
### 2.2 组件清单
| 组件 | 文件 |
|------|------|
| VMM | `vmm.c/vmx.c/ept.c`, `vmexit.c/vmexit_asm.S` |
| Linux装载 | `linux_loader.c/linux_boot.c` |
| 唤醒 | `linux_resume.c` |
| 兼容服务 | `linux_compat.c`+`linux_compat.h` |
| IPC | `CODE/utsm-ipc/ipc_proto.h` |
| virtio后端 | `virtio_mmio.c/virtio_blk.c/virtio_net.c` |
| Linux侧驱动 | `CODE/linux/patches/utsm_hcall.c` |
| exec daemon | `CODE/linux/initramfs/bin/utsm_exec_daemon.c` |
### 2.3 guest构建产物
| 产物 | 位置 | 说明 |
|------|------|------|
| bzImage | `SYSTEM/boot/linux-bzImage` | Limine boot module |
| initramfs | `SYSTEM/boot/linux-initrd.img` | phase-1最小用户态(init+daemon) |
| Arch rootfs | `SYSTEM/boot/linux-rootfs.img` | virtio-blk /dev/vdb,含pacman+国内镜像 |
---
## 3. Guest GPA内存布局
定义于`CODE/UTSM/include/utsm/linux_loader.h`:
| GPA范围 | 用途 |
|----------|------|
| 0x00000000–0x003FFFFF | UTSM保留 |
| 0x00400000 | boot_params(4KB) |
| 0x00500000 | 内核cmdline(≤4096B) |
| 0x00600000/0x00700000/0x00800000 | guest GDT/页表/栈 |
| 0x01000000–0x02FFFFFF | Linux内核镜像(2MB对齐) |
| 0x03000000–0x03FFFFFF | initrd |
| **0x04000000–0x040FFFFF** | **IPC共享内存(1MB)** |
| 0x05000000+ | Linux通用RAM |
| 0xF4000000/0xF4001000/0xF4002000 | virtio-mmio blk(IRQ5)/net(IRQ6)/rootfs(IRQ7) |
virtio-mmio设备区EPT故意不映射→EPT violation→vmexit路由到后端模拟。guest经cmdline `virtio_mmio.device=4K@<gpa>:<irq>`发现设备。
guest cmdline:`console=ttyS0,115200 earlyprintk=serial nokaslr no_timer_check loglevel=7 nohlt idle=poll noapic nolapic nosmp virtio_mmio.device=4K@0xF4000000:5 virtio_mmio.device=4K@0xF4001000:6 virtio_mmio.device=4K@0xF4002000:7`
---
## 4. VMCS与VM-Exit处理
- VMCS不保存guest GPR,`vmexit_asm.S`保存16个GPR到`g_guest_regs`,vmresume前恢复
- VMCALL约定:a0=rdi, a1=rsi, a2=rdx,返回值写g_guest_regs.rax
- host恢复点:`g_saved_host_rsp/g_saved_return_rip/g_guest_terminated/g_last_exit_reason`(须非static全局变量)
已处理退出原因:
| Exit reason | 处理 |
|-------------|------|
| HLT | Linux→park(推进RIP);自检→terminate |
| EPT_VIOLATION | GPA在virtio-mmio区→模拟;否则EPT动态映射 |
| CPUID | 直通+屏蔽VMX/hypervisor位 |
| IO_INSTRUCTION | 端口I/O模拟 |
| INTERRUPT_WINDOW | 注入待决虚拟IRQ |
| VMX_PREEMPTION_TIMER | 周期调virtio_net_poll()填充RX buffer |
| VMCALL | hypercall分发 |
---
## 5. IPC协议
唯一定义在`CODE/utsm-ipc/ipc_proto.h`(`__UTSM_KERNEL__`/`__KERNEL__`条件包含)。
### 5.1 共享内存布局(GPA 0x04000000, 1MB, packed)
```text
0x04000000 utsm_ipc_shm_header 64B(magic "UTSMHC\0\0"+version+握手位)
0x04000040 utsm_to_linux ring 16400B(UTSM写,Linux读)
0x04004050 linux_to_utsm ring 16400B(Linux写,UTSM读)
0x04008060 payload_pool 1015712B(批量数据缓冲)
```
每ring:64槽×256B消息(16B头+240B inline data)。单生产者单消费者,head/tail volatile+内存屏障。
### 5.2 三条通信通道
1. 共享内存ring(异步双向)
2. VMCALL hypercall(同步请求/响应)
3. IPI通知(UTSM→Linux经guest IRQ注入)
### 5.3 消息类型
| 类型 | 值 | 方向/说明 |
|------|----|-----------|
| HELLO/HELLO_ACK | 1/2 | 握手 |
| PING/PONG | 3/4 | 连通性 |
| EXEC_REQUEST | 16 | UTSM→Linux: ipc_exec_request{argc,flags,path[128],argv_blob[96]} |
| EXEC_STDOUT/STDERR | 17/18 | Linux→UTSM: 裸字节流分块 |
| EXEC_EXIT | 19 | Linux→UTSM: exit_code |
| EXEC_READY | 20 | Linux→UTSM: daemon就绪 |
| FILE_LIST/READ/WRITE_REQUEST | 24/25/27 | UTSM→Linux: 文件操作 |
| FILE_RESPONSE | 26 | Linux→UTSM: status+data_len+total_size |
### 5.4 hypercall操作
| op | 值 | 说明 |
|----|----|------|
| PING/HELLO | 0x0001/0x0002 | 连通性 |
| SHM_INFO | 0x0010 | 查询共享内存GPA+size |
| CAP_VALIDATE | 0x0020 | capability校验 |
| UTRW_READ/WRITE | 0x0030/0x0031 | 封缄内存读写 |
| DRR_CHECKPOINT | 0x0040 | 触发checkpoint |
| CONSOLE_WRITE/READ | 0x0050/0x0051 | 串口控制台 |
| **FILE_READ** | 0x0060 | 读UTSM FAT32文件到payload_pool(a0=文件名GPA,a1=偏移,a2=最大字节;RAX低20位=暂存字节,高位=总大小) |
| **FILE_WRITE** | 0x0061 | payload_pool写为FAT32文件(整文件替换) |
单文件≤256KB;payload_pool为单写者通道,禁止并发。
### 5.5 文件传输协议
- 读/列目录:UTSM写请求→linux_resume→daemon opendir/readdir或open/pread→数据写进payload_pool→FILE_RESPONSE→HLT park
- 写:UTSM预摆数据进payload_pool→daemon读出pwrite(offset 0以O_TRUNC打开)
- payload_pool≈1MB,单次往返最多~1MB,更大文件按递增file_offset循环
- 状态码:OK=0, NOENT, IO, NOTDIR, ISDIR, PERM, INVAL, NOSPC
---
## 6. virtio-mmio设备模拟
Virtio Spec 1.1 §4.2,32位寄存器。框架`virtio_mmio.c`,后端`virtio_blk.c`/`virtio_net.c`。
- guest访问设备GPA→EPT violation→handle_virtio_mmio_access→按GPA定位设备+按偏移模拟寄存器
- 后端注册表`struct virtio_backend{device_id,gpa_base,irq,num_queues,queue_size,device_features,config_len,read_config,queue_notify,reset}`
- virtqueue split ring(desc 16B/avail/used)
- `virtio_gpa_to_host()`:EPT翻译GPA→HPA+HHDM offset
- 中断:置INTERRUPT_STATUS bit0+注入虚拟IRQ(blk→5,net→6,rootfs→7, vector=0x30+irq)
- net RX异步路径:VMX preemption timer周期调virtio_net_poll()填充guest RX buffer+注入IRQ
- blk后端已支撑guest挂载Arch rootfs(/dev/vdb)
---
## 7. Linux兼容层服务接口
`linux_compat_service`(magic "LNXCOMP\0")经`dsk_boot_context.reserved[5]`暴露:
| 接口 | 说明 |
|------|------|
| is_available() | guest已park+IPC就绪 |
| exec(path,argc,argv,stdout_buf,cap,len,exit_code) | 执行Linux程序取回stdout/exit_code |
| file_list/read/write(path,...) | 列目录/分块读/分块写Linux文件 |
| file_pull/push(linux_path,fat32_name,...) | Linux文件↔UTSM FAT32根目录(≤256KB) |
| status(buf,cap) | guest状态字符串 |
shell命令:`dsl <prog> [args]`(Tab可补全Linux程序名)、`dsl push/pull`、`dsl ls [path]`、`dsl cat <path>`
---
## 8. Linux guest侧组件
**utsm_hcall驱动**:VMCALL发起hypercall;/dev/utsm ioctl: RECV_MSG/SEND_MSG/PARK/GET_READY/WRITE_POOL/READ_POOL
**exec daemon**(PID 2):启动→发EXEC_READY→ioctl(PARK)→HLT;循环:vmresume唤醒→RECV_MSG→处理(EXEC_REQUEST:fork+exec+pipe; FILE_*:opendir/open/pread/pwrite)→ioctl(PARK)
---
## 9. PE/EXE兼容层
四组件经`dsk_boot_context.reserved[4]`暴露`pe_service`(magic "PESVC\0\0",接口load/run/unload):
| 组件 | 职责 |
|------|------|
| pe_loader.c | DOS/NT头校验+节区映射+重定位+import表解析 |
| pe_shim.c | Windows API shim(ms_abi包装)+IAT填充 |
| x86emu32.c | x86-32解释器(PE32执行引擎) |
| pe_service.c | 服务装配+执行策略 |
执行策略:
- **PE32+**:重定位加载→IAT填ms_abi shim→Ring0原生执行;ExitProcess经__builtin_longjmp跳回
- **PE32**:preferred_base直接加载(64KB栈+256KB堆)+IAT填合成地址(0x00010000|shim_idx)→x86emu32解释执行。约束:镜像≤64MB, preferred_base≤0x10000000, IAT≤256项
安全方向:PE shim白名单+IAT拦截审计。
---
## 10. Pacman五阶段方案
| 阶段 | 内容 | 状态 |
|------|------|------|
| 1. Linux guest跑起来 | virtio-blk/net+initramfs/rootfs+EPT动态映射 | ✅ |
| 2. guest内Arch+pacman | Arch bootstrap rootfs+国内mirrorlist | ✅(网络下载待联网验证) |
| 3. UTSM↔Linux文件传输IPC | FILE_READ/WRITE hypercall+ring分块+shell接入 | ✅(代码全链路就绪) |
| 4. shell命令委托执行 | IPC exec(16–20)+daemon fork/exec | ✅(全链路已验证) |
| 5. desktop集成 | app_descriptor.linux_cmd+LINUXAPP.CNF | ✅ |
**最大遗留项:VMX实机验证**(需嵌套虚拟化环境)。WHPX不支持嵌套VMX,已通过vmx_truly_available()检测+QEMU -cpu qemu64,-vmx规避,无VMX时linux命令优雅降级。
---
## 11. 实现状态总览
| 能力 | 状态 |
|------|------|
| VMM(VMX/EPT/VMCS/VM-Exit) | ✅ |
| Linux guest装载与启动 | ✅ |
| park-and-resume | ✅ |
| IPC(ring+hypercall+payload_pool) | ✅ |
| virtio-mmio blk/rootfs | ✅ |
| virtio-mmio net | 🔶(后端框架+RX poll) |
| linux_compat_service | ✅ |
| PE32+/PE32执行 | ✅ |
| VMX实机验证 | ❌ |