Files
Deshab-OS/CODE/UTSM/drr/drr_stub.c
T
Linehu 583262f5f0 feat: SKEL skeleton instrumentation - designed-but-unimplemented paths panic
- hypercall.c: 5 Phase 1.3 stubs -> HCALL-E01..E05 panic (no NOSYS return)
- drr_stub.c: snapshot alloc fail -> DRR-E01; new skeletons DRR-E02 root key
  seal, DRR-E03 task kill crypto erase, DRR-E04/E05 segment/system rollback,
  DRR-E06/E07 driver recovery ops dispatch
- sched.c: enable fail -> SCH-E02 panic (no silent demo skip)
- dkm/kernel_api.c: D1 hot-unload DKM-E01, D2 bare code loader DKM-E02,
  SIPI AP wake DKM-E03 skeletons
- virtio_net tx/rx stubs -> VNET-E01/E02; ath9k tx stub -> ATH-E01;
  xhci port reset -> XHC-E01; nvme MSI/MSI-X fail -> NVME-E01..E03 (no
  silent polling downgrade); e1000 MAC fallback -> E1K-E01
- pe_shim unimpl API -> PE-E01; PE ordinal import -> PE-E02
- kernel/main.c: lib sync / vscode install fail -> LNX-E01/E02
- NEW brand/brand.c (E1 boot anim BRAND-E01, E2 time egg BRAND-E02) and
  pkg/pkg.c (pacman skeleton PKG-E01..03), wired into UTSM MAKEFILE
- Deliberate design-internal fallbacks kept and documented (VMX skip,
  bzImage skip, KDE fallback, boot-module fallback, apic->PIC route)
2026-10-03 00:30:54 +08:00

