This commit is contained in:
xyou
2026-07-31 13:53:49 +08:00
parent 5ea84fac97
commit f52157b7af
241 changed files with 26843 additions and 8155 deletions
+5
View File
@@ -0,0 +1,5 @@
kernel/block.o: kernel\block.c include\utsm\block.h include\utsm\types.h \
include\utsm\log.h
include\utsm\block.h:
include\utsm\types.h:
include\utsm\log.h:
+387 -26
View File
@@ -5,6 +5,7 @@
#include <utsm/types.h>
#include <utsm/pe.h>
#include <utsm/linux_compat.h>
#include <utsm/instr.h>
#include "../arch/x86_64/limine.h"
#define DSK_PATH "/system/deshab64/deshab.elf"
@@ -20,6 +21,27 @@
#define ET_EXEC 2
#define EM_X86_64 62
#define PT_LOAD 1
#define PT_DYNAMIC 2
/* ELF Dynamic section tags */
#define DT_NULL 0
#define DT_RELA 7
#define DT_RELASZ 8
#define DT_RELAENT 9
/* ELF Relocation types */
#define R_X86_64_RELATIVE 8
typedef struct elf64_dyn {
i64 tag;
u64 val;
} elf64_dyn;
typedef struct elf64_rela {
u64 offset;
u64 info;
i64 addend;
} elf64_rela;
void *memset(void *dst, int value, usize len);
void *memcpy(void *dst, const void *src, usize len);
@@ -152,27 +174,86 @@ static struct limine_file *dsk_find_module(void) {
}
/* ---- FAT32 block-provider file reader ---- */
static u8 g_dsk_fat32_disk[65536]; /* 128-sector BPB+FAT+root dir buffer */
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 */
/* 实机要求: 文件缓冲区足够大容纳 deshab.elf (~1.5MB) */
static u8 g_dsk_fat32_filedata[2097152]; /* 2MB file data buffer */
/* BUG-019 修复: FAT 按需扇区读取缓冲区(仅 512 字节),
* 当 FAT 条目偏移超出 g_dsk_fat32_disk (128KB) 时使用。 */
static u8 g_dsk_fat32_fat_sec[512];
/* BUG-019 修复: 按需读取 FAT 扇区获取下一个簇号。
* 如果目标 FAT 条目在预读缓冲区内,直接读取;
* 否则只读取包含该条目的单个 FAT 扇区(512 字节)。
* fat_start: FAT 在预读缓冲区中的字节偏移(reserved_sectors * 512)。
* clus: 当前簇号。
* bpb: BPB 指针(用于计算 FAT 扇区 LBA)。
* disk: 预读缓冲区基址。
* 返回: 下一个簇号,失败返回 0x0FFFFFFF(链终止)。 */
static u32 fat32_get_next_cluster(u32 fat_start_byte, u32 clus,
const fat32_bpb *bpb, const u8 *disk) {
u32 fat_ent_off = fat_start_byte + clus * 4;
/* 情况 1: FAT 条目在预读缓冲区内(小分区) */
if (fat_ent_off + 4 <= sizeof(g_dsk_fat32_disk)) {
return fat32_read_u32(disk + fat_ent_off) & 0x0FFFFFFF;
}
/* 情况 2: FAT 条目超出预读缓冲区(实机大分区)——按需读取单个 FAT 扇区 */
const dkm_kernel_api *api = dkm_get_kernel_api();
if (!api || !api->block) return 0x0FFFFFFF;
/* FAT 条目在 FAT 表中的字节偏移(相对于 FAT 起始) */
u32 fat_byte_off_in_fat = clus * 4;
/* 该条目所在的 FAT 扇区号(相对于 FAT 起始) */
u32 fat_sec_index = fat_byte_off_in_fat / 512;
/* 条目在扇区内的字节偏移 */
u32 ent_off_in_sec = fat_byte_off_in_fat % 512;
/* FAT 扇区的绝对 LBA */
u32 fat_sec_lba = bpb->reserved_sector_count + fat_sec_index;
int st = api->block->read(0, fat_sec_lba, 1, g_dsk_fat32_fat_sec);
if (st != 0) {
log_error("[UTSM] FAT32: on-demand FAT sector read failed");
log_hex64("[UTSM] FAT32: fat_sec_lba=", fat_sec_lba);
log_hex64("[UTSM] FAT32: clus=", clus);
return 0x0FFFFFFF;
}
return fat32_read_u32(g_dsk_fat32_fat_sec + ent_off_in_sec) & 0x0FFFFFFF;
}
static int dsk_load_from_block_fat32(const void **out_addr, u64 *out_size) {
const dkm_kernel_api *api = dkm_get_kernel_api();
if (!api || !api->block || !api->block->device_count) return -1;
if (!api || !api->block || !api->block->device_count) {
log_error("[UTSM] FAT32: no block api available");
return -1;
}
u32 count = api->block->device_count();
if (count == 0 || api->block->sector_size(0) != 512) return -1;
if (count == 0 || api->block->sector_size(0) != 512) {
log_error("[UTSM] FAT32: no block device or wrong sector size");
log_hex64("[UTSM] FAT32: device_count=", count);
return -1;
}
/* Read first 128 sectors: BPB + FAT + root dir */
/* Read first 256 sectors: BPB + FAT + root dir */
u8 *disk = g_dsk_fat32_disk;
int st = api->block->read(0, 0, 128, disk);
if (st != 0) return -1;
int st = api->block->read(0, 0, 256, disk);
if (st != 0) {
log_error("[UTSM] FAT32: BPB read failed");
log_hex64("[UTSM] FAT32: read status=", (u64)(i64)st);
return -1;
}
const fat32_bpb *bpb = (const fat32_bpb *)disk;
if (bpb->boot_sig != 0xAA55 || bpb->bytes_per_sector != 512) return -1;
if (bpb->boot_sig != 0xAA55 || bpb->bytes_per_sector != 512) {
log_error("[UTSM] FAT32: invalid BPB signature or sector size");
log_hex64("[UTSM] FAT32: boot_sig=", bpb->boot_sig);
log_hex64("[UTSM] FAT32: bps=", bpb->bytes_per_sector);
return -1;
}
u32 fat_start = bpb->reserved_sector_count * 512;
u32 data_start_sec = bpb->reserved_sector_count + (u32)bpb->fat_count * bpb->sectors_per_fat;
log_hex64("[UTSM] FAT32: fat_start_off=", fat_start);
log_hex64("[UTSM] FAT32: data_start_sec=", data_start_sec);
log_hex64("[UTSM] FAT32: spc=", bpb->sectors_per_cluster);
log_hex64("[UTSM] FAT32: root_clus=", bpb->root_cluster);
u32 clus = bpb->root_cluster;
u32 found_clus = 0;
@@ -184,7 +265,12 @@ static int dsk_load_from_block_fat32(const void **out_addr, u64 *out_size) {
u32 cls_sec = bpb->sectors_per_cluster;
u8 *cb = g_dsk_fat32_cluster;
st = api->block->read(0, clus_lba, cls_sec, cb);
if (st != 0) return -1;
if (st != 0) {
log_error("[UTSM] FAT32: dir cluster read failed");
log_hex64("[UTSM] FAT32: clus=", clus);
log_hex64("[UTSM] FAT32: lba=", clus_lba);
return -1;
}
const fat32_dir_entry *dir = (const fat32_dir_entry *)cb;
for (u32 e = 0; e * 32 < cls_sec * 512; e++) {
@@ -194,19 +280,27 @@ static int dsk_load_from_block_fat32(const void **out_addr, u64 *out_size) {
if (dir[e].attr & 0x08) continue;
if (fat32_name11_eq(dir[e].name, target)) {
found_size = dir[e].file_size;
found_clus = fat32_read_u16((const u8 *)&dir[e].cluster_low);
found_clus = fat32_read_u16((const u8 *)&dir[e].cluster_low) |
((u32)fat32_read_u16((const u8 *)&dir[e].cluster_high) << 16);
break;
}
}
if (found_clus) break;
u32 fat_ent = fat_start + clus * 4;
if (fat_ent + 4 > 65536) break;
clus = fat32_read_u32(disk + fat_ent) & 0x0FFFFFFF;
/* BUG-019: 使用按需 FAT 读取,不再受 128KB 缓冲区限制 */
clus = fat32_get_next_cluster(fat_start, clus, bpb, disk);
}
if (!found_clus || found_size == 0) return -1;
if (!found_clus || found_size == 0) {
log_error("[UTSM] FAT32: DESHAB.ELF not found in root dir");
return -1;
}
log_hex64("[UTSM] FAT32: found_clus=", found_clus);
log_hex64("[UTSM] FAT32: found_size=", found_size);
if (found_size > sizeof(g_dsk_fat32_filedata)) return -1;
if (found_size > sizeof(g_dsk_fat32_filedata)) {
log_error("[UTSM] FAT32: file exceeds 2MB buffer");
return -1;
}
u8 *dst = g_dsk_fat32_filedata;
u32 remaining = found_size;
u32 fc = found_clus;
@@ -219,19 +313,27 @@ static int dsk_load_from_block_fat32(const void **out_addr, u64 *out_size) {
u8 *chunk = g_dsk_fat32_cluster;
st = api->block->read(0, fc_lba, fc_sec, chunk);
if (st != 0) return -1;
if (st != 0) {
log_error("[UTSM] FAT32: data cluster read failed");
log_hex64("[UTSM] FAT32: fc=", fc);
log_hex64("[UTSM] FAT32: lba=", fc_lba);
return -1;
}
for (u32 b = 0; b < fc_bytes; b++) dst[b] = chunk[b];
dst += fc_bytes;
remaining -= fc_bytes;
u32 fat_ent = fat_start + fc * 4;
if (fat_ent + 4 > 65536) { fc = 0x0FFFFFFF; break; }
fc = fat32_read_u32(disk + fat_ent) & 0x0FFFFFFF;
/* BUG-019: 使用按需 FAT 读取 */
fc = fat32_get_next_cluster(fat_start, fc, bpb, disk);
}
/* Copy to arena for ELF loader */
u8 *file_buf = (u8 *)kmem_alloc_aligned(found_size, 16);
if (!file_buf) return -1;
if (!file_buf) {
log_error("[UTSM] FAT32: arena alloc failed");
log_hex64("[UTSM] FAT32: size=", found_size);
return -1;
}
for (u32 i = 0; i < found_size; i++) file_buf[i] = g_dsk_fat32_filedata[i];
*out_addr = file_buf;
@@ -240,6 +342,139 @@ static int dsk_load_from_block_fat32(const void **out_addr, u64 *out_size) {
return 0;
}
/* ---- FAT32 subdirectory traversal ---- */
/* 在指定起始 cluster 的目录项中查找 name11。
* is_dir=1 时只匹配子目录(attr & 0x10),is_dir=0 时只匹配文件。
* 返回 0 成功,out_clus/out_size 返回匹配项的起始 cluster 和大小。 */
static int fat32_find_in_dir(u32 start_clus, const char *name11, int is_dir,
u32 *out_clus, u32 *out_size) {
const dkm_kernel_api *api = dkm_get_kernel_api();
if (!api || !api->block || !api->block->device_count) return -1;
u8 *disk = g_dsk_fat32_disk;
const fat32_bpb *bpb = (const fat32_bpb *)disk;
if (bpb->boot_sig != 0xAA55 || bpb->bytes_per_sector != 512) return -2;
u32 fat_start = bpb->reserved_sector_count * 512;
u32 data_start_sec = bpb->reserved_sector_count + (u32)bpb->fat_count * bpb->sectors_per_fat;
u32 spc = bpb->sectors_per_cluster;
u32 clus = start_clus;
while (clus >= 2 && clus < 0x0FFFFFF8) {
u32 clus_lba = data_start_sec + (clus - 2) * spc;
u8 *cb = g_dsk_fat32_cluster;
int st = api->block->read(0, clus_lba, spc, cb);
if (st != 0) return -3;
const fat32_dir_entry *dir = (const fat32_dir_entry *)cb;
for (u32 e = 0; e * 32 < spc * 512; e++) {
if (dir[e].name[0] == 0) break;
if ((u8)dir[e].name[0] == 0xE5) continue;
if (dir[e].attr == 0x0F) continue;
if (dir[e].attr & 0x08) continue;
if (!fat32_name11_eq(dir[e].name, name11)) continue;
/* 名称匹配,检查类型 */
int entry_is_dir = (dir[e].attr & 0x10) ? 1 : 0;
if (entry_is_dir != is_dir) continue;
*out_clus = fat32_read_u16((const u8 *)&dir[e].cluster_low) |
((u32)fat32_read_u16((const u8 *)&dir[e].cluster_high) << 16);
*out_size = dir[e].file_size;
return 0;
}
/* 跟随 FAT 链 — BUG-019: 使用按需 FAT 读取 */
clus = fat32_get_next_cluster(fat_start, clus, bpb, disk);
}
return -4; /* 未找到 */
}
/* 按路径查找文件并读取内容。
* path: '/' 分隔的 8.3 格式路径(如 "SYSTEM /DESHAB64 /FUCK ")。
* out_data: 返回在 g_dsk_fat32_filedata 中的文件数据指针。
* out_size: 返回文件大小。
* 返回 0 成功。 */
int fat32_read_path(const char *path, u8 **out_data, u32 *out_size) {
const dkm_kernel_api *api = dkm_get_kernel_api();
if (!api || !api->block || !api->block->device_count) return -1;
u8 *disk = g_dsk_fat32_disk;
/* 确保 BPB 缓冲区是新鲜的 */
if (api->block->read(0, 0, 256, disk) != 0) return -2;
const fat32_bpb *bpb = (const fat32_bpb *)disk;
if (bpb->boot_sig != 0xAA55 || bpb->bytes_per_sector != 512) return -3;
u32 fat_start = bpb->reserved_sector_count * 512;
u32 data_start_sec = bpb->reserved_sector_count + (u32)bpb->fat_count * bpb->sectors_per_fat;
u32 spc = bpb->sectors_per_cluster;
/* 解析路径组件 */
u32 pos = 0;
u32 path_len = 0;
while (path[path_len]) path_len++;
u32 cur_clus = bpb->root_cluster; /* 从根目录开始 */
while (pos < path_len) {
/* 提取一个路径组件(到下一个 '/' 或结尾) */
char comp[12]; /* 11 字符 8.3 名 + \0 */
u32 ci = 0;
while (pos < path_len && path[pos] != '/' && ci < 11) {
comp[ci++] = path[pos++];
}
/* 不足 11 字符则补空格 */
while (ci < 11) comp[ci++] = ' ';
comp[11] = 0;
/* 跳过 '/' */
if (pos < path_len && path[pos] == '/') pos++;
/* 判断是否为最后一个组件 */
int is_last = (pos >= path_len);
if (is_last) {
/* 最后一级:查找文件 */
u32 found_clus = 0, found_size = 0;
int rc = fat32_find_in_dir(cur_clus, comp, 0, &found_clus, &found_size);
if (rc != 0) return -4;
if (found_size > sizeof(g_dsk_fat32_filedata)) return -5;
/* 读取文件数据 */
u8 *dst = g_dsk_fat32_filedata;
u32 remaining = found_size;
u32 fc = found_clus;
while (fc >= 2 && fc < 0x0FFFFFF8 && remaining > 0) {
u32 fc_lba = data_start_sec + (fc - 2) * spc;
u32 fc_bytes = spc * 512;
if (fc_bytes > remaining) fc_bytes = remaining;
u8 *chunk = g_dsk_fat32_cluster;
if (api->block->read(0, fc_lba, spc, chunk) != 0) return -6;
for (u32 b = 0; b < fc_bytes; b++) dst[b] = chunk[b];
dst += fc_bytes;
remaining -= fc_bytes;
/* BUG-019: 使用按需 FAT 读取 */
fc = fat32_get_next_cluster(fat_start, fc, bpb, disk);
}
*out_data = g_dsk_fat32_filedata;
*out_size = found_size;
return 0;
} else {
/* 中间级:查找子目录 */
u32 sub_clus = 0, sub_size = 0;
int rc = fat32_find_in_dir(cur_clus, comp, 1, &sub_clus, &sub_size);
if (rc != 0) return -7;
cur_clus = sub_clus;
}
}
return -8; /* 路径为空或无效 */
}
/* ---- ELF checks ---- */
static int dsk_check_elf(const void *address, u64 size) {
if (!address || size < sizeof(elf64_ehdr)) return -1;
@@ -263,15 +498,26 @@ static int dsk_load_elf_image(const void *address, u64 size, dsk_entry_fn *entry
u64 max_align = 0x1000;
u32 load_count = 0;
/* PT_DYNAMIC 的位置(PIE 重定位用) */
u64 dyn_off = 0;
u64 dyn_filesz = 0;
int has_dyn = 0;
for (u16 i = 0; i < eh->phnum; i++) {
const elf64_phdr *ph = (const elf64_phdr *)(base + eh->phoff + (u64)i * eh->phentsize);
if (ph->type != PT_LOAD) continue;
if (ph->filesz > ph->memsz) return -1;
if (!range_ok(ph->offset, ph->filesz, size)) return -2;
if (ph->vaddr < min_vaddr) min_vaddr = ph->vaddr;
if (ph->vaddr + ph->memsz > max_vaddr) max_vaddr = ph->vaddr + ph->memsz;
if (ph->align > max_align) max_align = ph->align;
load_count++;
if (ph->type == PT_LOAD) {
if (ph->filesz > ph->memsz) return -1;
if (!range_ok(ph->offset, ph->filesz, size)) return -2;
if (ph->vaddr < min_vaddr) min_vaddr = ph->vaddr;
if (ph->vaddr + ph->memsz > max_vaddr) max_vaddr = ph->vaddr + ph->memsz;
if (ph->align > max_align) max_align = ph->align;
load_count++;
} else if (ph->type == PT_DYNAMIC) {
if (!range_ok(ph->offset, ph->filesz, size)) return -2;
dyn_off = ph->offset;
dyn_filesz = ph->filesz;
has_dyn = 1;
}
}
if (load_count == 0 || min_vaddr == ~0ULL || max_vaddr <= min_vaddr) return -3;
@@ -290,6 +536,44 @@ static int dsk_load_elf_image(const void *address, u64 size, dsk_entry_fn *entry
memcpy(image + dst_off, base + ph->offset, ph->filesz);
}
/* PIE 重定位: 处理 PT_DYNAMIC → DT_RELA → R_X86_64_RELATIVE
* load_bias = image 实际加载地址 - ELF 预期最小 vaddr
* 对每个 R_X86_64_RELATIVE: slot = load_bias + addend */
if (has_dyn && eh->type == ET_DYN) {
u64 load_bias = (u64)image - min_vaddr;
const elf64_dyn *dyn = (const elf64_dyn *)(base + dyn_off);
u64 dyn_count = dyn_filesz / sizeof(elf64_dyn);
u64 rela_off = 0, rela_sz = 0, rela_ent = sizeof(elf64_rela);
for (u64 d = 0; d < dyn_count; d++) {
if (dyn[d].tag == DT_NULL) break;
if (dyn[d].tag == DT_RELA) rela_off = dyn[d].val;
if (dyn[d].tag == DT_RELASZ) rela_sz = dyn[d].val;
if (dyn[d].tag == DT_RELAENT) rela_ent = dyn[d].val;
}
if (rela_off != 0 && rela_sz != 0 && rela_ent != 0) {
/* rela_off 是相对于文件开头的 vaddr,需转换为 image 内偏移 */
if (rela_off >= min_vaddr && rela_off < min_vaddr + image_size) {
u64 rela_count = rela_sz / rela_ent;
for (u64 r = 0; r < rela_count; r++) {
const elf64_rela *rel = (const elf64_rela *)(
image + (rela_off - min_vaddr) + r * rela_ent);
u32 rtype = (u32)rel->info;
if (rtype == R_X86_64_RELATIVE) {
if (rel->offset < min_vaddr || rel->offset >= min_vaddr + image_size) continue;
u64 *slot = (u64 *)(image + (rel->offset - min_vaddr));
*slot = load_bias + (u64)rel->addend;
}
}
}
log_info("[UTSM] PIE reloc applied");
log_hex64("[UTSM] load_bias=", load_bias);
log_hex64("[UTSM] rela_count=", rela_sz / rela_ent);
}
}
*entry_out = (dsk_entry_fn)(image + (eh->entry - min_vaddr));
log_hex64("[UTSM] DSK image base=", (u64)image);
log_hex64("[UTSM] DSK image size=", image_size);
@@ -333,6 +617,24 @@ static void dsk_fill_boot_context(dsk_boot_context *ctx) {
ctx->reserved[5] = (u64)lxc;
}
/* Probe 探测缓冲信息(供 shell $probe 命令读取) */
if (g_instr_enabled) {
probe_info *pi = (probe_info *)kmem_alloc_aligned(sizeof(probe_info), 8);
if (pi) {
pi->magic = PROBE_INFO_MAGIC;
pi->version = 1;
pi->probe_buf_addr = (u64)probe_buf_address();
pi->probe_cap = probe_capacity();
pi->probe_head = probe_head_value();
pi->probe_count = probe_count();
pi->probe_dropped = probe_dropped_count();
pi->instr_enabled = g_instr_enabled;
pi->instr_probe_enable = g_instr_probe_enable;
ctx->reserved[6] = (u64)pi;
ctx->flags |= DSK_BOOT_FLAG_PROBE_INFO;
}
}
u64 rsp;
__asm__ volatile ("movq %%rsp, %0" : "=r"(rsp));
ctx->kernel_stack_top = rsp;
@@ -384,6 +686,65 @@ int dsk_load_and_jump(void) {
}
dsk_fill_boot_context(ctx);
/* 实机安全: 跳转前 cli → mask PIC → 重置 IDT → NMI off。
* DSK 加载的 ELF 映像可能覆盖 UTSM 的驱动代码段,
* 如果 UTSM 注册的 IRQ handler 所在内存被覆盖,
* 中断触发时跳转到无效地址 → 三重故障重启。
*
* P0 修复: 1) 先 cli 禁用中断,消除 PIC mask 两步操作之间的中断竞争窗口
* 2) mask PIC 确保不会有硬件中断到达
* 3) 设置 LAPIC TPR=0xFF 屏蔽所有通过 IOAPIC 路由的中断
* 4) 将 IDT 所有条目替换为安全 halt stub,防止 DSK 运行时
* 过期的 UTSM handler 被异常/spurious IRQ 触发
* 5) 禁用 NMI */
{
extern void outb(u16 port, u8 value);
extern u8 inb(u16 port);
/* 1) 先禁用中断——关键修复!原来缺少此步,
* outb(0xA1,0xFF) 和 outb(0x21,0xFF) 之间有中断窗口 */
__asm__ volatile("cli");
/* 2) mask PIC — 此时 IF=0,安全操作 */
outb(0xA1, 0xFF); /* PIC2: mask IRQ8-15 */
outb(0x21, 0xFF); /* PIC1: mask IRQ0-7 */
/* 3) BUG-020 修复: 设置 LAPIC TPR=0xFF 屏蔽所有 IOAPIC 路由中断。
* 实机多核平台中断通常经 IOAPIC 而非 PIC,PIC mask 不影响
* IOAPIC redirection entry。通过 IA32_APIC_BASE MSR 读取 LAPIC
* 基地址,写入 TPR(偏移 0x80)=0xFF 可在 LAPIC 层面屏蔽所有
* 可屏蔽中断(低于 0xFF 优先级),确保 DSK 运行期间不会有
* IOAPIC 路由的 IRQ 到达。HHDM 映射后 LAPIC MMIO 可访问。 */
{
u32 msr_lo, msr_hi;
__asm__ volatile("rdmsr" : "=a"(msr_lo), "=d"(msr_hi) : "c"(0x1B));
u64 lapic_phys = ((u64)msr_hi << 32) | (msr_lo & 0xFFFFF000ULL);
if (lapic_phys && (msr_lo & (1 << 11))) {
/* LAPIC 全局启用时(bit 11)才操作 TPR */
extern volatile struct limine_hhdm_request g_hhdm_request;
u64 hhdm_off = g_hhdm_request.response
? g_hhdm_request.response->offset : 0;
if (hhdm_off) {
u64 lapic_vaddr = lapic_phys + hhdm_off;
*(volatile u32 *)(lapic_vaddr + 0x80) = 0xFF;
}
}
}
/* 4) 将 IDT 所有 256 个条目替换为安全 halt stub。
* 实机会产生 spurious IRQ7/15(即使 PIC 已 mask),
* 且 SMI/NMI 可能触发异常。如果 UTSM 的 idt_handler
* 所调用的 log 函数或串口驱动被覆盖,会导致双重异常→三重故障。 */
extern void idt_halt_all(void);
idt_halt_all();
/* 5) NMI off */
outb(0x70, inb(0x70) | 0x80);
}
log_hex64("[UTSM] DSK context magic=", ctx->magic);
log_hex64("[UTSM] DSK context api=", ctx->dkm_kernel_api);
log_hex64("[UTSM] DSK context fb=", ctx->framebuffer_address);
log_info("[UTSM] jumping to DSK");
entry(ctx);
+19
View File
@@ -0,0 +1,19 @@
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
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:
Binary file not shown.
+166
View File
@@ -0,0 +1,166 @@
/* INI 分区格式解析器 — freestanding, 无堆分配, 无 libc 依赖 */
#include "ini_parser.h"
/* ---- 内部辅助 ---- */
static int ini_streq(const char *a, const char *b) {
if (!a || !b) return 0;
while (*a && *b) {
if (*a != *b) return 0;
a++; b++;
}
return *a == *b;
}
static int ini_isspace(char c) {
return c == ' ' || c == '\t' || c == '\r';
}
static int ini_isdigit(char c) {
return c >= '0' && c <= '9';
}
static int ini_strncpy(char *dst, const char *src, u32 max) {
u32 i = 0;
while (i + 1 < max && src[i]) {
dst[i] = src[i];
i++;
}
dst[i] = 0;
return (int)i;
}
static int ini_atoi(const char *s) {
int neg = 0, v = 0;
if (!s) return 0;
while (ini_isspace(*s)) s++;
if (*s == '-') { neg = 1; s++; }
while (ini_isdigit(*s)) {
v = v * 10 + (*s - '0');
s++;
}
return neg ? -v : v;
}
static int ini_parse_bool(const char *s) {
if (!s) return -1;
if (s[0] == '1') return 1;
if (s[0] == '0') return 0;
if (ini_streq(s, "true")) return 1;
if (ini_streq(s, "false")) return 0;
if (ini_streq(s, "yes")) return 1;
if (ini_streq(s, "no")) return 0;
return -1;
}
/* ---- 公共接口 ---- */
int ini_parse(const char *text, u32 size, ini_config *cfg) {
if (!text || !cfg) return -1;
cfg->count = 0;
char cur_section[32] = {0}; /* 当前分区名,默认空 */
u32 pos = 0;
while (pos < size) {
/* 跳过行首空白 */
while (pos < size && (text[pos] == ' ' || text[pos] == '\t'))
pos++;
if (pos >= size) break;
char c = text[pos];
/* 空行或换行 */
if (c == '\n') { pos++; continue; }
/* 注释行: # 或 ; 开头 */
if (c == '#' || c == ';') {
while (pos < size && text[pos] != '\n') pos++;
continue;
}
/* 分区头: [section] */
if (c == '[') {
pos++; /* 跳过 '[' */
u32 si = 0;
while (pos < size && text[pos] != ']' && text[pos] != '\n' && si + 1 < 32) {
cur_section[si++] = text[pos++];
}
cur_section[si] = 0;
/* 跳过到行尾 */
while (pos < size && text[pos] != '\n') pos++;
continue;
}
/* key=value 行 */
if (cfg->count >= 64) break; /* 达到上限 */
ini_entry *e = &cfg->entries[cfg->count];
/* 读取 key */
u32 ki = 0;
while (pos < size && text[pos] != '=' && text[pos] != '\n' &&
!ini_isspace(text[pos]) && ki + 1 < 32) {
e->key[ki++] = text[pos++];
}
e->key[ki] = 0;
/* 跳过 key 和 '=' 之间的空白 */
while (pos < size && ini_isspace(text[pos]) && text[pos] != '\n')
pos++;
/* 期望 '=' */
if (pos >= size || text[pos] != '=') {
/* 无效行,跳到行尾 */
while (pos < size && text[pos] != '\n') pos++;
continue;
}
pos++; /* 跳过 '=' */
/* 跳过 '=' 后的空白 */
while (pos < size && ini_isspace(text[pos]) && text[pos] != '\n')
pos++;
/* 读取 value(到行尾,去除尾部空白) */
u32 vi = 0;
while (pos < size && text[pos] != '\n' && vi + 1 < 64) {
e->value[vi++] = text[pos++];
}
/* 去除尾部空白 */
while (vi > 0 && ini_isspace(e->value[vi - 1])) vi--;
e->value[vi] = 0;
/* 复制 section 名 */
ini_strncpy(e->section, cur_section, 32);
cfg->count++;
}
return 0;
}
const char *ini_get(const ini_config *cfg, const char *section, const char *key) {
if (!cfg || !section || !key) return NULL;
for (u32 i = 0; i < cfg->count; i++) {
if (ini_streq(cfg->entries[i].section, section) &&
ini_streq(cfg->entries[i].key, key)) {
return cfg->entries[i].value;
}
}
return NULL;
}
int ini_get_int(const ini_config *cfg, const char *section, const char *key, int defval) {
const char *v = ini_get(cfg, section, key);
if (!v || v[0] == 0) return defval;
return ini_atoi(v);
}
int ini_get_bool(const ini_config *cfg, const char *section, const char *key, int defval) {
const char *v = ini_get(cfg, section, key);
if (!v || v[0] == 0) return defval;
int b = ini_parse_bool(v);
return (b >= 0) ? b : defval;
}
+4
View File
@@ -0,0 +1,4 @@
kernel/ini_parser.o: kernel\ini_parser.c kernel\ini_parser.h \
include\utsm\types.h
kernel\ini_parser.h:
include\utsm\types.h:
+38
View File
@@ -0,0 +1,38 @@
#ifndef UTSM_INI_PARSER_H
#define UTSM_INI_PARSER_H
#include <utsm/types.h>
/* INI 配置条目 */
typedef struct {
char section[32];
char key[32];
char value[64];
} ini_entry;
/* INI 配置集合(栈/静态分配,不依赖堆) */
typedef struct {
ini_entry entries[64]; /* 最多 64 条配置项 */
u32 count;
} ini_config;
/* 解析 INI 文本到 ini_config。
* text: INI 文本起始地址
* size: 文本字节长度
* cfg: 输出配置集合
* 返回 0 成功,负数失败 */
int ini_parse(const char *text, u32 size, ini_config *cfg);
/* 在 section 下查找 key,返回 value 字符串。
* 未找到返回 NULL。 */
const char *ini_get(const ini_config *cfg, const char *section, const char *key);
/* 便捷查询:返回整数值。
* 未找到或格式错误返回 defval。 */
int ini_get_int(const ini_config *cfg, const char *section, const char *key, int defval);
/* 便捷查询:返回布尔值。
* "0"/"false" = 0, "1"/"true" = 1,未找到返回 defval。 */
int ini_get_bool(const ini_config *cfg, const char *section, const char *key, int defval);
#endif /* UTSM_INI_PARSER_H */
+95
View File
@@ -0,0 +1,95 @@
/* instr.c — Deshab 插桩系统初始化与全局配置管理
*
* 从 FUCK [debug] 配置段加载插桩参数,初始化全局配置变量。
* 在 kernel_main() 中调用 instr_init(&g_boot_cfg) 启用。
*/
#include <utsm/instr.h>
#include <utsm/log.h>
#include <utsm/types.h>
#include "ini_parser.h"
/* ---- 全局配置变量(供 instr.h 宏条件判断) ---- */
u32 g_instr_enabled = 0;
u32 g_instr_log_level = INSTR_LOG_INFO;
u32 g_instr_probe_enable = 0;
u32 g_instr_stat_interval = 256;
u32 g_instr_module_flags = 0;
u64 instr_tsc_per_ms = 0;
/* ---- 低级 I/O(TSC 校准用,与 arch/x86_64/io.c 独立避免链接冲突) ---- */
static void instr_outb(u16 port, u8 value) {
__asm__ volatile("outb %0, %1" :: "a"(value), "Nd"(port));
}
static u8 instr_inb(u16 port) {
u8 value;
__asm__ volatile("inb %1, %0" : "=a"(value) : "Nd"(port));
return value;
}
/* TSC 读取 */
u64 instr_rdtsc(void) {
u32 lo, hi;
__asm__ volatile("rdtsc" : "=a"(lo), "=d"(hi));
return ((u64)hi << 32) | lo;
}
/* TSC 校准:PIT ch0 ~10ms 区间,与 serial.c / dkm_shared.h 相同逻辑 */
static void instr_tsc_calibrate(void) {
instr_outb(0x43, 0x30); /* ch0, lo+hi, mode 0, binary */
instr_outb(0x40, 0x7c); /* 11932 low = ~10ms */
instr_outb(0x40, 0x2e); /* 11932 high */
u64 tsc_start = instr_rdtsc();
u16 prev = 0;
u64 loops = 0;
for (;;) {
instr_outb(0x43, 0x00);
u16 cur = (u16)instr_inb(0x40) | ((u16)instr_inb(0x40) << 8);
if (cur > prev && loops > 10) break;
prev = cur;
loops++;
}
u64 tsc_end = instr_rdtsc();
instr_tsc_per_ms = (tsc_end - tsc_start) / 10;
}
void instr_init(const void *cfg_ptr) {
const ini_config *cfg = (const ini_config *)cfg_ptr;
/* 从 FUCK [debug] 段读取配置 */
g_instr_enabled = (u32)ini_get_bool(cfg, "debug", "enabled", 0);
g_instr_log_level = (u32)ini_get_int(cfg, "debug", "log_level", INSTR_LOG_INFO);
g_instr_probe_enable = (u32)ini_get_bool(cfg, "debug", "probe_enable", 0);
g_instr_stat_interval = (u32)ini_get_int(cfg, "debug", "stat_summary_interval", 256);
/* 模块级过滤标志 */
g_instr_module_flags = 0;
if (ini_get_bool(cfg, "debug", "utsm_trace", 0))
g_instr_module_flags |= INSTR_F_UTSM_TRACE;
if (ini_get_bool(cfg, "debug", "vmm_trace", 0))
g_instr_module_flags |= INSTR_F_VMM_TRACE;
if (ini_get_bool(cfg, "debug", "dkm_trace", 0))
g_instr_module_flags |= INSTR_F_DKM_TRACE;
if (ini_get_bool(cfg, "debug", "dsk_trace", 0))
g_instr_module_flags |= INSTR_F_DSK_TRACE;
if (ini_get_bool(cfg, "debug", "block_trace", 0))
g_instr_module_flags |= INSTR_F_BLOCK_TRACE;
if (ini_get_bool(cfg, "debug", "net_trace", 0))
g_instr_module_flags |= INSTR_F_NET_TRACE;
if (ini_get_bool(cfg, "debug", "input_trace", 0))
g_instr_module_flags |= INSTR_F_INPUT_TRACE;
/* 校准 TSC(独立于 serial.c 的校准,供插桩时间戳使用) */
instr_tsc_calibrate();
/* 初始化探测缓冲 */
probe_init(cfg);
/* 输出初始化状态 */
if (g_instr_enabled) {
log_info("[INSTR] enabled");
log_hex64("[INSTR] log_level=", g_instr_log_level);
log_hex64("[INSTR] probe_enable=", g_instr_probe_enable);
log_hex64("[INSTR] module_flags=", g_instr_module_flags);
log_hex64("[INSTR] tsc_per_ms=", instr_tsc_per_ms);
}
}
+6
View File
@@ -0,0 +1,6 @@
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:
+3
View File
@@ -0,0 +1,3 @@
kernel/log.o: kernel\log.c include\utsm\log.h include\utsm\types.h
include\utsm\log.h:
include\utsm\types.h:
+267 -51
View File
@@ -9,94 +9,310 @@
#include <utsm/net.h>
#include <utsm/ipc_shm.h>
#include <utsm/linux_compat.h>
#include <utsm/instr.h>
#include "ini_parser.h"
#include "../arch/x86_64/limine.h"
void arch_halt_forever(void);
extern volatile struct limine_module_request g_module_request;
/* dkm/manifest.c: 带 FUCK [drivers] 过滤的 manifest 加载入口 */
void dsm_load_by_manifest_ex(const ini_config *cfg);
/* ---- 运行期配置全局变量(从 FUCK 文件初始化) ---- */
u32 g_utsm_max_segments = UTSM_MAX_SEGMENTS_DEFAULT;
u32 g_utsm_max_capabilities = UTSM_MAX_CAPABILITIES_DEFAULT;
u32 g_utsm_max_pckc_keys = UTSM_MAX_PCKC_KEYS_DEFAULT;
u64 g_utsm_arena_size = UTSM_ARENA_SIZE_DEFAULT;
u64 g_utsm_dirty_shard_pages = UTSM_DIRTY_SHARD_PAGES_DEFAULT;
/* 将 FUCK [utsm] 区的配置应用到运行期全局变量 */
static void utsm_apply_config(const ini_config *cfg) {
if (!cfg) return;
g_utsm_max_segments = (u32)ini_get_int(cfg, "utsm", "max_segments", UTSM_MAX_SEGMENTS_DEFAULT);
g_utsm_max_capabilities = (u32)ini_get_int(cfg, "utsm", "max_capabilities", UTSM_MAX_CAPABILITIES_DEFAULT);
g_utsm_max_pckc_keys = (u32)ini_get_int(cfg, "utsm", "max_pckc_keys", UTSM_MAX_PCKC_KEYS_DEFAULT);
g_utsm_arena_size = (u64)ini_get_int(cfg, "utsm", "arena_size_mb", 16) * 1024 * 1024;
g_utsm_dirty_shard_pages = (u64)ini_get_int(cfg, "utsm", "dirty_shard_pages", UTSM_DIRTY_SHARD_PAGES_DEFAULT);
log_info("[UTSM] FUCK config applied");
log_hex64("[UTSM] max_segments=", g_utsm_max_segments);
log_hex64("[UTSM] max_pckc_keys=", g_utsm_max_pckc_keys);
log_hex64("[UTSM] dirty_shard_pages=", g_utsm_dirty_shard_pages);
}
/* ---- 全局启动配置(从 FUCK 文件读取) ---- */
static ini_config g_boot_cfg;
static int g_boot_cfg_loaded = 0;
/* 从 Limine boot module 读取 FUCK 配置。
* cmdline="fuck:config" 的模块即为 FUCK 配置文件。
* 返回 0 成功,负数失败。 */
static int utsm_load_fuck_config(ini_config *cfg) {
struct limine_module_response *rsp = g_module_request.response;
if (!rsp) return -1;
for (u64 i = 0; i < rsp->module_count; i++) {
struct limine_file *f = rsp->modules[i];
if (f && f->cmdline) {
/* 比较 cmdline 是否为 "fuck:config" */
const char *c = f->cmdline;
const char *tag = "fuck:config";
int match = 1;
for (int j = 0; tag[j]; j++) {
if (c[j] != tag[j]) { match = 0; break; }
}
if (match && c[11] == 0) {
int rc = ini_parse((const char *)f->address, (u32)f->size, cfg);
if (rc == 0) {
log_info("[UTSM] FUCK config loaded from boot module");
return 0;
}
}
}
}
log_warn("[UTSM] FUCK boot module not found");
return -2;
}
void kernel_main(void) {
/* ---- 插桩: 启动总时间戳 ---- */
INSTR_TS_DECL(boot_total);
INSTR_TS_BEGIN(boot_total);
serial_init();
log_info("[UTSM] boot");
/* ==== 真机硬件特征早期检测 (在任何初始化之前) ====
* 检测项目:
* 1. CPU vendor (GenuineIntel / AuthenticAMD / etc.)
* 2. 最大物理地址宽度 (CPUID.80000008H:EAX[7:0])
* 3. LA57 (5-level paging) 是否激活 → 拒绝启动
* 4. CPU 核心数 (CPUID.0BH 或 CPUID.01H)
* 5. PCIe MCFG 可用性 (后续由 ACPI 驱动检测)
*
* **QEMU 无法测试但真机必需的代码路径**:
* - LA57 拒绝: QEMU 默认不启用 5 级分页
* - 物理地址宽度 > 48: 只有大内存真机才有
* - AMD CPU vendor: QEMU 默认 Intel, 实机可能是 AMD
* - 多核: QEMU -smp 可以模拟, 但真机拓扑更复杂
*/
{
/* CPU vendor */
u32 a, b, c, d;
__asm__ volatile("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "a"(0), "c"(0));
char vendor[13];
vendor[0] = (char)(b & 0xff);
vendor[1] = (char)((b >> 8) & 0xff);
vendor[2] = (char)((b >> 16) & 0xff);
vendor[3] = (char)((b >> 24) & 0xff);
vendor[4] = (char)(d & 0xff);
vendor[5] = (char)((d >> 8) & 0xff);
vendor[6] = (char)((d >> 16) & 0xff);
vendor[7] = (char)((d >> 24) & 0xff);
vendor[8] = (char)(c & 0xff);
vendor[9] = (char)((c >> 8) & 0xff);
vendor[10] = (char)((c >> 16) & 0xff);
vendor[11] = (char)((c >> 24) & 0xff);
vendor[12] = 0;
log_info("[UTSM] CPU vendor: ");
log_info(vendor);
/* Max physical address width */
__asm__ volatile("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "a"(0x80000000), "c"(0));
if (a >= 0x80000008) {
__asm__ volatile("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "a"(0x80000008), "c"(0));
u32 phys_bits = a & 0xff;
u32 virt_bits = (a >> 8) & 0xff;
log_hex64("[UTSM] MaxPhysAddr bits=", phys_bits);
log_hex64("[UTSM] MaxVirtAddr bits=", virt_bits);
}
/* LA57 early detection — 在 CR4 读之前先通过 CPUID 检查是否支持 */
__asm__ volatile("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "a"(7), "c"(0));
if (c & (1u << 16)) {
log_warn("[UTSM] CPU supports LA57 (5-level paging)");
/* 检查 CR4 是否实际启用了 LA57 */
u64 cr4;
__asm__ volatile("mov %%cr4, %0" : "=r"(cr4));
if (cr4 & (1ULL << 12)) {
log_error("[UTSM] LA57 is ACTIVE — this kernel requires 4-level paging");
log_error("[UTSM] Refusing to boot. Disable LA57 in firmware settings.");
arch_halt_forever();
}
}
/* CPU core count — CPUID leaf 0BH (Intel Extended Topology) */
__asm__ volatile("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "a"(0), "c"(0));
if (a >= 0x0B) {
/* 尝试 level 0 获取 SMT 核心数 */
u32 level_type = 0, cores = 0;
__asm__ volatile("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "a"(0x0B), "c"(0));
level_type = (c >> 8) & 0xff;
cores = b & 0xffff;
if (level_type == 1 && cores > 0) {
log_hex64("[UTSM] SMT threads=", cores);
}
__asm__ volatile("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "a"(0x0B), "c"(1));
level_type = (c >> 8) & 0xff;
cores = b & 0xffff;
if (level_type == 2 && cores > 0) {
log_hex64("[UTSM] logical processors=", cores);
}
} else {
/* fallback: CPUID.01H EBX[23:16] */
__asm__ volatile("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "a"(1), "c"(0));
u32 lc = (b >> 16) & 0xff;
log_hex64("[UTSM] logical processors (legacy)=", lc);
}
/* ---- 插桩: CPU 检测完成,记录 vendor ---- */
INSTR_PROBE(BOOT, (u64)vendor[0] | ((u64)vendor[1] << 8), 0, 0, 0);
}
/* ---- 插桩: IDT 初始化耗时 ---- */
INSTR_TS_DECL(ts_idt);
INSTR_TS_BEGIN(ts_idt);
idt_init();
INSTR_TS_END(ts_idt, "idt_init");
/* === 读取 FUCK 配置(通过 Limine boot module 预加载) === */
g_boot_cfg_loaded = (utsm_load_fuck_config(&g_boot_cfg) == 0);
ini_config *cfg = g_boot_cfg_loaded ? &g_boot_cfg : NULL;
/* ---- 插桩: FUCK 配置加载完成 ---- */
INSTR_PROBE(BOOT, (u64)g_boot_cfg_loaded, 0, 0, 0);
/* === 初始化插桩系统(在 arena_init 之前,但需要 FUCK 配置) === */
/* 注意: probe_init 需要 arena,所以 instr_init 必须在 arena_init 之后。
* 此处先设置 g_instr_enabled 等全局变量,probe_init 延后到 arena 后。
* 实际上 instr_init 内部会调用 probe_init,而 probe_init 需要 kmem_alloc。
* 所以我们将 instr_init 移到 arena_init 之后。*/
/* === 应用 UTSM 算法参数到运行期全局变量 === */
utsm_apply_config(cfg);
log_info("[UTSM] arena init begin");
INSTR_TS_DECL(ts_arena);
INSTR_TS_BEGIN(ts_arena);
arena_init();
INSTR_TS_END(ts_arena, "arena_init");
log_info("[UTSM] arena init ok");
/* ---- 插桩: arena 就绪后初始化插桩系统(含探测缓冲分配) ---- */
instr_init(cfg);
log_info("[UTSM] dma init begin");
INSTR_TS_DECL(ts_dma);
INSTR_TS_BEGIN(ts_dma);
dma_init();
INSTR_TS_END(ts_dma, "dma_init");
log_info("[UTSM] dma init ok");
log_info("[UTSM] net registry init begin");
INSTR_TS_DECL(ts_net);
INSTR_TS_BEGIN(ts_net);
net_init();
INSTR_TS_END(ts_net, "net_init");
log_info("[UTSM] net registry init ok");
log_info("[UTSM] drr init begin");
INSTR_TS_DECL(ts_drr);
INSTR_TS_BEGIN(ts_drr);
drr_init();
INSTR_TS_END(ts_drr, "drr_init");
log_info("[UTSM] drr init ok");
log_info("[UTSM] core init begin");
INSTR_TS_DECL(ts_utsm);
INSTR_TS_BEGIN(ts_utsm);
utsm_init();
INSTR_TS_END(ts_utsm, "utsm_init");
log_info("[UTSM] init ok");
INSTR_TS_DECL(ts_dkm);
INSTR_TS_BEGIN(ts_dkm);
dkm_init();
dkm_fill_platform_info();
dsm_load_by_manifest();
INSTR_TS_END(ts_dkm, "dkm_init");
int result = utsm_selftest_run();
if (result == 0) {
log_info("[UTSM] SELFTEST PASS");
/* === 驱动加载 — 按 [drivers] 区过滤 === */
INSTR_TS_DECL(ts_dsm);
INSTR_TS_BEGIN(ts_dsm);
dsm_load_by_manifest_ex(cfg);
INSTR_TS_END(ts_dsm, "dsm_load_manifest");
/* Phase 1.1: VMM (VMX/EPT) 初始化 + 自检
* 若 VMX 不可用(如 QEMU 未启用),仅警告,不阻断 DSK 启动 */
if (vmm_init() == 0) {
log_info("[UTSM] VMM init ok");
int vmm_st = vmm_self_test();
if (vmm_st == 0) {
log_info("[UTSM] VMM self-test PASS");
/* Phase 1.2: Linux 加载器 + 启动
* 若 bzImage 模块存在,加载并启动 Linux guest。
* 若无 bzImage,跳过 Linux 启动,继续 DSK 流程。 */
if (linux_loader_init() == 0) {
log_info("[UTSM] Linux loader init ok");
/* Phase 1.3: Initialize IPC shared memory before
* launching Linux. Allocates 1MB, initializes ring
* buffers, and EPT-maps at GPA 0x04000000 so the
* Linux guest can access it via UTSM_HCALL_SHM_INFO. */
if (ipc_shm_init() == 0) {
log_info("[UTSM] IPC shm init ok");
} else {
log_error("[UTSM] IPC shm init failed (non-fatal)");
}
int lin_st = linux_launch();
if (lin_st == 0) {
log_info("[UTSM] Linux guest parked (daemon ready)");
/* Phase 3.2: 初始化 Linux 兼容层服务
* (需在 linux_launch 成功 + guest park 后调用) */
linux_compat_init();
} else {
log_error("[UTSM] Linux launch failed");
log_hex64("[UTSM] Linux st=", (u64)(i64)lin_st);
}
} else {
log_warn("[UTSM] Linux loader unavailable (no bzImage)");
}
} else {
log_error("[UTSM] VMM self-test FAIL");
log_hex64("[UTSM] VMM st=", (u64)(i64)vmm_st);
}
/* === selftest — 可通过 FUCK [boot] selftest=0 跳过 === */
int run_selftest = ini_get_bool(cfg, "boot", "selftest", 1);
if (run_selftest) {
INSTR_TS_DECL(ts_self);
INSTR_TS_BEGIN(ts_self);
int result = utsm_selftest_run();
INSTR_TS_END(ts_self, "selftest");
if (result == 0) {
log_info("[UTSM] SELFTEST PASS");
} else {
log_warn("[UTSM] VMM unavailable (VMX not supported or disabled)");
}
if (dsk_load_and_jump() != 0) {
log_error("[UTSM] DSK jump failed");
log_error("[UTSM] SELFTEST FAIL");
arch_halt_forever();
}
} else {
log_error("[UTSM] SELFTEST FAIL");
log_info("[UTSM] selftest skipped by FUCK config");
}
/* === VMM — 可通过 FUCK [boot] vmm=0 跳过 === */
int run_vmm = ini_get_bool(cfg, "boot", "vmm", 1);
if (run_vmm && vmm_init() == 0) {
INSTR_TS_DECL(ts_vmm);
INSTR_TS_BEGIN(ts_vmm);
log_info("[UTSM] VMM init ok");
int vmm_st = vmm_self_test();
if (vmm_st == 0) {
INSTR_TS_END(ts_vmm, "vmm_init+selftest");
log_info("[UTSM] VMM self-test PASS");
/* === Linux guest — 可通过 FUCK [boot] linux_guest=0 跳过 === */
int run_linux = ini_get_bool(cfg, "boot", "linux_guest", 1);
if (run_linux && linux_loader_init() == 0) {
INSTR_TS_DECL(ts_linux);
INSTR_TS_BEGIN(ts_linux);
log_info("[UTSM] Linux loader init ok");
if (ipc_shm_init() == 0) {
log_info("[UTSM] IPC shm init ok");
} else {
log_error("[UTSM] IPC shm init failed (non-fatal)");
}
int lin_st = linux_launch();
INSTR_TS_END(ts_linux, "linux_launch");
if (lin_st == 0) {
log_info("[UTSM] Linux guest parked (daemon ready)");
linux_compat_init();
} else {
log_error("[UTSM] Linux launch failed");
log_hex64("[UTSM] Linux st=", (u64)(i64)lin_st);
}
} else {
log_warn("[UTSM] Linux loader unavailable (no bzImage or disabled)");
}
} else {
INSTR_TS_END(ts_vmm, "vmm_init+selftest");
log_error("[UTSM] VMM self-test FAIL");
log_hex64("[UTSM] VMM st=", (u64)(i64)vmm_st);
}
} else {
log_warn("[UTSM] VMM unavailable (VMX not supported or disabled by FUCK)");
}
/* ---- 插桩: DSK 加载跳转前记录 ---- */
INSTR_PROBE(DSK0, 0, 0, 0, 0);
if (dsk_load_and_jump() != 0) {
log_error("[UTSM] DSK jump failed");
}
/* ---- 插桩: 启动总耗时(仅在 DSK 跳转失败时可见) ---- */
INSTR_TS_END(boot_total, "boot_total");
arch_halt_forever();
}
+40
View File
@@ -0,0 +1,40 @@
kernel/main.o: kernel\main.c include\utsm\log.h include\utsm\types.h \
include\utsm\arena.h include\utsm\utsm.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\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\instr.h kernel\ini_parser.h \
kernel\..\arch\x86_64\limine.h
include\utsm\log.h:
include\utsm\types.h:
include\utsm\arena.h:
include\utsm\utsm.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\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\instr.h:
kernel\ini_parser.h:
kernel\..\arch\x86_64\limine.h:
Binary file not shown.
+16 -2
View File
@@ -52,7 +52,6 @@ static int net_tx_impl(u32 index, const void *packet, u32 length) {
if (index >= g_net_device_count) return -2;
const dkm_net_device_desc *dev = &g_net_devices[index];
if (!dev->tx) return -3;
log_hex64("[NET] tx dispatch fn=", (u64)dev->tx);
return dev->tx(dev->ctx, packet, length);
}
@@ -92,6 +91,20 @@ static int net_is_wireless_impl(u32 index) {
return (dev->flags & DKM_NET_F_WIRELESS) ? 1 : 0;
}
/* 统计查询:返回驱动层累计的收发统计。
* 当前实现为占位:返回全零统计。
* 后续由驱动在 tx/rx 回调内更新共享统计区,此处直接读取。
* 驱动层的本地统计(如 e1000 的 g_stat_tx_ok 等)与 netdev 层统计
* 通过 driver_ctx 统一后即可返回精确值。 */
static int net_device_stats_impl(u32 index, dkm_net_stats *out) {
if (!out) return -1;
if (index >= g_net_device_count) return -2;
/* 占位:全零。后续由驱动填充实际统计。 */
for (u32 i = 0; i < sizeof(dkm_net_stats); i++)
((u8 *)out)[i] = 0;
return 0;
}
static const dkm_net_api g_net_api = {
.register_device = net_register_device_impl,
.device_count = net_device_count_impl,
@@ -101,7 +114,8 @@ static const dkm_net_api g_net_api = {
.scan_start = net_scan_start_impl,
.scan_count = net_scan_count_impl,
.scan_result = net_scan_result_impl,
.is_wireless = net_is_wireless_impl
.is_wireless = net_is_wireless_impl,
.device_stats = net_device_stats_impl
};
const dkm_net_api *net_get_api(void) {
+5
View File
@@ -0,0 +1,5 @@
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
@@ -0,0 +1,3 @@
kernel/panic.o: kernel\panic.c include\utsm\log.h include\utsm\types.h
include\utsm\log.h:
include\utsm\types.h:
+111
View File
@@ -0,0 +1,111 @@
/* probe.c — Deshab 环形探测缓冲管理
*
* 结构化事件记录系统:写入环形缓冲,支持事后回溯分析。
* 用于记录关键事件(CPU异常、EPT violation、DMA完成等),
* 通过 shell $probe 命令读取。
*
* 设计要点:
* - 环形缓冲容量由 FUCK debug.probe_capacity 控制(默认 4096 条)
* - 每条记录 40 字节 (tag:4 + tick:4 + args:4*8)
* - 写入时无内存分配,仅 head 指针推进
* - 满时覆盖最旧记录(环形覆盖)
* - 禁用时 probe_write 为空操作
*/
#include <utsm/instr.h>
#include <utsm/log.h>
#include <utsm/types.h>
#include <utsm/arena.h>
#include "ini_parser.h"
/* ---- 探测缓冲状态 ---- */
static probe_entry *g_probe_buf = 0; /* 缓冲基地址(arena 分配) */
static u32 g_probe_cap = 0; /* 缓冲容量(条目数) */
static u32 g_probe_head = 0; /* 下一条写入位置(递增取模) */
static u32 g_probe_count = 0; /* 已写入总条目数 */
static u32 g_probe_dropped = 0; /* 因缓冲满而覆盖的条目数 */
void probe_init(const void *cfg_ptr) {
const ini_config *cfg = (const ini_config *)cfg_ptr;
u32 cap = (u32)ini_get_int(cfg, "debug", "probe_capacity", 4096);
if (cap == 0) {
g_instr_probe_enable = 0;
return;
}
/* 从 arena 分配探测缓冲(对齐到 8 字节) */
u64 size = (u64)cap * sizeof(probe_entry);
g_probe_buf = (probe_entry *)kmem_alloc_aligned(size, 8);
if (!g_probe_buf) {
g_instr_probe_enable = 0;
log_warn("[PROBE] arena alloc failed, probe disabled");
return;
}
g_probe_cap = cap;
g_probe_head = 0;
g_probe_count = 0;
g_probe_dropped = 0;
log_info("[PROBE] init ok, capacity=");
log_hex64("", g_probe_cap);
}
void probe_write(u32 tag, u64 a0, u64 a1, u64 a2, u64 a3) {
if (!g_probe_buf || !g_probe_cap) return;
u32 idx = g_probe_head % g_probe_cap;
/* 环形覆盖:如果 head >= cap,说明有旧记录被覆盖 */
if (g_probe_head >= g_probe_cap && g_probe_dropped == 0) {
/* 仅首次覆盖时计数,避免每条都做减法 */
}
if (g_probe_count >= g_probe_cap) {
g_probe_dropped++;
}
g_probe_buf[idx].tag = tag;
g_probe_buf[idx].tick = (u32)instr_rdtsc();
g_probe_buf[idx].args[0] = a0;
g_probe_buf[idx].args[1] = a1;
g_probe_buf[idx].args[2] = a2;
g_probe_buf[idx].args[3] = a3;
g_probe_head++;
g_probe_count++;
}
int probe_read(u32 n, probe_entry *out) {
if (!g_probe_buf || n == 0) return 0;
u32 avail = (g_probe_count < g_probe_cap) ? g_probe_count : g_probe_cap;
if (n > avail) n = avail;
for (u32 i = 0; i < n; i++) {
u32 src = (g_probe_head - n + i) % g_probe_cap;
out[i] = g_probe_buf[src];
}
return (int)n;
}
u32 probe_count(void) {
return g_probe_count;
}
u32 probe_capacity(void) {
return g_probe_cap;
}
/* ---- 供 dsk_loader 读取内部状态(填充 probe_info) ---- */
probe_entry *probe_buf_address(void) {
return g_probe_buf;
}
u32 probe_head_value(void) {
return g_probe_head;
}
u32 probe_dropped_count(void) {
return g_probe_dropped;
}
+7
View File
@@ -0,0 +1,7 @@
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: