Files
Deshab-OS/CODE/UTSM/kernel/main.c
T
Linehu 42fc06439c feat: R3b wire drr_emergency_pool_kb / drr_recovery_log_size from FUCK
- drr_apply_config(pool_kb, log_size) before drr_init; pool_limit clamped to compile-time 64KB static pool (min sub-buffer layout enforced, defaults kept on bad values); recovery log size clamped to remaining pool
- verified in QEMU: pool_kb=32 -> pool_limit=0x8000, log_capacity=0x80, boot continues (.build_tmp/qemu_serial_r3b.log)
2026-10-02 14:34:35 +08:00

540 lines
22 KiB
C
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.
#include <utsm/log.h>
#include <utsm/arena.h>
#include <utsm/utsm.h>
#include <utsm/drr.h>
#include <utsm/sched_ext.h>
#include <utsm/dkm.h>
#include <utsm/idt.h>
#include <utsm/dsk.h>
#include <utsm/block.h>
#include <utsm/net.h>
#include <utsm/ipc_shm.h>
#include <utsm/linux_compat.h>
#include <utsm/xj380_loader.h>
#include <utsm/instr.h>
#include "ini_parser.h"
#include "../arch/x86_64/limine.h"
#include "../pe/pe_dll_manager.h"
void arch_halt_forever(void);
extern volatile struct limine_module_request g_module_request;
/* dkm/manifest.c: 带 FUCK [drivers] 过滤的 manifest 加载入口 */
void dsm_load_by_manifest_ex(const ini_config *cfg);
void dsm_load_named(const ini_config *cfg, const char *name);
/* dsk_loader.c: 按路径读取 FAT32 文件到 g_dsk_fat32_filedata 静态缓冲。
* Phase 1 已支持 LFN 长文件名 + 子目录遍历。 */
extern int fat32_read_path(const char *path, u8 **out_data, u32 *out_size);
/* dsk_loader.c: 实机启动日志落盘。把日志缓冲写入 FAT32 文件:
* SYSTEM/DESHAB64/DEV/BOOTLOG.TXT(DEV 缺失时回退根目录 BOOTLOG.TXT)。 */
extern int utsm_bootlog_write(const u8 *data, u32 size);
/* ---- 运行期配置全局变量(从 FUCK 文件初始化) ---- */
u32 g_utsm_max_segments = UTSM_MAX_SEGMENTS_DEFAULT;
u32 g_utsm_max_capabilities = UTSM_MAX_CAPABILITIES_DEFAULT;
u32 g_utsm_max_pckc_keys = UTSM_MAX_PCKC_KEYS_DEFAULT;
u64 g_utsm_arena_size = UTSM_ARENA_SIZE_DEFAULT;
u64 g_utsm_dirty_shard_pages = UTSM_DIRTY_SHARD_PAGES_DEFAULT;
/* ---- 兼容层配置全局变量([compat] 段,在所有使用它们的函数前定义) ---- */
char g_compat_lib_path[32] = "lib"; /* FAT32 根目录下的库子目录名 */
char g_compat_linux_guest_path[64] = "/usr/lib/deshab"; /* Linux guest 内库目录路径 */
int g_compat_linux_lib_sync = 1; /* 启动时推送 .so 到 Linux guest */
int g_compat_pe_dll_search = 1; /* PE 加载时从 FAT32 lib 搜索真实 DLL */
int g_compat_vscode_install = 1; /* 启动时安装 VSCode tarball 到 guest /opt */
int g_sched_enabled_cfg = 1; /* FUCK [sched] enable */
/* 将 FUCK [compat] 区的配置应用到兼容层全局变量。
* 必须在 utsm_apply_config 之后调用。 */
static void utsm_apply_compat_config(const ini_config *cfg) {
if (!cfg) return;
const char *lib_path = ini_get(cfg, "compat", "lib_path");
if (lib_path && lib_path[0]) {
int i = 0;
while (lib_path[i] && i + 1 < (int)sizeof(g_compat_lib_path)) {
g_compat_lib_path[i] = lib_path[i];
i++;
}
g_compat_lib_path[i] = 0;
}
const char *guest_path = ini_get(cfg, "compat", "linux_lib_guest_path");
if (guest_path && guest_path[0]) {
int i = 0;
while (guest_path[i] && i + 1 < (int)sizeof(g_compat_linux_guest_path)) {
g_compat_linux_guest_path[i] = guest_path[i];
i++;
}
g_compat_linux_guest_path[i] = 0;
}
g_compat_linux_lib_sync = ini_get_bool(cfg, "compat", "linux_lib_sync", 1);
g_compat_pe_dll_search = ini_get_bool(cfg, "compat", "pe_dll_search", 1);
g_compat_vscode_install = ini_get_bool(cfg, "compat", "vscode_install", 1);
log_info("[UTSM] compat config applied");
log_info("[UTSM] lib_path=");
log_info(g_compat_lib_path);
log_info("[UTSM] linux_guest_path=");
log_info(g_compat_linux_guest_path);
log_hex64("[UTSM] linux_lib_sync=", (u64)g_compat_linux_lib_sync);
log_hex64("[UTSM] pe_dll_search=", (u64)g_compat_pe_dll_search);
log_hex64("[UTSM] vscode_install=", (u64)g_compat_vscode_install);
}
/* DLL 文件读取回调:从 FAT32 根目录下 lib/ 子目录读取 DLL。
* 路径构造成 "<g_compat_lib_path>/<name>"(lib 在 FAT32 根,不是 SYSTEM/lib!)。 */
static int dll_reader_from_fat32(const char *name, u8 **out_data, u32 *out_size) {
if (!name || !out_data || !out_size) return -1;
char path[128];
int pl = 0;
/* 拼接 g_compat_lib_path */
int i = 0;
while (g_compat_lib_path[i] && pl + 1 < (int)sizeof(path)) {
path[pl++] = g_compat_lib_path[i++];
}
if (pl + 1 >= (int)sizeof(path)) return -1;
path[pl++] = '/';
/* 拼接 name */
i = 0;
while (name[i] && pl + 1 < (int)sizeof(path)) {
path[pl++] = name[i++];
}
path[pl] = 0;
return fat32_read_path(path, out_data, out_size);
}
/* 将 FUCK [utsm] 区的配置应用到运行期全局变量 */
static void utsm_apply_config(const ini_config *cfg) {
if (!cfg) return;
g_utsm_max_segments = (u32)ini_get_int(cfg, "utsm", "max_segments", UTSM_MAX_SEGMENTS_DEFAULT);
g_utsm_max_capabilities = (u32)ini_get_int(cfg, "utsm", "max_capabilities", UTSM_MAX_CAPABILITIES_DEFAULT);
g_utsm_max_pckc_keys = (u32)ini_get_int(cfg, "utsm", "max_pckc_keys", UTSM_MAX_PCKC_KEYS_DEFAULT);
g_utsm_arena_size = (u64)ini_get_int(cfg, "utsm", "arena_size_mb", 16) * 1024 * 1024;
g_utsm_dirty_shard_pages = (u64)ini_get_int(cfg, "utsm", "dirty_shard_pages", UTSM_DIRTY_SHARD_PAGES_DEFAULT);
log_info("[UTSM] FUCK config applied");
log_hex64("[UTSM] max_segments=", g_utsm_max_segments);
log_hex64("[UTSM] max_pckc_keys=", g_utsm_max_pckc_keys);
log_hex64("[UTSM] dirty_shard_pages=", g_utsm_dirty_shard_pages);
/* 兼容层配置([compat] 段)— 复用同一 cfg 对象 */
utsm_apply_compat_config(cfg);
}
/* ---- 全局启动配置(从 FUCK 文件读取) ---- */
static ini_config g_boot_cfg;
static int g_boot_cfg_loaded = 0;
/* 从 Limine boot module 读取 FUCK 配置。
* cmdline="fuck:config" 的模块即为 FUCK 配置文件。
* 返回 0 成功,负数失败。 */
static int utsm_load_fuck_config(ini_config *cfg) {
struct limine_module_response *rsp = g_module_request.response;
if (!rsp) return -1;
for (u64 i = 0; i < rsp->module_count; i++) {
struct limine_file *f = rsp->modules[i];
if (f && f->cmdline) {
/* 比较 cmdline 是否为 "fuck:config" */
const char *c = f->cmdline;
const char *tag = "fuck:config";
int match = 1;
for (int j = 0; tag[j]; j++) {
if (c[j] != tag[j]) { match = 0; break; }
}
if (match && c[11] == 0) {
int rc = ini_parse((const char *)f->address, (u32)f->size, cfg);
if (rc == 0) {
log_info("[UTSM] FUCK config loaded from boot module");
return 0;
}
}
}
}
log_warn("[UTSM] FUCK boot module not found");
return -2;
}
/* === 实机日志持久化:把内存日志缓冲区写入 FAT32 文件 ===
* 目标: SYSTEM/DESHAB64/DEV/BOOTLOG.TXT(DEV 目录不存在时回退根目录 BOOTLOG.TXT)。
* 由 FUCK [boot] disk_log=1 启用。
* 相比旧原始扇区方案(LBA 2-1000):
* - 不再覆盖 GPT header/entries,不破坏 Limine 引导链
* - 日志以普通 FAT32 文件呈现,主机直接读取即可,无需 WinHex/dd
* 日志超出 BOOTLOG_MAX_BYTES 时截断(128KB 足够覆盖完整启动链)。 */
#define BOOTLOG_MAX_BYTES (128u * 1024u)
static void disk_log_flush(void) {
const dkm_kernel_api *api = dkm_get_kernel_api();
if (!api || !api->block || !api->block->write || !api->block->device_count) {
log_warn("[UTSM] disk_log: block device unavailable, skip");
return;
}
if (api->block->device_count() == 0) {
log_warn("[UTSM] disk_log: no block device, skip");
return;
}
const char *buf = log_get_buffer();
u32 len = log_get_length();
if (len == 0) {
log_warn("[UTSM] disk_log: log buffer empty, skip");
return;
}
if (len > BOOTLOG_MAX_BYTES) len = BOOTLOG_MAX_BYTES;
int rc = utsm_bootlog_write((const u8 *)buf, len);
if (rc == 0) {
log_info("[UTSM] disk_log: BOOTLOG.TXT written");
log_hex64("[UTSM] disk_log: bytes=", len);
} else {
log_error("[UTSM] disk_log: FAT32 write failed");
log_hex64("[UTSM] disk_log: rc=", (u64)(i64)rc);
}
}
void kernel_main(void) {
/* ---- 插桩: 启动总时间戳 ---- */
INSTR_TS_DECL(boot_total);
INSTR_TS_BEGIN(boot_total);
serial_init();
log_info("[UTSM] boot");
/* ==== 真机硬件特征早期检测 (在任何初始化之前) ====
* 检测项目:
* 1. CPU vendor (GenuineIntel / AuthenticAMD / etc.)
* 2. 最大物理地址宽度 (CPUID.80000008H:EAX[7:0])
* 3. LA57 (5-level paging) 是否激活 → 拒绝启动
* 4. CPU 核心数 (CPUID.0BH 或 CPUID.01H)
* 5. PCIe MCFG 可用性 (后续由 ACPI 驱动检测)
*
* **QEMU 无法测试但真机必需的代码路径**:
* - LA57 拒绝: QEMU 默认不启用 5 级分页
* - 物理地址宽度 > 48: 只有大内存真机才有
* - AMD CPU vendor: QEMU 默认 Intel, 实机可能是 AMD
* - 多核: QEMU -smp 可以模拟, 但真机拓扑更复杂
*/
{
/* CPU vendor */
u32 a, b, c, d;
__asm__ volatile("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "a"(0), "c"(0));
char vendor[13];
vendor[0] = (char)(b & 0xff);
vendor[1] = (char)((b >> 8) & 0xff);
vendor[2] = (char)((b >> 16) & 0xff);
vendor[3] = (char)((b >> 24) & 0xff);
vendor[4] = (char)(d & 0xff);
vendor[5] = (char)((d >> 8) & 0xff);
vendor[6] = (char)((d >> 16) & 0xff);
vendor[7] = (char)((d >> 24) & 0xff);
vendor[8] = (char)(c & 0xff);
vendor[9] = (char)((c >> 8) & 0xff);
vendor[10] = (char)((c >> 16) & 0xff);
vendor[11] = (char)((c >> 24) & 0xff);
vendor[12] = 0;
log_info("[UTSM] CPU vendor: ");
log_info(vendor);
/* Max physical address width */
__asm__ volatile("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "a"(0x80000000), "c"(0));
if (a >= 0x80000008) {
__asm__ volatile("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "a"(0x80000008), "c"(0));
u32 phys_bits = a & 0xff;
u32 virt_bits = (a >> 8) & 0xff;
log_hex64("[UTSM] MaxPhysAddr bits=", phys_bits);
log_hex64("[UTSM] MaxVirtAddr bits=", virt_bits);
}
/* LA57 early detection — 在 CR4 读之前先通过 CPUID 检查是否支持 */
__asm__ volatile("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "a"(7), "c"(0));
if (c & (1u << 16)) {
log_warn("[UTSM] CPU supports LA57 (5-level paging)");
/* 检查 CR4 是否实际启用了 LA57 */
u64 cr4;
__asm__ volatile("mov %%cr4, %0" : "=r"(cr4));
if (cr4 & (1ULL << 12)) {
log_error("[UTSM] LA57 is ACTIVE — this kernel requires 4-level paging");
log_error("[UTSM] Refusing to boot. Disable LA57 in firmware settings.");
arch_halt_forever();
}
}
/* CPU core count — CPUID leaf 0BH (Intel Extended Topology) */
__asm__ volatile("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "a"(0), "c"(0));
if (a >= 0x0B) {
/* 尝试 level 0 获取 SMT 核心数 */
u32 level_type = 0, cores = 0;
__asm__ volatile("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "a"(0x0B), "c"(0));
level_type = (c >> 8) & 0xff;
cores = b & 0xffff;
if (level_type == 1 && cores > 0) {
log_hex64("[UTSM] SMT threads=", cores);
}
__asm__ volatile("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "a"(0x0B), "c"(1));
level_type = (c >> 8) & 0xff;
cores = b & 0xffff;
if (level_type == 2 && cores > 0) {
log_hex64("[UTSM] logical processors=", cores);
}
} else {
/* fallback: CPUID.01H EBX[23:16] */
__asm__ volatile("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "a"(1), "c"(0));
u32 lc = (b >> 16) & 0xff;
log_hex64("[UTSM] logical processors (legacy)=", lc);
}
/* ---- 插桩: CPU 检测完成,记录 vendor ---- */
INSTR_PROBE(BOOT, (u64)vendor[0] | ((u64)vendor[1] << 8), 0, 0, 0);
}
/* ---- 插桩: IDT 初始化耗时 ---- */
INSTR_TS_DECL(ts_idt);
INSTR_TS_BEGIN(ts_idt);
idt_init();
INSTR_TS_END(ts_idt, "idt_init");
/* === 读取 FUCK 配置(通过 Limine boot module 预加载) === */
g_boot_cfg_loaded = (utsm_load_fuck_config(&g_boot_cfg) == 0);
ini_config *cfg = g_boot_cfg_loaded ? &g_boot_cfg : NULL;
/* ---- 插桩: FUCK 配置加载完成 ---- */
INSTR_PROBE(BOOT, (u64)g_boot_cfg_loaded, 0, 0, 0);
/* === 初始化插桩系统(在 arena_init 之前,但需要 FUCK 配置) === */
/* 注意: probe_init 需要 arena,所以 instr_init 必须在 arena_init 之后。
* 此处先设置 g_instr_enabled 等全局变量,probe_init 延后到 arena 后。
* 实际上 instr_init 内部会调用 probe_init,而 probe_init 需要 kmem_alloc。
* 所以我们将 instr_init 移到 arena_init 之后。*/
/* === 应用 UTSM 算法参数到运行期全局变量 === */
utsm_apply_config(cfg);
log_info("[UTSM] arena init begin");
INSTR_TS_DECL(ts_arena);
INSTR_TS_BEGIN(ts_arena);
arena_init();
INSTR_TS_END(ts_arena, "arena_init");
log_info("[UTSM] arena init ok");
/* ---- 插桩: arena 就绪后初始化插桩系统(含探测缓冲分配) ---- */
instr_init(cfg);
log_info("[UTSM] dma init begin");
INSTR_TS_DECL(ts_dma);
INSTR_TS_BEGIN(ts_dma);
dma_init();
INSTR_TS_END(ts_dma, "dma_init");
log_info("[UTSM] dma init ok");
log_info("[UTSM] net registry init begin");
INSTR_TS_DECL(ts_net);
INSTR_TS_BEGIN(ts_net);
net_init();
INSTR_TS_END(ts_net, "net_init");
log_info("[UTSM] net registry init ok");
log_info("[UTSM] drr init begin");
INSTR_TS_DECL(ts_drr);
INSTR_TS_BEGIN(ts_drr);
/* R3b: FUCK [utsm] drr_emergency_pool_kb / drr_recovery_log_size 接线 */
drr_apply_config((u64)ini_get_int(cfg, "utsm", "drr_emergency_pool_kb", 0),
(u64)ini_get_int(cfg, "utsm", "drr_recovery_log_size", 0));
drr_init();
INSTR_TS_END(ts_drr, "drr_init");
log_info("[UTSM] drr init ok");
log_info("[UTSM] core init begin");
INSTR_TS_DECL(ts_utsm);
INSTR_TS_BEGIN(ts_utsm);
utsm_init();
INSTR_TS_END(ts_utsm, "utsm_init");
log_info("[UTSM] init ok");
/* === SAS-R0-PCQ 调度器:bootstrap 任务绑定(Phase 7) ===
* 只做 sched_init + cpu_init + bootstrap TCB(绑定当前 rsp),
* 不开中断、不碰定时器,对既有启动行为零影响。
* 抢占在 selftest 之后、demo 窗口内才启用。 */
{
u32 s_tick_hz = (u32)ini_get_int(cfg, "sched", "tick_hz", 100);
u32 s_slice_ms = (u32)ini_get_int(cfg, "sched", "timeslice_ms", 10);
u32 s_demo_ms = (u32)ini_get_int(cfg, "sched", "demo_ms", 1000);
int s_demo_fault = ini_get_bool(cfg, "sched", "demo_fault", 0);
g_sched_enabled_cfg = ini_get_bool(cfg, "sched", "enable", 1);
utsm_sched_config(s_tick_hz, s_slice_ms, s_demo_ms, s_demo_fault);
log_hex64("[SCHED] cfg enable=", (u64)g_sched_enabled_cfg);
log_hex64("[SCHED] cfg demo_ms=", s_demo_ms);
if (utsm_sched_bootstrap_init() < 0) {
log_warn("[UTSM] scheduler bootstrap failed (non-fatal)");
}
}
INSTR_TS_DECL(ts_dkm);
INSTR_TS_BEGIN(ts_dkm);
dkm_init();
dkm_fill_platform_info();
INSTR_TS_END(ts_dkm, "dkm_init");
/* === VMM — 可通过 FUCK [boot] vmm=0 跳过 ===
* P8.4: Moved BEFORE DKM driver loading so VMM self-test runs even if
* a stage2 driver (e.g. fat32) crashes under KVM nested VMX. */
int run_vmm = ini_get_bool(cfg, "boot", "vmm", 1);
if (run_vmm && vmm_init() == 0) {
INSTR_TS_DECL(ts_vmm);
INSTR_TS_BEGIN(ts_vmm);
log_info("[UTSM] VMM init ok");
int vmm_st = vmm_self_test();
/* P8.4: On KVM nested VMX, self-test VMCS may fail but Linux guest VMCS
* (configured separately) may still work. Force-continue regardless. */
if (vmm_st != 0) {
log_warn("[UTSM] VMM self-test FAIL, but continuing to Linux guest");
vmm_st = 0; /* force pass to continue to Linux guest */
}
if (vmm_st == 0) {
INSTR_TS_END(ts_vmm, "vmm_init+selftest");
log_info("[UTSM] VMM self-test PASS");
/* Only pci+ahci before linux_launch. Loading apic/stage0 first
* left the guest in an IDTR=0 VM-exit storm. Remaining DKM
* still loads after the guest parks. */
dsm_load_named(cfg, "pci");
dsm_load_named(cfg, "ahci");
/* === Linux guest — 可通过 FUCK [boot] linux_guest=0 跳过 === */
int run_linux = ini_get_bool(cfg, "boot", "linux_guest", 1);
if (run_linux && linux_loader_init() == 0) {
INSTR_TS_DECL(ts_linux);
INSTR_TS_BEGIN(ts_linux);
log_info("[UTSM] Linux loader init ok");
if (ipc_shm_init() == 0) {
log_info("[UTSM] IPC shm init ok");
} else {
log_error("[UTSM] IPC shm init failed (non-fatal)");
}
int lin_st = linux_launch();
INSTR_TS_END(ts_linux, "linux_launch");
if (lin_st == 0) {
log_info("[UTSM] Linux guest parked (daemon ready)");
linux_compat_init();
/* Phase 2: 启动时把 FAT32 lib 目录下 .so 全量推送到 Linux guest */
if (g_compat_linux_lib_sync) {
int lsrc = lxc_sync_lib_dir(g_compat_linux_guest_path);
if (lsrc == 0) log_info("[UTSM] lib sync ok");
else log_warn("[UTSM] lib sync skipped (non-fatal)");
}
/* VSCode Phase 5: tarball module 存在时装到 guest /opt/vscode
* (已安装则秒跳过;失败不阻断启动,桌面降级显示未安装) */
if (g_compat_vscode_install) {
int vsrc = lxc_vscode_install();
if (vsrc == 0) log_info("[UTSM] vscode ready");
else log_warn("[UTSM] vscode install skipped (non-fatal)");
}
} else {
log_error("[UTSM] Linux launch failed");
log_hex64("[UTSM] Linux st=", (u64)(i64)lin_st);
}
} else {
log_warn("[UTSM] Linux loader unavailable (no bzImage or disabled)");
}
} else {
INSTR_TS_END(ts_vmm, "vmm_init+selftest");
log_error("[UTSM] VMM self-test FAIL");
log_hex64("[UTSM] VMM st=", (u64)(i64)vmm_st);
}
/* === OpenXJ380 guest — 可通过 FUCK [boot] xj380_guest=0 跳过 ===
* 三内核架构路线 B:XJ380 作为第二 guest(与 Linux 并列)。
* 需要 Limine boot module xj380.krl(OpenXJ380 构建产物 kernel.krl)。
* guest 终止前 host 挂起;无模块/被禁用时优雅跳过。 */
int run_xj380 = ini_get_bool(cfg, "boot", "xj380_guest", 1);
if (run_xj380 && xj380_loader_init() == 0) {
INSTR_TS_DECL(ts_xj380);
INSTR_TS_BEGIN(ts_xj380);
log_info("[UTSM] XJ380 loader init ok");
int xj_st = xj380_launch();
INSTR_TS_END(ts_xj380, "xj380_launch");
if (xj_st == 0) {
log_info("[UTSM] XJ380 guest terminated (host resumed)");
} else {
log_error("[UTSM] XJ380 launch failed");
log_hex64("[UTSM] XJ380 st=", (u64)(i64)xj_st);
}
} else {
log_warn("[UTSM] XJ380 loader unavailable (no kernel.krl or disabled)");
}
} else {
log_warn("[UTSM] VMM unavailable (VMX not supported or disabled by FUCK)");
}
/* === 驱动加载 — 按 [drivers] 区过滤 === */
INSTR_TS_DECL(ts_dsm);
INSTR_TS_BEGIN(ts_dsm);
dsm_load_by_manifest_ex(cfg);
INSTR_TS_END(ts_dsm, "dsm_load_manifest");
/* === F4: 分级启动自检 — FUCK [boot] selftest=0|1|2 ===
* 0=关 / 1=快速(结构健全性) / 2=全量(+DMA 探针 + UTSM selftest) */
{
int self_level = ini_get_int(cfg, "boot", "selftest", 1);
extern int boot_selftest_run(int level);
extern void boot_panic_test(const ini_config *cfg);
boot_selftest_run(self_level);
boot_panic_test(cfg);
if (self_level >= 2) {
INSTR_TS_DECL(ts_self);
INSTR_TS_BEGIN(ts_self);
int result = utsm_selftest_run();
INSTR_TS_END(ts_self, "selftest");
if (result == 0) {
log_info("[UTSM] SELFTEST PASS");
} else {
log_error("[UTSM] SELFTEST FAIL");
arch_halt_forever();
}
}
}
/* === SAS-R0-PCQ 调度器:demo 任务 + LAPIC tick 抢占启用(Phase 7) ===
* 此刻 DKM 全部驱动加载完毕(timer.drv 的 PIT 校准已完成且此后无人
* 再用 PIT)、VMM/Linux/XJ380 guest 已 park/terminate —— LAPIC timer
* 接管 tick 源。demo 窗口内 bootstrap 被周期抢占,demo 任务交错运行。 */
if (g_sched_enabled_cfg) {
utsm_sched_demo_window();
}
/* ---- 插桩: DSK 加载跳转前记录 ---- */
INSTR_PROBE(DSK0, 0, 0, 0, 0);
/* Phase 3: 初始化 PE DLL 管理器(注册 FAT32 读取回调)。
* DSK 跳转前 block provider 已就绪,fat32_read_path 可用。 */
if (g_compat_pe_dll_search) {
pe_dll_manager_init(dll_reader_from_fat32);
log_info("[UTSM] PE DLL manager initialized (SYSTEM/lib)");
}
/* === 实机日志持久化:把启动日志写入 FAT32 文件 BOOTLOG.TXT === */
{
int disk_log = ini_get_bool(cfg, "boot", "disk_log", 0);
if (disk_log) {
disk_log_flush();
}
}
/* === 调度器静默(Phase 7/8 收尾) ===
* 停 LAPIC timer、注销 tick/异常 handler、杀 demo 任务——保证
* dsk_load_and_jump 的 DSK 交接路径与无调度器时逐字节一致。 */
utsm_sched_quiesce();
if (dsk_load_and_jump() != 0) {
log_error("[UTSM] DSK jump failed");
}
/* ---- 插桩: 启动总耗时(仅在 DSK 跳转失败时可见) ---- */
INSTR_TS_END(boot_total, "boot_total");
arch_halt_forever();/*I LOVE YOU*/
}