Files
Deshab-OS/docs/上下文/Deshab Linux_EXE 兼容层开发.md
T
2026-07-31 13:53:49 +08:00

7.3 KiB
Raw Blame History

Deshab Linux/EXE 兼容层开发

需求

  • Linux 程序兼容层(依赖双内核架构,WSL 互操作模式)
  • EXE 兼容层直接写在 UTSM 里(PE32+ 64位原生 Ring0 执行 + PE32 32位 x86 解释器)
  • cmd.exe 编译到 SYSTEM/system/deshab64
  • 桌面命令行1: shell.elf(原生 + linux 命令运行 Linux 程序)
  • 桌面命令行2: cmd.elf(Windows 风格 + PE/EXE 兼容)

PE/EXE 兼容层(UTSM 内置)

核心文件

文件 职责
CODE/UTSM/pe/pe_loader.c / .h PE 解析、映射、重定位(R_X86_64_64/32/32S/PC32)、import 解析
CODE/UTSM/pe/pe_shim.c / .h Windows API shim(__attribute__((ms_abi)),__builtin_setjmp/__builtin_longjmp)
CODE/UTSM/pe/x86emu32.c / .h x86-32 解释器:支持 push/call/add esp/ret/mov/xor/ModRM 解码/IAT 拦截
CODE/UTSM/pe/pe_service.c 统一服务:pe_service_load/pe_service_run/pe_service_unload

PE 加载流程

  • PE32+: 原生 Ring0 执行,MS x64 ABI shim
  • PE32: x86emu32 解释器执行,preferred_base 加载(0x00400000),专用大缓冲区含栈和堆
  • pe_image_info 结构体返回加载信息(entry_point, image_base, image_size, is_pe32_plus)
  • 通过 dsk_boot_context.reserved[4] 暴露给 cmd.elf

关键结构

// pe.h - PE 服务接口
struct pe_service {
    int (*load)(const char *name, u8 **out_data, u64 *out_size, pe_image_info *info);
    int (*run)(u8 *data, u64 size, pe_image_info *info, int argc, char **argv);
    void (*unload)(u8 *data, u64 size, pe_image_info *info);
};

// pe_loader.h - PE 结构体(DOS/NT/File/Optional32/64/Section/Import Descriptor)
#define PE_DOS_MAGIC    0x5A4D
#define PE_NT_MAGIC     0x00004550
#define PE32_MAGIC      0x010B
#define PE32_PLUS_MAGIC 0x020B

Linux 兼容层(双内核 park-and-resume)

架构

shell 输入 `linux ls` → g_lxc_svc->exec("/bin/ls") → 写 IPC 请求
→ linux_resume() vmresume 唤醒 Linux guest
→ daemon fork+exec ls → pipe 捕获 stdout
→ 发 EXEC_STDOUT/EXIT → HLT park → UTSM 读取响应返回 shell

核心文件

组件 文件 说明
park-and-resume vmm/linux_resume.c, vmm/linux_boot.c, vmm/vmexit.c Linux guest HLT 时 park(推进 RIP),UTSM 通过 vmresume 唤醒
IPC exec 协议 CODE/utsm-ipc/ipc_proto.h EXEC_REQUEST/STDOUT/STDERR/EXIT/READY 消息类型 + 载荷
Linux compat 服务 vmm/linux_compat.c, include/utsm/linux_compat.h exec(): 写 IPC 请求 → linux_resume → 读取响应
Boot context kernel/dsk_loader.c reserved[4]=pe_service, reserved[5]=linux_compat_service
shell linux 命令 CODE/shell/main.c linux ls -la → /bin/ls,支持绝对路径
Linux 驱动 ioctl CODE/linux/patches/utsm_hcall.c RECV_MSG/SEND_MSG/PARK/GET_READY ioctl
Linux exec daemon CODE/linux/initramfs/bin/utsm_exec_daemon.c fork+exec+pipe 捕获输出,通过 IPC 回传
init 脚本 CODE/linux/initramfs/init 启动 daemon,daemon 发 EXEC_READY 后 HLT park

关键全局变量

// vmm.c
volatile int g_guest_parked;       // Linux guest 是否已 park
volatile int g_guest_terminated;   // self-test guest 是否已终止

// linux_boot.c
volatile u64 g_saved_host_rsp;     // linux_launch/linux_resume 保存的 host RSP
volatile u64 g_saved_return_rip;   // linux_launch/linux_resume 保存的返回 RIP

IPC 消息类型(ipc_proto.h 扩展)

#define UTSMB_MSG_EXEC_REQUEST  0x10  // {cmd_path[256], argc, argv[8][128]}
#define UTSMB_MSG_EXEC_STDOUT   0x11  // {data[N], len}
#define UTSMB_MSG_EXEC_STDERR   0x12  // {data[N], len}
#define UTSMB_MSG_EXEC_EXIT     0x13  // {exit_code}
#define UTSMB_MSG_EXEC_READY    0x14  // daemon 就绪

