ohhhhhhhhhhh (exclude linux-extra-rootfs.img build artifact)

This commit is contained in:
Linehu
2026-10-01 23:13:42 +08:00
parent 737a2cb0db
commit 1074962546
533 changed files with 133239 additions and 5460 deletions
+2 -2
View File
@@ -9,8 +9,8 @@ CFLAGS := -target x86_64-unknown-none -std=c11 -ffreestanding -fno-builtin -fno-
ASFLAGS := -target x86_64-unknown-none -ffreestanding -fno-pic -fno-pie -mcmodel=kernel -mno-red-zone -mno-sse -mno-sse2 -mno-mmx -msoft-float -m64 -Iinclude -I../utsm-ipc
LDFLAGS := -nostdlib -static -z max-page-size=0x1000 -T linker.ld
C_SOURCES := $(wildcard arch/x86_64/*.c kernel/*.c runtime/*.c mm/*.c core/*.c crypto/*.c pckc/*.c utrw/*.c drr/*.c dkm/*.c test/*.c vmm/*.c pe/*.c)
S_SOURCES := $(wildcard arch/x86_64/*.S vmm/*.S)
C_SOURCES := $(wildcard arch/x86_64/*.c kernel/*.c runtime/*.c mm/*.c core/*.c crypto/*.c pckc/*.c utrw/*.c drr/*.c sched/*.c dkm/*.c test/*.c vmm/*.c pe/*.c)
S_SOURCES := $(wildcard arch/x86_64/*.S vmm/*.S sched/*.S)
OBJECTS := $(C_SOURCES:.c=.o) $(S_SOURCES:.S=.o)
DEPS := $(C_SOURCES:.c=.d)
-1
View File
@@ -1 +0,0 @@
arch/x86_64/halt.o: arch\x86_64\halt.c
Binary file not shown.
+26
View File
@@ -591,6 +591,26 @@ int irq_register(u8 vector, irq_handler_t handler) {
return 0;
}
/* Phase7: 显式 EOI(调度器 tick 等"handler 内可能切换任务"的路径用)。
* 序列复刻 idt_handler 默认 EOI: 先 LAPIC 钩子再 8259(按向量范围)。
* spurious 0xFF 特判与 idt_handler 一致(空 ISR 不该有 EOI)。 */
void idt_irq_eoi(u8 vector) {
if (vector < 16) vector = (u8)(0x20u + vector);
if (vector >= 32 && vector <= 47) {
if (g_apic_eoi_hook) g_apic_eoi_hook();
if (vector >= 0x28) outb(PIC2_CMD, 0x20);
outb(PIC1_CMD, 0x20);
} else if (vector >= 48 && vector != 0xFF) {
if (g_apic_eoi_hook) g_apic_eoi_hook();
}
}
/* Phase8: CPU 异常钩子(DRR 任务级 fault 接管)。 */
static int (*g_exc_hook)(u64 vector, u64 err, u64 rip) = 0;
void idt_set_exception_hook(int (*hook)(u64 vector, u64 err, u64 rip)) {
g_exc_hook = hook;
}
/* Stack frame pushed by isr_common in idt.S */
typedef struct {
u64 r11, r10, r9, r8, rax, rcx, rdx, rsi, rdi;
@@ -601,6 +621,12 @@ typedef struct {
void idt_handler(isr_frame *frame) {
if (frame->vector < 32) {
/* Phase8: DRR 异常钩子最前——返回非 0 = 异常已被消费
* (fault 任务被杀/切换,控制权不回到日志+停机路径) */
if (g_exc_hook &&
g_exc_hook(frame->vector, frame->error_code, frame->rip)) {
return;
}
/* CR2: #PF 的 fault 线性地址;CR3: 当前页表基址。
* 寄存器 dump 用于定位 fault 指令的操作数来源。 */
u64 cr2, cr3;
-6
View File
@@ -1,6 +0,0 @@
arch/x86_64/idt.o: arch\x86_64\idt.c include\utsm\idt.h \
include\utsm\types.h include\utsm\log.h include\utsm\instr.h
include\utsm\idt.h:
include\utsm\types.h:
include\utsm\log.h:
include\utsm\instr.h:
Binary file not shown.
-2
View File
@@ -1,2 +0,0 @@
arch/x86_64/io.o: arch\x86_64\io.c include\utsm\types.h
include\utsm\types.h:
Binary file not shown.
+182
View File
@@ -0,0 +1,182 @@
/* lapic_timer.c — 宿主自持 LAPIC 定时器(调度器 tick 源)
*
* 为什么不用 PIT 周期中断:默认 FUCK apic_route=1 时 apic.drv 验证完
* tick 链路后重新 mask GSI2(PIT IRQ0 线),PIT 周期中断不可达;
* LAPIC timer 不经 IOAPIC/PIC 路由,与路由模式解耦,且是 ROADMAP
* Phase 2 "LAPIC timer 替代 PIT" 的目标方案。
*
* 流程:MSR 0x1B → 物理基址 → map_mmio(SAS-R0 直接扩当前 CR3)
* → PIT ch0 单发 10ms 采样 CCR 差值校准
* → irq_vector_alloc 动态向量 + LVT periodic(先 mask,start 再放开)
*/
#include <utsm/lapic_timer.h>
#include <utsm/pit.h>
#include <utsm/paging.h>
#include <utsm/idt.h>
#include <utsm/dkm.h>
#include <utsm/log.h>
extern void outb(u16 port, u8 value);
extern u8 inb(u16 port);
#define MSR_IA32_APIC_BASE 0x1Bu
#define APIC_BASE_ENABLE (1ULL << 11)
#define APIC_BASE_X2APIC (1ULL << 10)
#define LAPIC_DEFAULT_PHYS 0xFEE00000ULL
#define LAPIC_EOI 0x0B0u
#define LAPIC_TPR 0x080u
#define LAPIC_SPURIOUS 0x0F0u
#define LAPIC_LVT_TIMER 0x320u
#define LAPIC_DIV_CONF 0x3E0u
#define LAPIC_INIT_CNT 0x380u
#define LAPIC_CUR_CNT 0x390u
#define LVT_MASK (1u << 16)
#define LVT_PERIODIC (1u << 17)
static volatile u32 *g_lapic = 0;
static int g_timer_vector = -1;
static inline u64 rdmsr_(u32 msr) {
u32 lo, hi;
__asm__ volatile("rdmsr" : "=a"(lo), "=d"(hi) : "c"(msr));
return ((u64)hi << 32) | lo;
}
static inline void wrmsr_(u32 msr, u64 v) {
u32 lo = (u32)v, hi = (u32)(v >> 32);
__asm__ volatile("wrmsr" :: "c"(msr), "a"(lo), "d"(hi));
}
static u32 lapic_read(u32 reg) { return g_lapic[reg / 4]; }
static void lapic_write(u32 reg, u32 v) { g_lapic[reg / 4] = v; }
int lapic_timer_init(u32 freq_hz) {
if (freq_hz == 0) freq_hz = 100;
if (!g_lapic) {
u64 base = rdmsr_(MSR_IA32_APIC_BASE);
if (!(base & APIC_BASE_ENABLE)) {
wrmsr_(MSR_IA32_APIC_BASE, base | APIC_BASE_ENABLE);
base = rdmsr_(MSR_IA32_APIC_BASE);
}
if (base & APIC_BASE_X2APIC) {
log_warn("[LAPIC] x2APIC mode, MMIO timer unsupported");
return -1;
}
u64 phys = base & 0xFFFFF000ULL;
if (phys == 0) phys = LAPIC_DEFAULT_PHYS;
const dkm_mmio_api *mm = paging_get_api();
if (!mm || !mm->map_mmio) return -2;
if (mm->map_mmio(phys, 0x1000) != 0) {
log_warn("[LAPIC] map_mmio failed");
return -3;
}
u64 hhdm = 0;
const dkm_kernel_api *api = dkm_get_kernel_api();
if (api) hhdm = api->hhdm_offset;
g_lapic = (volatile u32 *)(hhdm + phys);
if (mm->is_mapped && !mm->is_mapped((u64)g_lapic)) {
g_lapic = 0;
log_warn("[LAPIC] mapped page not reachable");
return -4;
}
/* 软件使能(spurious bit8);vector 保留既有值,无则 0xFF */
u32 svr = lapic_read(LAPIC_SPURIOUS);
if (!(svr & 0x100u)) {
u8 vec = (u8)(svr & 0xFFu);
if (vec == 0) vec = 0xFFu;
lapic_write(LAPIC_SPURIOUS, (u32)vec | 0x100u);
}
lapic_write(LAPIC_TPR, 0);
log_info("[LAPIC] mmio mapped");
log_hex64("[LAPIC] phys=", phys);
}
/* ---- PIT 单发校准:divide=16,10ms 窗口采样 CCR 差值 ---- */
lapic_write(LAPIC_DIV_CONF, 0x3); /* divide by 16 */
lapic_write(LAPIC_LVT_TIMER, (u32)0xFF | LVT_MASK | LVT_PERIODIC); /* 校准期 mask */
lapic_write(LAPIC_INIT_CNT, 0xFFFFFFFFu);
u32 ccr0 = 0;
for (int i = 0; i < 1000; i++) {
ccr0 = lapic_read(LAPIC_CUR_CNT);
if (ccr0 != 0) break;
__asm__ volatile("pause");
}
pit_oneshot_ms(10);
u16 prev = pit_latch_count();
u32 loops = 0;
for (;;) {
u16 cur = pit_latch_count();
if (cur > prev && loops > 10) break; /* 回绕 = 10ms 到期 */
prev = cur;
loops++;
}
u32 ccr1 = lapic_read(LAPIC_CUR_CNT);
u64 delta = (u64)ccr0 - (u64)ccr1; /* 16 分频时钟 10ms tick 数 */
if (delta < 1000) {
log_warn("[LAPIC] timer calibration implausible");
lapic_timer_stop();
return -5;
}
/* 期望周期 = delta * (1000 / freq_hz) / 10 */
u64 init = delta * 1000ULL / (u64)freq_hz / 10ULL;
if (init == 0) init = 1;
if (init > 0xFFFFFFFFULL) init = 0xFFFFFFFFULL;
if (g_timer_vector < 0) {
int vec = irq_vector_alloc();
if (vec < 0) {
log_warn("[LAPIC] irq_vector_alloc failed");
return -6;
}
g_timer_vector = vec;
}
/* 按校准值定频编程(LVT 保持 mask,start() 再放开)。
* 顺序:divide config → LVT(masked) → initial count。 */
lapic_write(LAPIC_DIV_CONF, 0x3);
lapic_write(LAPIC_LVT_TIMER,
((u32)g_timer_vector & 0xFFu) | LVT_MASK | LVT_PERIODIC);
lapic_write(LAPIC_INIT_CNT, (u32)init);
log_info("[LAPIC] timer calibrated");
log_hex64("[LAPIC] ticks/10ms=", delta);
log_hex64("[LAPIC] init_count=", init);
log_hex64("[LAPIC] vector=", (u64)g_timer_vector);
return 0;
}
int lapic_timer_vector(void) {
return g_timer_vector;
}
void lapic_timer_start(void) {
if (!g_lapic || g_timer_vector < 0) return;
/* 保持 divide/init 不变,仅解除 mask(periodic 模式已配) */
lapic_write(LAPIC_LVT_TIMER,
((u32)g_timer_vector & 0xFFu) | LVT_PERIODIC);
}
void lapic_timer_stop(void) {
if (g_lapic) {
lapic_write(LAPIC_LVT_TIMER, lapic_read(LAPIC_LVT_TIMER) | LVT_MASK);
lapic_write(LAPIC_INIT_CNT, 0);
}
if (g_timer_vector >= 0) {
irq_vector_free(g_timer_vector);
g_timer_vector = -1;
}
}
void lapic_timer_eoi(void) {
if (g_lapic) {
lapic_write(LAPIC_EOI, 0);
}
}
+45
View File
@@ -0,0 +1,45 @@
/* pit.c — PIT ch0 单发定时(LAPIC timer 校准用)
*
* 只用 mode 0(terminal count):单发、无周期中断、不注册 IRQ handler。
* 禁用 mode 3 —— B7 定论:PIT mode3 方波经 IOAPIC 边沿路由会双触发 (~200Hz)。
*/
#include <utsm/pit.h>
extern void outb(u16 port, u8 value);
extern u8 inb(u16 port);
#define PIT_CH0_DATA 0x40
#define PIT_CMD 0x43
#define PIT_BASE_HZ 1193182ULL
void pit_oneshot_ms(u32 ms) {
u64 div = (PIT_BASE_HZ * (u64)ms) / 1000ULL;
if (div == 0) div = 1;
if (div > 65535) div = 65535;
/* ch0 | lo/hi | mode0 (terminal count) | binary */
outb(PIT_CMD, 0x30);
outb(PIT_CH0_DATA, (u8)(div & 0xFF));
outb(PIT_CH0_DATA, (u8)((div >> 8) & 0xFF));
}
u16 pit_latch_count(void) {
outb(PIT_CMD, 0x00); /* ch0 latch 计数(读前锁存) */
u16 lo = inb(PIT_CH0_DATA);
u16 hi = inb(PIT_CH0_DATA);
return (u16)(lo | (hi << 8));
}
int pit_oneshot_expired(void) {
u16 c1 = pit_latch_count();
u16 c2 = pit_latch_count();
/* mode0 计到 0 后回绕继续递减:cur 回升即视为到期 */
return c2 >= c1;
}
void pit_quiet(void) {
/* ch0 mode0、计数 0:terminal count 立即到期,无后续输出/中断 */
outb(PIT_CMD, 0x30);
outb(PIT_CH0_DATA, 0x00);
outb(PIT_CH0_DATA, 0x00);
}
-2
View File
@@ -1,2 +0,0 @@
arch/x86_64/serial.o: arch\x86_64\serial.c include\utsm\types.h
include\utsm\types.h:
Binary file not shown.
-9
View File
@@ -1,9 +0,0 @@
core/capability.o: core\capability.c include\utsm\capability.h \
include\utsm\types.h include\utsm\status.h include\utsm\segment.h \
include\utsm\uuid.h include\utsm\dirty.h
include\utsm\capability.h:
include\utsm\types.h:
include\utsm\status.h:
include\utsm\segment.h:
include\utsm\uuid.h:
include\utsm\dirty.h:
Binary file not shown.
-11
View File
@@ -1,11 +0,0 @@
core/dirty.o: core\dirty.c include\utsm\dirty.h include\utsm\types.h \
include\utsm\segment.h include\utsm\uuid.h include\utsm\status.h \
include\utsm\capability.h include\utsm\arena.h include\utsm\config.h
include\utsm\dirty.h:
include\utsm\types.h:
include\utsm\segment.h:
include\utsm\uuid.h:
include\utsm\status.h:
include\utsm\capability.h:
include\utsm\arena.h:
include\utsm\config.h:
Binary file not shown.
-10
View File
@@ -1,10 +0,0 @@
core/dmp.o: core\dmp.c include\utsm\dmp.h include\utsm\types.h \
include\utsm\segment.h include\utsm\uuid.h include\utsm\status.h \
include\utsm\capability.h include\utsm\dirty.h
include\utsm\dmp.h:
include\utsm\types.h:
include\utsm\segment.h:
include\utsm\uuid.h:
include\utsm\status.h:
include\utsm\capability.h:
include\utsm\dirty.h:
Binary file not shown.
-13
View File
@@ -1,13 +0,0 @@
core/process.o: core\process.c include\utsm\process.h \
include\utsm\types.h include\utsm\uuid.h include\utsm\capability.h \
include\utsm\status.h include\utsm\config.h include\utsm\drr.h \
include\utsm\arena.h include\utsm\log.h
include\utsm\process.h:
include\utsm\types.h:
include\utsm\uuid.h:
include\utsm\capability.h:
include\utsm\status.h:
include\utsm\config.h:
include\utsm\drr.h:
include\utsm\arena.h:
include\utsm\log.h:
Binary file not shown.
-14
View File
@@ -1,14 +0,0 @@
core/segment.o: core\segment.c include\utsm\segment.h \
include\utsm\types.h include\utsm\uuid.h include\utsm\status.h \
include\utsm\capability.h include\utsm\dirty.h include\utsm\process.h \
include\utsm\config.h include\utsm\arena.h include\utsm\dmp.h
include\utsm\segment.h:
include\utsm\types.h:
include\utsm\uuid.h:
include\utsm\status.h:
include\utsm\capability.h:
include\utsm\dirty.h:
include\utsm\process.h:
include\utsm\config.h:
include\utsm\arena.h:
include\utsm\dmp.h:
Binary file not shown.
-25
View File
@@ -1,25 +0,0 @@
core/utsm_init.o: core\utsm_init.c include\utsm\utsm.h \
include\utsm\types.h include\utsm\status.h include\utsm\config.h \
include\utsm\uuid.h include\utsm\process.h include\utsm\capability.h \
include\utsm\segment.h include\utsm\dirty.h include\utsm\utrw.h \
include\utsm\vmm.h include\utsm\linux_loader.h include\utsm\ipc_shm.h \
..\utsm-ipc\ipc_proto.h include\utsm\hypercall.h include\utsm\pckc.h \
include\utsm\crypto.h include\utsm\log.h
include\utsm\utsm.h:
include\utsm\types.h:
include\utsm\status.h:
include\utsm\config.h:
include\utsm\uuid.h:
include\utsm\process.h:
include\utsm\capability.h:
include\utsm\segment.h:
include\utsm\dirty.h:
include\utsm\utrw.h:
include\utsm\vmm.h:
include\utsm\linux_loader.h:
include\utsm\ipc_shm.h:
..\utsm-ipc\ipc_proto.h:
include\utsm\hypercall.h:
include\utsm\pckc.h:
include\utsm\crypto.h:
include\utsm\log.h:
Binary file not shown.
+137
View File
@@ -0,0 +1,137 @@
/* blake2b.c — BLAKE2b(RFC 7693)实现
*
* 12 轮、128B 块、64-bit G 函数(旋转 32/24/16/63)。
* keyed 模式:init 时将 key 填充为首个 128B 块(RFC 7693 §2.3),
* update/final 沿用引用实现语义(惰性缓冲 + 计数器含 key 块)。
*/
#include <utsm/blake2b.h>
static const u64 blake2b_iv[8] = {
0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
};
static const u8 blake2b_sigma[10][16] = {
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 }
};
static inline u64 rotr64(u64 v, u32 c) {
return (v >> c) | (v << (64 - c));
}
#define B2B_G(v, a, b, c, d, x, y) do { \
(v)[a] = (v)[a] + (v)[b] + (x); (v)[d] = rotr64((v)[d] ^ (v)[a], 32); \
(v)[c] = (v)[c] + (v)[d]; (v)[b] = rotr64((v)[b] ^ (v)[c], 24); \
(v)[a] = (v)[a] + (v)[b] + (y); (v)[d] = rotr64((v)[d] ^ (v)[a], 16); \
(v)[c] = (v)[c] + (v)[d]; (v)[b] = rotr64((v)[b] ^ (v)[c], 63); \
} while (0)
static void blake2b_compress(utsm_blake2b_ctx *ctx, const u8 *block) {
u64 m[16];
u64 v[16];
for (int i = 0; i < 16; i++) {
m[i] = utsm_load64_le(block + 8 * i);
}
for (int i = 0; i < 8; i++) {
v[i] = ctx->h[i];
v[i + 8] = blake2b_iv[i];
}
v[12] ^= ctx->t[0];
v[13] ^= ctx->t[1];
if (ctx->last_block) {
v[14] ^= ~(u64)0;
}
for (int r = 0; r < 12; r++) {
const u8 *s = blake2b_sigma[r % 10];
B2B_G(v, 0, 4, 8, 12, m[s[0]], m[s[1]]);
B2B_G(v, 1, 5, 9, 13, m[s[2]], m[s[3]]);
B2B_G(v, 2, 6, 10, 14, m[s[4]], m[s[5]]);
B2B_G(v, 3, 7, 11, 15, m[s[6]], m[s[7]]);
B2B_G(v, 0, 5, 10, 15, m[s[8]], m[s[9]]);
B2B_G(v, 1, 6, 11, 12, m[s[10]], m[s[11]]);
B2B_G(v, 2, 7, 8, 13, m[s[12]], m[s[13]]);
B2B_G(v, 3, 4, 9, 14, m[s[14]], m[s[15]]);
}
for (int i = 0; i < 8; i++) {
ctx->h[i] ^= v[i] ^ v[i + 8];
}
}
void utsm_blake2b_init(utsm_blake2b_ctx *ctx, u32 out_len, const void *key, u32 key_len) {
if (out_len == 0 || out_len > UTSM_BLAKE2B_MAXOUT) out_len = UTSM_BLAKE2B_MAXOUT;
if (key_len > 64u) key_len = 64u;
for (int i = 0; i < 8; i++) ctx->h[i] = blake2b_iv[i];
ctx->h[0] ^= 0x01010000ULL ^ ((u64)key_len << 8) ^ (u64)out_len;
ctx->t[0] = 0;
ctx->t[1] = 0;
ctx->out_len = out_len;
ctx->buf_len = 0;
ctx->last_block = 0;
if (key && key_len > 0u) {
const u8 *k = (const u8 *)key;
for (u32 i = 0; i < key_len; i++) ctx->buf[i] = k[i];
for (u32 i = key_len; i < 128u; i++) ctx->buf[i] = 0;
ctx->buf_len = 128u; /* key 块挂起,随首个 update/final 压缩 */
}
}
void utsm_blake2b_update(utsm_blake2b_ctx *ctx, const void *data, u64 len) {
const u8 *in = (const u8 *)data;
while (len > 0) {
u32 left = ctx->buf_len;
u32 fill = UTSM_BLAKE2B_BLOCKBYTES - left;
if (len > (u64)fill) {
for (u32 i = 0; i < fill; i++) ctx->buf[left + i] = in[i];
ctx->t[0] += 128;
if (ctx->t[0] < 128) ctx->t[1]++;
blake2b_compress(ctx, ctx->buf);
ctx->buf_len = 0;
in += fill;
len -= fill;
} else {
for (u64 i = 0; i < len; i++) ctx->buf[left + i] = in[i];
ctx->buf_len += (u32)len;
return;
}
}
}
void utsm_blake2b_final(utsm_blake2b_ctx *ctx, void *out) {
ctx->t[0] += ctx->buf_len;
if (ctx->t[0] < (u64)ctx->buf_len) ctx->t[1]++;
ctx->last_block = 1;
for (u32 i = ctx->buf_len; i < UTSM_BLAKE2B_BLOCKBYTES; i++) ctx->buf[i] = 0;
blake2b_compress(ctx, ctx->buf);
u8 tmp[64];
for (int i = 0; i < 8; i++) utsm_store64_le(tmp + 8 * i, ctx->h[i]);
u8 *o = (u8 *)out;
for (u32 i = 0; i < ctx->out_len; i++) o[i] = tmp[i];
}
void utsm_blake2b(const void *data, u64 len, const void *key, u32 key_len, void *out, u32 out_len) {
utsm_blake2b_ctx ctx;
utsm_blake2b_init(&ctx, out_len, key, key_len);
utsm_blake2b_update(&ctx, data, len);
utsm_blake2b_final(&ctx, out);
}
+4
View File
@@ -0,0 +1,4 @@
crypto/blake2b.o: crypto\blake2b.c include\utsm\blake2b.h \
include\utsm\types.h
include\utsm\blake2b.h:
include\utsm\types.h:
+60
View File
@@ -0,0 +1,60 @@
/* chacha20.c — ChaCha20 block function(RFC 8439 §2.3)
*
* block function = 20 轮纯 ARX(无 message word 吸收;sigma 表仅用于
* 带明文的加密模式)。UTSM 用途:1 block = 1×64B cache line keystream。
* counter = 0(整条 line 只消费一个 block)
* nonce = tweak(低 32 位在前,高 32 位在后,第三字为 0)
* 纯 32-bit 整数运算,-mno-sse 下可用。
*/
#include <utsm/blake2b.h>
#include <utsm/crypto.h>
static const u32 chacha_iv[4] = {
0x61707865u, 0x3320646eu, 0x79622d32u, 0x6b206574u
};
static inline u32 rotl32(u32 v, u32 c) {
return (v << c) | (v >> (32 - c));
}
static void chacha_qr(u32 *v, int a, int b, int c, int d) {
v[a] += v[b]; v[d] ^= v[a]; v[d] = rotl32(v[d], 16);
v[c] += v[d]; v[b] ^= v[c]; v[b] = rotl32(v[b], 12);
v[a] += v[b]; v[d] ^= v[a]; v[d] = rotl32(v[d], 8);
v[c] += v[d]; v[b] ^= v[c]; v[b] = rotl32(v[b], 7);
}
void utsm_chacha20_block(const u32 key_words[8], u64 nonce, u64 counter, u8 out[64]) {
u32 st[16];
u32 v[16];
st[0] = chacha_iv[0];
st[1] = chacha_iv[1];
st[2] = chacha_iv[2];
st[3] = chacha_iv[3];
for (int i = 0; i < 8; i++) st[4 + i] = key_words[i];
st[12] = (u32)counter;
st[13] = (u32)(counter >> 32);
st[14] = (u32)nonce;
st[15] = (u32)(nonce >> 32);
for (int i = 0; i < 16; i++) v[i] = st[i];
for (int r = 0; r < 10; r++) {
/* column rounds */
chacha_qr(v, 0, 4, 8, 12);
chacha_qr(v, 1, 5, 9, 13);
chacha_qr(v, 2, 6, 10, 14);
chacha_qr(v, 3, 7, 11, 15);
/* diagonal rounds */
chacha_qr(v, 0, 5, 10, 15);
chacha_qr(v, 1, 6, 11, 12);
chacha_qr(v, 2, 7, 8, 13);
chacha_qr(v, 3, 4, 9, 14);
}
for (int i = 0; i < 16; i++) {
utsm_store32_le(out + 4 * i, v[i] + st[i]);
}
}
+6
View File
@@ -0,0 +1,6 @@
crypto/chacha20.o: crypto\chacha20.c include\utsm\blake2b.h \
include\utsm\types.h include\utsm\crypto.h include\utsm\uuid.h
include\utsm\blake2b.h:
include\utsm\types.h:
include\utsm\crypto.h:
include\utsm\uuid.h:
+26 -14
View File
@@ -1,19 +1,31 @@
#include <utsm/crypto.h>
#include <utsm/drr.h>
/* kdf.c — 段密钥派生(Phase 9:keyed BLAKE2b)
*
* segment_key = BLAKE2b-256(key=root_key, "UTSMSEGK"||p_uuid||s_uuid||key_epoch)
* root key 不直接加密数据;UUID 作为派生调谐因子(非明文密钥)。
* 确定性:同 (puuid, suuid, epoch) 恒得同 key —— PCKC 缓存正确性依赖此性质。
*/
static u64 mix64(u64 x) {
x ^= x >> 30;
x *= 0xbf58476d1ce4e5b9ULL;
x ^= x >> 27;
x *= 0x94d049bb133111ebULL;
x ^= x >> 31;
return x;
}
#include <utsm/crypto.h>
#include <utsm/blake2b.h>
#include <utsm/drr.h>
void utsm_kdf_segment_key(uuid128_t process_uuid, uuid128_t segment_uuid, u64 key_epoch, utsm_key_material *out_key) {
const u64 *root = drr_get_root_key();
out_key->words[0] = mix64(root[0] ^ process_uuid.hi ^ segment_uuid.lo ^ key_epoch);
out_key->words[1] = mix64(root[1] ^ process_uuid.lo ^ segment_uuid.hi ^ (key_epoch << 1));
out_key->words[2] = mix64(root[2] ^ process_uuid.hi ^ segment_uuid.hi ^ (key_epoch << 7));
out_key->words[3] = mix64(root[3] ^ process_uuid.lo ^ segment_uuid.lo ^ (key_epoch << 13));
u8 root_le[32];
u8 data[8 + 8 + 8 + 8 + 8];
u8 digest[32];
for (int i = 0; i < 4; i++) utsm_store64_le(root_le + 8 * i, root[i]);
utsm_store64_le(data + 0, 0x4B4745534D535455ULL); /* "UTSMSEGK" LE */
utsm_store64_le(data + 8, process_uuid.hi);
utsm_store64_le(data + 16, process_uuid.lo);
utsm_store64_le(data + 24, segment_uuid.hi);
utsm_store64_le(data + 32, segment_uuid.lo);
utsm_store64_le(data + 40, key_epoch);
utsm_blake2b(data, sizeof(data), root_le, 32, digest, 32);
for (int i = 0; i < 4; i++) out_key->words[i] = utsm_load64_le(digest + 8 * i);
}
+3 -1
View File
@@ -1,7 +1,9 @@
crypto/kdf.o: crypto\kdf.c include\utsm\crypto.h include\utsm\types.h \
include\utsm\uuid.h include\utsm\drr.h include\utsm\config.h
include\utsm\uuid.h include\utsm\blake2b.h include\utsm\drr.h \
include\utsm\config.h
include\utsm\crypto.h:
include\utsm\types.h:
include\utsm\uuid.h:
include\utsm\blake2b.h:
include\utsm\drr.h:
include\utsm\config.h:
Binary file not shown.
+32
View File
@@ -0,0 +1,32 @@
/* mac.c — 4KB 密文页 MAC(Phase 9:keyed BLAKE2b)
*
* page_mac = BLAKE2b-256(key=root_key, "UTSMPAGE"||seg_slot||page_index||key_epoch||cipher_page)[0..8)
* 绑定页归属(段/页号/纪元),防密文页在段间移位或跨纪元重放。
* 用途:DRR checkpoint 快照完整性 / rollback 校验(替换 CRC64 占位 MAC)。
*/
#include <utsm/crypto.h>
#include <utsm/blake2b.h>
#include <utsm/config.h>
u64 utsm_page_mac(const u64 *root_key, u32 seg_slot, u64 page_index, u64 key_epoch, const void *page) {
u8 root_le[32];
u8 ctx_data[8 + 4 + 4 + 8 + 8];
u8 digest[32];
for (int i = 0; i < 4; i++) utsm_store64_le(root_le + 8 * i, root_key[i]);
utsm_store64_le(ctx_data + 0, 0x454741504D535455ULL); /* "UTSMPAGE" LE */
utsm_store32_le(ctx_data + 8, seg_slot);
utsm_store32_le(ctx_data + 12, 0);
utsm_store64_le(ctx_data + 16, page_index);
utsm_store64_le(ctx_data + 24, key_epoch);
utsm_blake2b_ctx c;
utsm_blake2b_init(&c, 32, root_le, 32);
utsm_blake2b_update(&c, ctx_data, sizeof(ctx_data));
utsm_blake2b_update(&c, page, UTSM_PAGE_SIZE);
utsm_blake2b_final(&c, digest);
return utsm_load64_le(digest);
}
+7
View File
@@ -0,0 +1,7 @@
crypto/mac.o: crypto\mac.c include\utsm\crypto.h include\utsm\types.h \
include\utsm\uuid.h include\utsm\blake2b.h include\utsm\config.h
include\utsm\crypto.h:
include\utsm\types.h:
include\utsm\uuid.h:
include\utsm\blake2b.h:
include\utsm\config.h:
+20 -13
View File
@@ -1,19 +1,26 @@
/* stream.c — 64B cache line 流加密(Phase 9:ChaCha20)
*
* ct = pt XOR ChaCha20_block(segment_key, nonce=tweak, counter=0)
* 1 block = 1 line;加密解密同函数(XOR 流)。
* nonce 唯一性:(segment_key 全局唯一) × (line_index 段内唯一),
* key_epoch 混入 key 派生,故同 (key,nonce) 只生成一次 keystream。
*/
#include <utsm/crypto.h>
#include <utsm/blake2b.h>
#include <utsm/config.h>
static u64 next_stream_word(u64 x) {
x ^= x << 13;
x ^= x >> 7;
x ^= x << 17;
return x;
}
void utsm_crypt_line(const utsm_key_material *key, u64 tweak, const u8 *in, u8 *out) {
u64 state = key->words[0] ^ key->words[1] ^ key->words[2] ^ key->words[3] ^ tweak;
for (u64 i = 0; i < UTSM_CACHE_LINE_SIZE; i += 8) {
state = next_stream_word(state + i + 0xa5a5a5a5a5a5a5a5ULL);
for (u64 j = 0; j < 8; j++) {
out[i + j] = in[i + j] ^ (u8)(state >> (j * 8));
}
u32 kw[8];
for (int i = 0; i < 4; i++) {
kw[2 * i] = (u32)(key->words[i] & 0xFFFFFFFFu);
kw[2 * i + 1] = (u32)(key->words[i] >> 32);
}
u8 ks[64];
utsm_chacha20_block(kw, tweak, 0, ks);
for (u32 i = 0; i < UTSM_CACHE_LINE_SIZE; i++) {
out[i] = in[i] ^ ks[i];
}
}
+3 -1
View File
@@ -1,6 +1,8 @@
crypto/stream.o: crypto\stream.c include\utsm\crypto.h \
include\utsm\types.h include\utsm\uuid.h include\utsm\config.h
include\utsm\types.h include\utsm\uuid.h include\utsm\blake2b.h \
include\utsm\config.h
include\utsm\crypto.h:
include\utsm\types.h:
include\utsm\uuid.h:
include\utsm\blake2b.h:
include\utsm\config.h:
Binary file not shown.
-5
View File
@@ -1,5 +0,0 @@
crypto/tweak.o: crypto\tweak.c include\utsm\crypto.h include\utsm\types.h \
include\utsm\uuid.h
include\utsm\crypto.h:
include\utsm\types.h:
include\utsm\uuid.h:
Binary file not shown.
-13
View File
@@ -1,13 +0,0 @@
dkm/boot_modules.o: dkm\boot_modules.c include\utsm\dkm.h \
include\utsm\types.h include\utsm\dma.h include\utsm\block.h \
include\utsm\net.h include\utsm\paging.h include\utsm\log.h \
include\utsm\arena.h dkm\..\arch\x86_64\limine.h
include\utsm\dkm.h:
include\utsm\types.h:
include\utsm\dma.h:
include\utsm\block.h:
include\utsm\net.h:
include\utsm\paging.h:
include\utsm\log.h:
include\utsm\arena.h:
dkm\..\arch\x86_64\limine.h:
Binary file not shown.
-9
View File
@@ -1,9 +0,0 @@
dkm/console_early.o: dkm\console_early.c include\utsm\dkm.h \
include\utsm\types.h include\utsm\dma.h include\utsm\block.h \
include\utsm\net.h include\utsm\paging.h
include\utsm\dkm.h:
include\utsm\types.h:
include\utsm\dma.h:
include\utsm\block.h:
include\utsm\net.h:
include\utsm\paging.h:
Binary file not shown.
-10
View File
@@ -1,10 +0,0 @@
dkm/dkm_core.o: dkm\dkm_core.c include\utsm\dkm.h include\utsm\types.h \
include\utsm\dma.h include\utsm\block.h include\utsm\net.h \
include\utsm\paging.h include\utsm\log.h
include\utsm\dkm.h:
include\utsm\types.h:
include\utsm\dma.h:
include\utsm\block.h:
include\utsm\net.h:
include\utsm\paging.h:
include\utsm\log.h:
Binary file not shown.
+5 -1
View File
@@ -57,7 +57,8 @@ static dkm_kernel_api g_kernel_api = {
.mmio = 0,
.mm_map_mmio = 0,
.mm_unmap_mmio = 0,
.register_apic_eoi = 0
.register_apic_eoi = 0,
.sched = 0
};
const dkm_kernel_api *dkm_get_kernel_api(void) {
@@ -75,6 +76,9 @@ void dkm_fill_platform_info(void) {
g_kernel_api.net = net_get_api();
g_kernel_api.block = block_get_api();
g_kernel_api.mmio = paging_get_api();
/* M4/Phase7-8: 调度器与恢复根服务表(drr 为原占位字段,此处激活) */
g_kernel_api.sched = utsm_sched_get_api();
g_kernel_api.drr = drr_get_recovery_api();
if (g_rsdp_request.response && g_rsdp_request.response->address) {
g_kernel_api.rsdp_address = g_rsdp_request.response->address;
}
-14
View File
@@ -1,14 +0,0 @@
dkm/kernel_api.o: dkm\kernel_api.c include\utsm\dkm.h \
include\utsm\types.h include\utsm\dma.h include\utsm\block.h \
include\utsm\net.h include\utsm\paging.h include\utsm\log.h \
include\utsm\idt.h include\utsm\mm.h dkm\..\arch\x86_64\limine.h
include\utsm\dkm.h:
include\utsm\types.h:
include\utsm\dma.h:
include\utsm\block.h:
include\utsm\net.h:
include\utsm\paging.h:
include\utsm\log.h:
include\utsm\idt.h:
include\utsm\mm.h:
dkm\..\arch\x86_64\limine.h:
Binary file not shown.
+81 -10
View File
@@ -290,15 +290,20 @@ void dsm_load_by_manifest(void) {
dsm_load_by_manifest_ex(NULL);
}
void dsm_load_by_manifest_ex(const ini_config *cfg) {
struct limine_module_response *rsp = g_module_request.response;
static int dsm_ensure_manifest(void) {
struct limine_module_response *rsp;
struct limine_file *manifest_file;
u64 i;
if (g_stage_count) return 0;
rsp = g_module_request.response;
if (!rsp) {
log_warn("[DSM] no Limine module response");
return;
return -1;
}
struct limine_file *manifest_file = 0;
for (u64 i = 0; i < rsp->module_count; i++) {
manifest_file = 0;
for (i = 0; i < rsp->module_count; i++) {
struct limine_file *f = rsp->modules[i];
if (f && f->path && f->cmdline && streq_static(f->cmdline, "dkm:manifest")) {
manifest_file = f;
@@ -308,22 +313,33 @@ void dsm_load_by_manifest_ex(const ini_config *cfg) {
if (!manifest_file) {
log_warn("[DSM] manifest not found in boot modules");
return;
return -1;
}
log_info("[DSM] parsing manifest");
dsm_parse_manifest((const char *)manifest_file->address, manifest_file->size);
log_info("[DSM] manifest parsed");
log_hex64("[DSM] stages=", (u64)g_stage_count);
return 0;
}
static void dsm_load_stage_range(const ini_config *cfg, int limit_stage, u32 max_stage_id) {
if (dsm_ensure_manifest() != 0) return;
for (u32 si = 0; si < g_stage_count; si++) {
dsm_stage_entry *stage = &g_stages[si];
if (limit_stage && stage->id > max_stage_id) continue;
log_info("[DSM] stage begin");
log_info(stage->name);
log_hex64("[DSM] driver count=", stage->driver_count);
for (u32 di = 0; di < stage->driver_count; di++) {
dsm_driver_entry *drv = &stage->drivers[di];
struct limine_file *f;
struct dkm_symbol_scan symbols;
int result;
if (drv->loaded) continue;
/* === FUCK [drivers] 驱动开关检查 === */
if (cfg) {
@@ -331,7 +347,7 @@ void dsm_load_by_manifest_ex(const ini_config *cfg) {
if (!enabled) {
log_info("[DSM] driver disabled by FUCK: ");
log_info(drv->name);
continue; /* 跳过此驱动 */
continue;
}
}
@@ -346,7 +362,7 @@ void dsm_load_by_manifest_ex(const ini_config *cfg) {
continue;
}
struct limine_file *f = drv->boot_module;
f = drv->boot_module;
log_info("[DSM] loading driver");
log_info(drv->name);
@@ -355,13 +371,12 @@ void dsm_load_by_manifest_ex(const ini_config *cfg) {
continue;
}
struct dkm_symbol_scan symbols;
if (dkm_scan_symbols(f->address, f->size, &symbols) != 0) {
log_error("[DSM] symbol scan failed");
continue;
}
int result = dkm_load_elf_rel(f->address, f->size, &symbols);
result = dkm_load_elf_rel(f->address, f->size, &symbols);
if (result != 0) {
log_error("[DSM] load failed");
if (drv->required && stage->required) {
@@ -375,3 +390,59 @@ void dsm_load_by_manifest_ex(const ini_config *cfg) {
log_info("[DSM] stage end");
}
}
void dsm_load_by_manifest_upto(const ini_config *cfg, u32 max_stage_id) {
dsm_load_stage_range(cfg, 1, max_stage_id);
}
void dsm_load_named(const ini_config *cfg, const char *name) {
if (!name || dsm_ensure_manifest() != 0) return;
for (u32 si = 0; si < g_stage_count; si++) {
dsm_stage_entry *stage = &g_stages[si];
for (u32 di = 0; di < stage->driver_count; di++) {
dsm_driver_entry *drv = &stage->drivers[di];
struct limine_file *f;
struct dkm_symbol_scan symbols;
int result;
if (!streq_static(drv->name, name)) continue;
if (drv->loaded) return;
if (cfg && !ini_get_bool(cfg, "drivers", drv->name, 1)) {
log_info("[DSM] driver disabled by FUCK: ");
log_info(drv->name);
return;
}
drv->boot_module = dsm_find_boot_module(drv->path);
if (!drv->boot_module) {
log_warn("[DSM] named module not found");
log_info(name);
return;
}
f = drv->boot_module;
log_info("[DSM] loading named driver");
log_info(drv->name);
if (dkm_check_elf64(f->address, f->size) != 0) {
log_error("[DSM] ELF check failed");
return;
}
if (dkm_scan_symbols(f->address, f->size, &symbols) != 0) {
log_error("[DSM] symbol scan failed");
return;
}
result = dkm_load_elf_rel(f->address, f->size, &symbols);
if (result != 0) {
log_error("[DSM] load failed");
return;
}
drv->loaded = 1;
return;
}
}
log_warn("[DSM] named driver not in manifest");
log_info(name);
}
void dsm_load_by_manifest_ex(const ini_config *cfg) {
dsm_load_stage_range(cfg, 0, 0);
}
-13
View File
@@ -1,13 +0,0 @@
dkm/manifest.o: dkm\manifest.c include\utsm\dkm.h include\utsm\types.h \
include\utsm\dma.h include\utsm\block.h include\utsm\net.h \
include\utsm\paging.h include\utsm\log.h dkm\..\arch\x86_64\limine.h \
dkm\..\kernel\ini_parser.h
include\utsm\dkm.h:
include\utsm\types.h:
include\utsm\dma.h:
include\utsm\block.h:
include\utsm\net.h:
include\utsm\paging.h:
include\utsm\log.h:
dkm\..\arch\x86_64\limine.h:
dkm\..\kernel\ini_parser.h:
Binary file not shown.
+405 -3
View File
@@ -10,6 +10,14 @@
#include <utsm/drr.h>
#include <utsm/log.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) {
@@ -71,14 +79,118 @@ u64 drr_crc64(const void *data, u64 len) {
/* ---- 全局 DRR 状态 ---- */
static drr_state g_drr;
/* ---- Root key(最终应从安全启动链获取) ---- */
static const u64 g_root_key[4] = {
/* ---- 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;
@@ -112,7 +224,7 @@ void drr_init(void) {
g_drr.pool_offset = 0;
g_drr.pool_limit = DRR_EMERGENCY_POOL_SIZE;
g_drr.root_key = g_root_key;
drr_root_key_generate();
g_drr.recovery_generation = 1;
g_drr.heartbeat_interval = 1000;
g_drr.active_slot = 0; /* A */
@@ -142,6 +254,38 @@ void drr_init(void) {
g_drr.ckpt_b.version = DRR_CKPT_VERSION;
g_drr.initialized = 1;
/* ---- 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 {
log_warn("[DRR] snapshot region unavailable (metadata-only mode)");
}
}
log_info("[DRR] init ok");
}
@@ -314,3 +458,261 @@ void drr_heartbeat_tick(void) {
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;
}
+17 -1
View File
@@ -1,6 +1,22 @@
drr/drr_stub.o: drr\drr_stub.c include\utsm\drr.h include\utsm\types.h \
include\utsm\config.h include\utsm\log.h
include\utsm\config.h include\utsm\log.h include\utsm\dma.h \
include\utsm\segment.h include\utsm\uuid.h include\utsm\status.h \
include\utsm\capability.h include\utsm\dirty.h include\utsm\dkm.h \
include\utsm\block.h include\utsm\net.h include\utsm\paging.h \
include\utsm\crypto.h include\utsm\blake2b.h
include\utsm\drr.h:
include\utsm\types.h:
include\utsm\config.h:
include\utsm\log.h:
include\utsm\dma.h:
include\utsm\segment.h:
include\utsm\uuid.h:
include\utsm\status.h:
include\utsm\capability.h:
include\utsm\dirty.h:
include\utsm\dkm.h:
include\utsm\block.h:
include\utsm\net.h:
include\utsm\paging.h:
include\utsm\crypto.h:
include\utsm\blake2b.h:
Binary file not shown.
+48
View File
@@ -0,0 +1,48 @@
#ifndef UTSM_BLAKE2B_H
#define UTSM_BLAKE2B_H
#include <utsm/types.h>
/* ===================================================================
* BLAKE2b(RFC 7693)— Phase 9 真实加密原语
*
* 纯 64-bit 整数实现(无 SSE/FPU 依赖,-mno-sse 下可用)。
* 支持 1-64B 可变输出与 keyed 模式(key 0-64B)。
* 角色:KDF(root→segment key)、页 MAC、mac_root 链。
* =================================================================== */
#define UTSM_BLAKE2B_BLOCKBYTES 128u
#define UTSM_BLAKE2B_MAXOUT 64u
typedef struct {
u64 h[8]; /* 链值 */
u64 t[2]; /* 已处理字节数(128 位计数器) */
u8 buf[128]; /* 待压缩块缓冲 */
u32 buf_len; /* buf 内有效字节数 */
u32 out_len; /* 摘要输出长度 1-64 */
u32 last_block; /* 最后一块标志 */
} utsm_blake2b_ctx;
void utsm_blake2b_init(utsm_blake2b_ctx *ctx, u32 out_len, const void *key, u32 key_len);
void utsm_blake2b_update(utsm_blake2b_ctx *ctx, const void *data, u64 len);
void utsm_blake2b_final(utsm_blake2b_ctx *ctx, void *out);
/* one-shot:out_len 1-64,key_len 0-64(key=NULL 表示无 key) */
void utsm_blake2b(const void *data, u64 len, const void *key, u32 key_len, void *out, u32 out_len);
/* ---- 小端序列化辅助(crypto 各处共用) ---- */
static inline void utsm_store32_le(u8 *p, u32 v) {
p[0] = (u8)(v); p[1] = (u8)(v >> 8); p[2] = (u8)(v >> 16); p[3] = (u8)(v >> 24);
}
static inline u32 utsm_load32_le(const u8 *p) {
return (u32)p[0] | ((u32)p[1] << 8) | ((u32)p[2] << 16) | ((u32)p[3] << 24);
}
static inline void utsm_store64_le(u8 *p, u64 v) {
utsm_store32_le(p, (u32)v);
utsm_store32_le(p + 4, (u32)(v >> 32));
}
static inline u64 utsm_load64_le(const u8 *p) {
return (u64)utsm_load32_le(p) | ((u64)utsm_load32_le(p + 4) << 32);
}
#endif /* UTSM_BLAKE2B_H */
+13
View File
@@ -14,4 +14,17 @@ void utsm_kdf_segment_key(uuid128_t process_uuid, uuid128_t segment_uuid, u64 ke
u64 utsm_make_tweak(u64 tweak_seed, u64 line_index, u64 key_epoch);
void utsm_crypt_line(const utsm_key_material *key, u64 tweak, const u8 *in, u8 *out);
/* ===================================================================
* Phase 9 扩展:真实加密原语服务(尾部追加,ABI 兼容)
* stream = ChaCha20 block(RFC 8439),hash/KDF/MAC = BLAKE2b(RFC 7693)
* =================================================================== */
/* ChaCha20 block function:64B keystream。
* counter=0 用法下 nonce=tweak 即可保证 (key,nonce) 唯一。 */
void utsm_chacha20_block(const u32 key_words[8], u64 nonce, u64 counter, u8 out[64]);
/* 4KB 密文页 MAC:keyed BLAKE2b(key=root_key, domain||seg_slot||page||epoch||data),
* 截断 64 位。root_key 为 4×u64(DRR root key)。 */
u64 utsm_page_mac(const u64 *root_key, u32 seg_slot, u64 page_index, u64 key_epoch, const void *page);
#endif
+27 -1
View File
@@ -63,6 +63,24 @@ typedef struct dkm_driver_desc {
typedef int (*dkm_driver_init_fn)(const struct dkm_kernel_api *api, struct dkm_driver_handle *handle);
typedef int (*dkm_driver_exit_fn)(struct dkm_driver_handle *handle);
/* DRR 恢复根服务表(Phase8;驱动经 kernel_api->drr 使用) */
typedef struct drr_recovery_api {
void (*report_fault)(const char *reason);
u64 (*heartbeat_get)(void);
void *(*emergency_alloc)(u64 size, u64 alignment);
int (*ckpt_snapshot_dirty)(void);
int (*rollback_pages)(void);
} drr_recovery_api;
/* SAS-R0-PCQ 调度器服务表(Phase7;驱动经 kernel_api->sched 使用) */
typedef struct utsm_sched_api {
u64 (*uptime_ns)(void);
void (*yield)(void);
u32 (*current_task_slot)(void);
int (*task_create)(u32 process_slot, u32 priority, void (*entry)(void *), void *arg);
void (*sleep_ms)(u32 ms);
} utsm_sched_api;
typedef struct dkm_log_api {
void (*info)(const char *msg);
void (*warn)(const char *msg);
@@ -84,7 +102,7 @@ typedef struct dkm_kernel_api {
const void *vfs;
const dkm_net_api *net;
const void *timer;
const void *drr;
const drr_recovery_api *drr; /* 恢复根服务(原占位 void* 改具体类型,布局不变) */
const void *rsdp_address; /* ACPI RSDP physical address */
const void *fb_address; /* framebuffer base */
@@ -111,6 +129,10 @@ typedef struct dkm_kernel_api {
* 接口已接受向量命名空间,无需新注册 ABI)。 */
int (*irq_vector_alloc)(void);
void (*irq_vector_free)(int vector);
/* M4/Phase7-8: 调度器服务(尾部追加,ABI 兼容;drr 服务见上方原占位字段)。
* 驱动可用:task_create/uptime/sleep/current_task_slot。
* DSK 以 api+0xA8 硬偏移读 block 的约定不受影响(仅尾部追加)。 */
const utsm_sched_api *sched;
} dkm_kernel_api;
typedef enum dkm_driver_state {
@@ -142,6 +164,10 @@ void dsm_load_by_manifest(void);
void dkm_fill_platform_info(void);
const dkm_kernel_api *dkm_get_kernel_api(void);
/* 服务表实现(drr_stub.c / sched/sched.c 提供,fill 时挂入 kernel_api) */
const struct drr_recovery_api *drr_get_recovery_api(void);
const struct utsm_sched_api *utsm_sched_get_api(void);
/* exposed for manifest parser */
struct dkm_symbol_scan {
const void *driver_desc;
+51
View File
@@ -124,4 +124,55 @@ u64 drr_heartbeat_get(void);
/* CRC64 */
u64 drr_crc64(const void *data, u64 len);
/* ===================================================================
* Phase 8 扩展:真实脏页快照 / 页级回滚 / 看门狗 / system rollback
* (尾部追加,不动既有结构与语义)
* =================================================================== */
/* 快照区条目(快照区第 0 页:头(64B) + 条目数组顺序存放) */
typedef struct {
u32 seg_slot; /* utsm_get_segment 的 slot */
u32 page_index; /* 段内页号 */
u64 cipher_vaddr; /* 段内目标页虚拟地址(HHDM,回滚目标) */
u64 crc; /* 快照数据 CRC64(drr_crc64,区域完整性) */
u32 region_idx; /* 快照数据所在页序号(区域第 1+idx 页) */
u32 used;
/* Phase 9: 真实 MAC(keyed BLAKE2b,绑定 seg/page/epoch) */
u64 key_epoch; /* 快照时刻段 key_epoch(MAC 上下文 + 防跨纪元重放) */
u64 mac; /* 页 MAC(utsm_page_mac,截断 64 位) */
} drr_ckpt_page_entry;
/* 真实脏页快照:扫描全部 ACTIVE 段的 dirty shard 位图,逐脏页复制到
* 快照区(先快照后清位;区满则部分提交且不清位),随后走 A/B checkpoint
* 原子切换。O(dirty_shards + dirty_pages)。
* 返回快照页数(>=0);负数失败(未初始化/快照区不可用)。 */
int drr_ckpt_snapshot_dirty(void);
/* 页级回滚:按 active slot 元数据 + 快照区逐页 CRC 校验后恢复密文页
* 并清除对应脏位;触碰段状态 RECOVERING → ACTIVE,CRC 失败段 POISONED。
* 返回恢复页数(>=0);失败 -2(任一页 CRC 不符)。 */
int drr_rollback_pages(void);
/* 系统级回滚:crash 留痕 + 8042 复位(不返回)。
* Emergency Pool 耗尽 / 双槽皆坏 / 无任务可切换时调用。 */
void drr_system_rollback(const char *reason);
/* 统一 fault 入口:report_fault → 页级回滚 → sched fault 回调(可能不
* 返回);回调缺失且 reboot 使能时 → system rollback。 */
void drr_handle_task_fault(u32 task_slot, const char *reason);
/* 看门狗(独立于调度器:由 tick handler 直接调用 check,非调度任务) */
#define DRR_WATCHDOG_MAX 8
int drr_watchdog_register(u32 task_slot, u32 timeout_ticks);
int drr_watchdog_unregister(u32 task_slot);
void drr_watchdog_kick(u32 task_slot);
void drr_watchdog_check(void);
/* 恢复行为控制:关闭后 fault 只留日志不真重启(selftest 用) */
void drr_set_reboot_enabled(int enabled);
/* 调度器 fault 回调(sched enable 时注入;缺失时 fault → system rollback)。
* DRR 独立性:对调度器只依赖这一个函数指针。 */
void drr_set_sched_fault_cb(void (*cb)(u32 task_slot));
#endif /* UTSM_DRR_H */
+8
View File
@@ -31,6 +31,14 @@ int ept_identity_map(u64 gpa, u64 size, u64 flags);
* Handles 4KB pages and 2MB large pages. */
u64 ept_gpa_to_hpa(u64 gpa);
/* Rewrite an existing EPT leaf (4K or 2MB) as RWX+WB+Ignore PAT.
* Returns 0 if a leaf was found and rewritten, -1 if unmapped.
* Used to recover from nested-KVM EPT misconfig (guest PAT vs EPT type). */
int ept_repair_leaf(u64 gpa, u64 flags);
/* Log PML4/PDPT/PD/PT entries for a GPA (misconfig diagnostics). */
void ept_log_walk(u64 gpa);
/* Map a 2MB large page in EPT (PD-level direct mapping).
* GPA and HPA must be 2MB-aligned. memtype = EPT_MEMORY_TYPE_*.
* Required for real hardware MTRR compliance. */
+475
View File
@@ -0,0 +1,475 @@
/* fluent_ui.h — Deshab "Win11 Fluent" 视觉组件库
*
* 设计目标:商业化 Windows 11 风格 —— 居中悬浮圆角任务栏、亚克力半透明
* 弹层、圆角窗口、浅色/深色主题(见桌面重构计划第二节)。
*
* 分层:
* L1 wf_theme 主题令牌(色板 + 圆角),g_wf_light / g_wf_dark 预设
* L2 原语 du_wf_acrylic(读背景 alpha 混合圆角面板)、du_wf_shadow、
* du_wf_line(Bresenham 带宽线)、du_wf_ring(圆环/半弧)
* L3 组件 按钮/图标钮/开关/滑块/列表项/卡片/文本框/滚动条/提示
* L4 图标 du_wf_icon 矢量线性图标(24 网格设计,2px 笔触)
*
* 约定(与 deshab_ui.h 相同):包含本头前,编译单元须已定义 g_ascii
* (include ascii_font.h 或 ascii_bitmaps.c)。所有组件为纯绘制函数,
* hover/press 态由调用方检测并传入。
*
* 中文文本:本库组件标签为 ASCII;中文请调用方用 zh_draw_string +
* 主题令牌色绘制(zhfont.h 在 CODE/desktop/,不进 UTSM 公共头)。
*/
#ifndef DESHAB_FLUENT_UI_H
#define DESHAB_FLUENT_UI_H
#include <utsm/deshab_ui.h>
/* ===================================================================
* L1 — 主题令牌 (wf_theme)
* =================================================================== */
typedef struct {
/* 亚克力面板 */
du_u32 acrylic_tint; /* 混入背景的 tint 色 */
du_u32 acrylic_stroke; /* 1px 边线 */
du_u32 acrylic_solid; /* 不透明回退底色(无 alpha 场景) */
/* 文本 */
du_u32 text_primary;
du_u32 text_secondary;
du_u32 text_dim;
/* 强调色(Win11 accent) */
du_u32 accent;
du_u32 accent_hover;
du_u32 accent_press;
du_u32 on_accent; /* accent 上的文字 */
/* 控件 */
du_u32 control_stroke;
du_u32 window_border;
du_u32 divider;
du_u32 shadow;
/* 语义色 */
du_u32 success, warning, error;
du_u32 close_hover; /* 窗口关闭钮 hover 红 #E81123 */
/* 圆角 */
int radius_sm; /* 4 按钮/输入框 */
int radius_md; /* 8 卡片/窗口 */
int radius_lg; /* 12 任务栏/开始菜单/弹层 */
} wf_theme;
/* 浅色主题(Win11 Light:底 #F3F3F3,accent #0067C0) */
static const wf_theme g_wf_light = {
0xFFF3F3F3u, /* acrylic_tint */
0xFFEDEDEDu, /* acrylic_stroke */
0xFFF6F6F6u, /* acrylic_solid */
0xFF1A1A1Au, 0xFF5D5D5Du, 0xFF8A8A8Au,
0xFF0067C0u, 0xFF0078D4u, 0xFF005A9Eu, 0xFFFFFFFFu,
0xFFD6D6D6u, /* control_stroke */
0xFFE5E5E5u, /* window_border */
0xFFEDEDEDu, /* divider */
0x66000000u, /* shadow */
0xFF0F7B0Fu, 0xFF9D5D00u, 0xFFC42B1Cu,
0xFFC42B1Cu,
4, 8, 12,
};
/* 深色主题(Win11 Dark:底 #202020,accent #4CC2FF) */
static const wf_theme g_wf_dark = {
0xFF202020u,
0xFF3C3C3Cu, /* acrylic_stroke */
0xFF2B2B2Bu,
0xFFFFFFFFu, 0xFFC8C8C8u, 0xFF9A9A9Au,
0xFF4CC2FFu, 0xFF62CBFFu, 0xFF29A8E0u, 0xFF00293Cu,
0xFF3C3C3Cu, /* control_stroke */
0xFF3F3F3Fu, /* window_border */
0xFF3A3A3Au, /* divider */
0x99000000u, /* shadow */
0xFF6CCB5Fu, 0xFFFCE100u, 0xFFFF99A4u,
0xFFC42B1Cu,
4, 8, 12,
};
/* ===================================================================
* L2 — 原语
* =================================================================== */
/* 亚克力面板:逐像素读背景 → alpha 混合 tint → 圆角掩码。
* 真实 backdrop blur 不可行,靠"高透 tint + 1px 边 + 壁纸层透出"模拟。
* 仅用于弹层/任务栏(面积 <40% 屏,性能预算见计划第七节)。 */
static inline void du_wf_acrylic(du_context *ctx, du_i64 x, du_i64 y,
du_i64 w, du_i64 h,
du_u32 alpha, du_u32 radius,
const wf_theme *t) {
du_i64 r = (du_i64)radius;
if (r * 2 > w) r = w / 2;
if (r * 2 > h) r = h / 2;
for (du_i64 row = 0; row < h; row++) {
for (du_i64 col = 0; col < w; col++) {
du_i64 dx = 0, dy = 0;
int corner = 0;
if (col < r && row < r) { dx = r - 1 - col; dy = r - 1 - row; corner = 1; }
else if (col >= w - r && row < r) { dx = col - (w - r); dy = r - 1 - row; corner = 1; }
else if (col < r && row >= h - r) { dx = r - 1 - col; dy = row - (h - r); corner = 1; }
else if (col >= w - r && row >= h - r) { dx = col - (w - r); dy = row - (h - r); corner = 1; }
if (corner && dx * dx + dy * dy > r * r) continue;
du_u32 bg = du_pixel_read(ctx, x + col, y + row);
du_pixel(ctx, x + col, y + row, du_blend(bg, t->acrylic_tint, alpha));
}
}
du_rect_outline(ctx, x, y, w, h, t->acrylic_stroke, (du_u32)r);
}
/* 投影:外扩 2 圈递减 alpha 描边(比逐像素卷积便宜 100 倍) */
static inline void du_wf_shadow(du_context *ctx, du_i64 x, du_i64 y,
du_i64 w, du_i64 h, du_u32 radius,
const wf_theme *t) {
du_u32 base = du_pixel_read(ctx, x, y + h + 2);
for (int i = 2; i >= 1; i--) {
du_u32 alpha = (i == 2) ? 40 : 70;
du_rect_outline(ctx, x - i, y - i, w + 2 * i, h + 2 * i,
du_blend(base, t->shadow, alpha),
radius + (du_u32)i);
}
}
/* 半透明控件蒙层(hover/press 态) */
static inline void du_wf_overlay(du_context *ctx, du_i64 x, du_i64 y,
du_i64 w, du_i64 h, du_u32 overlay) {
du_u32 alpha = overlay >> 24;
if (!alpha) return;
for (du_i64 row = 0; row < h; row++)
for (du_i64 col = 0; col < w; col++)
du_pixel(ctx, x + col, y + row,
du_blend(du_pixel_read(ctx, x + col, y + row),
overlay, alpha));
}
/* Bresenham 直线(带厚度 w 像素) */
static inline void du_wf_line(du_context *ctx, du_i64 x0, du_i64 y0,
du_i64 x1, du_i64 y1, du_i64 w, du_u32 color) {
du_i64 dx = (x1 > x0) ? x1 - x0 : x0 - x1;
du_i64 dy = (y1 > y0) ? y1 - y0 : y0 - y1;
du_i64 sx = (x0 < x1) ? 1 : -1;
du_i64 sy = (y0 < y1) ? 1 : -1;
du_i64 err = dx - dy;
du_i64 half = w / 2;
for (;;) {
du_fill_rect(ctx, x0 - half, y0 - half, w, w, color);
if (x0 == x1 && y0 == y1) break;
du_i64 e2 = 2 * err;
if (e2 > -dy) { err -= dy; x0 += sx; }
if (e2 < dx) { err += dx; y0 += sy; }
}
}
/* 圆环:中心 (cx,cy),外半径 r,厚度 s。
* half : 0 全环,1 仅上半(dy<=0),-1 仅下半 */
static inline void du_wf_ring(du_context *ctx, du_i64 cx, du_i64 cy,
du_i64 r, du_i64 s, int half, du_u32 color) {
for (du_i64 dy = -r; dy <= r; dy++) {
if (half == 1 && dy > 0) continue;
if (half == -1 && dy < 0) continue;
for (du_i64 dx = -r; dx <= r; dx++) {
du_i64 d2 = dx * dx + dy * dy;
if (d2 <= r * r && d2 > (r - s) * (r - s))
du_pixel(ctx, cx + dx, cy + dy, color);
}
}
}
/* ===================================================================
* L3 — 组件
* =================================================================== */
/* 按钮态 */
typedef enum { WF_BTN_NORMAL = 0, WF_BTN_HOVER, WF_BTN_PRESS } wf_btn_state;
/* 标准按钮:圆角 4,三态底色,ASCII 标签居中(accent=1 为强调按钮) */
static inline void du_wf_button(du_context *ctx, du_i64 x, du_i64 y, du_i64 w,
const char *label, const wf_theme *t,
wf_btn_state st, int accent) {
du_i64 h = 32;
du_u32 bg = accent ? t->accent : t->acrylic_solid;
du_u32 fg = accent ? t->on_accent : t->text_primary;
if (accent) {
du_fill_rounded_rect(ctx, x, y, w, h, bg, 4);
if (st != WF_BTN_NORMAL)
du_wf_overlay(ctx, x + 1, y + 1, w - 2, h - 2,
(st == WF_BTN_PRESS) ? 0x44FFFFFFu : 0x22FFFFFFu);
} else {
du_fill_rounded_rect(ctx, x, y, w, h, bg, 4);
du_rect_outline(ctx, x, y, w, h, t->control_stroke, 4);
if (st != WF_BTN_NORMAL)
du_wf_overlay(ctx, x + 1, y + 1, w - 2, h - 2,
(st == WF_BTN_PRESS) ? 0x33000000u : 0x22000000u);
}
du_i64 len = 0;
while (label[len]) len++;
du_draw_string(ctx, label,
x + (w - len * (du_i64)DU_ASCII_STEP) / 2,
y + (h - (du_i64)DU_ASCII_CELL_H) / 2,
fg, bg, DU_ASCII_STEP);
}
/* 图标按钮:圆角 4 悬停/按下蒙层(图标由调用方叠加绘制) */
static inline void du_wf_icon_button(du_context *ctx, du_i64 x, du_i64 y,
du_i64 size, const wf_theme *t,
wf_btn_state st) {
(void)t;
if (st == WF_BTN_NORMAL) return;
du_wf_overlay(ctx, x, y, size, size,
(st == WF_BTN_PRESS) ? 0x33000000u : 0x22000000u);
du_rect_outline(ctx, x, y, size, size, 0x33000000u, 4);
}
/* 开关:轨道 40×20 圆角 full + 滑块 */
static inline void du_wf_toggle(du_context *ctx, du_i64 x, du_i64 y,
int on, const wf_theme *t) {
du_u32 track = on ? t->accent : 0xFF8A8A8Au;
du_fill_rounded_rect(ctx, x, y, 40, 20, track, 10);
if (on) du_fill_rounded_rect(ctx, x + 20, y + 2, 16, 16, 0xFFFFFFFFu, 8);
else du_fill_rounded_rect(ctx, x + 4, y + 2, 16, 16, 0xFFFFFFFFu, 8);
}
/* 滑块:细轨 4px 圆头 + 圆形拇指。rect_out 返回可拖拽轨道命中区。 */
static inline void du_wf_slider(du_context *ctx, du_i64 x, du_i64 y,
du_i64 w, int val, const wf_theme *t,
int rect_out[4]) {
du_i64 ty = y + 8;
du_fill_rounded_rect(ctx, x, ty, w, 4, t->control_stroke, 2);
du_i64 fw = w * val / 100;
if (fw > 2) du_fill_rounded_rect(ctx, x, ty, fw, 4, t->accent, 2);
du_i64 kx = x + fw - 8;
if (kx < x) kx = x;
if (kx > x + w - 16) kx = x + w - 16;
du_fill_rounded_rect(ctx, kx, y, 16, 16, t->accent, 8);
if (rect_out) {
rect_out[0] = (int)x; rect_out[1] = (int)y - 2;
rect_out[2] = (int)w; rect_out[3] = 20;
}
}
/* 列表项:32px 行高,hover/selected 蒙层 + 左侧 3px accent 条 */
static inline void du_wf_list_item(du_context *ctx, du_i64 x, du_i64 y,
du_i64 w, const char *label,
const wf_theme *t, int hover, int selected) {
if (selected) du_wf_overlay(ctx, x, y, w, 32, 0x28000000u);
else if (hover) du_wf_overlay(ctx, x, y, w, 32, 0x1A000000u);
if (selected) du_fill_rect(ctx, x, y + 8, 3, 16, t->accent);
du_draw_string(ctx, label, x + 12,
y + (32 - (du_i64)DU_ASCII_CELL_H) / 2,
selected ? t->text_primary : t->text_secondary,
0, DU_ASCII_STEP);
}
/* 卡片:圆角 8 + 投影 + 亚克力 */
static inline void du_wf_card(du_context *ctx, du_i64 x, du_i64 y,
du_i64 w, du_i64 h, du_u32 alpha,
const wf_theme *t) {
du_wf_shadow(ctx, x, y, w, h, (du_u32)t->radius_md, t);
du_wf_acrylic(ctx, x, y, w, h, alpha, (du_u32)t->radius_md, t);
}
/* 文本框(搜索框):圆角 4,聚焦时 accent 底边线 + 光标 */
static inline void du_wf_textbox(du_context *ctx, du_i64 x, du_i64 y,
du_i64 w, const char *text, int cursor_blink,
const wf_theme *t, int focused) {
du_i64 h = 36;
du_fill_rounded_rect(ctx, x, y, w, h, t->acrylic_solid, 4);
du_rect_outline(ctx, x, y, w, h, focused ? t->accent : t->control_stroke, 4);
if (focused) du_fill_rect(ctx, x + 4, y + h - 2, w - 8, 2, t->accent);
du_u32 fg = text[0] ? t->text_primary : t->text_dim;
du_draw_string(ctx, text, x + 12, y + (h - (du_i64)DU_ASCII_CELL_H) / 2,
fg, t->acrylic_solid, DU_ASCII_STEP);
if (focused && cursor_blink) {
du_i64 len = 0;
while (text[len]) len++;
du_fill_rect(ctx, x + 12 + len * (du_i64)DU_ASCII_STEP + 2,
y + 9, 2, (du_i64)DU_ASCII_CELL_H, t->accent);
}
}
/* 滚动条:4px 覆盖式 */
static inline void du_wf_scrollbar(du_context *ctx, du_i64 x, du_i64 y,
du_i64 h, int pos_0_100, int ratio_0_100,
const wf_theme *t) {
if (ratio_0_100 >= 100) return;
du_i64 thumb_h = h * ratio_0_100 / 100;
if (thumb_h < 24) thumb_h = 24;
du_i64 max_travel = h - thumb_h;
du_i64 ty = y + max_travel * pos_0_100 / 100;
du_fill_rounded_rect(ctx, x, ty, 4, thumb_h, t->text_dim, 2);
}
/* 提示(tooltip):小圆角不透明底 */
static inline void du_wf_tooltip(du_context *ctx, du_i64 x, du_i64 y,
const char *label, const wf_theme *t) {
du_i64 len = 0;
while (label[len]) len++;
du_i64 w = len * (du_i64)DU_ASCII_STEP + 16;
du_fill_rounded_rect(ctx, x, y, w, 28, t->acrylic_solid, 4);
du_rect_outline(ctx, x, y, w, 28, t->control_stroke, 4);
du_draw_string(ctx, label, x + 8, y + (28 - (du_i64)DU_ASCII_CELL_H) / 2,
t->text_primary, t->acrylic_solid, DU_ASCII_STEP);
}
/* ===================================================================
* L4 — 矢量图标(24 网格设计,线性 2px 笔触,Win11 Segoe 风格)
*
* 所有图标以 (x, y) 为左上角、size 为边长绘制,按 u = size/24 缩放
* (u 为最小单位,笔触 s = 2u)。
* =================================================================== */
typedef enum {
WF_ICON_START = 1, /* 四方块(开始) */
WF_ICON_SEARCH, /* 放大镜 */
WF_ICON_NETWORK, /* WiFi 扇形 */
WF_ICON_VOLUME, /* 喇叭 */
WF_ICON_POWER, /* 电源 */
WF_ICON_TASKMGR, /* 折线图 */
WF_ICON_SETTINGS, /* 齿轮(简化) */
WF_ICON_FOLDER, /* 文件夹 */
WF_ICON_TERMINAL, /* 终端 >_ */
WF_ICON_EDITOR, /* 文档横线 */
WF_ICON_CALC, /* 计算器格子 */
WF_ICON_BROWSER, /* 地球 */
WF_ICON_TASKVIEW, /* 双矩形 */
WF_ICON_WIDGETS, /* 四小件 */
WF_ICON_NOTIFY, /* 铃铛 */
WF_ICON_CLOSE, /* × */
WF_ICON_MIN, /* – */
WF_ICON_MAX, /* □ */
WF_ICON_RESTORE, /* 双层 □ */
WF_ICON_USER, /* 人形 */
} wf_icon_id;
static inline void du_wf_icon(du_context *ctx, wf_icon_id id,
du_i64 x, du_i64 y, du_i64 size, du_u32 color) {
du_i64 u = size / 24;
if (u < 1) u = 1;
du_i64 s = u * 2; /* 笔触宽 */
switch (id) {
case WF_ICON_START:
du_fill_rounded_rect(ctx, x + 3 * u, y + 3 * u, 8 * u, 8 * u, color, (du_u32)u);
du_fill_rounded_rect(ctx, x + 13 * u, y + 3 * u, 8 * u, 8 * u, color, (du_u32)u);
du_fill_rounded_rect(ctx, x + 3 * u, y + 13 * u, 8 * u, 8 * u, color, (du_u32)u);
du_fill_rounded_rect(ctx, x + 13 * u, y + 13 * u, 8 * u, 8 * u, color, (du_u32)u);
break;
case WF_ICON_SEARCH:
du_wf_ring(ctx, x + 10 * u, y + 10 * u, 7 * u, s, 0, color);
du_wf_line(ctx, x + 15 * u, y + 15 * u, x + 20 * u, y + 20 * u, s, color);
break;
case WF_ICON_NETWORK:
du_fill_rounded_rect(ctx, x + 10 * u, y + 17 * u, 3 * u, 3 * u, color, (du_u32)u);
du_wf_ring(ctx, x + 11 * u, y + 19 * u, 6 * u, s, 1, color);
du_wf_ring(ctx, x + 11 * u, y + 21 * u, 10 * u, s, 1, color);
break;
case WF_ICON_VOLUME:
/* 喇叭主体:梯形 */
du_fill_rect(ctx, x + 3 * u, y + 9 * u, 4 * u, 6 * u, color);
du_wf_line(ctx, x + 7 * u, y + 9 * u, x + 11 * u, y + 5 * u, s, color);
du_wf_line(ctx, x + 11 * u, y + 5 * u, x + 11 * u, y + 19 * u, s, color);
du_wf_line(ctx, x + 11 * u, y + 19 * u, x + 7 * u, y + 15 * u, s, color);
/* 声波弧 */
du_wf_ring(ctx, x + 11 * u, y + 12 * u, 7 * u, s, 1, color);
break;
case WF_ICON_POWER:
du_fill_rect(ctx, x + 11 * u, y + 3 * u, s, 8 * u, color);
du_wf_ring(ctx, x + 12 * u, y + 13 * u, 8 * u, s, 0, color);
break;
case WF_ICON_TASKMGR:
du_rect_outline(ctx, x + 2 * u, y + 3 * u, 20 * u, 18 * u, color, (du_u32)u);
du_wf_line(ctx, x + 5 * u, y + 15 * u, x + 9 * u, y + 10 * u, s, color);
du_wf_line(ctx, x + 9 * u, y + 10 * u, x + 13 * u, y + 13 * u, s, color);
du_wf_line(ctx, x + 13 * u, y + 13 * u, x + 19 * u, y + 6 * u, s, color);
break;
case WF_ICON_SETTINGS:
du_wf_ring(ctx, x + 12 * u, y + 12 * u, 5 * u, s, 0, color);
for (int i = 0; i < 8; i++) {
/* 8 个齿:每 45° 一个短径向线 */
du_i64 ax[8] = {0, 1, 1, 1, 0, -1, -1, -1};
du_i64 ay[8] = {-1, -1, 0, 1, 1, 1, 0, -1};
du_wf_line(ctx, x + 12 * u + ax[i] * 7 * u, y + 12 * u + ay[i] * 7 * u,
x + 12 * u + ax[i] * 10 * u, y + 12 * u + ay[i] * 10 * u,
s, color);
}
break;
case WF_ICON_FOLDER:
du_fill_rect(ctx, x + 3 * u, y + 6 * u, 7 * u, 3 * u, color);
du_rect_outline(ctx, x + 3 * u, y + 6 * u, 18 * u, 12 * u, color, (du_u32)u);
du_fill_rect(ctx, x + 3 * u, y + 11 * u, 18 * u, u, color);
break;
case WF_ICON_TERMINAL:
du_rect_outline(ctx, x + 2 * u, y + 4 * u, 20 * u, 16 * u, color, (du_u32)u);
du_wf_line(ctx, x + 6 * u, y + 9 * u, x + 10 * u, y + 12 * u, u + 1, color);
du_wf_line(ctx, x + 10 * u, y + 12 * u, x + 6 * u, y + 15 * u, u + 1, color);
du_fill_rect(ctx, x + 12 * u, y + 15 * u, 5 * u, u + 1, color);
break;
case WF_ICON_EDITOR:
du_rect_outline(ctx, x + 5 * u, y + 2 * u, 14 * u, 20 * u, color, (du_u32)u);
du_fill_rect(ctx, x + 8 * u, y + 8 * u, 8 * u, u, color);
du_fill_rect(ctx, x + 8 * u, y + 12 * u, 8 * u, u, color);
du_fill_rect(ctx, x + 8 * u, y + 16 * u, 5 * u, u, color);
break;
case WF_ICON_CALC:
du_rect_outline(ctx, x + 4 * u, y + 2 * u, 16 * u, 20 * u, color, (du_u32)u);
du_rect_outline(ctx, x + 7 * u, y + 5 * u, 10 * u, 4 * u, color, (du_u32)u);
for (int r = 0; r < 3; r++)
for (int c = 0; c < 3; c++)
du_fill_rect(ctx, x + (7 + c * 4) * u, y + (12 + r * 3) * u,
2 * u, 2 * u, color);
break;
case WF_ICON_BROWSER:
du_wf_ring(ctx, x + 12 * u, y + 12 * u, 9 * u, s, 0, color);
du_fill_rect(ctx, x + 3 * u, y + 11 * u, 18 * u, s, color);
du_wf_ring(ctx, x + 12 * u, y + 12 * u, 5 * u, u, 0, 0); /* 清理中圈 */
du_wf_line(ctx, x + 8 * u, y + 4 * u, x + 8 * u, y + 20 * u, u, color);
du_wf_line(ctx, x + 16 * u, y + 4 * u, x + 16 * u, y + 20 * u, u, color);
break;
case WF_ICON_TASKVIEW:
du_rect_outline(ctx, x + 3 * u, y + 5 * u, 13 * u, 11 * u, color, (du_u32)u);
du_rect_outline(ctx, x + 9 * u, y + 8 * u, 12 * u, 11 * u, color, (du_u32)u);
break;
case WF_ICON_WIDGETS:
du_fill_rounded_rect(ctx, x + 3 * u, y + 3 * u, 8 * u, 8 * u, color, (du_u32)u);
du_fill_rounded_rect(ctx, x + 13 * u, y + 3 * u, 8 * u, 8 * u, color, (du_u32)u);
du_fill_rounded_rect(ctx, x + 3 * u, y + 13 * u, 5 * u, 8 * u, color, (du_u32)u);
du_fill_rounded_rect(ctx, x + 10 * u, y + 13 * u, 11 * u, 8 * u, color, (du_u32)u);
break;
case WF_ICON_NOTIFY:
/* 铃铛:拱顶 + 两侧斜线 + 底线 + 铃锤 */
du_wf_ring(ctx, x + 12 * u, y + 14 * u, 8 * u, s, 1, color);
du_wf_line(ctx, x + 4 * u, y + 14 * u, x + 4 * u, y + 18 * u, s, color);
du_wf_line(ctx, x + 20 * u, y + 14 * u, x + 20 * u, y + 18 * u, s, color);
du_fill_rect(ctx, x + 3 * u, y + 19 * u, 18 * u, s, color);
du_fill_rounded_rect(ctx, x + 10 * u, y + 21 * u, 4 * u, 3 * u, color, (du_u32)u);
break;
case WF_ICON_CLOSE:
du_wf_line(ctx, x + 6 * u, y + 6 * u, x + 18 * u, y + 18 * u, s, color);
du_wf_line(ctx, x + 18 * u, y + 6 * u, x + 6 * u, y + 18 * u, s, color);
break;
case WF_ICON_MIN:
du_fill_rect(ctx, x + 6 * u, y + 11 * u, 12 * u, s, color);
break;
case WF_ICON_MAX:
du_rect_outline(ctx, x + 5 * u, y + 5 * u, 14 * u, 14 * u, color, (du_u32)u);
break;
case WF_ICON_RESTORE:
du_rect_outline(ctx, x + 4 * u, y + 8 * u, 11 * u, 11 * u, color, (du_u32)u);
du_fill_rect(ctx, x + 8 * u, y + 5 * u, 12 * u, s, color);
du_fill_rect(ctx, x + 18 * u, y + 5 * u, s, 6 * u, color);
du_fill_rect(ctx, x + 12 * u, y + 8 * u, 8 * u, u, color);
break;
case WF_ICON_USER:
du_wf_ring(ctx, x + 12 * u, y + 8 * u, 4 * u, s, 0, color);
du_wf_ring(ctx, x + 12 * u, y + 26 * u, 9 * u, s, 1, color);
break;
default:
du_rect_outline(ctx, x + 4 * u, y + 4 * u, 16 * u, 16 * u, color, (du_u32)u);
break;
}
}
#endif /* DESHAB_FLUENT_UI_H */
+13
View File
@@ -45,4 +45,17 @@ void idt_register_apic_eoi(void (*eoi_fn)(void));
int irq_vector_alloc(void);
void irq_vector_free(int vector);
/* 显式 EOI(Phase7: 调度器 tick 等可能切换任务的中断路径用)。
* 在任何可能换栈的工作之前完成 EOI,防止 EOI 悬挂一个时间片。
* 序列与 idt_handler 默认路径一致: LAPIC 钩子 → 8259 EOI(按向量范围)。
* 参数兼容双命名空间(同 irq_register): 0-15=ISA IRQ, 0x20+=向量。 */
void idt_irq_eoi(u8 vector);
/* CPU 异常钩子(Phase8: DRR 任务级 fault 接管)。
* 在 idt_handler 的 vector<32 分支最前调用: 返回非 0 = 异常已被消费
* (fault 任务被杀/切换,控制权不回到日志+停机路径);返回 0 = 走原
* 全量日志 + cli;hlt 路径(DSK 阶段行为不变)。传 NULL 注销。 */
typedef int (*idt_exception_hook_t)(u64 vector, u64 error_code, u64 rip);
void idt_set_exception_hook(idt_exception_hook_t hook);
#endif
+38
View File
@@ -0,0 +1,38 @@
#ifndef UTSM_LAPIC_TIMER_H
#define UTSM_LAPIC_TIMER_H
#include <utsm/types.h>
/* 宿主自持 LAPIC 定时器 —— SAS-R0-PCQ 调度器 tick 源(ROADMAP Phase 2 目标方案)。
*
* 动机:默认 FUCK 配置 apic_route=1 时,apic.drv 验证完 tick 链路后会把
* GSI2(PIT IRQ0 线)重新 mask(apic.c route_switch 收尾),PIT 周期中断
* 在该配置下不可达。LAPIC timer 不经 IOAPIC/PIC 路由,与路由模式解耦。
*
* 实现要点:
* - IA32_APIC_BASE MSR (0x1B) 取 LAPIC 物理基址,经 paging map_mmio 映射
* (SAS-R0:直接扩当前 CR3,全 CPU 可见)。
* - x2APIC(MSR bit10)不支持 → 返回负数,调度器降级为协作模式。
* - 频率校准:LAPIC 定时器 divide=16、initial=0xFFFFFFFF,用 PIT ch0
* 单发 10ms 窗口采样 CCR 差值(pit.h 单发助手)。
* - 向量来自 irq_vector_alloc(0x40-0xDF 动态池);EOI 由本模块直写
* LAPIC EOI 寄存器(不依赖 apic.drv 钩子,PIC/IOAPIC 两模式均成立)。
*/
/* 校准并配置周期定时器(LVT 保持 mask,尚未投递)。
* 返回 0 成功,负数失败(x2APIC/映射失败/校准异常)。 */
int lapic_timer_init(u32 freq_hz);
/* init 成功后返回分配到的 IDT 向量(0x40-0xDF),未初始化返回 -1 */
int lapic_timer_vector(void);
/* LVT 解除 mask —— 开始周期投递(须在 irq_register 向量 handler 之后调用) */
void lapic_timer_start(void);
/* 停止:LVT 置 mask + initial count 清零 + 归还动态向量 */
void lapic_timer_stop(void);
/* 直写 LAPIC EOI 寄存器(tick handler 用;未初始化时为空操作) */
void lapic_timer_eoi(void);
#endif /* UTSM_LAPIC_TIMER_H */
+5
View File
@@ -156,6 +156,11 @@ typedef struct linux_compat_service {
* (-1=服务不可用, -2=IPC 发送失败, -3=linux_resume 失败,
* -4=无响应, -5=daemon 报告 spawn 失败)。 */
int (*exec_async)(const char *path, int argc, const char *const *argv);
/* 不发送 IPC,只跑一段 Linux vCPU(HLT 或 preemption timeslice)。
* KDE/Plasma 全屏循环用这个唤醒 async 子进程,避免再 exec sleep。
* 返回 0 成功,负值同 linux_resume。 */
int (*run_slice)(void);
} linux_compat_service;
/* ===== UTSM 内部接口(不进服务表,供 hypercall.c 等内核代码使用) =====
+22 -14
View File
@@ -49,6 +49,9 @@ struct linux_setup_header {
/* boot_params is 4096 bytes. The setup_header is at offset 0x1f1. */
#define BOOT_PARAMS_SIZE 4096
#define SETUP_HEADER_OFFSET 0x1f1
#define BOOT_PARAMS_ACPI_RSDP_ADDR_OFF 0x070
#define BOOT_PARAMS_RSDP_COPY_OFF 0x800
#define BOOT_PARAMS_RSDP_COPY_SIZE 36
/* Key field offsets within bzImage / boot_params */
#define BZ_BOOT_FLAG_OFF 0x1fe
@@ -88,11 +91,10 @@ struct linux_setup_header {
#define E820_TYPE_UNUSABLE 5
#define E820_TYPE_PMEM 7
/* e820_table entry in boot_params at offset 0x2e0 (actually 0x2d0 in older,
* 0x2e0 in newer). We use 0x2e0 and the e820_entries count at 0x1e8.
* Each entry is 20 bytes: u64 addr, u64 size, u32 type. */
/* e820_table is at 0x2d0 in Linux 6.6 boot_params (arch/x86/include/uapi/asm/bootparam.h).
* e820_entries count is at 0x1e8. Each entry is 20 bytes: u64 addr, u64 size, u32 type. */
#define E820_ENTRIES_OFFSET 0x1e8
#define E820_TABLE_OFFSET 0x2e0
#define E820_TABLE_OFFSET 0x2d0
#define E820_MAX_ENTRIES 128
#define E820_ENTRY_SIZE 20
@@ -215,10 +217,13 @@ void *linux_find_extra_rootfs_module(u64 *size_out);
* Returns NULL when the module is absent (install skipped, non-fatal). */
void *linux_find_vscode_module(u64 *size_out);
/* Parse bzImage header and extract key parameters.
/* Parse bzImage header and return the protected-mode image's file offset,
* load length, decompression allocation size, and startup_64 entry offset.
* The protected-mode image starts after setup sectors; setup_header's
* payload_offset instead locates compressed data inside that image.
* Returns 0 on success, negative on error. */
int linux_parse_bzimage(const void *bzimage, u64 size,
u64 *payload_offset_out, u64 *payload_length_out,
u64 *kernel_offset_out, u64 *kernel_length_out,
u64 *init_size_out, u64 *entry_offset_out);
/* Initialize the Linux guest: parse bzImage, allocate guest memory,
@@ -249,9 +254,9 @@ void *linux_get_surface_vaddr(void);
int linux_launch(void);
/* Default Linux command line (can be overridden).
* nohlt: prevent kernel idle loop from using HLT — only the exec daemon's
* explicit ioctl(PARK) HLT should trigger VM-Exit park, so that
* linux_launch() returns only after the daemon is ready.
* Daemon PARK is a VMCALL. Guest idle may HLT; that stays in the
* guest (wait-for-IRQ). Do not use nohlt/idle=poll — poll idle
* NULL-derefs current after the first real sleep.
* noapic/nolapic/nosmp: UTSM VMM 只模拟 legacy PIC(8259) + PIT(8254),
* 不提供 LAPIC/IOAPIC;guest 走 XT-PIC 模式,IRQ vector = 0x30+irq。
* virtio_mmio.device=: 向 guest 声明 virtio-mmio 设备(blk@0xF4000000 IRQ5,
@@ -259,12 +264,15 @@ int linux_launch(void);
* VSCode Phase 2: kbd@0xF4003000 IRQ8, mouse@0xF4004000 IRQ9 (virtio-input)。
* VSCode Phase 3: gpu@0xF4005000 IRQ10 (virtio-gpu 2D, /dev/dri/card0)。
* VSCode Phase 4: xrootfs@0xF4006000 IRQ11 (可写 virtio-blk, /dev/vdc)。
* 注:slot6 无对应 boot module 时后端不注册,guest 探测会超时跳过,
* 不影响启动(virtio_mmio 对无响应设备只打一条 warn)。 */
* 注:无 extra-rootfs boot module 时,后端改映射 ESP 上的
* boot/linux-extra-rootfs.img(AHCI+FAT32),避免 Limine 把 4GiB
* 打进 RAM。文件也没有则不注册,guest 探测超时跳过。 */
#define LINUX_DEFAULT_CMDLINE \
"console=ttyS0,115200 earlyprintk=serial nokaslr " \
"no_timer_check loglevel=7 nohlt idle=poll " \
"noapic nolapic nosmp " \
"earlyprintk=serial,ttyS0,115200 console=ttyS0,115200 " \
"nokaslr debug loglevel=8 noinvpcid nopcid nopti pti=off nogbpages " \
"tsc_early_khz=2000000 lpj=4000000 i8042.nokbd i8042.noaux " \
"no_timer_check " \
"noapic nolapic nosmp ibt=off user_shstk=off " \
"virtio_mmio.device=4K@0xF4000000:5 " \
"virtio_mmio.device=4K@0xF4001000:6 " \
"virtio_mmio.device=4K@0xF4002000:7 " \
+21
View File
@@ -0,0 +1,21 @@
#ifndef UTSM_LINUX_XSAVE_H
#define UTSM_LINUX_XSAVE_H
#include <utsm/types.h>
/* L2 Linux XSAVE (x87+SSE first). UTSM is built -mno-sse, so every
* XSAVE/XRSTOR/XSETBV goes through raw opcodes. Guest state must be
* saved before returning to DSK/desktop and restored on linux_resume. */
int linux_xsave_available(void);
void linux_xsave_init(void);
void linux_xsave_save_guest(void);
void linux_xsave_load_guest(void);
void linux_xsave_save_host(void);
void linux_xsave_load_host(void);
void linux_xsave_set_guest_xcr0(u64 xcr0);
void linux_xsave_adjust_cpuid(u32 leaf, u32 subleaf,
u32 *eax, u32 *ebx, u32 *ecx, u32 *edx,
u64 guest_cr4);
#endif
+3
View File
@@ -26,4 +26,7 @@ typedef struct {
void utsm_pckc_init(void);
int utsm_pckc_get_or_derive(u32 segment_slot, struct utsm_segment_desc *desc, utsm_key_material *out_key);
/* Phase 9: 失效某段全部缓存 key(key_epoch bump / task_kill crypto erase 用) */
void utsm_pckc_invalidate_slot(u32 segment_slot);
#endif
+22
View File
@@ -0,0 +1,22 @@
#ifndef UTSM_PIT_H
#define UTSM_PIT_H
#include <utsm/types.h>
/* PIT ch0 单发定时(LAPIC timer 校准用,见 arch/x86_64/lapic_timer.c)。
* 模式 0(terminal count),单发不产生周期中断,不注册 IRQ handler。
* 注意:不用 mode 3 —— B7 定论 PIT mode3 经 IOAPIC 边沿路由会双触发。 */
/* 编程 ch0 单发 ms 毫秒(>54ms 截断到 54ms) */
void pit_oneshot_ms(u32 ms);
/* latch 并返回 ch0 当前递减计数(16 位) */
u16 pit_latch_count(void);
/* 单发是否到期(两次 latch 回绕检测)。1=到期,0=未到期 */
int pit_oneshot_expired(void);
/* 静默:ch0 编程 mode0 计数 0,不再产生任何输出/中断 */
void pit_quiet(void);
#endif /* UTSM_PIT_H */
+84
View File
@@ -0,0 +1,84 @@
#ifndef UTSM_SCHED_EXT_H
#define UTSM_SCHED_EXT_H
#include <utsm/types.h>
#include <utsm/sched.h>
/*
* SAS-R0-PCQ 调度器扩展接口(ROADMAP Phase 7)。
*
* 冻结 ABI(sched.h)之外的内核本体能力层,仅供 UTSM 内核与 selftest
* 使用,不跨组件边界(DKM 驱动经 kernel_api.sched 使用精简服务表)。
*
* 切换模型(xv6 式栈驱动):
* - 新任务初始栈帧由 utsm_task_create 伪造(7 个 u64):
* sp[0..3]=r15/r14/r13/r12(0), sp[4]=rbx(task slot), sp[5]=rbp(0),
* sp[6]=&utsm_task_trampoline —— switch 的 ret 直接落 trampoline。
* - 抢占:IRQ 帧落在被抢占任务自己的栈上,切换只换 rsp(arch.rsp);
* 恢复时沿原栈 iretq。TCB arch.rip/rflags 仅占位零(resume 全由 rsp 驱动)。
* - 协作:schedule() 入口 pushfq 保存本任务 rflags → cli;恢复点 popfq。
*/
/* 应用 FUCK [sched] 配置(enable 前生效;tick_hz=0 用默认 100) */
void utsm_sched_config(u32 tick_hz, u32 timeslice_ms, u32 demo_ms, int demo_fault);
/* bootstrap 任务绑定:sched_init + cpu_init(0) + 当前 rsp 注册为 RUNNING
* 任务(priority 最低,K_KERNEL|NO_MIGRATE)。不开中断、不碰定时器。
* 返回 bootstrap slot(>=0),负数失败。 */
int utsm_sched_bootstrap_init(void);
/* 创建任务:4 页任务栈(arena kmem_alloc_page)+ 伪造初始栈帧 + 入队。
* process_slot = 0xFFFFFFFF 表示无进程关联(纯内核任务,crypto_context=NULL)。
* 返回 task slot(>=0),负数失败。仅在未启用抢占时(bootstrap 上下文)调用。 */
int utsm_task_create(u32 process_slot, u32 priority, void (*entry)(void *), void *arg);
/* 启用抢占:LAPIC timer 校准配置 → 注册 tick handler → 异常钩子 →
* DRR fault 回调接线 → LVT 解除 mask。tick_hz=0 用配置默认。
* 返回 0 成功;失败时调度器保持协作模式(系统继续正常启动)。 */
int utsm_sched_enable(u32 tick_hz);
/* 静默:cli → 停 LAPIC timer → 异常钩子注销 → DRR 回调解绑 → 杀掉全部
* 非 bootstrap 任务 → sti。dsk_load_and_jump 之前调用,保证 DSK 交接
* 路径与无调度器时逐字节一致。 */
void utsm_sched_quiesce(void);
/* demo 窗口:创建 3 个不同优先级 demo 任务(prio 1/20/40)→ enable →
* bootstrap 忙等 demo_ms 毫秒(被周期抢占,demo 任务交错运行 = 抢占证据)。
* FUCK [sched] demo_ms=0 时为空操作。 */
void utsm_sched_demo_window(void);
/* 协作让出(当前任务重新入队并切换) */
void utsm_sched_yield(void);
/* 睡眠 ms 毫秒(wake_deadline 到期后由 tick 唤醒) */
void utsm_sched_sleep_ms(u32 ms);
/* 任务退出(trampoline 在 entry 返回后自动调用;不返回) */
void utsm_sched_task_exit(void) __attribute__((noreturn));
/* DRR fault 回调:杀掉指定任务(crypto erase + FAULTED→ZOMBIE)。
* 若 fault 任务是当前任务(tick/异常上下文)则立即切换走且不返回。 */
void utsm_sched_fault_task(u32 task_slot);
/* task_kill(ROADMAP Phase7 验收项):crypto erase(key_epoch++)+
* 摘链 + ZOMBIE。对 RUNNING(当前)任务返回 ERR_STATE。 */
int utsm_sched_task_kill(u32 task_slot);
/* 当前运行任务 slot */
u32 utsm_sched_current_slot(void);
/* ---- switch.S 汇编符号 ----
* utsm_sched_switch: 保存 prev 的 callee-saved + arch.rsp,载入 next->arch.rsp
* 恢复并 ret。调用后 volatile 视为全部破坏(C 调用约定保证)。 */
void utsm_sched_switch(utsm_sched_tcb *prev, utsm_sched_tcb *next);
void utsm_task_trampoline(void);
/* trampoline 的 C 入口(rbx 传入 task slot) */
void utsm_task_main(u64 slot);
/* ---- selftest 钩子(内部状态观察,仅 test/ 使用) ---- */
int utsm_sched_selftest_runqueue(void);
int utsm_sched_selftest_blockwake(void);
int utsm_sched_debug_ready_count(u32 cpu_id);
#endif /* UTSM_SCHED_EXT_H */
+8
View File
@@ -40,6 +40,14 @@
#define VIRTIO_MMIO_QUEUE_DRIVER_HIGH 0x094 /* W modern */
#define VIRTIO_MMIO_QUEUE_DEVICE_LOW 0x0A0 /* W modern */
#define VIRTIO_MMIO_QUEUE_DEVICE_HIGH 0x0A4 /* W modern */
/* Shared-memory region (Virtio 1.1 §4.2.2). Linux virtio-gpu always probes
* VIRTIO_GPU_SHM_ID_HOST_VISIBLE. A missing region MUST report length=-1;
* length 0 is treated as a real window at address 0 and probe fails -EBUSY. */
#define VIRTIO_MMIO_SHM_SEL 0x0AC /* W */
#define VIRTIO_MMIO_SHM_LEN_LOW 0x0B0 /* R */
#define VIRTIO_MMIO_SHM_LEN_HIGH 0x0B4 /* R */
#define VIRTIO_MMIO_SHM_BASE_LOW 0x0B8 /* R */
#define VIRTIO_MMIO_SHM_BASE_HIGH 0x0BC /* R */
#define VIRTIO_MMIO_CONFIG_GENERATION 0x0FC /* R modern */
#define VIRTIO_MMIO_CONFIG 0x100 /* RW device-specific config */
+3
View File
@@ -91,4 +91,7 @@ u64 vmm_get_eptp(void);
/* P8.5: VMCS 物理地址(linux_launch 前 VMCLEAR+VMPTRLD 用) */
u64 vmm_get_vmcs_phys(void);
/* Walk the current guest CR3 to translate GVA→GPA. Returns 0 if unmapped. */
u64 vmx_guest_gva_to_gpa(u64 gva);
#endif
+53
View File
@@ -16,6 +16,10 @@
#define IA32_VMX_TRUE_PROCBASED_CTLS 0x48E
#define IA32_VMX_TRUE_EXIT_CTLS 0x48F
#define IA32_VMX_TRUE_ENTRY_CTLS 0x490
#define IA32_VMX_CR0_FIXED0 0x486
#define IA32_VMX_CR0_FIXED1 0x487
#define IA32_VMX_CR4_FIXED0 0x488
#define IA32_VMX_CR4_FIXED1 0x489
/* ===== CR4 / CR0 bits ===== */
#define CR4_VMXE_BIT 13ULL
@@ -23,8 +27,15 @@
#define CR4_PAE (1ULL << 5)
#define CR4_PGE (1ULL << 7)
#define CR4_PSE (1ULL << 4)
#define CR4_OSFXSR (1ULL << 9)
#define CR4_OSXMMEXCPT (1ULL << 10)
#define CR4_FSGSBASE (1ULL << 16)
#define CR4_OSXSAVE (1ULL << 18)
#define CR4_CET (1ULL << 23)
#define CR0_PE (1ULL << 0)
#define CR0_MP (1ULL << 1)
#define CR0_ET (1ULL << 4)
#define CR0_NE (1ULL << 5)
#define CR0_WP (1ULL << 16)
#define CR0_PG (1ULL << 31)
@@ -44,8 +55,14 @@
#define VMCS_IO_BITMAP_A 0x2000
#define VMCS_IO_BITMAP_B 0x2002
#define VMCS_MSR_BITMAP 0x2004
#define VMCS_VM_EXIT_MSR_STORE_ADDR 0x2006
#define VMCS_VM_EXIT_MSR_LOAD_ADDR 0x2008
#define VMCS_VM_ENTRY_MSR_LOAD_ADDR 0x200A
#define VMCS_TSC_OFFSET 0x2010
#define VMCS_EPT_POINTER 0x201A
#define VMCS_VM_EXIT_MSR_STORE_COUNT 0x400E
#define VMCS_VM_EXIT_MSR_LOAD_COUNT 0x4010
#define VMCS_VM_ENTRY_MSR_LOAD_COUNT 0x4014
/* Read-only data fields */
#define VMCS_GUEST_PHYSICAL_ADDR 0x2400
@@ -164,6 +181,10 @@
#define VMCS_PIN_BASED_VM_EXEC_CONTROL 0x4000
#define VMCS_CPU_BASED_VM_EXEC_CONTROL 0x4002
#define VMCS_EXCEPTION_BITMAP 0x4004
#define VMCS_CR0_GUEST_HOST_MASK 0x6000
#define VMCS_CR4_GUEST_HOST_MASK 0x6002
#define VMCS_CR0_READ_SHADOW 0x6004
#define VMCS_CR4_READ_SHADOW 0x6006
#define VMCS_VM_EXIT_CONTROLS 0x400C
#define VMCS_VM_ENTRY_CONTROLS 0x4012
#define VMCS_VM_ENTRY_INTERRUPT_INFO 0x4016
@@ -183,6 +204,8 @@
#define CPU_BASED_MWAIT_EXITING (1ULL << 10)
#define CPU_BASED_RDPMC_EXITING (1ULL << 11)
#define CPU_BASED_RDTSC_EXITING (1ULL << 12)
#define CPU_BASED_CR3_LOAD_EXITING (1ULL << 15)
#define CPU_BASED_CR3_STORE_EXITING (1ULL << 16)
#define CPU_BASED_CR8_LOAD_EXITING (1ULL << 19)
#define CPU_BASED_CR8_STORE_EXITING (1ULL << 20)
#define CPU_BASED_MOV_DR_EXITING (1ULL << 23)
@@ -194,6 +217,7 @@
/* ===== Secondary processor-based controls ===== */
#define SEC_EXEC_ENABLE_EPT (1ULL << 1)
#define SEC_EXEC_ENABLE_RDTSCP (1ULL << 3)
#define SEC_EXEC_ENABLE_VPID (1ULL << 5)
#define SEC_EXEC_UNRESTRICTED_GUEST (1ULL << 7)
@@ -204,11 +228,21 @@
#define VM_EXIT_ACK_INTR_ON_EXIT (1ULL << 15)
#define VM_EXIT_SAVE_GUEST_EFER (1ULL << 20)
#define VM_EXIT_LOAD_HOST_EFER (1ULL << 21)
#define VM_EXIT_SAVE_CET_STATE (1ULL << 28)
#define VM_EXIT_LOAD_CET_STATE (1ULL << 29)
/* ===== VM-entry controls ===== */
#define VM_ENTRY_LOAD_DEBUG_CONTROLS (1ULL << 2)
#define VM_ENTRY_IA32E_MODE_GUEST (1ULL << 9)
#define VM_ENTRY_LOAD_GUEST_EFER (1ULL << 15)
#define VM_ENTRY_LOAD_CET_STATE (1ULL << 20)
#define VMCS_GUEST_S_CET 0x2828
#define VMCS_GUEST_SSP 0x282A
#define VMCS_GUEST_INTR_SSP_TABLE 0x282C
#define VMCS_HOST_S_CET 0x2C28
#define VMCS_HOST_SSP 0x2C2A
#define VMCS_HOST_INTR_SSP_TABLE 0x2C2C
/* ===== Exit reasons ===== */
#define EXIT_EXCEPTION_NMI 0
@@ -220,6 +254,8 @@
#define EXIT_INVD 13
#define EXIT_RDMSR 31
#define EXIT_WRMSR 32
#define EXIT_ENTRY_FAIL_GUEST_STATE 33
#define EXIT_ENTRY_FAIL_MSR_LOADING 34
#define EXIT_MONITOR 39
#define EXIT_MWAIT 36
#define EXIT_VMCALL 18
@@ -240,6 +276,8 @@
#define EXIT_INVLPG 14
#define EXIT_EPT_VIOLATION 48
#define EXIT_EPT_MISCONFIG 49
#define EXIT_WBINVD 54
#define EXIT_XSETBV 55
#define EXIT_VMX_PREEMPTION_TIMER 52
#define EXIT_APIC_ACCESS 44
@@ -259,6 +297,7 @@
#define EPT_WRITE (1ULL << 1)
#define EPT_EXECUTE (1ULL << 2)
#define EPT_RWX (EPT_READ | EPT_WRITE | EPT_EXECUTE)
#define EPT_IGNORE_PAT (1ULL << 6)
#define EPT_LARGE_PAGE (1ULL << 7)
/* ===== VMX instruction errors ===== */
@@ -281,6 +320,7 @@ int vmx_vmlaunch(void);
int vmx_vmresume(void);
u64 vmx_read_msr(u32 msr);
void vmx_write_msr(u32 msr, u64 value);
/* Capability polarity used by KVM and verified under nested KVM:
* low bit=1 => must be 1; high bit=0 => must be 0.
* Formula: (desired | allowed0) & allowed1. */
@@ -291,6 +331,13 @@ u64 vmx_get_host_cr3(void);
* distinct from the HHDM and must never be translated by subtracting HHDM. */
u64 vmx_kernel_virt_to_phys(const void *address);
/* Nested KVM leaks host CET into L2 unless VMCS switches CET state. */
extern int g_linux_cet_vmcs;
extern int g_linux_cet_force;
void linux_cet_vmcs_sync_host(void);
void linux_cet_restore_host(void);
void linux_cet_force_guest_off(void);
/* ===== 虚拟中断注入(vmexit.c 实现) ===== */
/* 向 guest 队列注入一个 ISA IRQ 向量(legacy PIC:vector = 0x30 + irq)。
* 仅排队;实际在下一次 vmresume 前(guest RFLAGS.IF=1 且无阻塞时)注入,
@@ -302,5 +349,11 @@ void vmx_guest_queue_irq(u32 vector);
u64 vmx_preemption_quantum(void);
/* 检查 CPU 是否支持 VMX preemption timer。 */
int vmx_preemption_timer_supported(void);
/* linux_resume() 入口清零 timeslice 计数,避免上次 HLT 残留导致立刻归还。 */
void vmx_linux_timeslice_reset(void);
/* linux_resume() 返回后关闭 timeslice,避免 linux_launch 早期误归还。 */
void vmx_linux_timeslice_disarm(void);
/* linux_resume() vmresume 前:arm timer + 注入 pending virtio/PIT IRQ。 */
void vmx_linux_prepare_entry(void);
#endif
+1 -1
View File
@@ -176,7 +176,7 @@ static struct limine_file *dsk_find_module(void) {
/* ---- FAT32 block-provider file reader ---- */
static u8 g_dsk_fat32_disk[131072]; /* 256-sector BPB+FAT+root dir buffer (与 DSK 端一致) */
static u8 g_dsk_fat32_cluster[4096]; /* 8-sector cluster buffer */
static u8 g_dsk_fat32_cluster[32768]; /* 32KiB: ESP>=4GiB uses 64 sectors/cluster */
/* 实机要求: 文件缓冲区足够容纳 deshab.elf (~1.5MB) 及 SYSTEM/lib 下的
* 大型 DLL(shell32.dll ~8MB, uiautomationcore.dll ~4.3MB) */
static u8 g_dsk_fat32_filedata[10485760]; /* 10MB file data buffer */
-20
View File
@@ -1,20 +0,0 @@
kernel/dsk_loader.o: kernel\dsk_loader.c include\utsm\dsk.h \
include\utsm\types.h include\utsm\arena.h include\utsm\dkm.h \
include\utsm\dma.h include\utsm\block.h include\utsm\net.h \
include\utsm\paging.h include\utsm\log.h include\utsm\pe.h \
include\utsm\linux_compat.h include\utsm\instr.h \
kernel\..\arch\x86_64\limine.h kernel\..\..\tools\fat32_lfn.h
include\utsm\dsk.h:
include\utsm\types.h:
include\utsm\arena.h:
include\utsm\dkm.h:
include\utsm\dma.h:
include\utsm\block.h:
include\utsm\net.h:
include\utsm\paging.h:
include\utsm\log.h:
include\utsm\pe.h:
include\utsm\linux_compat.h:
include\utsm\instr.h:
kernel\..\arch\x86_64\limine.h:
kernel\..\..\tools\fat32_lfn.h:
Binary file not shown.
+1 -1
View File
@@ -95,7 +95,7 @@ int ini_parse(const char *text, u32 size, ini_config *cfg) {
}
/* key=value 行 */
if (cfg->count >= 64) break; /* 达到上限 */
if (cfg->count >= 128) break; /* 达到上限 */
ini_entry *e = &cfg->entries[cfg->count];
-4
View File
@@ -1,4 +0,0 @@
kernel/ini_parser.o: kernel\ini_parser.c kernel\ini_parser.h \
include\utsm\types.h
kernel\ini_parser.h:
include\utsm\types.h:
+1 -1
View File
@@ -12,7 +12,7 @@ typedef struct {
/* INI 配置集合(栈/静态分配,不依赖堆) */
typedef struct {
ini_entry entries[64]; /* 最多 64 条配置项 */
ini_entry entries[128]; /* 最多 128 条配置项(M4: [sched]/[drr] 加入后 64 不够用) */
u32 count;
} ini_config;
-6
View File
@@ -1,6 +0,0 @@
kernel/instr.o: kernel\instr.c include\utsm\instr.h include\utsm\types.h \
include\utsm\log.h kernel\ini_parser.h
include\utsm\instr.h:
include\utsm\types.h:
include\utsm\log.h:
kernel\ini_parser.h:
+11
View File
@@ -22,6 +22,10 @@ u32 log_get_length(void) {
}
static void log_emit(const char *s) {
/* Phase7: 日志行临界区——抢占可能把一行日志切成两半(串口与
* BOOTLOG 缓冲都会花),pushfq/popfq 保存并恢复本上下文的 IF。 */
u64 flags;
__asm__ volatile("pushfq; popq %0; cli" : "=r"(flags) :: "memory");
serial_write(s);
if (g_log_capture_on && s) {
while (*s) {
@@ -31,6 +35,13 @@ static void log_emit(const char *s) {
s++;
}
}
/* BUG-GP-IRET: 只恢复 IF,不做全量 popfq。全量 popfq 会把进入本
* 函数前 flags 里的历史污染位(如 NT=1)原样写回 RFLAGS 并在上下文
* 间传播(NT=1 时下一次 iretq 直接 #GP(0))。本临界区的语义仅仅是
* "保存并恢复 IF"。 */
if (flags & (1ULL << 9)) { /* 恢复进入前的 IF */
__asm__ volatile("sti" ::: "memory");
}
}
static void log_line(const char *level, const char *msg) {
Binary file not shown.
+42 -2
View File
@@ -2,6 +2,7 @@
#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>
@@ -21,6 +22,7 @@ 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 长文件名 + 子目录遍历。 */
@@ -43,6 +45,7 @@ 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 之后调用。 */
@@ -346,6 +349,24 @@ void kernel_main(void) {
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();
@@ -371,6 +392,12 @@ void kernel_main(void) {
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) {
@@ -462,6 +489,14 @@ void kernel_main(void) {
log_info("[UTSM] selftest skipped by FUCK config");
}
/* === 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);
@@ -476,10 +511,15 @@ void kernel_main(void) {
{
int disk_log = ini_get_bool(cfg, "boot", "disk_log", 0);
if (disk_log) {
disk_log_flush();
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");
}
@@ -487,5 +527,5 @@ void kernel_main(void) {
/* ---- 插桩: 启动总耗时(仅在 DSK 跳转失败时可见) ---- */
INSTR_TS_END(boot_total, "boot_total");
arch_halt_forever();
arch_halt_forever();/*I LOVE YOU*/
}
+7 -5
View File
@@ -4,11 +4,11 @@ kernel/main.o: kernel\main.c include\utsm\log.h include\utsm\types.h \
include\utsm\capability.h include\utsm\segment.h include\utsm\dirty.h \
include\utsm\utrw.h include\utsm\vmm.h include\utsm\linux_loader.h \
include\utsm\ipc_shm.h ..\utsm-ipc\ipc_proto.h \
include\utsm\hypercall.h include\utsm\drr.h include\utsm\dkm.h \
include\utsm\dma.h include\utsm\block.h include\utsm\net.h \
include\utsm\paging.h include\utsm\idt.h include\utsm\dsk.h \
include\utsm\linux_compat.h include\utsm\xj380_loader.h \
include\utsm\instr.h kernel\ini_parser.h \
include\utsm\hypercall.h include\utsm\drr.h include\utsm\sched_ext.h \
include\utsm\sched.h include\utsm\dkm.h include\utsm\dma.h \
include\utsm\block.h include\utsm\net.h include\utsm\paging.h \
include\utsm\idt.h include\utsm\dsk.h include\utsm\linux_compat.h \
include\utsm\xj380_loader.h include\utsm\instr.h kernel\ini_parser.h \
kernel\..\arch\x86_64\limine.h kernel\..\pe\pe_dll_manager.h
include\utsm\log.h:
include\utsm\types.h:
@@ -28,6 +28,8 @@ include\utsm\ipc_shm.h:
..\utsm-ipc\ipc_proto.h:
include\utsm\hypercall.h:
include\utsm\drr.h:
include\utsm\sched_ext.h:
include\utsm\sched.h:
include\utsm\dkm.h:
include\utsm\dma.h:
include\utsm\block.h:
Binary file not shown.
-5
View File
@@ -1,5 +0,0 @@
kernel/net.o: kernel\net.c include\utsm\net.h include\utsm\types.h \
include\utsm\log.h
include\utsm\net.h:
include\utsm\types.h:
include\utsm\log.h:
Binary file not shown.
-3
View File
@@ -1,3 +0,0 @@
kernel/panic.o: kernel\panic.c include\utsm\log.h include\utsm\types.h
include\utsm\log.h:
include\utsm\types.h:
Binary file not shown.
-7
View File
@@ -1,7 +0,0 @@
kernel/probe.o: kernel\probe.c include\utsm\instr.h include\utsm\types.h \
include\utsm\log.h include\utsm\arena.h kernel\ini_parser.h
include\utsm\instr.h:
include\utsm\types.h:
include\utsm\log.h:
include\utsm\arena.h:
kernel\ini_parser.h:
-6
View File
@@ -1,6 +0,0 @@
mm/arena.o: mm\arena.c include\utsm\arena.h include\utsm\types.h \
include\utsm\config.h include\utsm\log.h
include\utsm\arena.h:
include\utsm\types.h:
include\utsm\config.h:
include\utsm\log.h:
Binary file not shown.
-6
View File
@@ -1,6 +0,0 @@
mm/dma.o: mm\dma.c include\utsm\dma.h include\utsm\types.h \
include\utsm\log.h mm\..\arch\x86_64\limine.h
include\utsm\dma.h:
include\utsm\types.h:
include\utsm\log.h:
mm\..\arch\x86_64\limine.h:
Binary file not shown.
-7
View File
@@ -1,7 +0,0 @@
mm/mmio.o: mm\mmio.c include\utsm\mm.h include\utsm\types.h \
include\utsm\dma.h include\utsm\log.h mm\..\arch\x86_64\limine.h
include\utsm\mm.h:
include\utsm\types.h:
include\utsm\dma.h:
include\utsm\log.h:
mm\..\arch\x86_64\limine.h:
-7
View File
@@ -1,7 +0,0 @@
mm/paging.o: mm\paging.c include\utsm\paging.h include\utsm\types.h \
include\utsm\dma.h include\utsm\log.h mm\..\arch\x86_64\limine.h
include\utsm\paging.h:
include\utsm\types.h:
include\utsm\dma.h:
include\utsm\log.h:
mm\..\arch\x86_64\limine.h:
+10
View File
@@ -34,3 +34,13 @@ int utsm_pckc_get_or_derive(u32 segment_slot, utsm_segment_desc *desc, utsm_key_
*out_key = entry->key;
return UTSM_OK;
}
void utsm_pckc_invalidate_slot(u32 segment_slot) {
for (u32 i = 0; i < UTSM_MAX_PCKC_KEYS; i++) {
utsm_pckc_entry *entry = &g_pckc.entries[i];
if (entry->valid && entry->segment_slot == segment_slot) {
entry->valid = false;
entry->key = (utsm_key_material){ { 0, 0, 0, 0 } }; /* 擦除密钥材料 */
}
}
}
Binary file not shown.
-10
View File
@@ -1,10 +0,0 @@
pe/pe_dll_manager.o: pe\pe_dll_manager.c pe\pe_dll_manager.h \
include\utsm\types.h pe\pe_loader.h include\utsm\pe.h pe\pe_shim.h \
include\utsm\arena.h include\utsm\log.h
pe\pe_dll_manager.h:
include\utsm\types.h:
pe\pe_loader.h:
include\utsm\pe.h:
pe\pe_shim.h:
include\utsm\arena.h:
include\utsm\log.h:
-12
View File
@@ -1,12 +0,0 @@
pe/pe_loader.o: pe\pe_loader.c pe\pe_loader.h include\utsm\types.h \
include\utsm\pe.h pe\pe_shim.h pe\pe_dll_manager.h pe\x86emu32.h \
pe\..\include\utsm\pe.h include\utsm\arena.h include\utsm\log.h
pe\pe_loader.h:
include\utsm\types.h:
include\utsm\pe.h:
pe\pe_shim.h:
pe\pe_dll_manager.h:
pe\x86emu32.h:
pe\..\include\utsm\pe.h:
include\utsm\arena.h:
include\utsm\log.h:
-14
View File
@@ -1,14 +0,0 @@
pe/pe_service.o: pe\pe_service.c pe\pe_loader.h include\utsm\types.h \
include\utsm\pe.h pe\pe_shim.h pe\pe_dll_manager.h pe\x86emu32.h \
pe\..\include\utsm\pe.h include\utsm\arena.h include\utsm\idt.h \
include\utsm\log.h
pe\pe_loader.h:
include\utsm\types.h:
include\utsm\pe.h:
pe\pe_shim.h:
pe\pe_dll_manager.h:
pe\x86emu32.h:
pe\..\include\utsm\pe.h:
include\utsm\arena.h:
include\utsm\idt.h:
include\utsm\log.h:
-10
View File
@@ -1,10 +0,0 @@
pe/pe_shim.o: pe\pe_shim.c pe\pe_shim.h include\utsm\types.h \
pe\pe_dll_manager.h pe\..\include\utsm\pe.h include\utsm\arena.h \
include\utsm\log.h pe\..\arch\x86_64\limine.h
pe\pe_shim.h:
include\utsm\types.h:
pe\pe_dll_manager.h:
pe\..\include\utsm\pe.h:
include\utsm\arena.h:
include\utsm\log.h:
pe\..\arch\x86_64\limine.h:
-6
View File
@@ -1,6 +0,0 @@
pe/x86emu32.o: pe\x86emu32.c pe\x86emu32.h include\utsm\types.h \
pe\pe_shim.h include\utsm\log.h
pe\x86emu32.h:
include\utsm\types.h:
pe\pe_shim.h:
include\utsm\log.h:

Some files were not shown because too many files have changed in this diff Show More