837 lines
31 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.
/* drr_core.c — DRR Dedicated Recovery Root 核心实现
*
* 替换原 drr_stub.c,提供完整的:
* - Emergency Pool(独立于普通堆分配器)
* - Recovery Log(write intent/commit 追踪)
* - Checkpoint A/B 双槽(CRC 校验、原子 active slot 切换)
* - Root key 管理
* - Heartbeat
*/
#include <utsm/drr.h>
#include <utsm/log.h>
#include <utsm/panic.h>
#include <utsm/dma.h>
#include <utsm/segment.h>
#include <utsm/config.h>
#include <utsm/dkm.h>
#include <utsm/crypto.h>
#include <utsm/blake2b.h>
extern void outb(u16 port, u8 value);
/* ---- 内部内存操作(不依赖 libc) ---- */
static void drr_memzero(void *dst, u64 n) {
u8 *d = (u8 *)dst;
while (n--) *d++ = 0;
}
static void drr_memcpy(void *dst, const void *src, u64 n) {
u8 *d = (u8 *)dst;
const u8 *s = (const u8 *)src;
while (n--) *d++ = *s++;
}
/* ---- CRC64-ECMA ---- */
static const u64 crc64_table[256] = {
0x0000000000000000ULL, 0x42F0E1EBA5EA001AULL, 0x85E1C3D753D46D34ULL, 0xC711223CF63E6D2EULL,
0x493366450E42ECDFULL, 0x0BC387AEABA8ECC5ULL, 0xCCD2A5925D9681EBULL, 0x8E224479F87C81F1ULL,
0x9266CC8A1C85D9BEULL, 0xD0962D61B96FD9A4ULL, 0x17870F5D4F51B48AULL, 0x5577EEB6EABBB490ULL,
0xDB55AACF12C73561ULL, 0x99A54B24B72D357BULL, 0x5EB4691841135855ULL, 0x1C4488F3E4F9584FULL,
0x2644C6D0383BF54AULL, 0x64B4273B9DD1F550ULL, 0xA3A505076BEF987EULL, 0xE155E4ECCE059864ULL,
0x6F77A09536791995ULL, 0x2D87417E9393198FULL, 0xEA96634265AD74A1ULL, 0xA86682A9C04774BBULL,
0xB4220A5A24BE2CF4ULL, 0xF6D2EBB181542CEEULL, 0x31C3C98D776A41C0ULL, 0x73332866D28041DAULL,
0xFD116C1F2AFCC02BULL, 0xBFE18DF48F16C031ULL, 0x78F0AFC87928AD1FULL, 0x3A004E23DCC2AD05ULL,
0x4C898D607077A834ULL, 0x0E796C8BD19DA82EULL, 0xC9684EB723A3C500ULL, 0x8B98AF5C8649C51AULL,
0x05BAEB257E3544EBULL, 0x474A0ACEDBDF44F1ULL, 0x805B28F22DE129DFULL, 0xC2ABC919880B29C5ULL,
0xDEEF41EA6CF2718AULL, 0x9C1FA001C9187190ULL, 0x5B0E823D3F261CBEULL, 0x19FE63D69ACC1CA4ULL,
0x97DC27AF62B09D55ULL, 0xD52CC644C75A9D4FULL, 0x123DE4783164F061ULL, 0x50CD0593948EF07BULL,
0x6ACD4BB0484C5D7EULL, 0x283DAA5BECA65D64ULL, 0xEF2C88671B98304AULL, 0xADDC698CBE723050ULL,
0x23FE2DF5460EB1A1ULL, 0x610ECC1EE3E4B1BBULL, 0xA61FEE2215DADC95ULL, 0xE4EF0FC9B030DC8FULL,
0xF8AB873A54C984C0ULL, 0xBA5B66D1F12384DAULL, 0x7D4A44ED071DE9F4ULL, 0x3FBAA506A2F7E9EEULL,
0xB198E17F5A8B681FULL, 0xF3680094FF616805ULL, 0x347922A8095F052BULL, 0x7689C343ACB50531ULL,
0x98131AE0E0ED2F68ULL, 0xDAE3FB0B45072F72ULL, 0x1DF2D937B339425CULL, 0x5F0238DC16D34246ULL,
0xD1207CA5EEAFC3B7ULL, 0x93D09D4E4B45C3ADULL, 0x54C1B172BD7BAE83ULL, 0x163150991891AE99ULL,
0x0A75D66AFC68F6D6ULL, 0x488537815982F6CCULL, 0x8F9415BDAFBC9BE2ULL, 0xCD64F4560A569BF8ULL,
0x4346B02FF22A1A09ULL, 0x01B651C457C01A13ULL, 0xC6A773F8A1FE773DULL, 0x8457921304147727ULL,
0xBE57DC30D8D6DA22ULL, 0xFCA73DDB7D3CDA38ULL, 0x3BB61FE78B02B716ULL, 0x7946FE0C2EE8B70CULL,
0xF764BA75D69436FDULL, 0xB5945B9E737E36E7ULL, 0x728579A285405BC9ULL, 0x3075984920AA5BD3ULL,
0x2C3110BAC453039CULL, 0x6EC1F15161B90386ULL, 0xA9D0D36D97876EA8ULL, 0xEB203286326D6EB2ULL,
0x650276FFCA11EF43ULL, 0x27F297146FFBEF59ULL, 0xE0E3B52899C58277ULL, 0xA21354C33C2F826DULL,
0xD49A9780909A875CULL, 0x966A766B35708746ULL, 0x517B5457C34EEA68ULL, 0x138BB5BC66A4EA72ULL,
0x9DA9F1C59ED86B83ULL, 0xDF59102E3B326B99ULL, 0x18483212CD0C06B7ULL, 0x5AB8D3F968E606ADULL,
0x46FC5B0A8C1F5EE2ULL, 0x040CBA4129F55EF8ULL, 0xC31D98DDDFCB33D6ULL, 0x81ED79367A2133CCULL,
0x0FCF3D4F825DB23DULL, 0x4D3FDCA427B7B227ULL, 0x8A2EFE98D189DF09ULL, 0xC8DE1F737463DF13ULL,
0xF2DE5150A8A17216ULL, 0xB02EB0BB0D4B720CULL, 0x773F9287FB751F22ULL, 0x35CF736C5E9F1F38ULL,
0xBBED3715A6E39EC9ULL, 0xF91DD6FE03099ED3ULL, 0x3E0CF4C2F537F3FDULL, 0x7CFC152950DDF3E7ULL,
0x60B89DDAB424ABA8ULL, 0x22487C3111CEABB2ULL, 0xE5595E0DE7F0C69CULL, 0xA7A9BFE6421AC686ULL,
0x298BFB9FBA664777ULL, 0x6B7B1A741F8C476DULL, 0xAC6A3848E9B22A43ULL, 0xEE9AD9A34C582A59ULL,
};
u64 drr_crc64(const void *data, u64 len) {
const u8 *p = (const u8 *)data;
u64 crc = 0xFFFFFFFFFFFFFFFFULL;
for (u64 i = 0; i < len; i++) {
crc = crc64_table[(crc ^ p[i]) & 0xFF] ^ (crc >> 8);
}
return crc ^ 0xFFFFFFFFFFFFFFFFULL;
}
/* ---- 全局 DRR 状态 ---- */
static drr_state g_drr;
/* ---- Phase 8: 快照区 / 看门狗 / 恢复行为控制 ---- */
#define DRR_SNAP_MAGIC 0x445252534E415021ULL /* "DRRSNAP!" */
#define DRR_SNAP_VERSION 1u
typedef struct {
u64 magic;
u32 version;
u32 capacity; /* 条目容量(page0 空间决定) */
u32 used;
u32 generation;
u64 crc;
} drr_snap_header;
static dkm_dma_buffer g_snap_region;
static int g_snap_ok = 0;
static u32 g_snap_capacity = 0;
static int g_reboot_enabled = 1;
static void (*g_sched_fault_cb)(u32 task_slot) = 0;
typedef struct {
u32 task_slot; /* 0xFFFFFFFF = 空闲 */
u32 timeout_ticks;
u64 last_kick_tick;
} drr_watchdog_entry;
static drr_watchdog_entry g_drr_wd[DRR_WATCHDOG_MAX];
static drr_snap_header *snap_header(void) {
return (drr_snap_header *)g_snap_region.virt;
}
static drr_ckpt_page_entry *snap_entries(void) {
return (drr_ckpt_page_entry *)((u8 *)g_snap_region.virt + 64);
}
static u8 *snap_page_ptr(u32 idx) {
return (u8 *)g_snap_region.virt + 4096ULL * (1ULL + (u64)idx);
}
/* ---- Root key(Phase 9: RDRAND + TSC jitter 混合,boot 生成一次)
* 生成一次后固化:drr_init 可重入(emergency reset),root key 不换,
* 否则旧 segment key 全部失效。持久化(sealed disk region)留待后续。 ---- */
static u64 g_root_key_storage[4];
static int g_root_key_ready = 0;
static const u64 g_root_key_fallback[4] = {
0x4452525554534D31ULL, /* "DRRUTSM1" */
0xFEEDFACECAFEF00DULL,
0x0123456789ABCDEFULL,
0xFEDCBA9876543210ULL
};
static u64 drr_tsc(void) {
u64 v;
__asm__ volatile("rdtsc" : "=A"(v));
return v;
}
static int drr_have_rdrand(void) {
u32 a, b, c, d;
__asm__ volatile("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "a"(1u), "c"(0u));
return (int)((c >> 30) & 1u);
}
static int drr_rdrand64(u64 *out) {
u8 ok;
u64 v;
__asm__ volatile("rdrand %0; setc %1" : "=r"(v), "=qm"(ok) :: "cc");
if (!ok) return 0;
*out = v;
return 1;
}
static void drr_root_key_generate(void) {
if (g_root_key_ready) {
g_drr.root_key = g_root_key_storage;
return;
}
int rdrand_ok = 1;
if (drr_have_rdrand()) {
for (int i = 0; i < 4; i++) {
if (!drr_rdrand64(&g_root_key_storage[i])) {
rdrand_ok = 0;
break;
}
}
} else {
rdrand_ok = 0;
}
if (rdrand_ok) {
/* 纵深:混入 TSC jitter,防 RDRAND 单点失效 */
for (int i = 0; i < 4; i++) {
g_root_key_storage[i] ^= drr_tsc() * 0x9e3779b97f4a7c15ULL;
}
} else {
/* 无 RDRAND:常量基底 + 多轮 TSC jitter 混合 */
for (int i = 0; i < 4; i++) {
g_root_key_storage[i] = g_root_key_fallback[i];
}
for (int r = 0; r < 16; r++) {
u64 j = drr_tsc();
for (int i = 0; i < 4; i++) {
j = (j ^ drr_tsc()) * 0x9e3779b97f4a7c15ULL;
g_root_key_storage[i] ^= j;
for (volatile int d = 0; d < 50; d++) { }
}
}
}
g_root_key_ready = 1;
g_drr.root_key = g_root_key_storage;
log_info("[DRR] root key generated");
log_hex64("[DRR] rdrand=", (u64)rdrand_ok);
}
/* ---- Emergency Pool 内部分配 ---- */
static void *pool_alloc_internal(u64 size, u64 alignment) {
u64 current = (u64)&g_drr.pool[0] + g_drr.pool_offset;
u64 aligned = utsm_align_up_u64(current, alignment);
u64 new_offset = (aligned - (u64)&g_drr.pool[0]) + size;
if (new_offset > g_drr.pool_limit) {
return NULL;
}
g_drr.pool_offset = new_offset;
return (void *)aligned;
}
void *drr_emergency_alloc(u64 size, u64 alignment) {
if (!g_drr.initialized) return NULL;
return pool_alloc_internal(size, alignment);
}
void drr_emergency_reset(void) {
if (!g_drr.initialized) return;
/* 保留已分配的子缓冲区,仅重置池偏移到子缓冲区之后 */
/* 注意:此函数仅在 recovery 路径紧急情况下使用 */
g_drr.pool_offset = 0;
/* 重新分配子缓冲区 */
drr_init();
}
/* ---- R3b: FUCK 配置接线(drr_apply_config 设置,drr_init 消费) ---- */
static u64 g_cfg_pool_bytes; /* 0 = 编译期默认 */
static u64 g_cfg_log_size; /* 0 = 编译期默认 */
void drr_apply_config(u64 pool_kb, u64 recovery_log_size) {
g_cfg_pool_bytes = pool_kb ? pool_kb * 1024ULL : 0;
g_cfg_log_size = recovery_log_size;
if (g_cfg_pool_bytes > DRR_EMERGENCY_POOL_SIZE) {
log_warn("[DRR] pool_kb exceeds compile-time pool, clamped");
log_hex64("[DRR] compile-time=", DRR_EMERGENCY_POOL_SIZE);
g_cfg_pool_bytes = DRR_EMERGENCY_POOL_SIZE;
}
}
/* ---- 初始化 ---- */
void drr_init(void) {
log_info("[DRR] init begin");
drr_memzero(&g_drr, sizeof(g_drr));
/* R3b: 池上限 = min(编译期池, FUCK 配置);小于最小子缓冲布局时回退默认 */
g_drr.pool_offset = 0;
g_drr.pool_limit = DRR_EMERGENCY_POOL_SIZE;
{
const u64 MIN_LAYOUT =
DRR_EMERGENCY_STACK_SIZE + DRR_RECOVERY_LOG_SIZE +
DRR_CKPT_META_BUF_SIZE + DRR_CRASH_BUF_SIZE + DRR_META_SLAB_SIZE;
if (g_cfg_pool_bytes && g_cfg_pool_bytes >= MIN_LAYOUT) {
g_drr.pool_limit = g_cfg_pool_bytes;
} else if (g_cfg_pool_bytes) {
log_warn("[DRR] pool_kb below minimum sub-buffer layout, default kept");
log_hex64("[DRR] minimum=", MIN_LAYOUT);
}
}
drr_root_key_generate();
g_drr.recovery_generation = 1;
g_drr.heartbeat_interval = 1000;
g_drr.active_slot = 0; /* A */
/* 分配 Emergency Pool 子缓冲区(recovery log 大小可由 FUCK 配置) */
g_drr.stack_base = (u8 *)pool_alloc_internal(DRR_EMERGENCY_STACK_SIZE, 64);
g_drr.stack_size = DRR_EMERGENCY_STACK_SIZE;
g_drr.stack_ptr = DRR_EMERGENCY_STACK_SIZE; /* 栈从顶部向下增长 */
u64 log_size = DRR_RECOVERY_LOG_SIZE;
if (g_cfg_log_size && g_cfg_log_size >= sizeof(drr_log_entry) &&
g_cfg_log_size <= g_drr.pool_limit - g_drr.pool_offset) {
log_size = g_cfg_log_size;
} else if (g_cfg_log_size) {
log_warn("[DRR] recovery_log_size out of range, default kept");
}
g_drr.log_base = (drr_log_entry *)pool_alloc_internal(log_size, 64);
g_drr.log_capacity = (u32)(log_size / sizeof(drr_log_entry));
g_drr.log_count = 0;
g_drr.ckpt_meta_buf = (drr_checkpoint_meta *)pool_alloc_internal(DRR_CKPT_META_BUF_SIZE, 64);
g_drr.crash_buf = (u8 *)pool_alloc_internal(DRR_CRASH_BUF_SIZE, 64);
g_drr.crash_buf_size = DRR_CRASH_BUF_SIZE;
g_drr.meta_slab = pool_alloc_internal(DRR_META_SLAB_SIZE, 64);
g_drr.meta_slab_offset = 0;
/* 初始化 A/B slot */
drr_memzero(&g_drr.ckpt_a, sizeof(drr_checkpoint_meta));
drr_memzero(&g_drr.ckpt_b, sizeof(drr_checkpoint_meta));
g_drr.ckpt_a.magic = DRR_CKPT_MAGIC;
g_drr.ckpt_a.version = DRR_CKPT_VERSION;
g_drr.ckpt_a.active = 1;
g_drr.ckpt_b.magic = DRR_CKPT_MAGIC;
g_drr.ckpt_b.version = DRR_CKPT_VERSION;
g_drr.initialized = 1;
log_hex64("[DRR] pool_limit=", g_drr.pool_limit);
log_hex64("[DRR] log_capacity=", (u64)g_drr.log_capacity);
/* ---- Phase 8: 快照区(dma 页,独立于普通堆;失败降级 metadata-only) ---- */
g_snap_ok = 0;
g_snap_capacity = 0;
g_reboot_enabled = 1;
g_sched_fault_cb = 0;
for (int wdi = 0; wdi < DRR_WATCHDOG_MAX; wdi++) {
g_drr_wd[wdi].task_slot = 0xFFFFFFFFu;
g_drr_wd[wdi].timeout_ticks = 0;
g_drr_wd[wdi].last_kick_tick = 0;
}
{
/* page0 = 头 + 条目数组,其后 128 页快照数据(共 129 页) */
dkm_dma_buffer buf;
if (dma_alloc_pages(1 + 128, 4096, 0xFFFFFFFFULL, &buf) == 0 && buf.virt) {
g_snap_region = buf;
u32 cap = (u32)((4096 - 64) / sizeof(drr_ckpt_page_entry));
drr_snap_header *h = (drr_snap_header *)buf.virt;
drr_memzero(h, 4096);
h->magic = DRR_SNAP_MAGIC;
h->version = DRR_SNAP_VERSION;
h->capacity = cap;
h->used = 0;
g_snap_capacity = cap;
g_snap_ok = 1;
log_info("[DRR] snapshot region ok");
log_hex64("[DRR] pages=", 1 + 128);
} else {
/* 严格错误策略插桩:快照区是 DRR 页回滚的前提,缺失即降级
* metadata-only——按零降级原则直接 panic(DRR-E01)。 */
panic_full("DRR-E01 SNAPSHOT REGION ALLOC FAILED",
"snapshot dma pages unavailable; metadata-only mode is forbidden", 0);
}
}
log_info("[DRR] init ok");
}
/* ===================================================================
* 严格错误策略插桩:设计已定但未实现的 DRR 能力,建立代码骨架,
* 调用即 panic(DRR-E2x 系列)。当前无调用方(骨架)。
* =================================================================== */
/* Root key 持久化(sealed disk region):drr_init 可重入要求 root key
* 跨 emergency reset 固化。当前实现走内存 fallback key(见
* drr_root_key_generate),sealed disk 尚未落盘。 */
void drr_root_key_seal_to_disk(void) {
panic_full("DRR-E02 ROOT KEY SEAL NOT IMPLEMENTED",
"sealed disk region for root key persistence: designed, not implemented", 0);
}
/* task_kill crypto erase:任务被杀时 key_epoch++ 并擦除其密钥材料。
* 当前 task_exit 只回收 slot,不做 crypto erase。 */
void drr_task_kill_crypto_erase(u32 task_slot) {
(void)task_slot;
panic_full("DRR-E03 TASK KILL CRYPTO ERASE NOT IMPLEMENTED",
"key_epoch++ erase on task kill: designed, not implemented", 0);
}
/* segment/system 级回滚入口(R4 遗留):页级回滚已实现,
* segment/system 级接口的调用方尚未接线。 */
void drr_rollback_segment(u32 seg_slot) {
(void)seg_slot;
panic_full("DRR-E04 SEGMENT ROLLBACK NOT IMPLEMENTED",
"segment-level rollback: designed (R4), not verified/implemented", 0);
}
void drr_rollback_system(void) {
panic_full("DRR-E05 SYSTEM ROLLBACK NOT IMPLEMENTED",
"system-level rollback: designed (R4), not verified/implemented", 0);
}
/* DKM 驱动 recovery ops(DKM README 设计:quiesce/reset/reinit/dump_state)。
* 驱动侧从未提供该回调表,DRR 亦未在恢复路径调用。 */
typedef struct {
u32 magic; /* 'D','R','O','P' */
u32 version;
void (*quiesce)(void *drv);
void (*reset)(void *drv);
void (*reinit)(void *drv);
void (*dump_state)(void *drv);
} dkm_driver_recovery_ops;
void drr_driver_recovery_dispatch(const dkm_driver_recovery_ops *ops, void *drv) {
(void)drv;
if (!ops) {
panic_full("DRR-E06 DRIVER RECOVERY OPS MISSING",
"driver did not provide dkm_driver_recovery_ops", 0);
}
panic_full("DRR-E07 DRIVER RECOVERY NOT IMPLEMENTED",
"quiesce/reset/reinit dispatch: designed (DKM README), not implemented", 0);
}
const u64 *drr_get_root_key(void) {
return g_drr.root_key;
}
u64 drr_recovery_generation(void) {
return g_drr.recovery_generation;
}
/* ---- Fault 报告 ---- */
void drr_report_fault(const char *reason) {
if (!g_drr.initialized) return;
log_error("[DRR] FAULT: ");
log_error(reason);
/* 记录到 crash buffer */
if (g_drr.crash_buf && g_drr.crash_buf_size > 0) {
/* 简单记录:写入 reason 的前 N 字节 */
u64 i = 0;
const char *s = reason;
while (*s && i < g_drr.crash_buf_size - 1) {
g_drr.crash_buf[i++] = (u8)*s++;
}
g_drr.crash_buf[i] = 0;
}
/* 增加 recovery generation */
g_drr.recovery_generation++;
}
/* ---- F1: 崩溃归档(panic_full 调用;crash_buf 写 symbol+msg+rip 简表) ----
* 返回 0=已归档;-1=DRR 未初始化(crash_buf 不可用)。 */
int drr_crash_archive(const char *symbol, const char *msg, const void *regs) {
if (!g_drr.initialized || !g_drr.crash_buf || g_drr.crash_buf_size == 0) {
return -1;
}
u64 i = 0;
u8 *b = g_drr.crash_buf;
u64 cap = g_drr.crash_buf_size - 1;
/* 头部标记 */
const char *magic = "CRASH1";
for (const char *s = magic; *s && i < cap; s++) b[i++] = (u8)*s;
b[i++] = '|';
for (const char *s = symbol ? symbol : "UNKNOWN"; *s && i < cap; s++) b[i++] = (u8)*s;
b[i++] = '|';
for (const char *s = msg ? msg : "-"; *s && i < cap; s++) b[i++] = (u8)*s;
b[i] = 0;
/* recovery generation 前进(归档计数) */
g_drr.recovery_generation++;
log_error("[DRR] crash archived");
log_hex64("[DRR] generation=", g_drr.recovery_generation);
return 0;
}
/* ---- Recovery Log ---- */
void drr_log_write_intent(u32 segment_slot, u64 offset, u64 len) {
if (!g_drr.initialized || !g_drr.log_base) return;
if (g_drr.log_count >= g_drr.log_capacity) {
/* 日志满,最简单的策略:丢弃最早的条目 */
for (u32 i = 1; i < g_drr.log_count; i++) {
g_drr.log_base[i - 1] = g_drr.log_base[i];
}
g_drr.log_count--;
}
drr_log_entry *e = &g_drr.log_base[g_drr.log_count++];
e->segment_slot = segment_slot;
e->flags = DRR_LOG_FLAG_INTENT;
e->offset = offset;
e->length = len;
e->timestamp = g_drr.heartbeat_counter;
}
void drr_log_write_commit(u32 segment_slot, u64 offset, u64 len) {
if (!g_drr.initialized || !g_drr.log_base) return;
if (g_drr.log_count >= g_drr.log_capacity) {
for (u32 i = 1; i < g_drr.log_count; i++) {
g_drr.log_base[i - 1] = g_drr.log_base[i];
}
g_drr.log_count--;
}
drr_log_entry *e = &g_drr.log_base[g_drr.log_count++];
e->segment_slot = segment_slot;
e->flags = DRR_LOG_FLAG_COMMIT;
e->offset = offset;
e->length = len;
e->timestamp = g_drr.heartbeat_counter;
}
/* ---- Checkpoint ---- */
int drr_checkpoint_begin(drr_checkpoint_type type) {
if (!g_drr.initialized) return -1;
/* 选择 inactive slot */
drr_checkpoint_meta *target;
if (g_drr.active_slot == 0) {
target = &g_drr.ckpt_b;
} else {
target = &g_drr.ckpt_a;
}
target->magic = DRR_CKPT_MAGIC;
target->version = DRR_CKPT_VERSION;
target->active = 0; /* 写入时为 inactive */
target->type = type;
target->global_epoch = g_drr.recovery_generation;
target->dirty_page_count = 0;
target->mac_root = 0;
target->segment_count = 0;
target->crc = 0;
return 0;
}
int drr_checkpoint_finish(void) {
if (!g_drr.initialized) return -1;
/* 写入 inactive slot 的 CRC */
drr_checkpoint_meta *target;
if (g_drr.active_slot == 0) {
target = &g_drr.ckpt_b;
} else {
target = &g_drr.ckpt_a;
}
/* 计算 CRC(不含 crc 字段本身) */
target->crc = drr_crc64(target,
sizeof(drr_checkpoint_meta) - sizeof(u64));
/* 原子切换 active slot */
target->active = 1;
/* 旧 slot 标记 inactive */
if (g_drr.active_slot == 0) {
g_drr.ckpt_a.active = 0;
g_drr.active_slot = 1;
} else {
g_drr.ckpt_b.active = 0;
g_drr.active_slot = 0;
}
/* 增加 recovery generation */
g_drr.recovery_generation++;
/* 清空 recovery log */
g_drr.log_count = 0;
return 0;
}
int drr_checkpoint_recover(drr_checkpoint_meta *out_meta) {
if (!g_drr.initialized || !out_meta) return -1;
/* 尝试 active slot */
drr_checkpoint_meta *active = (g_drr.active_slot == 0) ?
&g_drr.ckpt_a : &g_drr.ckpt_b;
drr_checkpoint_meta *fallback = (g_drr.active_slot == 0) ?
&g_drr.ckpt_b : &g_drr.ckpt_a;
/* 验证 active slot */
if (active->magic == DRR_CKPT_MAGIC && active->active == 1) {
u64 expected_crc = active->crc;
active->crc = 0;
u64 actual_crc = drr_crc64(active,
sizeof(drr_checkpoint_meta) - sizeof(u64));
active->crc = expected_crc;
if (actual_crc == expected_crc) {
drr_memcpy(out_meta, active, sizeof(drr_checkpoint_meta));
return 0;
}
}
/* active 无效,尝试 fallback */
if (fallback->magic == DRR_CKPT_MAGIC && fallback->active == 1) {
u64 expected_crc = fallback->crc;
fallback->crc = 0;
u64 actual_crc = drr_crc64(fallback,
sizeof(drr_checkpoint_meta) - sizeof(u64));
fallback->crc = expected_crc;
if (actual_crc == expected_crc) {
drr_memcpy(out_meta, fallback, sizeof(drr_checkpoint_meta));
return 0;
}
}
/* 双槽都无效 */
return -2;
}
/* ---- Heartbeat ---- */
void drr_heartbeat_tick(void) {
if (!g_drr.initialized) return;
g_drr.heartbeat_counter++;
}
u64 drr_heartbeat_get(void) {
return g_drr.heartbeat_counter;
}
/* ===================================================================
* Phase 8: 真实脏页快照 / 页级回滚 / 看门狗 / system rollback
* =================================================================== */
int drr_ckpt_snapshot_dirty(void) {
if (!g_drr.initialized) return -1;
if (!g_snap_ok) return -2; /* metadata-only 模式不支持页快照 */
drr_checkpoint_begin(DRR_CKPT_DIRTY_PAGE);
drr_snap_header *h = snap_header();
drr_ckpt_page_entry *entries = snap_entries();
u32 used = 0;
for (u32 slot = 0; slot < g_utsm_max_segments; slot++) {
utsm_segment_desc *desc = utsm_get_segment(slot);
if (!desc || desc->state != UTSM_SEG_ACTIVE) continue;
desc->state = UTSM_SEG_CHECKPOINTING;
for (u32 s = 0; s < desc->dirty_shard_count && desc->dirty_shards; s++) {
utsm_dirty_shard *shard = &desc->dirty_shards[s];
if (!shard->bitmap) continue;
u64 words = (shard->page_count + 63) / 64;
for (u64 w = 0; w < words && used < g_snap_capacity; w++) {
u64 word = shard->bitmap[w];
while (word && used < g_snap_capacity) {
u64 bit = (u64)__builtin_ctzll(word);
u64 page = w * 64 + bit;
u8 *src = desc->cipher_base + page * UTSM_PAGE_SIZE;
u8 *dst = snap_page_ptr(used);
drr_memcpy(dst, src, UTSM_PAGE_SIZE);
entries[used].seg_slot = slot;
entries[used].page_index = (u32)page;
entries[used].cipher_vaddr = (u64)src;
entries[used].crc = drr_crc64(dst, UTSM_PAGE_SIZE);
entries[used].key_epoch = desc->key_epoch;
entries[used].mac = utsm_page_mac(g_drr.root_key, slot, page,
desc->key_epoch, dst);
entries[used].region_idx = used;
entries[used].used = 1;
used++;
/* 快照成功才清脏位;区满时保留脏位(部分提交,下轮重试) */
shard->bitmap[w] &= ~(1ULL << bit);
if (shard->dirty_count > 0) shard->dirty_count--;
word &= ~(1ULL << bit);
}
}
shard->last_checkpoint_epoch = g_drr.recovery_generation;
}
desc->state = UTSM_SEG_ACTIVE;
desc->checkpoint_generation = g_drr.recovery_generation;
if (used >= g_snap_capacity) break;
}
/* 区域头(crc 不含自身字段) */
h->used = used;
h->generation = (u32)g_drr.recovery_generation;
h->crc = drr_crc64(h, sizeof(drr_snap_header) - sizeof(u64));
/* 元数据 + A/B 原子切换(begin 已选好 inactive slot,同一表达式取回) */
drr_checkpoint_meta *target = (g_drr.active_slot == 0) ? &g_drr.ckpt_b : &g_drr.ckpt_a;
target->dirty_page_count = used;
/* Phase 9: mac_root = keyed BLAKE2b 链(root_key 派生,绑定全部页 MAC) */
{
u8 kb[32];
u8 chain[64];
for (int i = 0; i < 4; i++) utsm_store64_le(kb + 8 * i, g_drr.root_key[i]);
utsm_blake2b_ctx mc;
utsm_blake2b_init(&mc, 64, kb, 32);
for (u32 i = 0; i < used; i++) {
u8 rec[8 + 8 + 8 + 8];
utsm_store64_le(rec + 0, 0x544F4F524D535455ULL); /* "UTSMROOT" LE */
utsm_store64_le(rec + 8, ((u64)entries[i].seg_slot) |
((u64)entries[i].page_index << 32));
utsm_store64_le(rec + 16, entries[i].key_epoch);
utsm_store64_le(rec + 24, entries[i].mac);
utsm_blake2b_update(&mc, rec, sizeof(rec));
}
utsm_blake2b_final(&mc, chain);
target->mac_root = utsm_load64_le(chain);
}
target->segment_count = 0;
drr_checkpoint_finish();
log_info("[DRR] ckpt snapshot ok");
log_hex64("[DRR] pages=", used);
return (int)used;
}
int drr_rollback_pages(void) {
if (!g_drr.initialized) return -1;
if (!g_snap_ok) return -2;
drr_checkpoint_meta meta;
if (drr_checkpoint_recover(&meta) != 0) return -3;
if (meta.type != DRR_CKPT_DIRTY_PAGE) return -4;
drr_snap_header *h = snap_header();
if (h->magic != DRR_SNAP_MAGIC || h->version != DRR_SNAP_VERSION) return -5;
u32 used = h->used;
if (used > h->capacity) used = h->capacity;
drr_ckpt_page_entry *entries = snap_entries();
/* 触碰段先置 RECOVERING */
for (u32 i = 0; i < used; i++) {
utsm_segment_desc *d = utsm_get_segment(entries[i].seg_slot);
if (d && d->state == UTSM_SEG_ACTIVE) d->state = UTSM_SEG_RECOVERING;
}
int failed = 0;
u32 restored = 0;
for (u32 i = 0; i < used; i++) {
drr_ckpt_page_entry *e = &entries[i];
u8 *snap = snap_page_ptr(e->region_idx);
utsm_segment_desc *d = utsm_get_segment(e->seg_slot);
if (drr_crc64(snap, UTSM_PAGE_SIZE) != e->crc) {
failed = 1;
if (d) d->state = UTSM_SEG_POISONED;
log_error("[DRR] rollback crc fail");
log_hex64("[DRR] seg_slot=", e->seg_slot);
log_hex64("[DRR] page=", e->page_index);
continue;
}
/* Phase 9: 页 MAC 校验(伪造/跨纪元重放/区域篡改在此被拒) */
u64 mac = utsm_page_mac(g_drr.root_key, e->seg_slot, e->page_index,
e->key_epoch, snap);
if (mac != e->mac) {
failed = 1;
if (d) d->state = UTSM_SEG_POISONED;
log_error("[DRR] rollback mac fail");
log_hex64("[DRR] seg_slot=", e->seg_slot);
log_hex64("[DRR] page=", e->page_index);
continue;
}
drr_memcpy((void *)e->cipher_vaddr, snap, UTSM_PAGE_SIZE);
restored++;
/* 清除该页脏位(P2 之类的回写不再被误判为未 checkpoint) */
if (d && d->dirty_shard_count > 0 && d->dirty_shards && d->dirty_shards[0].bitmap) {
utsm_dirty_shard *sh = &d->dirty_shards[0];
u64 page = e->page_index;
if (page < sh->page_count && (sh->bitmap[page / 64] & (1ULL << (page % 64)))) {
sh->bitmap[page / 64] &= ~(1ULL << (page % 64));
if (sh->dirty_count > 0) sh->dirty_count--;
}
}
if (d && d->state == UTSM_SEG_RECOVERING) d->state = UTSM_SEG_ACTIVE;
}
log_info("[DRR] rollback done");
log_hex64("[DRR] pages=", restored);
return failed ? -2 : (int)restored;
}
void drr_system_rollback(const char *reason) {
log_error("[DRR] SYSTEM ROLLBACK");
if (reason) log_error(reason);
log_hex64("[DRR] generation=", g_drr.recovery_generation);
log_hex64("[DRR] heartbeat=", g_drr.heartbeat_counter);
log_error("[DRR] rebooting (8042 reset)");
for (;;) {
__asm__ volatile("cli");
outb(0x64, 0xFE); /* 8042 复位(A20 gate 已无关紧要) */
for (volatile u32 i = 0; i < 1000000u; i++) { }
__asm__ volatile("hlt");
}
}
void drr_handle_task_fault(u32 task_slot, const char *reason) {
log_error("[DRR] FAULT");
if (reason) log_error(reason);
log_hex64("[DRR] task_slot=", task_slot);
drr_report_fault(reason ? reason : "task fault");
drr_log_write_intent(task_slot, 0, 0);
int pages = drr_rollback_pages();
log_hex64("[DRR] rollback_pages=", (u64)(i64)pages);
if (g_sched_fault_cb) {
g_sched_fault_cb(task_slot); /* 可能不返回(当前任务被杀+切换) */
drr_log_write_commit(task_slot, 0, 0);
return;
}
if (g_reboot_enabled) {
drr_system_rollback(reason ? reason : "task fault (no sched cb)");
}
/* reboot disabled(selftest):仅留日志 */
}
int drr_watchdog_register(u32 task_slot, u32 timeout_ticks) {
if (!g_drr.initialized || timeout_ticks == 0) return -1;
for (int i = 0; i < DRR_WATCHDOG_MAX; i++) {
if (g_drr_wd[i].task_slot == task_slot) {
g_drr_wd[i].timeout_ticks = timeout_ticks;
g_drr_wd[i].last_kick_tick = g_drr.heartbeat_counter;
return 0;
}
}
for (int i = 0; i < DRR_WATCHDOG_MAX; i++) {
if (g_drr_wd[i].task_slot == 0xFFFFFFFFu) {
g_drr_wd[i].task_slot = task_slot;
g_drr_wd[i].timeout_ticks = timeout_ticks;
g_drr_wd[i].last_kick_tick = g_drr.heartbeat_counter;
return 0;
}
}
return -2;
}
int drr_watchdog_unregister(u32 task_slot) {
for (int i = 0; i < DRR_WATCHDOG_MAX; i++) {
if (g_drr_wd[i].task_slot == task_slot) {
g_drr_wd[i].task_slot = 0xFFFFFFFFu;
return 0;
}
}
return -1;
}
void drr_watchdog_kick(u32 task_slot) {
for (int i = 0; i < DRR_WATCHDOG_MAX; i++) {
if (g_drr_wd[i].task_slot == task_slot) {
g_drr_wd[i].last_kick_tick = g_drr.heartbeat_counter;
return;
}
}
}
void drr_watchdog_check(void) {
if (!g_drr.initialized) return;
for (int i = 0; i < DRR_WATCHDOG_MAX; i++) {
u32 slot = g_drr_wd[i].task_slot;
if (slot == 0xFFFFFFFFu) continue;
u64 now = g_drr.heartbeat_counter;
if (now - g_drr_wd[i].last_kick_tick > g_drr_wd[i].timeout_ticks) {
g_drr_wd[i].last_kick_tick = now; /* 防重复触发 */
drr_handle_task_fault(slot, "watchdog timeout");
}
}
}
void drr_set_reboot_enabled(int enabled) {
g_reboot_enabled = enabled;
}
void drr_set_sched_fault_cb(void (*cb)(u32 task_slot)) {
g_sched_fault_cb = cb;
}
/* kernel_api.drr 服务表(dkm_fill_platform_info 挂入) */
static const drr_recovery_api g_drr_api = {
.report_fault = drr_report_fault,
.heartbeat_get = drr_heartbeat_get,
.emergency_alloc = drr_emergency_alloc,
.ckpt_snapshot_dirty = drr_ckpt_snapshot_dirty,
.rollback_pages = drr_rollback_pages
};
const drr_recovery_api *drr_get_recovery_api(void) {
return &g_drr_api;
}