9.7 KiB
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)常驻内存。
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)
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 三条通信通道
- 共享内存ring(异步双向)
- VMCALL hypercall(同步请求/响应)
- 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实机验证 | ❌ |