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

196 lines
7.3 KiB
Markdown
Raw Permalink 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/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
### 关键结构
```c
// 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 |
### 关键全局变量
```c
// 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 扩展)
```c
#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**:
```c
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 构建命令
```bash
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 的兼容性。