第一阶段:Linux guest 底层基础设施

EPT 动态页映射

  • vmexit.c handle_ept_violation 区分 RAM(按需分配 HPA)和 MMIO(路由到设备模拟)
  • 需从 guest 指令解码 MMIO 访问大小和数据

virtio-mmio 框架

文件 说明
vmm/virtio_mmio.c / .h 寄存器分发 + virtqueue 状态机 + 后端路由
vmm/virtio_blk.c virtio-blk 后端,桥接 guest 块请求到 UTSM block API
vmm/virtio_net.c virtio-net 后端占位

GPA 布局:

  • 0x0A000000-0x0A0001FF: virtio-mmio #0 (blk, IRQ5)
  • 0x0A000200-0x0A0003FF: virtio-mmio #1 (net, IRQ6)

virtqueue 关键 API:

void virtio_queue_get_ptrs(virtio_dev_state *dev, int qidx,
    u16 *avail_idx, u16 *used_idx, u64 *desc_addr, u64 *avail_addr, u64 *used_addr);

vmexit dispatch 接线

Exit Reason Handler 说明
EXIT_CPUID handle_cpuid host passthrough + 屏蔽 VMX/hypervisor 位
EXIT_IO_INSTRUCTION handle_io COM1/PIC/PIT 模拟
EXIT_INTERRUPT_WINDOW 新增 guest 开中断时注入 pending IRQ
EXIT_VMX_PREEMPTION_TIMER 新增 1ms 周期 exit
resume 路径 vmexit_before_resume() arm timer + 串口 RX 轮询 + PIT tick + IRQ 注入

virtio IRQ:QUEUE_NOTIFY 后 vmx_guest_queue_irq(0x30+irq),blk→0x35,net→0x36

initramfs

  • build.sh: busybox 1.35.0 静态下载 + gen_init_cpio 打包
  • init: daemon 缺失时 setsid cttyhack sh 回退 ttyS0 交互 shell
  • /dev/console, /dev/ttyS0 节点 + 12 个 applet symlink

linux_boot 集成

  • linux_launch() 调用 virtio_mmio_init() + 启用 PIN_VMX_PREEMPTION_TIMER + 初始 arm preemption timer

cmd.elf

Windows 风格命令行,支持 PE/EXE 执行。

关键功能

  • FAT32 根目录 + /bin 子目录 PE 查找(PATH 查找:先根目录,再 /bin)
  • pe 命令:显式运行 PE 程序
  • peinfo 命令:解析 PE 头显示 DOS/NT/File/Optional Header、节区表、导入表
  • 内建命令:help, echo, cls, dir, ver, exit, type, copy, del, ren, cd, color
  • 通过 reserved[4] 获取 pe_service,reserved[5] 获取 linux_compat_service

PE 样本部署

文件 格式 位置
hello64.exe PE32+ (1536B) SYSTEM/bin/
hello32.exe PE32 (2048B) SYSTEM/bin/
cmd.exe PE32+ (1536B) SYSTEM/bin/

构建验证

全量构建成功,新代码零警告:

  • utsm.elf, deshab.elf, shell.elf (791KB), cmd.elf (490KB), desktop.elf (140KB)
  • FAT32 镜像含 CMD ELF

待办(需 WSL)

Linux 内核需在 WSL 构建(CODE/linux/build.sh,约 30 分钟)。构建后取消注释 SYSTEM/limine/limine.conf 中 bzImage/initrd module 条目即可启用。Linux 未构建时 linux 命令显示"兼容层不可用"。

WSL 构建命令

sudo apt update && sudo apt install -y build-essential bc flex bison libelf-dev libssl-dev cpio
cd ~
curl -L -o linux-6.6.tar.xz https://mirrors.tuna.tsinghua.edu.cn/kernel/v6.x/linux-6.6.tar.xz
tar xf linux-6.6.tar.xz && cd linux-6.6
# 安装 UTSM 驱动 + 配置 + 编译
cp /mnt/d/Code/Deshab/CODE/linux/configs/utsm_x86_64_defconfig .config
make olddefconfig
make -j$(nproc) KCFLAGS='-std=gnu17' bzImage
# 拷贝产物 + 构建 initramfs
mkdir -p /mnt/d/Code/Deshab/SYSTEM/boot
cp arch/x86/boot/bzImage /mnt/d/Code/Deshab/SYSTEM/boot/linux-bzImage
cd /mnt/d/Code/Deshab/CODE/linux && ./build.sh

注意:gcc 15 默认 C23,需 KCFLAGS='-std=gnu17' 修复与 Linux 6.6 的兼容性。