中断路由 (B7): - apic.drv: LAPIC enable + IOAPIC重定向表编程(MADT ISO感知) + apic_route/apic_route_legacy/apic_diag开关 - UTSM: LAPIC EOI钩子(register_apic_eoi, ABI尾部追加) + IDT 0-255全覆盖 + spurious 0xFF特判 - FUCK: apic_route=0默认PIC(零回归) / =1 IOAPIC->LAPIC接管(失败完整降级) / legacy放开IRQ1/12/11 存储: - nvme.drv: 写路径 + PRP list + 读回校验 + MSI/MSI-X中断驱动(nvme_msi开关, 回退纯轮询) - build.ps1: apic.drv纳入构建(原为预置二进制) 网络: - virtio_net: virtqueue RX/TX + netdev注册 + DHCP自测(slirp真实OFFER) PE兼容层: - pe_shim: guest->host指针转换(g_emu_mem_base + gp()) + shim fn32列补齐 - gen_pe.py: PE32+ RVA偏置修复(BUG-004) + cmd.exe生成 - desktop_app.h: da_mouse_poll先判AUX位 + da_mouse_init冲刷残留(BUG-003/008) - shell: Ctrl修饰键跟踪(BUG-001) + g_run_image扩至1MB(BUG-002) QEMU测试套件: - 9用例全自动化(Run-All.ps1): boot-regression/driver-matrix/linux-compat/pe-compat/deaicup-e2e/userapps-matrix/network-e2e/performance-baseline/x86emu32-coverage - QemuTest.ps1公共库: 串口断言/monitor sendkey/screendump/HTTP服务器/并发隔离 文档: - CLAUDE.md: APIC/IOAPIC能力 + kernel_api暴露 + IRQ后端升级状态 - LESSONS_LEARNED.md: B7 LAPIC/IOAPIC经验教训(2条) - Bug记录.txt: BUG-20260801-001~008 + BUG-20260803-009(9条) - test-cases/*.md: 全部补充自动化脚本小节 - 桌面设计.md: .lnk快捷方式 + LINUXAPP.CNF Linux应用图标 - 系统开发策划.md: NVMe/virtio_net标完成 + B2/B7标已解决 + M2进度列
168 lines
8.2 KiB
PowerShell
168 lines
8.2 KiB
PowerShell
#requires -Version 5.1
|
||
<#
|
||
.SYNOPSIS
|
||
linux-compat — UTSM+Linux 双内核兼容层端到端(docs/RE/test-cases/linux-compat.md)
|
||
|
||
.DESCRIPTION
|
||
动态检测 VMM/Linux guest 可用性,自动分流两条验证路径:
|
||
|
||
路径 A(guest VMX 可用,真机/KVM):
|
||
[UTSM] VMM init ok → VMM self-test PASS → bzImage 解析 → IPC shm →
|
||
vmlaunch → Linux version → initramfs init → daemon park →
|
||
[LNXC] service ready → DSK → shell dev_tests → dsl 命令实测
|
||
|
||
路径 B(QEMU WHPX/TCG 无 nested VMX —— 本环境预期路径):
|
||
[UTSM] VMM unavailable → Linux loader 跳过 → DSK 正常启动不崩溃 →
|
||
shell 收到 linux_compat 服务表 → dsl 报告运行态不可用 → desktop。
|
||
A5.1~A5.12 标记 SKIP(环境限制,非产品缺陷)。
|
||
|
||
依据 ISO/run_qemu.bat 说明:WHPX 下 VMXON 会触发致命 hypervisor exit,
|
||
因此框架默认 -cpu qemu64,-vmx 关闭 guest VMX CPUID,UTSM 走优雅降级。
|
||
若未来 WHPX/KVM 支持 nested VMX,可用 -Cpu 'max' 复测路径 A。
|
||
|
||
退出码:全部通过 0,任一 FAIL 1。
|
||
#>
|
||
param(
|
||
[switch]$Build,
|
||
[string]$Cpu = ''
|
||
)
|
||
$ErrorActionPreference = 'Stop'
|
||
. (Join-Path $PSScriptRoot 'lib\QemuTest.ps1')
|
||
|
||
Initialize-QemuTest -Build:$Build
|
||
$result = New-TestCaseResult 'linux-compat'
|
||
|
||
Set-DeshabFirstInit -First 1 -DevMode 1
|
||
Set-DeshabAutoexec -Lines @('ver', 'exit')
|
||
|
||
$s = Start-QemuSession -Name 'linux-compat' -Cpu $Cpu -MonitorPort 45503
|
||
try {
|
||
# ---- 分流点:VMM 自检通过 还是 VMM 不可用 ----
|
||
$fork = Wait-QemuLog -Session $s -Patterns @(
|
||
'[UTSM] VMM self-test PASS',
|
||
'[UTSM] VMM unavailable'
|
||
) -TimeoutSeconds 180
|
||
|
||
if ($fork -eq '[UTSM] VMM self-test PASS') {
|
||
# ================= 路径 A:VMX 可用,完整双内核流程 =================
|
||
Write-Host "`n--- 路径 A: guest VMX 可用,验证完整 Linux 兼容层 ---"
|
||
$hit = Wait-QemuLog -Session $s -Patterns @('=== 自动测试完成 ===', '[PANIC]') -TimeoutSeconds 300
|
||
$log = Read-QemuLogText $s.LogPath
|
||
$result.LogPath = $s.LogPath
|
||
|
||
# A5.1 ~ A5.7 启动链
|
||
Assert-QemuLog $result $log -Ordered @(
|
||
'[UTSM] VMM init ok',
|
||
'[UTSM] VMM self-test PASS',
|
||
'[LINUX] found bzImage module:',
|
||
'[UTSM] Linux loader init ok',
|
||
'[UTSM] IPC shm init ok',
|
||
'[VMM] launching guest',
|
||
'Linux version',
|
||
'[utsm-linux] init started',
|
||
'[LINUX] guest parked (daemon ready)',
|
||
'[LNXC] service ready',
|
||
'[DSK] boot',
|
||
'[shell] linux_compat service ok'
|
||
) -MustNotContain @('[PANIC]')
|
||
if (-not $hit -or $hit -eq '[PANIC]') {
|
||
Add-TestCheck $result 'A5.7: DSK/shell 接管' 'FAIL' 'dev_tests did not complete'
|
||
} else {
|
||
Add-TestCheck $result 'A5.7: DSK/shell 接管' 'PASS'
|
||
}
|
||
|
||
# A5.8 ~ A5.12 shell dsl 交互(dev_mode 串口镜像开启)
|
||
if ($hit -eq '=== 自动测试完成 ===') {
|
||
Start-Sleep -Seconds 1
|
||
Send-QemuText -Session $s -Text 'dsl' -Enter
|
||
$h1 = Wait-QemuLog -Session $s -Patterns @('Linux 兼容层已就绪') -TimeoutSeconds 60
|
||
if ($h1) { Add-TestCheck $result 'A5.8: dsl 状态查询' 'PASS' }
|
||
else { Add-TestCheck $result 'A5.8: dsl 状态查询' 'FAIL' 'missing 兼容层已就绪' }
|
||
|
||
Send-QemuText -Session $s -Text 'dsl ls' -Enter
|
||
$h2 = Wait-QemuLog -Session $s -Patterns @('bin', 'etc', 'deshab#') -TimeoutSeconds 60
|
||
if ($h2) { Add-TestCheck $result 'A5.9: dsl ls 目录列表' 'PASS' }
|
||
else { Add-TestCheck $result 'A5.9: dsl ls 目录列表' 'FAIL' 'no listing output' }
|
||
|
||
Send-QemuText -Session $s -Text 'dsl uname -a' -Enter
|
||
$h3 = Wait-QemuLog -Session $s -Patterns @('Linux') -TimeoutSeconds 60
|
||
if ($h3) { Add-TestCheck $result 'A5.10: dsl uname -a' 'PASS' }
|
||
else { Add-TestCheck $result 'A5.10: dsl uname -a' 'FAIL' 'no uname output' }
|
||
|
||
Send-QemuText -Session $s -Text 'dsl nosuchprog' -Enter
|
||
$h4 = Wait-QemuLog -Session $s -Patterns @('deshab# ') -TimeoutSeconds 60
|
||
Start-Sleep -Seconds 1
|
||
$log2 = Read-QemuLogText $s.LogPath
|
||
if ($h4 -and -not $log2.Contains('[PANIC]')) {
|
||
Add-TestCheck $result 'A5.12: dsl 错误路径不崩溃' 'PASS'
|
||
} else {
|
||
Add-TestCheck $result 'A5.12: dsl 错误路径不崩溃' 'FAIL' 'shell did not recover'
|
||
}
|
||
|
||
Send-QemuKeys -Session $s -Keys @('esc')
|
||
$h5 = Wait-QemuLog -Session $s -Patterns @('desktop ready') -TimeoutSeconds 150
|
||
if ($h5) { Add-TestCheck $result 'A5.x: Esc 后到 desktop' 'PASS' }
|
||
else { Add-TestCheck $result 'A5.x: Esc 后到 desktop' 'FAIL' 'no desktop ready' }
|
||
}
|
||
Add-TestNote $result '路径 A 执行:guest VMX 可用(真机/KVM 环境)'
|
||
}
|
||
elseif ($fork -eq '[UTSM] VMM unavailable') {
|
||
# ================= 路径 B:无 nested VMX,优雅降级 =================
|
||
Write-Host "`n--- 路径 B: guest 无 VMX(QEMU 预期),验证优雅降级 ---"
|
||
$hit = Wait-QemuLog -Session $s -Patterns @('=== 自动测试完成 ===', '[PANIC]') -TimeoutSeconds 240
|
||
$log = Read-QemuLogText $s.LogPath
|
||
$result.LogPath = $s.LogPath
|
||
|
||
# 降级锚点 + 系统继续正常启动
|
||
Assert-QemuLog $result $log -MustContain @('[UTSM] VMM unavailable')
|
||
Assert-QemuLog $result $log -Ordered @(
|
||
'[UTSM] SELFTEST PASS',
|
||
'[UTSM] VMM unavailable',
|
||
'[DSK] boot',
|
||
'[DSK] dev_mode=1 (developer auto-test)',
|
||
'[shell] boot',
|
||
'[shell] linux_compat service ok'
|
||
) -MustNotContain @('[PANIC]')
|
||
if ($hit -eq '=== 自动测试完成 ===') {
|
||
Add-TestCheck $result '降级路径: dev_tests 完成(Linux 缺失不阻塞启动)' 'PASS'
|
||
} else {
|
||
Add-TestCheck $result '降级路径: dev_tests 完成(Linux 缺失不阻塞启动)' 'FAIL' "hit=$hit"
|
||
}
|
||
|
||
# dsl 运行态不可用报告(服务表已传递,is_available()=0)
|
||
if ($hit -eq '=== 自动测试完成 ===') {
|
||
Start-Sleep -Seconds 1
|
||
Send-QemuText -Session $s -Text 'dsl' -Enter
|
||
$h = Wait-QemuLog -Session $s -Patterns @('linux_compat: not initialized') -TimeoutSeconds 40
|
||
if ($h) { Add-TestCheck $result '降级路径: dsl 报告运行态不可用' 'PASS' }
|
||
else { Add-TestCheck $result '降级路径: dsl 报告运行态不可用' 'FAIL' 'missing linux_compat: not initialized' }
|
||
|
||
Send-QemuKeys -Session $s -Keys @('esc')
|
||
$h2 = Wait-QemuLog -Session $s -Patterns @('desktop ready') -TimeoutSeconds 150
|
||
if ($h2) { Add-TestCheck $result '降级路径: Esc 后经 cmd 到 desktop' 'PASS' }
|
||
else { Add-TestCheck $result '降级路径: Esc 后经 cmd 到 desktop' 'FAIL' 'no desktop ready' }
|
||
}
|
||
|
||
# A5.1~A5.12 环境性跳过
|
||
foreach ($t in @('A5.1 VMM self-test', 'A5.2 bzImage 加载', 'A5.3 EPT+vmlaunch',
|
||
'A5.4 Linux 内核启动', 'A5.5 init 脚本', 'A5.6 daemon park',
|
||
'A5.8 dsl 状态就绪', 'A5.9 dsl ls', 'A5.10 dsl uname',
|
||
'A5.11 dsl cat hostname', 'A5.12 dsl 错误路径')) {
|
||
Add-TestCheck $result $t 'SKIP' 'QEMU WHPX/TCG 无 nested VMX(见 run_qemu.bat 注释),需真机或 KVM 复测'
|
||
}
|
||
Add-TestCheck $result 'A5.7: Linux 缺失时 DSK 正常接管' 'PASS'
|
||
Add-TestNote $result '路径 B 执行:QEMU 无 nested VMX,Linux guest 不可用属预期环境限制'
|
||
Add-TestNote $result '如需完整验证:真机(VT-x)或 Linux KVM (-enable-kvm -cpu host) 下以 -Cpu max 重跑'
|
||
}
|
||
else {
|
||
$result.LogPath = $s.LogPath
|
||
Add-TestCheck $result 'VMM 分流探测' 'FAIL' 'neither VMM self-test PASS nor VMM unavailable within 180s'
|
||
}
|
||
} finally {
|
||
Stop-QemuSession $s
|
||
Restore-DeshabScenario
|
||
}
|
||
|
||
Write-TestCaseResult $result
|
||
if ($result.Status -eq 'FAIL') { exit 1 } else { exit 0 }
|