From 174af71b39bf4679276114adb26d6daa4335ae01 Mon Sep 17 00:00:00 2001 From: Linehu Date: Sat, 3 Oct 2026 21:26:04 +0800 Subject: [PATCH] feat: exhaustive STUB instrumentation - 241 panic sites across VMM/kernel + whitelist alignment - VMM cluster: XJ3-E/LIN-E/VMM-E/VMX-E/EPT-E/IPC-E/VVB-E (124 sites) - kernel cluster: TST-E/MM-E/UTRW-E/LAPIC-E/IDT-E/SAS-E/PRB-E/NETST-E/DKM-E (117 sites) - whitelist fixes: vmm_init env probes E10-E14 fallback, disk_log read-only block path, DSL-E05 non-FAT32 device 0 probe - QEMU smoke: wizard -> USER.CONF -> login -> desktop ready, zero spurious panic --- CODE/UTSM/arch/x86_64/idt.c | 2 + CODE/UTSM/arch/x86_64/idt.o | Bin 25560 -> 25728 bytes CODE/UTSM/arch/x86_64/lapic_timer.c | 10 ++++ CODE/UTSM/arch/x86_64/lapic_timer.d | 16 +++++++ CODE/UTSM/dkm/boot_modules.c | 31 +++++++++++- CODE/UTSM/dkm/boot_modules.d | 3 +- CODE/UTSM/dkm/boot_modules.o | Bin 9224 -> 11544 bytes CODE/UTSM/dkm/dkm_core.c | 11 ++++- CODE/UTSM/dkm/dkm_core.d | 3 +- CODE/UTSM/dkm/dkm_core.o | Bin 2296 -> 3032 bytes CODE/UTSM/dkm/manifest.c | 35 +++++++++++++- CODE/UTSM/dkm/manifest.o | Bin 19520 -> 20976 bytes CODE/UTSM/kernel/dsk_loader.c | 35 +++++++++++++- CODE/UTSM/kernel/dsk_loader.d | 21 ++++++++ CODE/UTSM/kernel/dsk_loader.o | Bin 26488 -> 25104 bytes CODE/UTSM/kernel/main.c | 15 +++++- CODE/UTSM/kernel/main.o | Bin 23064 -> 23784 bytes CODE/UTSM/kernel/probe.c | 3 ++ CODE/UTSM/kernel/probe.d | 9 ++++ CODE/UTSM/mm/dma.c | 7 +++ CODE/UTSM/mm/dma.d | 7 +++ CODE/UTSM/mm/dma.o | Bin 3952 -> 4512 bytes CODE/UTSM/mm/mmio.c | 19 ++++++++ CODE/UTSM/mm/mmio.d | 9 ++++ CODE/UTSM/mm/paging.c | 22 +++++++-- CODE/UTSM/mm/paging.d | 9 ++++ CODE/UTSM/pe/pe_dll_manager.c | 13 +++++ CODE/UTSM/pe/pe_dll_manager.d | 3 +- CODE/UTSM/pe/pe_service.c | 13 +++++ CODE/UTSM/pe/pe_service.d | 15 ++++++ CODE/UTSM/sched/sched.c | 4 ++ CODE/UTSM/test/utsm_selftest.c | 71 +++++++++++++++++++++++++++- CODE/UTSM/test/utsm_selftest.d | 4 +- CODE/UTSM/test/utsm_selftest.o | Bin 10320 -> 15784 bytes CODE/UTSM/utrw/debug.c | 3 ++ CODE/UTSM/utrw/debug.d | 4 +- CODE/UTSM/utrw/slow_path.c | 3 ++ CODE/UTSM/utrw/slow_path.d | 3 +- CODE/UTSM/utrw/slow_path.o | Bin 3072 -> 3328 bytes CODE/UTSM/vmm/ept.c | 5 ++ CODE/UTSM/vmm/ept.d | 10 ++++ CODE/UTSM/vmm/ipc_shm.c | 5 ++ CODE/UTSM/vmm/ipc_shm.d | 14 ++++++ CODE/UTSM/vmm/linux_boot.c | 8 ++++ CODE/UTSM/vmm/linux_boot.d | 17 +++++++ CODE/UTSM/vmm/linux_compat.c | 11 +++++ CODE/UTSM/vmm/linux_compat.d | 20 ++++++++ CODE/UTSM/vmm/linux_loader.c | 25 ++++++++++ CODE/UTSM/vmm/linux_loader.d | 12 +++++ CODE/UTSM/vmm/virtio_blk.c | 3 ++ CODE/UTSM/vmm/virtio_blk.d | 5 +- CODE/UTSM/vmm/virtio_net.c | 1 + CODE/UTSM/vmm/virtio_net.d | 9 ++++ CODE/UTSM/vmm/vmexit.c | 9 ++++ CODE/UTSM/vmm/vmexit.d | 22 +++++++++ CODE/UTSM/vmm/vmm.c | 28 +++++++++-- CODE/UTSM/vmm/vmm.d | 11 +++++ CODE/UTSM/vmm/vmx.c | 8 ++++ CODE/UTSM/vmm/vmx.d | 10 ++++ CODE/UTSM/vmm/xj380_loader.c | 55 ++++++++++++++++----- CODE/UTSM/vmm/xj380_loader.d | 12 +++++ SYSTEM/boot/utsm.elf | Bin 980264 -> 996600 bytes 62 files changed, 667 insertions(+), 36 deletions(-) create mode 100644 CODE/UTSM/arch/x86_64/lapic_timer.d create mode 100644 CODE/UTSM/kernel/dsk_loader.d create mode 100644 CODE/UTSM/kernel/probe.d create mode 100644 CODE/UTSM/mm/dma.d create mode 100644 CODE/UTSM/mm/mmio.d create mode 100644 CODE/UTSM/mm/paging.d create mode 100644 CODE/UTSM/pe/pe_service.d create mode 100644 CODE/UTSM/vmm/ept.d create mode 100644 CODE/UTSM/vmm/ipc_shm.d create mode 100644 CODE/UTSM/vmm/linux_boot.d create mode 100644 CODE/UTSM/vmm/linux_compat.d create mode 100644 CODE/UTSM/vmm/linux_loader.d create mode 100644 CODE/UTSM/vmm/virtio_net.d create mode 100644 CODE/UTSM/vmm/vmexit.d create mode 100644 CODE/UTSM/vmm/vmm.d create mode 100644 CODE/UTSM/vmm/vmx.d create mode 100644 CODE/UTSM/vmm/xj380_loader.d diff --git a/CODE/UTSM/arch/x86_64/idt.c b/CODE/UTSM/arch/x86_64/idt.c index b5c2448..8b0afc7 100644 --- a/CODE/UTSM/arch/x86_64/idt.c +++ b/CODE/UTSM/arch/x86_64/idt.c @@ -560,6 +560,8 @@ int irq_vector_alloc(void) { return vec; } log_warn("[IDT] vector alloc failed: pool exhausted"); + panic_full("IDT-E01 VECTOR POOL EXHAUSTED", + "irq_vector_alloc: dynamic vector pool exhausted", 0); return -1; } diff --git a/CODE/UTSM/arch/x86_64/idt.o b/CODE/UTSM/arch/x86_64/idt.o index fac639f64fd5414661a760d9e73ff94127807fca..d7d62d1f403efb6af553c8272dce9063506a0b2e 100644 GIT binary patch delta 952 zcmZ`$&1(};5Pxsk)>f_Nlh>%RYdsi?N^;01_K*@xG?n5uZCX4CWwR=j#@0lw#Dm8E z1u1j!AgK5kggxmc6|5mgdyt5D@RnnHQL%!~>%N6YAOrJe=Qkg}nb}T@*4nflQEFym z;)WWIO=k)hv(cEgn7vXk=CoPEn9;H~bLoZo zLN-H|E9Is2JJ!Rs%92?styz=W?dqy|Z`slu)P6Mla>zdJD=V}K&jVwy6&!`v0gcw- zLx9m;_!@XjYmg7J6T1VPoRAU6kSbaqQ3x4?jbO^|1hp}mgL0gO4An_Fg61fyNgaO? z(imOsiT-qg95k;4gWt|-KG7K)3!-l;QS>Wp58O`VzZA_wnAPND9L z&2C9}Si(zX48!l6UY4!V4IxTTl`OJWnQGhaU+RdMdT!<3`0VegWPj z3pM-Hwjqtt&wXmUb~)LM&@T`(uTdXV&BSo>681*<4e!jv;khBl^DFSj)aiYQ6{nQw cWvCQW=roE``0nA09V`swp<< delta 853 zcmZoT$#~;9;{*++8wne={8%`IJ&qq|0D{R=S*+O7_~l&~7&c#EIm)v6F=r3Q=0c%- zCdO5hABxCNmJn5tY+wN?Wnc(|Pz*UhT8M#(;lboU(Q?TGR)}yaRQ4QP_Mxaa(+Aec zzeMdOiArp?5L1w6jGVmCRGcwxvZ0wcW9sCKrs9&hP{To#I1vB&4*{ztGn$D@Zh^{j z17&!C*qISX0KrbM35P%?7@oyp0t3`xFukEry{wZbnu$-YFcT2%g^GwmRf63xd9Ims zASYBt6 #include #include +#include extern void outb(u16 port, u8 value); extern u8 inb(u16 port); @@ -63,6 +64,7 @@ int lapic_timer_init(u32 freq_hz) { base = rdmsr_(MSR_IA32_APIC_BASE); } if (base & APIC_BASE_X2APIC) { + /* 【插桩白名单】设计内降级:x2APIC 不支持 MMIO timer,降级协作模式 */ log_warn("[LAPIC] x2APIC mode, MMIO timer unsupported"); return -1; } @@ -73,6 +75,8 @@ int lapic_timer_init(u32 freq_hz) { if (!mm || !mm->map_mmio) return -2; if (mm->map_mmio(phys, 0x1000) != 0) { log_warn("[LAPIC] map_mmio failed"); + panic_full("LAPIC-E01 MAP_MMIO FAILED", + "lapic_timer_init: LAPIC MMIO mapping failed", 0); return -3; } u64 hhdm = 0; @@ -82,6 +86,8 @@ int lapic_timer_init(u32 freq_hz) { if (mm->is_mapped && !mm->is_mapped((u64)g_lapic)) { g_lapic = 0; log_warn("[LAPIC] mapped page not reachable"); + panic_full("LAPIC-E02 MAPPED PAGE NOT REACHABLE", + "lapic_timer_init: mapped LAPIC page not reachable", 0); return -4; } @@ -121,6 +127,8 @@ int lapic_timer_init(u32 freq_hz) { u64 delta = (u64)ccr0 - (u64)ccr1; /* 16 分频时钟 10ms tick 数 */ if (delta < 1000) { log_warn("[LAPIC] timer calibration implausible"); + panic_full("LAPIC-E03 CALIBRATION IMPLAUSIBLE", + "lapic_timer_init: PIT-vs-LAPIC calibration implausible", 0); lapic_timer_stop(); return -5; } @@ -134,6 +142,8 @@ int lapic_timer_init(u32 freq_hz) { int vec = irq_vector_alloc(); if (vec < 0) { log_warn("[LAPIC] irq_vector_alloc failed"); + panic_full("LAPIC-E04 IRQ VECTOR ALLOC FAILED", + "lapic_timer_init: dynamic vector allocation failed", 0); return -6; } g_timer_vector = vec; diff --git a/CODE/UTSM/arch/x86_64/lapic_timer.d b/CODE/UTSM/arch/x86_64/lapic_timer.d new file mode 100644 index 0000000..534c800 --- /dev/null +++ b/CODE/UTSM/arch/x86_64/lapic_timer.d @@ -0,0 +1,16 @@ +arch/x86_64/lapic_timer.o: arch\x86_64\lapic_timer.c \ + include\utsm\lapic_timer.h include\utsm\types.h include\utsm\pit.h \ + include\utsm\paging.h include\utsm\idt.h include\utsm\dkm.h \ + include\utsm\dma.h include\utsm\block.h include\utsm\net.h \ + include\utsm\log.h include\utsm\panic.h +include\utsm\lapic_timer.h: +include\utsm\types.h: +include\utsm\pit.h: +include\utsm\paging.h: +include\utsm\idt.h: +include\utsm\dkm.h: +include\utsm\dma.h: +include\utsm\block.h: +include\utsm\net.h: +include\utsm\log.h: +include\utsm\panic.h: diff --git a/CODE/UTSM/dkm/boot_modules.c b/CODE/UTSM/dkm/boot_modules.c index 79e3737..ada86ab 100644 --- a/CODE/UTSM/dkm/boot_modules.c +++ b/CODE/UTSM/dkm/boot_modules.c @@ -1,7 +1,8 @@ -#include +#include #include #include #include +#include #include "../arch/x86_64/limine.h" #define ELF_MAGIC0 0x7f @@ -178,10 +179,14 @@ int dkm_scan_symbols(const void *address, u64 size, struct dkm_symbol_scan *out) if (ehdr->shoff == 0 || ehdr->shnum == 0 || ehdr->shentsize < sizeof(elf64_shdr)) { log_error("[DKM] ELF has no section table"); + panic_full("DKM-E30 ELF NO SECTION TABLE", + "dkm_scan_symbols: driver ELF has no section table", 0); return -1; } if (!range_ok(ehdr->shoff, (u64)ehdr->shnum * ehdr->shentsize, size)) { log_error("[DKM] ELF section table out of range"); + panic_full("DKM-E31 ELF SECTION TABLE OUT OF RANGE", + "dkm_scan_symbols: section table out of file range", 0); return -1; } @@ -202,10 +207,14 @@ int dkm_scan_symbols(const void *address, u64 size, struct dkm_symbol_scan *out) if (!symtab || !strtab || strtab->type != SHT_STRTAB) { log_error("[DKM] missing symtab/strtab"); + panic_full("DKM-E32 ELF MISSING SYMTAB", + "dkm_scan_symbols: symtab/strtab missing or invalid", 0); return -1; } if (symtab->entsize < sizeof(elf64_sym) || !range_ok(symtab->offset, symtab->size, size) || !range_ok(strtab->offset, strtab->size, size)) { log_error("[DKM] invalid symtab/strtab range"); + panic_full("DKM-E33 ELF SYMTAB RANGE INVALID", + "dkm_scan_symbols: symtab/strtab out of file range", 0); return -1; } @@ -241,6 +250,8 @@ int dkm_scan_symbols(const void *address, u64 size, struct dkm_symbol_scan *out) return 0; } log_error("[DKM] required driver symbols missing"); + panic_full("DKM-E34 REQUIRED DRIVER SYMBOLS MISSING", + "dkm_scan_symbols: driver_desc/init/exit symbol missing", 0); return -1; } @@ -271,12 +282,16 @@ int dkm_load_elf_rel(const void *address, u64 size, const struct dkm_symbol_scan if (total_size == 0) { log_error("[DKM] no allocatable sections"); + panic_full("DKM-E35 ELF NO ALLOC SECTIONS", + "dkm_load_elf_rel: no allocatable sections", 0); return -1; } u8 *image = (u8 *)kmem_alloc_aligned(total_size, max_align); if (!image) { log_error("[DKM] failed to allocate module memory"); + panic_full("DKM-E36 MODULE MEM ALLOC FAILED", + "dkm_load_elf_rel: module memory allocation failed", 0); return -1; } memset(image, 0, total_size); @@ -353,6 +368,8 @@ int dkm_load_elf_rel(const void *address, u64 size, const struct dkm_symbol_scan } else { log_error("[DKM] unsupported relocation type"); log_hex64("[DKM] reloc type=", (u64)reloc_type); + panic_full("DKM-E37 UNSUPPORTED RELOCATION", + "dkm_load_elf_rel: unsupported relocation type", 0); return -1; } @@ -373,6 +390,8 @@ int dkm_load_elf_rel(const void *address, u64 size, const struct dkm_symbol_scan const dkm_driver_desc *desc = (const dkm_driver_desc *)(image + image_offset[desc_sym->shndx] + desc_sym->value); if (desc->magic != DKM_DRIVER_MAGIC) { log_error("[DKM] external driver_desc magic mismatch"); + panic_full("DKM-E38 DRIVER DESC MAGIC MISMATCH", + "dkm_load_elf_rel: external driver_desc magic mismatch", 0); return -1; } @@ -397,6 +416,8 @@ int dkm_load_elf_rel(const void *address, u64 size, const struct dkm_symbol_scan if (result != 0) { handle.state = DKM_STATE_FAILED; log_error("[DKM] external driver init failed"); + panic_full("DKM-E39 EXTERNAL DRIVER INIT FAILED", + "dkm_load_elf_rel: external driver_init returned non-zero", 0); return result; } handle.state = DKM_STATE_ACTIVE; @@ -408,6 +429,8 @@ void dkm_scan_boot_modules(void) { struct limine_module_response *response = g_module_request.response; if (!response) { log_warn("[DKM] no Limine module response"); + panic_full("DKM-E40 NO LIMINE MODULE RESPONSE", + "dkm_scan_boot_modules: no Limine module response", 0); return; } @@ -418,6 +441,8 @@ void dkm_scan_boot_modules(void) { struct limine_file *file = response->modules[i]; if (!file) { log_warn("[DKM] null module entry"); + panic_full("DKM-E41 NULL MODULE ENTRY", + "dkm_scan_boot_modules: null boot module entry", 0); continue; } @@ -439,11 +464,15 @@ void dkm_scan_boot_modules(void) { int load_result = dkm_load_elf_rel(file->address, file->size, &symbols); if (load_result != 0) { log_error("[DKM] external driver load failed"); + panic_full("DKM-E42 EXTERNAL DRIVER LOAD FAILED", + "dkm_scan_boot_modules: external driver load failed", 0); } } } else { log_error("[DKM] module ELF64 rejected"); log_hex64("[DKM] elf status=", (u64)(i64)status); + panic_full("DKM-E43 MODULE ELF64 REJECTED", + "dkm_scan_boot_modules: boot module ELF64 check rejected", 0); } } diff --git a/CODE/UTSM/dkm/boot_modules.d b/CODE/UTSM/dkm/boot_modules.d index aff84b6..3572e84 100644 --- a/CODE/UTSM/dkm/boot_modules.d +++ b/CODE/UTSM/dkm/boot_modules.d @@ -1,7 +1,7 @@ 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\arena.h include\utsm\panic.h dkm\..\arch\x86_64\limine.h include\utsm\dkm.h: include\utsm\types.h: include\utsm\dma.h: @@ -10,4 +10,5 @@ include\utsm\net.h: include\utsm\paging.h: include\utsm\log.h: include\utsm\arena.h: +include\utsm\panic.h: dkm\..\arch\x86_64\limine.h: diff --git a/CODE/UTSM/dkm/boot_modules.o b/CODE/UTSM/dkm/boot_modules.o index 9ddf1be1c6e831fd2929886d4660e068b65ff7e5..aa6971b3c31312d49dfd9cc46ae0c9f4feb6e129 100644 GIT binary patch literal 11544 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 +#include #include +#include static int dkm_validate_desc(const dkm_driver_desc *desc) { if (!desc) { @@ -27,18 +28,24 @@ void dkm_init(void) { log_info("[DKM] init ok"); } else { log_error("[DKM] init failed"); + panic_full("DKM-E50 BUILTIN INIT FAILED", + "dkm_init: builtin console_early load failed", 0); } } int dkm_load_builtin(const dkm_builtin_driver *driver) { if (!driver || !driver->desc || !driver->init) { log_error("[DKM] invalid builtin driver"); + panic_full("DKM-E51 INVALID BUILTIN DRIVER", + "dkm_load_builtin: builtin driver descriptor invalid", 0); return -1; } int status = dkm_validate_desc(driver->desc); if (status != 0) { log_error("[DKM] driver_desc rejected"); + panic_full("DKM-E52 DRIVER DESC REJECTED", + "dkm_load_builtin: builtin driver_desc validation failed", 0); return status; } @@ -60,6 +67,8 @@ int dkm_load_builtin(const dkm_builtin_driver *driver) { if (status != 0) { handle.state = DKM_STATE_FAILED; log_error("[DKM] builtin driver init failed"); + panic_full("DKM-E53 BUILTIN DRIVER INIT FAILED", + "dkm_load_builtin: builtin driver_init returned non-zero", 0); return status; } diff --git a/CODE/UTSM/dkm/dkm_core.d b/CODE/UTSM/dkm/dkm_core.d index d076779..1403200 100644 --- a/CODE/UTSM/dkm/dkm_core.d +++ b/CODE/UTSM/dkm/dkm_core.d @@ -1,6 +1,6 @@ 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\paging.h include\utsm\log.h include\utsm\panic.h include\utsm\dkm.h: include\utsm\types.h: include\utsm\dma.h: @@ -8,3 +8,4 @@ include\utsm\block.h: include\utsm\net.h: include\utsm\paging.h: include\utsm\log.h: +include\utsm\panic.h: diff --git a/CODE/UTSM/dkm/dkm_core.o b/CODE/UTSM/dkm/dkm_core.o index 5baca00f7076dece25790767c24542fb9f36a6bf..58dd3a7ae101c8ce0c47b3deabf9a4c385cff26f 100644 GIT binary patch literal 3032 zcmbVOPiP!v6#vqsZR#Jk(TgDHXjS4NlWfv#k{)W(?$lZHM@f@_gmjsmnca?=%q+9B zAt_3$$%4~Gs23@Mc=O^}u?IEM;vR|@MFY=Bo>w7crn|zsMEBIjMz4!Zm z-+SMClYL(Wq>e>nhxD7s-$HCk{Gf*}g3Pxph z^|@g3Zhf>nQ0}S0&YlA5?P`6cGb&WD8_F+-Fi3r#*50dbszIaqLvS!aU z?M`a_3J`(cf&Be_i+dC9+P40a@&%OC+7N}}~Vu1lWzhN=5;N&Qk3UCJuw&q~wE zE6Uj!s_8+wqF7-L&9_`F-!G@-jMRP6_sf-2y}c#NzgR8Ey1UeC+so0br|h}d zN~x%y)HGwLFlZD8ipAo|{#=!|4~{FR`_J3QHaA&*njl zc34SDF944*{53}MD(P9!$H^8I&bou}3xH#s*NFTU4aMOWe76ODrUibr1%4E8l!xKj zt%9*fLKJ%uJviD>9w!|6hsj3u1lh zk^d6m{QRrrX9d34xA6r3L-MB+_?P7K`tUqr-wFx-Dy*ZF2uHq{*Gcd{2-%EP6ZmI@ zzbV8K^IlExdEeg`_+sAc34RCpA1Cl<$p3_Nvfi%~{QKnJ68N}>f5*e&{HN)a-*dw- z*)wfT_RSTa;fz``9Y4O6nC+JGrsugHT_B}=#q{%Z<=~>_6y1H73oC1mrRR%P+h(%k z`lkHy)ND`1*Yw4ZTY?yiCJb0Ruazw(<5Z8Nqad6JjvEsRf{~}_Fet1NAl!juLI2?h%kHhr~g!PG=!F~!41yYPu{O0?( zz62}Wj!9sw(|!>{JIVbBu=a^2UJF;?iDiQd<$PW@_c`$^FcKw(OYc(tPTGJ9Tgl__ Gx&JSRVsW$p delta 752 zcmca1{zGtr2Gb6C%ynO8D85X^L7BW z|9>q273w@a`6*-M%lH&bew-Z0CO-KAn*^iqWJV5g zNo}YrU?z4#^%zWcWEYpTM3Xgy%G!Zteb8k6pt8YW*&H<4RZ!W&$tyY9CtGvQojjL? zosoI+LQY}Mm#h%UQ5MFihUXEe8P6daD)y diff --git a/CODE/UTSM/dkm/manifest.c b/CODE/UTSM/dkm/manifest.c index 94b9da2..f6e2b44 100644 --- a/CODE/UTSM/dkm/manifest.c +++ b/CODE/UTSM/dkm/manifest.c @@ -267,7 +267,12 @@ static int dsm_parse_manifest(const char *text, u64 size) { dsm_expect(&p, ':'); if (streq_static(key, "stages")) { - if (dsm_expect(&p, '[') != 0) return -1; + if (dsm_expect(&p, '[') != 0) { + /* 严格错误策略插桩:stage 解析失败零降级(DKM-E08) */ + panic_full("DKM-E08 MANIFEST STAGES PARSE FAILED", + "dsm_parse_manifest: stages array malformed", 0); + return -1; + } while (p < end && *p) { dsm_skip_ws(&p); if (*p == ']') { p++; break; } @@ -300,6 +305,9 @@ static int dsm_ensure_manifest(void) { rsp = g_module_request.response; if (!rsp) { log_warn("[DSM] no Limine module response"); + /* 严格错误策略插桩:manifest 缺失零降级(DKM-E09) */ + panic_full("DKM-E09 NO LIMINE MODULE RESPONSE", + "dsm_ensure_manifest: no Limine module response", 0); return -1; } @@ -314,6 +322,9 @@ static int dsm_ensure_manifest(void) { if (!manifest_file) { log_warn("[DSM] manifest not found in boot modules"); + /* 严格错误策略插桩:manifest 缺失零降级(DKM-E10) */ + panic_full("DKM-E10 MANIFEST NOT FOUND", + "dsm_ensure_manifest: dkm:manifest boot module missing", 0); return -1; } @@ -409,7 +420,12 @@ void dsm_load_by_manifest_upto(const ini_config *cfg, u32 max_stage_id) { } void dsm_load_named(const ini_config *cfg, const char *name) { - if (!name || dsm_ensure_manifest() != 0) return; + if (!name || dsm_ensure_manifest() != 0) { + /* 严格错误策略插桩:按名加载 manifest 缺失零降级(DKM-E11) */ + panic_full("DKM-E11 NAMED LOAD MANIFEST MISSING", + "dsm_load_named: null name or manifest unavailable", 0); + return; + } for (u32 si = 0; si < g_stage_count; si++) { dsm_stage_entry *stage = &g_stages[si]; @@ -430,6 +446,9 @@ void dsm_load_named(const ini_config *cfg, const char *name) { if (!drv->boot_module) { log_warn("[DSM] named module not found"); log_info(name); + /* 严格错误策略插桩:named 驱动缺模块零降级(DKM-E12) */ + panic_full("DKM-E12 NAMED DRIVER MODULE MISSING", + "dsm_load_named: named driver boot module not found", 0); return; } f = drv->boot_module; @@ -437,15 +456,24 @@ void dsm_load_named(const ini_config *cfg, const char *name) { log_info(drv->name); if (dkm_check_elf64(f->address, f->size) != 0) { log_error("[DSM] ELF check failed"); + /* 严格错误策略插桩:named 驱动 ELF 校验失败零降级(DKM-E13) */ + panic_full("DKM-E13 NAMED DRIVER ELF INVALID", + "dsm_load_named: named driver failed ELF64 check", 0); return; } if (dkm_scan_symbols(f->address, f->size, &symbols) != 0) { log_error("[DSM] symbol scan failed"); + /* 严格错误策略插桩:named 驱动符号扫描失败零降级(DKM-E14) */ + panic_full("DKM-E14 NAMED DRIVER SYMBOL SCAN FAILED", + "dsm_load_named: named driver symbol scan failed", 0); return; } result = dkm_load_elf_rel(f->address, f->size, &symbols); if (result != 0) { log_error("[DSM] load failed"); + /* 严格错误策略插桩:named 驱动加载失败零降级(DKM-E15) */ + panic_full("DKM-E15 NAMED DRIVER LOAD FAILED", + "dsm_load_named: named driver relocation/load failed", 0); return; } drv->loaded = 1; @@ -454,6 +482,9 @@ void dsm_load_named(const ini_config *cfg, const char *name) { } log_warn("[DSM] named driver not in manifest"); log_info(name); + /* 严格错误策略插桩:named 驱动不在 manifest 零降级(DKM-E16) */ + panic_full("DKM-E16 NAMED DRIVER NOT IN MANIFEST", + "dsm_load_named: named driver not found in manifest", 0); } void dsm_load_by_manifest_ex(const ini_config *cfg) { diff --git a/CODE/UTSM/dkm/manifest.o b/CODE/UTSM/dkm/manifest.o index b584dcf98d595975bda46b5872fa0bcdb818425a..a351f224feeede8efe8d32be51dbd7b8f14b0c21 100644 GIT binary patch delta 5449 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 S@+e2vz=ur9UJ9d4dH(@vkvo+D diff --git a/CODE/UTSM/kernel/dsk_loader.c b/CODE/UTSM/kernel/dsk_loader.c index 3a5577a..38a41a2 100644 --- a/CODE/UTSM/kernel/dsk_loader.c +++ b/CODE/UTSM/kernel/dsk_loader.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "../arch/x86_64/limine.h" #include "../../tools/fat32_lfn.h" @@ -215,6 +216,8 @@ static u32 fat32_get_next_cluster(u32 fat_start_byte, u32 clus, 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); + panic_full("DSL-E01 FAT SECTOR READ FAILED", + "fat32_get_next_cluster: on-demand FAT sector read failed", 0); return 0x0FFFFFFF; } return fat32_read_u32(g_dsk_fat32_fat_sec + ent_off_in_sec) & 0x0FFFFFFF; @@ -223,11 +226,14 @@ static u32 fat32_get_next_cluster(u32 fat_start_byte, u32 clus, 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) { + /* 【插桩白名单】设计内双路径回退:无块设备时由调用方回退 + * Limine boot module(CLAUDE.md 两阶段 DSK 加载设计)。 */ 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) { + /* 【插桩白名单】同上:无块设备属设计内回退路径。 */ log_error("[UTSM] FAT32: no block device or wrong sector size"); log_hex64("[UTSM] FAT32: device_count=", count); return -1; @@ -239,12 +245,17 @@ static int dsk_load_from_block_fat32(const void **out_addr, u64 *out_size) { if (st != 0) { log_error("[UTSM] FAT32: BPB read failed"); log_hex64("[UTSM] FAT32: read status=", (u64)(i64)st); + panic_full("DSL-E04 BPB READ FAILED", + "dsk_load_from_block_fat32: BPB 256-sector read failed", 0); return -1; } const fat32_bpb *bpb = (const fat32_bpb *)disk; if (bpb->boot_sig != 0xAA55 || bpb->bytes_per_sector != 512) { - log_error("[UTSM] FAT32: invalid BPB signature or sector size"); + /* 【插桩白名单】设计内设备探测:device 0 可能是 GPT 主盘(LBA0 为 + * 保护性 MBR,带 0x55AA 签名但非 FAT32 VBR)。非 FAT32 卷时由调用 + * 方回退 Limine boot module(CLAUDE.md 两阶段 DSK 加载设计)。 */ + log_error("[UTSM] FAT32: not a FAT32 volume on device 0 (fallback to boot module)"); log_hex64("[UTSM] FAT32: boot_sig=", bpb->boot_sig); log_hex64("[UTSM] FAT32: bps=", bpb->bytes_per_sector); return -1; @@ -271,6 +282,8 @@ static int dsk_load_from_block_fat32(const void **out_addr, u64 *out_size) { log_error("[UTSM] FAT32: dir cluster read failed"); log_hex64("[UTSM] FAT32: clus=", clus); log_hex64("[UTSM] FAT32: lba=", clus_lba); + panic_full("DSL-E06 DIR CLUSTER READ FAILED", + "dsk_load_from_block_fat32: root dir cluster read failed", 0); return -1; } @@ -294,6 +307,8 @@ static int dsk_load_from_block_fat32(const void **out_addr, u64 *out_size) { if (!found_clus || found_size == 0) { log_error("[UTSM] FAT32: DESHAB.ELF not found in root dir"); + panic_full("DSL-E07 DESHAB ELF NOT FOUND", + "dsk_load_from_block_fat32: DESHAB.ELF not found in root dir", 0); return -1; } log_hex64("[UTSM] FAT32: found_clus=", found_clus); @@ -301,6 +316,8 @@ static int dsk_load_from_block_fat32(const void **out_addr, u64 *out_size) { if (found_size > sizeof(g_dsk_fat32_filedata)) { log_error("[UTSM] FAT32: file exceeds 2MB buffer"); + panic_full("DSL-E08 DSK FILE EXCEEDS BUFFER", + "dsk_load_from_block_fat32: deshab.elf exceeds file buffer", 0); return -1; } u8 *dst = g_dsk_fat32_filedata; @@ -319,6 +336,8 @@ static int dsk_load_from_block_fat32(const void **out_addr, u64 *out_size) { log_error("[UTSM] FAT32: data cluster read failed"); log_hex64("[UTSM] FAT32: fc=", fc); log_hex64("[UTSM] FAT32: lba=", fc_lba); + panic_full("DSL-E09 DATA CLUSTER READ FAILED", + "dsk_load_from_block_fat32: file data cluster read failed", 0); return -1; } for (u32 b = 0; b < fc_bytes; b++) dst[b] = chunk[b]; @@ -334,6 +353,8 @@ static int dsk_load_from_block_fat32(const void **out_addr, u64 *out_size) { if (!file_buf) { log_error("[UTSM] FAT32: arena alloc failed"); log_hex64("[UTSM] FAT32: size=", found_size); + panic_full("DSL-E10 ARENA ALLOC FAILED", + "dsk_load_from_block_fat32: arena alloc for DSK image failed", 0); return -1; } for (u32 i = 0; i < found_size; i++) file_buf[i] = g_dsk_fat32_filedata[i]; @@ -1070,7 +1091,9 @@ int dsk_load_and_jump(void) { if (fat32_ok == 0) { log_info("[UTSM] DSK loaded from FAT32 block provider"); } else { - /* 2) fallback: Limine boot module */ + /* 2) fallback: Limine boot module + * 【插桩白名单】设计内双路径回退:块设备读 deshab.elf 失败时 + * 回退 Limine boot module 预加载,按任务要求保持原样不插桩。 */ log_info("[UTSM] FAT32 block path unavailable; trying Limine module"); struct limine_file *file = dsk_find_module(); if (!file) { @@ -1086,6 +1109,8 @@ int dsk_load_and_jump(void) { if (status != 0) { log_error("[UTSM] DSK ELF rejected"); log_hex64("[UTSM] DSK ELF status=", (u64)(i64)status); + panic_full("DSL-E11 DSK ELF REJECTED", + "dsk_load_and_jump: deshab.elf ELF check rejected", 0); return status; } @@ -1094,12 +1119,16 @@ int dsk_load_and_jump(void) { if (status != 0) { log_error("[UTSM] DSK load failed"); log_hex64("[UTSM] DSK load status=", (u64)(i64)status); + panic_full("DSL-E12 DSK LOAD FAILED", + "dsk_load_and_jump: DSK ELF image load failed", 0); return status; } dsk_boot_context *ctx = (dsk_boot_context *)kmem_alloc_aligned(sizeof(dsk_boot_context), 16); if (!ctx) { log_error("[UTSM] DSK context allocation failed"); + panic_full("DSL-E13 DSK CONTEXT ALLOC FAILED", + "dsk_load_and_jump: boot context allocation failed", 0); return -1; } dsk_fill_boot_context(ctx); @@ -1169,5 +1198,7 @@ int dsk_load_and_jump(void) { entry(ctx); log_error("[UTSM] DSK returned unexpectedly"); + panic_full("DSL-E14 DSK RETURNED UNEXPECTEDLY", + "dsk entry point returned to UTSM", 0); return -1; } diff --git a/CODE/UTSM/kernel/dsk_loader.d b/CODE/UTSM/kernel/dsk_loader.d new file mode 100644 index 0000000..40b8164 --- /dev/null +++ b/CODE/UTSM/kernel/dsk_loader.d @@ -0,0 +1,21 @@ +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 include\utsm\panic.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: +include\utsm\panic.h: +kernel\..\arch\x86_64\limine.h: +kernel\..\..\tools\fat32_lfn.h: diff --git a/CODE/UTSM/kernel/dsk_loader.o b/CODE/UTSM/kernel/dsk_loader.o index 9c6855f8116311630b1e5db6465d0b27d0a0bb9d..b7fcd34d9bb6ca0e44068af934f1d076a51dbfbb 100644 GIT binary patch literal 25104 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 AJ^%m! literal 26488 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 diff --git a/CODE/UTSM/kernel/main.c b/CODE/UTSM/kernel/main.c index ce03136..4c54518 100644 --- a/CODE/UTSM/kernel/main.c +++ b/CODE/UTSM/kernel/main.c @@ -190,7 +190,10 @@ static void disk_log_flush(void) { log_info("[UTSM] disk_log: BOOTLOG.TXT written"); log_hex64("[UTSM] disk_log: bytes=", len); } else { - log_error("[UTSM] disk_log: FAT32 write failed"); + /* 【插桩白名单】设计内只读块路径:AHCI provider 当前仅注册最小 + * read(CLAUDE.md ahci 驱动说明),write 恒为空,bootlog 落盘 + * 失败属环境能力缺失而非数据读写错误。诊断日志不得阻断启动。 */ + log_error("[UTSM] disk_log: FAT32 write failed (read-only block path, skip)"); log_hex64("[UTSM] disk_log: rc=", (u64)(i64)rc); } } @@ -258,6 +261,8 @@ void kernel_main(void) { 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."); + panic_full("VMM-E11 LA57 ACTIVE REFUSE BOOT", + "5-level paging active; kernel requires 4-level paging", 0); arch_halt_forever(); } } @@ -404,6 +409,8 @@ void kernel_main(void) { * (configured separately) may still work. Force-continue regardless. */ if (vmm_st != 0) { log_warn("[UTSM] VMM self-test FAIL, but continuing to Linux guest"); + panic_full("VMM-E12 VMM SELFTEST FAIL", + "VMM self-test failed; force-continue removed by instrumentation", 0); vmm_st = 0; /* force pass to continue to Linux guest */ } if (vmm_st == 0) { @@ -476,6 +483,8 @@ void kernel_main(void) { INSTR_TS_END(ts_vmm, "vmm_init+selftest"); log_error("[UTSM] VMM self-test FAIL"); log_hex64("[UTSM] VMM st=", (u64)(i64)vmm_st); + panic_full("VMM-E13 VMM SELFTEST FAIL", + "VMM self-test failed (non-zero status)", 0); } /* === OpenXJ380 guest — 可通过 FUCK [boot] xj380_guest=0 跳过 === @@ -532,6 +541,8 @@ void kernel_main(void) { log_info("[UTSM] SELFTEST PASS"); } else { log_error("[UTSM] SELFTEST FAIL"); + panic_full("VMM-E14 SELFTEST FAIL", + "utsm_selftest_run returned non-zero", 0); arch_halt_forever(); } } @@ -570,6 +581,8 @@ void kernel_main(void) { if (dsk_load_and_jump() != 0) { log_error("[UTSM] DSK jump failed"); + panic_full("VMM-E15 DSK JUMP FAILED", + "dsk_load_and_jump returned non-zero", 0); } /* ---- 插桩: 启动总耗时(仅在 DSK 跳转失败时可见) ---- */ diff --git a/CODE/UTSM/kernel/main.o b/CODE/UTSM/kernel/main.o index 933f9a7a15020673def6b4bf2dbfcba09d992aa9..9f91c31932cc46f903b623607415e968cdd50354 100644 GIT binary patch literal 23784 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 No&z8DAFin|{Wq1ITEhSU diff --git a/CODE/UTSM/kernel/probe.c b/CODE/UTSM/kernel/probe.c index 6490fb2..7505d3c 100644 --- a/CODE/UTSM/kernel/probe.c +++ b/CODE/UTSM/kernel/probe.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "ini_parser.h" /* ---- 探测缓冲状态 ---- */ @@ -39,6 +40,8 @@ void probe_init(const void *cfg_ptr) { if (!g_probe_buf) { g_instr_probe_enable = 0; log_warn("[PROBE] arena alloc failed, probe disabled"); + panic_full("PRB-E01 PROBE ARENA ALLOC FAILED", + "probe_init: probe buffer arena allocation failed", 0); return; } diff --git a/CODE/UTSM/kernel/probe.d b/CODE/UTSM/kernel/probe.d new file mode 100644 index 0000000..36eb103 --- /dev/null +++ b/CODE/UTSM/kernel/probe.d @@ -0,0 +1,9 @@ +kernel/probe.o: kernel\probe.c include\utsm\instr.h include\utsm\types.h \ + include\utsm\log.h include\utsm\arena.h include\utsm\panic.h \ + kernel\ini_parser.h +include\utsm\instr.h: +include\utsm\types.h: +include\utsm\log.h: +include\utsm\arena.h: +include\utsm\panic.h: +kernel\ini_parser.h: diff --git a/CODE/UTSM/mm/dma.c b/CODE/UTSM/mm/dma.c index 931db26..8bcb63c 100644 --- a/CODE/UTSM/mm/dma.c +++ b/CODE/UTSM/mm/dma.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "../arch/x86_64/limine.h" #define PAGE_SIZE 4096ULL @@ -54,6 +55,8 @@ void dma_init(void) { } if (!g_hhdm_offset || !g_memmap_request.response) { log_warn("[DMA] missing HHDM or memmap response"); + panic_full("MM-E20 MISSING HHDM OR MEMMAP", + "dma_init: HHDM or memmap response missing", 0); return; } @@ -84,6 +87,8 @@ void dma_init(void) { if (g_free_pages == 0) { log_warn("[DMA] no usable low pages found"); + panic_full("MM-E21 NO USABLE LOW PAGES", + "dma_init: no usable low-4G pages in memmap", 0); return; } @@ -133,6 +138,8 @@ int dma_alloc_pages(u64 page_count, u64 alignment, u64 max_phys, dkm_dma_buffer log_warn("[DMA] alloc failed"); log_hex64("[DMA] req pages=", page_count); log_hex64("[DMA] free pages=", g_free_pages); + panic_full("MM-E22 DMA ALLOC FAILED", + "dma_alloc_pages: no free pages satisfying request", 0); return -2; } diff --git a/CODE/UTSM/mm/dma.d b/CODE/UTSM/mm/dma.d new file mode 100644 index 0000000..14f51d0 --- /dev/null +++ b/CODE/UTSM/mm/dma.d @@ -0,0 +1,7 @@ +mm/dma.o: mm\dma.c include\utsm\dma.h include\utsm\types.h \ + include\utsm\log.h include\utsm\panic.h mm\..\arch\x86_64\limine.h +include\utsm\dma.h: +include\utsm\types.h: +include\utsm\log.h: +include\utsm\panic.h: +mm\..\arch\x86_64\limine.h: diff --git a/CODE/UTSM/mm/dma.o b/CODE/UTSM/mm/dma.o index 1bd2923457ff8f138a2015239176247ae8671e96..3657b3a5528224f12549ee28023155f4a4ac9f5d 100644 GIT binary patch delta 1468 zcmZ`&UuauZ7{4b?FUd`B(zIRg=3qVBq+5kHxmlAe_0NcFOfr(DT^YUz^(M{juH5`- zZ?ZWMx}hRL)QwNrYejvS`VzMX->jRigMq9?1@&QD1=%c2J2yobjpyW^V7%xLzH{#V zeZSxLedpZdw_Qtn&+fM^xz9cEJxYNcjiT!iK_6|q!x1D_R?O`x-Q+d+31$2LBeU_w zS(voF7d{!3msNGdGw>SKbBVY5_+)J@`Nc2%#G8HJQYz_rf6WjQjpamSrFwJYSPEU; zxD3DBC*3?JHGSZr1b z;PG@6M^mZHVfR-s| z3dx?xFBn>>hy#HUc_f7QAFou(#+c7Hr&W$uvm=LcrGih_PngSad7<=DK3BnNZd6fb z!`a|$_JFFYqXBtVjVO`OfpEwl%tmrbFcb+tSc)%6^l&!Le{qxl9H9@O?vNHgW=R)GI!O$Y zp!n3nkDD}ih4FUs?jiAre1D3s8BcpUNc57R_|8)28$BR1C_m~wq0l$D~En^CK}4v$=QbPwuXlJgbO)IAQXU5C)q;1$EdB)w;X?oK!= zhR|uKiTlttsEd;GG`&`WQ$#L_Y<#YRJRp!geTWCaJ&3kI7A4z@A{=o)<8<(*MTJ#y q09}H*Te1~-@;B^i{X32Sm!Ehyg>Mb3_{|u=r0H~oHQ0(%L)pxgY~bw0 zROWmjckc4&h2czKzZzD<(LgAYZK`Sy7TrErM%{cLrqO2^1`Fzz;y`fvXfMWTO8D4qjiK9LzVMJ`d^~;hpx*o z%X!wpN{i_X3mrMh7A-7cf%aO#IUDiSJ3MLb`OQ2k@S)q21i9M7`F2MS=WpQ)2l16U zZr$YS8$9VCW78e#1XpJ{&!(4YwYOW~Jp0+Y-ItD>_I4}($&n1rM!4uy;402J2^5;= zWb>?IoHCzKbrB$#aCN(sroDA2c+K?`_qm_5;a0KcCblGdCKNsd=`ifXxYTPGEG;f- z#M@E?2C*dV0XxTZ`zgye=QI$);9Jh #include #include +#include #include "../arch/x86_64/limine.h" #define MM_PAGE_SIZE 4096ULL @@ -79,11 +80,15 @@ static void mm_lazy_init(void) { g_max_phys_addr_bits = 0; if (!g_hhdm_request.response) { log_warn("[MM] missing HHDM response"); + panic_full("MM-E10 MISSING HHDM RESPONSE", + "mm_lazy_init: Limine HHDM response missing", 0); return; } g_hhdm = g_hhdm_request.response->offset; if (!g_hhdm) { log_warn("[MM] null HHDM offset"); + panic_full("MM-E11 NULL HHDM OFFSET", + "mm_lazy_init: HHDM offset is zero", 0); return; } @@ -95,6 +100,8 @@ static void mm_lazy_init(void) { log_error("[MM] LA57 5-level paging ACTIVE — REFUSING to proceed"); log_error("[MM] This kernel requires 4-level paging (48-bit virtual)"); log_error("[MM] Disable LA57 in BIOS/firmware settings"); + panic_full("MM-E12 LA57 ACTIVE REFUSE", + "mm_lazy_init: 5-level paging active; 4-level walk required", 0); return; } @@ -113,6 +120,8 @@ static void mm_lazy_init(void) { log_hex64("[MM] CPU MaxPhysAddr bits=", g_max_phys_addr_bits); if (g_max_phys_addr_bits > 52) { log_error("[MM] physical address width > 52 bits — PTE cannot represent"); + panic_full("MM-E13 PHYS ADDR WIDTH EXCEEDED", + "mm_lazy_init: physical address width exceeds 52 bits", 0); return; } } else { @@ -126,6 +135,8 @@ static void mm_lazy_init(void) { g_window_base = mm_find_window(); if (!g_window_base) { log_error("[MM] no free PML4 slot for mmio window"); + panic_full("MM-E14 NO FREE PML4 SLOT", + "mm_lazy_init: no free PML4 slot for mmio window", 0); return; } g_window_end = g_window_base + MM_WINDOW_SIZE; @@ -153,6 +164,8 @@ static u64 *mm_walk_create(u64 virt) { dkm_dma_buffer buf; if (dma_alloc_pages(1, MM_PAGE_SIZE, 0, &buf) != 0) { log_warn("[MM] page table alloc failed"); + panic_full("MM-E15 PAGE TABLE ALLOC FAILED", + "mm_walk_create: page table page alloc failed", 0); return 0; } table[idx] = buf.phys | PTE_PRESENT | PTE_RW; @@ -185,6 +198,8 @@ void *mm_map_mmio(u64 phys, u64 size) { log_error("[MM] phys address exceeds CPU MaxPhysAddr"); log_hex64("[MM] phys=", phys); log_hex64("[MM] max_phys=", max_phys); + panic_full("MM-E16 PHYS EXCEEDS MAXADDR", + "mm_map_mmio: physical address exceeds CPU MaxPhysAddr", 0); return 0; } } @@ -197,6 +212,8 @@ void *mm_map_mmio(u64 phys, u64 size) { u64 vbase = g_window_next; if (vbase < g_window_base || vbase + total > g_window_end) { log_error("[MM] mmio window exhausted"); + panic_full("MM-E17 MMIO WINDOW EXHAUSTED", + "mm_map_mmio: MMIO virtual window exhausted", 0); return 0; } @@ -207,6 +224,8 @@ void *mm_map_mmio(u64 phys, u64 size) { if (!pte || (*pte & PTE_PRESENT)) { /* 冲突/失败:回滚本次已建立的映射 */ log_error("[MM] map conflict"); + panic_full("MM-E18 MAP CONFLICT", + "mm_map_mmio: page table walk conflict or failure", 0); for (u64 j = 0; j < mapped; j++) { u64 v = vbase + j * MM_PAGE_SIZE; u64 *p = mm_walk_query(v); diff --git a/CODE/UTSM/mm/mmio.d b/CODE/UTSM/mm/mmio.d new file mode 100644 index 0000000..74d9bd5 --- /dev/null +++ b/CODE/UTSM/mm/mmio.d @@ -0,0 +1,9 @@ +mm/mmio.o: mm\mmio.c include\utsm\mm.h include\utsm\types.h \ + include\utsm\dma.h include\utsm\log.h include\utsm\panic.h \ + mm\..\arch\x86_64\limine.h +include\utsm\mm.h: +include\utsm\types.h: +include\utsm\dma.h: +include\utsm\log.h: +include\utsm\panic.h: +mm\..\arch\x86_64\limine.h: diff --git a/CODE/UTSM/mm/paging.c b/CODE/UTSM/mm/paging.c index 961dd90..2a05352 100644 --- a/CODE/UTSM/mm/paging.c +++ b/CODE/UTSM/mm/paging.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "../arch/x86_64/limine.h" extern volatile struct limine_hhdm_request g_hhdm_request; @@ -90,7 +91,12 @@ static int paging_map_mmio_impl(u64 phys, u64 size) { u64 idx4 = (v >> 39) & 0x1FF; if (!(pml4[idx4] & PTE_PRESENT)) { u64 t = paging_alloc_table(); - if (!t) { log_error("[PAGING] alloc PDPT failed"); return -2; } + if (!t) { + log_error("[PAGING] alloc PDPT failed"); + panic_full("MM-E01 PDPT ALLOC FAILED", + "paging_map_mmio: PDPT page alloc failed", 0); + return -2; + } pml4[idx4] = t | PTE_PRESENT | PTE_RW; } @@ -100,7 +106,12 @@ static int paging_map_mmio_impl(u64 phys, u64 size) { if (pdpt[idx3] & PTE_PS) { skipped++; continue; } /* 1G 大页已覆盖 */ } else { u64 t = paging_alloc_table(); - if (!t) { log_error("[PAGING] alloc PD failed"); return -3; } + if (!t) { + log_error("[PAGING] alloc PD failed"); + panic_full("MM-E02 PD ALLOC FAILED", + "paging_map_mmio: PD page alloc failed", 0); + return -3; + } pdpt[idx3] = t | PTE_PRESENT | PTE_RW; } @@ -110,7 +121,12 @@ static int paging_map_mmio_impl(u64 phys, u64 size) { if (pd[idx2] & PTE_PS) { skipped++; continue; } /* 2M 大页已覆盖 */ } else { u64 t = paging_alloc_table(); - if (!t) { log_error("[PAGING] alloc PT failed"); return -4; } + if (!t) { + log_error("[PAGING] alloc PT failed"); + panic_full("MM-E03 PT ALLOC FAILED", + "paging_map_mmio: PT page alloc failed", 0); + return -4; + } pd[idx2] = t | PTE_PRESENT | PTE_RW; } diff --git a/CODE/UTSM/mm/paging.d b/CODE/UTSM/mm/paging.d new file mode 100644 index 0000000..e61d958 --- /dev/null +++ b/CODE/UTSM/mm/paging.d @@ -0,0 +1,9 @@ +mm/paging.o: mm\paging.c include\utsm\paging.h include\utsm\types.h \ + include\utsm\dma.h include\utsm\log.h include\utsm\panic.h \ + mm\..\arch\x86_64\limine.h +include\utsm\paging.h: +include\utsm\types.h: +include\utsm\dma.h: +include\utsm\log.h: +include\utsm\panic.h: +mm\..\arch\x86_64\limine.h: diff --git a/CODE/UTSM/pe/pe_dll_manager.c b/CODE/UTSM/pe/pe_dll_manager.c index d5590bf..077ab88 100644 --- a/CODE/UTSM/pe/pe_dll_manager.c +++ b/CODE/UTSM/pe/pe_dll_manager.c @@ -18,6 +18,7 @@ #include #include #include +#include /* ---- PE 导出目录结构(packed,与 pe_loader.h 风格一致) ---- */ typedef struct __attribute__((packed)) { @@ -263,6 +264,8 @@ static u64 resolve_export_by_name(u64 image_base, u32 export_dir_rva, static u64 resolve_forwarded_export(u64 image_base, u32 func_rva, int depth) { if (depth > PE_DLL_FWD_DEPTH_MAX) { log_warn("[PE] forwarded export chain too deep"); + panic_full("PE-E20 FORWARD CHAIN TOO DEEP", + "resolve_forwarded_export: forwarded export chain too deep", 0); return 0; } const char *fwd = (const char *)(image_base + func_rva); @@ -280,6 +283,8 @@ static u64 resolve_forwarded_export(u64 image_base, u32 func_rva, int depth) { while (buf[dot] && buf[dot] != '.') dot++; if (buf[dot] != '.' || dot == 0 || buf[dot + 1] == 0) { log_warn("[PE] malformed forwarder string"); + panic_full("PE-E21 MALFORMED FORWARDER STRING", + "resolve_forwarded_export: malformed forwarder string", 0); return 0; } buf[dot] = 0; @@ -318,6 +323,8 @@ static u64 resolve_forwarded_export(u64 image_base, u32 func_rva, int depth) { u64 addr = resolve_export_by_ordinal(base, g_dll_cache[idx].export_dir_rva, ord); if (addr == 0) { log_warn("[PE] ordinal forward target not found"); + panic_full("PE-E22 ORDINAL FORWARD NOT FOUND", + "resolve_forwarded_export: ordinal forward target missing", 0); } return addr; } @@ -368,6 +375,8 @@ int pe_dll_load(const char *dll_name, u64 *out_base) { idx = dll_cache_alloc(); if (idx < 0) { log_warn("[PE] DLL cache full, cannot load"); + panic_full("PE-E23 DLL CACHE FULL", + "pe_dll_load: DLL cache exhausted", 0); if (out_base) *out_base = 0; return -2; } @@ -402,6 +411,8 @@ int pe_dll_load(const char *dll_name, u64 *out_base) { if (pe_load_image(file_copy, file_size, &info) != 0) { log_warn("[PE] DLL load failed: pe_load_image error"); log_info(dll_name); + panic_full("PE-E24 DLL IMAGE LOAD FAILED", + "pe_dll_load: pe_load_image failed for DLL", 0); entry->state = DLL_STATE_NONE; if (out_base) *out_base = 0; return -5; @@ -436,6 +447,8 @@ int pe_dll_load(const char *dll_name, u64 *out_base) { log_info("[PE] DllMain deferred"); } else { log_warn("[PE] DllMain pending queue full, skipped"); + panic_full("PE-E25 DLLMAIN PENDING QUEUE FULL", + "pe_dll_load: DllMain pending queue full", 0); } } else { typedef int (__attribute__((ms_abi)) *dllmain_fn)(u64, u32, u64); diff --git a/CODE/UTSM/pe/pe_dll_manager.d b/CODE/UTSM/pe/pe_dll_manager.d index 02f6211..c20e825 100644 --- a/CODE/UTSM/pe/pe_dll_manager.d +++ b/CODE/UTSM/pe/pe_dll_manager.d @@ -1,6 +1,6 @@ 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 + include\utsm\arena.h include\utsm\log.h include\utsm\panic.h pe\pe_dll_manager.h: include\utsm\types.h: pe\pe_loader.h: @@ -8,3 +8,4 @@ include\utsm\pe.h: pe\pe_shim.h: include\utsm\arena.h: include\utsm\log.h: +include\utsm\panic.h: diff --git a/CODE/UTSM/pe/pe_service.c b/CODE/UTSM/pe/pe_service.c index 73607b7..5e330bd 100644 --- a/CODE/UTSM/pe/pe_service.c +++ b/CODE/UTSM/pe/pe_service.c @@ -21,6 +21,7 @@ #include #include #include +#include /* 32位 PE 用的栈与堆 */ #define PE32_STACK_SIZE (64 * 1024) /* 64KB 栈 */ @@ -293,6 +294,8 @@ int pe_service_run(const void *pe_data, u64 size, const char *cmdline, u64 *exit if (rc != 0) { pe_dll_defer_dllmain(0); log_error("[PE] PE32+ load failed"); + panic_full("PE-E10 PE32+ LOAD FAILED", + "pe_service_run: PE32+ image load failed", 0); return -5; } log_info("[PE] running PE32+ natively"); @@ -307,6 +310,8 @@ int pe_service_run(const void *pe_data, u64 size, const char *cmdline, u64 *exit u8 *pe_stack = (u8 *)kmem_alloc_aligned(PE_STACK_BYTES, 4096); if (!pe_stack) { log_error("[PE] stack alloc failed"); + panic_full("PE-E11 PE STACK ALLOC FAILED", + "pe_service_run: 1MB PE stack allocation failed", 0); return -9; } u64 stack_top = (u64)pe_stack + PE_STACK_BYTES; /* 4096 对齐 -> 16 对齐 */ @@ -339,6 +344,8 @@ int pe_service_run(const void *pe_data, u64 size, const char *cmdline, u64 *exit if (rc != 0) { log_error("[PE] PE32 interp load failed"); log_hex64("[PE] rc=", (u64)(i64)rc); + panic_full("PE-E12 PE32 INTERP LOAD FAILED", + "pe_service_run: PE32 interpreter load failed", 0); return -6; } log_info("[PE] running PE32 via x86emu32"); @@ -351,6 +358,8 @@ int pe_service_run(const void *pe_data, u64 size, const char *cmdline, u64 *exit img.iat, img.iat_count, stack_top); if (irc != 0) { log_error("[PE32] emu init failed"); + panic_full("PE-E13 EMU INIT FAILED", + "pe_service_run: x86emu32 init failed", 0); return -7; } emu.eip = img.entry_point; @@ -367,12 +376,16 @@ int pe_service_run(const void *pe_data, u64 size, const char *cmdline, u64 *exit int rrc = x86emu32_run(&emu, &code); if (rrc != 0) { log_error("[PE32] emulator error"); + panic_full("PE-E14 EMULATOR ERROR", + "pe_service_run: x86emu32_run returned error", 0); code = 0xFFFFFFFFULL; } /* emu 字段只在未发生 longjmp 的正常返回路径读取 * (setjmp 语义:longjmp 后被修改的自动变量值不确定) */ if (emu.error && !emu.exited) { log_warn("[PE32] emulator stopped with error"); + panic_full("PE-E15 EMULATOR STOPPED WITH ERROR", + "pe_service_run: emulator stopped in error state", 0); } } else { code = pe_shim_get_exit_code(); diff --git a/CODE/UTSM/pe/pe_service.d b/CODE/UTSM/pe/pe_service.d new file mode 100644 index 0000000..2da0ab8 --- /dev/null +++ b/CODE/UTSM/pe/pe_service.d @@ -0,0 +1,15 @@ +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 include\utsm\panic.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: +include\utsm\panic.h: diff --git a/CODE/UTSM/sched/sched.c b/CODE/UTSM/sched/sched.c index a5ef816..12bde81 100644 --- a/CODE/UTSM/sched/sched.c +++ b/CODE/UTSM/sched/sched.c @@ -546,12 +546,16 @@ int utsm_sched_enable(u32 tick_hz) { if (lapic_timer_init(tick_hz) != 0) { log_error("[SCHED] lapic timer init failed, stays cooperative"); + panic_full("SAS-E04 LAPIC TIMER INIT FAILED", + "utsm_sched_enable: lapic_timer_init failed", 0); return -1; } int vec = lapic_timer_vector(); if (vec < 0 || irq_register((u8)vec, utsm_tick_handler) != 0) { lapic_timer_stop(); log_error("[SCHED] tick handler registration failed"); + panic_full("SAS-E05 TICK HANDLER REGISTER FAILED", + "utsm_sched_enable: tick handler registration failed", 0); return -2; } idt_set_exception_hook(utsm_sched_exc_hook); diff --git a/CODE/UTSM/test/utsm_selftest.c b/CODE/UTSM/test/utsm_selftest.c index ef77158..c54ec03 100644 --- a/CODE/UTSM/test/utsm_selftest.c +++ b/CODE/UTSM/test/utsm_selftest.c @@ -8,6 +8,7 @@ #include #include #include +#include int memcmp(const void *a, const void *b, usize len); usize strlen(const char *s); @@ -33,6 +34,8 @@ int utsm_selftest_run(void) { utsm_process_context *process = (utsm_process_context *)kmem_alloc(sizeof(utsm_process_context)); if (!process) { log_error("[UTSM] selftest: failed to allocate process context"); + panic_full("TST-E01 SELFTEST CTX ALLOC FAILED", + "utsm_selftest: process context allocation failed", 0); return UTSM_ERR_NO_MEMORY; } utsm_process_create_test(process, 1); @@ -41,6 +44,8 @@ int utsm_selftest_run(void) { int status = utsm_create_segment(process, UTSM_PAGE_SIZE, UTSM_SEG_F_READ | UTSM_SEG_F_WRITE | UTSM_SEG_F_STRONG_RECOVERY, &cap); if (status != UTSM_OK) { log_error("[UTSM] selftest create segment failed"); + panic_full("TST-E02 SELFTEST CREATE SEGMENT FAILED", + "utsm_selftest: create segment failed", 0); return status; } @@ -49,16 +54,22 @@ int utsm_selftest_run(void) { status = utsm_write(cap, 128, message, len); if (status != UTSM_OK) { log_error("[UTSM] selftest write failed"); + panic_full("TST-E03 SELFTEST WRITE FAILED", + "utsm_selftest: sealed write failed", 0); return status; } log_info("[UTSM] selftest write ok"); utsm_segment_desc *desc = utsm_get_segment(cap.segment_slot); if (!desc) { + panic_full("TST-E04 SELFTEST SEG DESC MISSING", + "utsm_selftest: segment desc lookup failed", 0); return UTSM_ERR_INVALID; } if (memcmp(desc->cipher_base + 128, message, len) == 0) { log_error("[UTSM] raw cipher equals plaintext"); + panic_full("TST-E05 SELFTEST CIPHER PLAINTEXT LEAK", + "utsm_selftest: raw cipher equals plaintext", 0); return UTSM_ERR_INVALID; } log_info("[UTSM] raw cipher check ok"); @@ -67,10 +78,14 @@ int utsm_selftest_run(void) { status = utsm_read(cap, 128, readback, len); if (status != UTSM_OK) { log_error("[UTSM] selftest read failed"); + panic_full("TST-E06 SELFTEST READ FAILED", + "utsm_selftest: sealed read failed", 0); return status; } if (memcmp(readback, message, len) != 0) { log_error("[UTSM] selftest read mismatch"); + panic_full("TST-E07 SELFTEST READ MISMATCH", + "utsm_selftest: readback mismatch", 0); return UTSM_ERR_INVALID; } log_info("[UTSM] selftest read ok"); @@ -86,6 +101,8 @@ int utsm_selftest_run(void) { utsm_chacha20_block(kat_key, kat_nonce, kat_counter, ks); if (memcmp(ks, kat_expect, 64) != 0) { log_error("[UTSM] selftest chacha20 KAT FAIL (RFC 8439 §2.4.2)"); + panic_full("TST-E08 CHACHA20 KAT FAIL", + "utsm_selftest: chacha20 KAT mismatch (RFC 8439 2.4.2)", 0); return UTSM_ERR_INVALID; } log_info("[UTSM] selftest chacha20 KAT ok (RFC 8439 §2.4.2)"); @@ -97,6 +114,8 @@ int utsm_selftest_run(void) { u64 m3 = utsm_page_mac(rk, 0, 1, 0, desc->cipher_base); if (m1 != m2 || m1 == m3) { log_error("[UTSM] selftest page MAC determinism FAIL"); + panic_full("TST-E09 PAGE MAC DETERMINISM FAIL", + "utsm_selftest: page MAC determinism broken", 0); return UTSM_ERR_INVALID; } log_info("[UTSM] selftest page MAC determinism ok"); @@ -114,6 +133,8 @@ int utsm_selftest_run(void) { int dst = utrw_debug_dump_page(cap.segment_slot, 0, 128); if (dst != UTSM_OK) { log_error("[UTSM] selftest cipher dump failed"); + panic_full("TST-E10 SELFTEST CIPHER DUMP FAILED", + "utsm_selftest: cipher page dump failed", 0); return dst; } } @@ -129,12 +150,16 @@ int utsm_selftest_run(void) { UTSM_ERR_EPOCH, &refreshed); if (status != UTSM_OK) { log_error("[UTSM] selftest slow EPOCH recover failed"); + panic_full("TST-E11 SLOW EPOCH RECOVER FAILED", + "utsm_selftest: slow path EPOCH recovery failed", 0); return status; } char slow_rb[64]; status = utsm_read(refreshed, 128, slow_rb, len); if (status != UTSM_OK || memcmp(slow_rb, message, len) != 0) { log_error("[UTSM] selftest slow EPOCH retry read failed"); + panic_full("TST-E12 SLOW EPOCH RETRY FAILED", + "utsm_selftest: read after EPOCH refresh failed", 0); return (status == UTSM_OK) ? UTSM_ERR_INVALID : status; } log_info("[UTSM] selftest slow EPOCH ok"); @@ -145,11 +170,15 @@ int utsm_selftest_run(void) { UTSM_ERR_KEY_MISS, 0); if (status != UTSM_OK) { log_error("[UTSM] selftest slow KEY_MISS recover failed"); + panic_full("TST-E13 SLOW KEY_MISS RECOVER FAILED", + "utsm_selftest: slow path KEY_MISS re-derive failed", 0); return status; } status = utsm_read(refreshed, 128, slow_rb, len); if (status != UTSM_OK || memcmp(slow_rb, message, len) != 0) { log_error("[UTSM] selftest slow KEY_MISS retry read failed"); + panic_full("TST-E14 SLOW KEY_MISS RETRY FAILED", + "utsm_selftest: read after KEY_MISS re-derive failed", 0); return (status == UTSM_OK) ? UTSM_ERR_INVALID : status; } log_info("[UTSM] selftest slow KEY_MISS ok"); @@ -160,6 +189,8 @@ int utsm_selftest_run(void) { UTSM_ERR_POISONED, 0); if (status != UTSM_ERR_POISONED) { log_error("[UTSM] selftest slow POISONED passthrough failed"); + panic_full("TST-E15 SLOW POISONED PASSTHROUGH FAILED", + "utsm_selftest: POISONED not passed through", 0); return UTSM_ERR_INVALID; } log_info("[UTSM] selftest slow POISONED ok"); @@ -174,6 +205,8 @@ int utsm_selftest_run(void) { &ucap); if (status != UTSM_OK) { log_error("[UTSM] selftest unsealed segment create failed"); + panic_full("TST-E16 UNSEALED SEGMENT CREATE FAILED", + "utsm_selftest: unsealed segment create failed", 0); return status; } const char *upl = "unsealed plain text 00"; @@ -181,19 +214,29 @@ int utsm_selftest_run(void) { status = utsm_write(ucap, 128, upl, ulen); if (status != UTSM_OK) { log_error("[UTSM] selftest unsealed write failed"); + panic_full("TST-E17 UNSEALED WRITE FAILED", + "utsm_selftest: unsealed plain write failed", 0); return status; } utsm_segment_desc *udesc = utsm_get_segment(ucap.segment_slot); - if (!udesc) return UTSM_ERR_INVALID; + if (!udesc) { + panic_full("TST-E18 UNSEALED DESC MISSING", + "utsm_selftest: unsealed segment desc lookup failed", 0); + return UTSM_ERR_INVALID; + } /* 明文直存:存储区内容必须与明文完全一致(0 开销的可观察证据) */ if (memcmp(udesc->cipher_base + 128, upl, ulen) != 0) { log_error("[UTSM] selftest unsealed store not plaintext"); + panic_full("TST-E19 UNSEALED STORE NOT PLAINTEXT", + "utsm_selftest: unsealed storage differs from plaintext", 0); return UTSM_ERR_INVALID; } char urb[64]; status = utsm_read(ucap, 128, urb, ulen); if (status != UTSM_OK || memcmp(urb, upl, ulen) != 0) { log_error("[UTSM] selftest unsealed read failed"); + panic_full("TST-E20 UNSEALED READ FAILED", + "utsm_selftest: unsealed readback mismatch", 0); return (status == UTSM_OK) ? UTSM_ERR_INVALID : status; } log_info("[UTSM] selftest unsealed segment ok (plain storage)"); @@ -204,27 +247,37 @@ int utsm_selftest_run(void) { const dkm_kernel_api *api = dkm_get_kernel_api(); if (!api->kapi || api->kapi->magic != DKM_KAPI_MAGIC) { log_error("[UTSM] selftest kapi table missing"); + panic_full("TST-E21 KAPI TABLE MISSING", + "utsm_selftest: kapi export table missing or bad magic", 0); return UTSM_ERR_INVALID; } void *fn = 0; if (api->kapi->lookup("log.info", &fn) != 0) { log_error("[UTSM] selftest kapi lookup log.info failed"); + panic_full("TST-E22 KAPI LOOKUP LOG FAILED", + "utsm_selftest: kapi lookup log.info failed", 0); return UTSM_ERR_INVALID; } void (*klog)(const char *) = (void (*)(const char *))fn; klog("[UTSM] selftest kapi: log.info via export table"); if (api->kapi->lookup("dma.alloc_pages", &fn) != 0) { log_error("[UTSM] selftest kapi lookup dma failed"); + panic_full("TST-E23 KAPI LOOKUP DMA FAILED", + "utsm_selftest: kapi lookup dma.alloc_pages failed", 0); return UTSM_ERR_INVALID; } int (*kalloc)(u64, u64, u64, dkm_dma_buffer *) = (int (*)(u64, u64, u64, dkm_dma_buffer *))fn; dkm_dma_buffer kbuf; if (kalloc(1, 4096, 0xFFFFFFFFULL, &kbuf) != 0 || !kbuf.virt) { log_error("[UTSM] selftest kapi dma alloc failed"); + panic_full("TST-E24 KAPI DMA ALLOC FAILED", + "utsm_selftest: kapi dma.alloc_pages call failed", 0); return UTSM_ERR_INVALID; } if (api->kapi->lookup("no.such.service", &fn) == 0) { log_error("[UTSM] selftest kapi negative lookup failed"); + panic_full("TST-E25 KAPI NEGATIVE LOOKUP FAILED", + "utsm_selftest: negative lookup unexpectedly succeeded", 0); return UTSM_ERR_INVALID; } log_hex64("[UTSM] selftest kapi entries=", api->kapi->count); @@ -240,11 +293,15 @@ int utsm_selftest_run(void) { selftest_irq_restore(st_flags); if (rq_rc != 0) { log_error("[SCHED] selftest: runqueue O(1) FAIL"); + panic_full("TST-E26 RUNQUEUE SELFTEST FAIL", + "utsm_selftest: O(1) runqueue semantics broken", 0); return UTSM_ERR_INVALID; } log_info("[SCHED] selftest: runqueue O(1) PASS"); if (bw_rc != 0) { log_error("[SCHED] selftest: block/wake FAIL"); + panic_full("TST-E27 BLOCKWAKE SELFTEST FAIL", + "utsm_selftest: block/wake semantics broken", 0); return UTSM_ERR_INVALID; } log_info("[SCHED] selftest: block/wake PASS"); @@ -259,34 +316,46 @@ int utsm_selftest_run(void) { status = utsm_write(cap, 512, p1, plen); if (status != UTSM_OK) { log_error("[DRR] selftest P1 write failed"); + panic_full("TST-E28 DRR P1 WRITE FAILED", + "utsm_selftest: DRR pre-snapshot write failed", 0); return status; } int snap = drr_ckpt_snapshot_dirty(); log_hex64("[DRR] ckpt snapshot pages=", (u64)(i64)snap); if (snap < 1) { log_error("[DRR] selftest snapshot failed"); + panic_full("TST-E29 DRR SNAPSHOT FAILED", + "utsm_selftest: dirty page snapshot failed", 0); return UTSM_ERR_INVALID; } drr_checkpoint_meta meta; if (drr_checkpoint_recover(&meta) != 0 || meta.type != DRR_CKPT_DIRTY_PAGE || meta.dirty_page_count < 1) { log_error("[DRR] selftest meta verify failed"); + panic_full("TST-E30 DRR META VERIFY FAILED", + "utsm_selftest: checkpoint meta verify failed", 0); return UTSM_ERR_INVALID; } status = utsm_write(cap, 512, p2, plen); if (status != UTSM_OK) { log_error("[DRR] selftest P2 write failed"); + panic_full("TST-E31 DRR P2 WRITE FAILED", + "utsm_selftest: DRR overwrite write failed", 0); return status; } int rb = drr_rollback_pages(); log_hex64("[DRR] rollback pages=", (u64)(i64)rb); if (rb < 1) { log_error("[DRR] selftest rollback failed"); + panic_full("TST-E32 DRR ROLLBACK FAILED", + "utsm_selftest: page rollback failed", 0); return UTSM_ERR_INVALID; } status = utsm_read(cap, 512, readback, plen); if (status != UTSM_OK || memcmp(readback, p1, plen) != 0) { log_error("[DRR] rollback verify FAIL"); + panic_full("TST-E33 DRR ROLLBACK VERIFY FAIL", + "utsm_selftest: rollback verify mismatch", 0); return UTSM_ERR_INVALID; } log_info("[DRR] rollback verify ok"); diff --git a/CODE/UTSM/test/utsm_selftest.d b/CODE/UTSM/test/utsm_selftest.d index e22314d..337df55 100644 --- a/CODE/UTSM/test/utsm_selftest.d +++ b/CODE/UTSM/test/utsm_selftest.d @@ -7,7 +7,8 @@ test/utsm_selftest.o: test\utsm_selftest.c include\utsm\utsm.h \ include\utsm\crypto.h include\utsm\dma.h include\utsm\dkm.h \ include\utsm\block.h include\utsm\net.h include\utsm\paging.h \ include\utsm\log.h include\utsm\arena.h include\utsm\drr.h \ - include\utsm\sched_ext.h include\utsm\sched.h test\chacha_kat.inc + include\utsm\sched_ext.h include\utsm\sched.h include\utsm\panic.h \ + test\chacha_kat.inc include\utsm\utsm.h: include\utsm\types.h: include\utsm\status.h: @@ -35,4 +36,5 @@ include\utsm\arena.h: include\utsm\drr.h: include\utsm\sched_ext.h: include\utsm\sched.h: +include\utsm\panic.h: test\chacha_kat.inc: diff --git a/CODE/UTSM/test/utsm_selftest.o b/CODE/UTSM/test/utsm_selftest.o index 64d9b1b0086f1ee2d5c8982c0d9031373f30f5ad..f7182290dc2dec79f1471622bbb98f408cb7d8f9 100644 GIT binary patch literal 15784 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 G|Njdd9JbW} literal 10320 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 diff --git a/CODE/UTSM/utrw/debug.c b/CODE/UTSM/utrw/debug.c index 8239a14..ba0bd5f 100644 --- a/CODE/UTSM/utrw/debug.c +++ b/CODE/UTSM/utrw/debug.c @@ -3,6 +3,7 @@ #include #include #include +#include void *memcpy(void *dst, const void *src, usize len); @@ -66,6 +67,8 @@ int utrw_debug_dump_page(u32 segment_slot, u64 page_index, u64 offset_in_page) { int st = utsm_pckc_get_or_derive(segment_slot, desc, &key); if (st != UTSM_OK) { log_warn("[UTRW] dump: key derive failed"); + panic_full("UTRW-E10 DUMP KEY DERIVE FAILED", + "utrw_debug_dump_page: PCKC key derivation failed", 0); return st; } u64 dump_line = (page_off + offset_in_page) / UTSM_CACHE_LINE_SIZE; diff --git a/CODE/UTSM/utrw/debug.d b/CODE/UTSM/utrw/debug.d index 94ef866..e372687 100644 --- a/CODE/UTSM/utrw/debug.d +++ b/CODE/UTSM/utrw/debug.d @@ -1,7 +1,8 @@ utrw/debug.o: utrw\debug.c include\utsm\utrw.h include\utsm\types.h \ include\utsm\status.h include\utsm\capability.h include\utsm\segment.h \ include\utsm\uuid.h include\utsm\dirty.h include\utsm\pckc.h \ - include\utsm\config.h include\utsm\crypto.h include\utsm\log.h + include\utsm\config.h include\utsm\crypto.h include\utsm\log.h \ + include\utsm\panic.h include\utsm\utrw.h: include\utsm\types.h: include\utsm\status.h: @@ -13,3 +14,4 @@ include\utsm\pckc.h: include\utsm\config.h: include\utsm\crypto.h: include\utsm\log.h: +include\utsm\panic.h: diff --git a/CODE/UTSM/utrw/slow_path.c b/CODE/UTSM/utrw/slow_path.c index a72975a..24b7a90 100644 --- a/CODE/UTSM/utrw/slow_path.c +++ b/CODE/UTSM/utrw/slow_path.c @@ -3,6 +3,7 @@ #include #include #include +#include /* =================================================================== * U2: UTRW Slow Path 真分支 @@ -53,6 +54,8 @@ int utsm_slow_path(utsm_capability cap, u32 rights, u64 offset, u64 len, st = utsm_pckc_get_or_derive(cap.segment_slot, desc, &key); if (st != UTSM_OK) { log_warn("[UTRW] slow: KEY_MISS re-derive failed"); + panic_full("UTRW-E01 KEY_MISS RE-DERIVE FAILED", + "utsm_slow_path: KEY_MISS key re-derivation failed", 0); return st; } log_warn("[UTRW] slow: KEY_MISS -> key re-derived (retry)"); diff --git a/CODE/UTSM/utrw/slow_path.d b/CODE/UTSM/utrw/slow_path.d index ca05671..4cfee79 100644 --- a/CODE/UTSM/utrw/slow_path.d +++ b/CODE/UTSM/utrw/slow_path.d @@ -2,7 +2,7 @@ utrw/slow_path.o: utrw\slow_path.c include\utsm\utrw.h \ include\utsm\types.h include\utsm\status.h include\utsm\capability.h \ include\utsm\segment.h include\utsm\uuid.h include\utsm\dirty.h \ include\utsm\pckc.h include\utsm\config.h include\utsm\crypto.h \ - include\utsm\drr.h include\utsm\log.h + include\utsm\drr.h include\utsm\log.h include\utsm\panic.h include\utsm\utrw.h: include\utsm\types.h: include\utsm\status.h: @@ -15,3 +15,4 @@ include\utsm\config.h: include\utsm\crypto.h: include\utsm\drr.h: include\utsm\log.h: +include\utsm\panic.h: diff --git a/CODE/UTSM/utrw/slow_path.o b/CODE/UTSM/utrw/slow_path.o index 4035e5e96f560479802c0bf8403050db2d2ad003..dc8317b783fb6b07eae9aef44f4cc06c0e487d15 100644 GIT binary patch delta 755 zcmZ8dO=uHA6yCRFlkBdtRk0iY$X2jXA=-E;Es6%aA+f2@#A?&aHfq{NV;kEi+d%ah)>Rbt!uSU9c}?rv*FSN>k1C;FUDBl?1sJz4Ub7d~U^``)LR* zXJ1H}HL9&!&}qX?xkTN#-qp#f6Z7zCi}9}N`BST*n?H{8tfQyzT;PIJZF4EzYDnwx z1%paJb#|!%-+5K>xP5-Li%BLXu4xmov71^voEYi+|MF^NQW=jpFGt3sH^PbN*yz(T zy9y>E{1A&KZCjE=+ZmQRsl$&hZWv~;G7UW6 zz>9hdo&N+L8HJjR-ZmRLZSWh0ZsC1?2fnfF1s7H=8eBo2byA3jN28atp=2zEMQZ_5 zECwEqQja?$1h delta 523 zcmZ8dO(<+(82;X4e$Jl`!r@A?;4lk63o#4KiF@xT8%1J67EH4cOJzYiO(!X*XCoWg z+)EY)8+E(4k-DR+Y*C~s3zioCt~9A#cCr-PH2Koot0YJ zc6Q4uK#WDxX~q$?kMBHxaX;@|)wOi;SfBlOIT~AfCCzH%^zbd4&3+9}j%!v2r{?qd z;k&C?@0w+xm8yFrw_*59OR(JKpO$#$P3;@6^~%teebaA0<(PeJrK0In?#=uNTJOt! z7k<(uOt}juf&s%qBY;dYI!pC%>aPx69T*C4FlkTaEO=CdRD<3~a zhx6h8cnIo9iVakSOL2?_5tiogTlzygSd?`sCVGkI*p#~|gpAxSCHSJ6uXA_f5Rp-9J^+D=iDUo( diff --git a/CODE/UTSM/vmm/ept.c b/CODE/UTSM/vmm/ept.c index f5258fa..5288586 100644 --- a/CODE/UTSM/vmm/ept.c +++ b/CODE/UTSM/vmm/ept.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -41,6 +42,7 @@ static u64 ept_alloc_page(void) { dkm_dma_buffer buf; if (dma_alloc_pages(1, EPT_PAGE_SIZE, 0x100000000ULL, &buf) != 0) { log_error("[EPT] alloc page failed"); + panic_full("EPT-E01 EPT PAGE ALLOC FAILED", "dma_alloc_pages failed for an ept page table page", 0); return 0; } /* dma_alloc_pages 已清零 */ @@ -51,6 +53,7 @@ int ept_init(void) { g_ept_pml4_phys = ept_alloc_page(); if (g_ept_pml4_phys == 0) { log_error("[EPT] failed to alloc PML4"); + panic_full("EPT-E02 ALLOC PML4 FAILED", "ept root pml4 page allocation failed", 0); return -1; } g_ept_pml4_virt = (u64)phys_to_virt(g_ept_pml4_phys); @@ -122,6 +125,7 @@ int ept_map_range(u64 gpa, u64 hpa, u64 size, u64 flags) { if ((gpa & (EPT_PAGE_SIZE - 1)) || (hpa & (EPT_PAGE_SIZE - 1)) || (size & (EPT_PAGE_SIZE - 1))) { log_error("[EPT] unaligned map request"); + panic_full("EPT-E03 UNALIGNED MAP REQUEST", "ept map request got a non page aligned gpa hpa or size", 0); return -2; } @@ -132,6 +136,7 @@ int ept_map_range(u64 gpa, u64 hpa, u64 size, u64 flags) { u64 *entry = ept_walk(cur_gpa, 1); if (!entry) { log_error("[EPT] walk failed"); + panic_full("EPT-E04 EPT WALK FAILED", "ept_walk could not allocate intermediate page tables", 0); return -3; } *entry = ept_make_leaf(cur_hpa, flags, EPT_MEMORY_TYPE_WB); diff --git a/CODE/UTSM/vmm/ept.d b/CODE/UTSM/vmm/ept.d new file mode 100644 index 0000000..8a406c2 --- /dev/null +++ b/CODE/UTSM/vmm/ept.d @@ -0,0 +1,10 @@ +vmm/ept.o: vmm\ept.c include\utsm\ept.h include\utsm\types.h \ + include\utsm\panic.h include\utsm\vmx.h include\utsm\log.h \ + include\utsm\dma.h vmm\..\arch\x86_64\limine.h +include\utsm\ept.h: +include\utsm\types.h: +include\utsm\panic.h: +include\utsm\vmx.h: +include\utsm\log.h: +include\utsm\dma.h: +vmm\..\arch\x86_64\limine.h: diff --git a/CODE/UTSM/vmm/ipc_shm.c b/CODE/UTSM/vmm/ipc_shm.c index 6198c03..1520430 100644 --- a/CODE/UTSM/vmm/ipc_shm.c +++ b/CODE/UTSM/vmm/ipc_shm.c @@ -14,6 +14,7 @@ */ #include +#include #include #include #include @@ -48,6 +49,7 @@ int ipc_shm_init(void) { u64 page_count = UTSM_IPC_SHM_SIZE / 4096; if (dma_alloc_pages(page_count, 4096, 0, &g_shm_buf) != 0) { log_error("[IPC] failed to alloc shared memory (1MB)"); + panic_full("IPC-E01 ALLOC SHARED MEMORY FAILED", "dma_alloc_pages failed for the 1mb ipc shared memory region", 0); return -1; } log_hex64("[IPC] shm HPA=", g_shm_buf.phys); @@ -84,6 +86,7 @@ int ipc_shm_init(void) { if (ept_map_range(LINUX_GUEST_IPC_SHM_GPA, g_shm_buf.phys, UTSM_IPC_SHM_SIZE, EPT_READ | EPT_WRITE) != 0) { log_error("[IPC] EPT map shared memory failed"); + panic_full("IPC-E02 EPT MAP SHARED MEMORY FAILED", "ept_map_range failed for the ipc shared memory region", 0); return -2; } log_hex64("[IPC] shm mapped GPA=", LINUX_GUEST_IPC_SHM_GPA); @@ -143,6 +146,7 @@ int ipc_shm_send(u32 msg_type, const void *data, u32 data_len) { /* Check if Linux is ready to receive */ if (!g_shm->header.linux_ready) { log_warn("[IPC] send: Linux not ready, dropping message"); + panic_full("IPC-E03 SEND WITH LINUX NOT READY", "message dropped because the linux side never became ready", 0); return -1; } @@ -169,6 +173,7 @@ int ipc_shm_send(u32 msg_type, const void *data, u32 data_len) { /* Enqueue into utsm_to_linux ring */ if (utsm_ipc_ring_push(&g_shm->utsm_to_linux, &msg) != 0) { log_warn("[IPC] send: ring full, dropping message"); + panic_full("IPC-E04 SEND RING FULL", "message dropped because the utsm to linux ring is full", 0); return -1; } diff --git a/CODE/UTSM/vmm/ipc_shm.d b/CODE/UTSM/vmm/ipc_shm.d new file mode 100644 index 0000000..13f162b --- /dev/null +++ b/CODE/UTSM/vmm/ipc_shm.d @@ -0,0 +1,14 @@ +vmm/ipc_shm.o: vmm\ipc_shm.c include\utsm\ipc_shm.h include\utsm\types.h \ + ..\utsm-ipc\ipc_proto.h include\utsm\panic.h include\utsm\vmx.h \ + include\utsm\ept.h include\utsm\log.h include\utsm\dma.h \ + include\utsm\linux_loader.h vmm\..\arch\x86_64\limine.h +include\utsm\ipc_shm.h: +include\utsm\types.h: +..\utsm-ipc\ipc_proto.h: +include\utsm\panic.h: +include\utsm\vmx.h: +include\utsm\ept.h: +include\utsm\log.h: +include\utsm\dma.h: +include\utsm\linux_loader.h: +vmm\..\arch\x86_64\limine.h: diff --git a/CODE/UTSM/vmm/linux_boot.c b/CODE/UTSM/vmm/linux_boot.c index c9f8c2d..67ce9d5 100644 --- a/CODE/UTSM/vmm/linux_boot.c +++ b/CODE/UTSM/vmm/linux_boot.c @@ -13,6 +13,7 @@ */ #include +#include #include #include #include @@ -440,11 +441,13 @@ int linux_launch(void) { const struct linux_guest_info *gi = linux_get_guest_info(); if (!gi || !gi->loaded) { log_error("[LINUX] guest not loaded"); + panic_full("LNX-E20 LINUX GUEST NOT LOADED", "linux_launch invoked before linux_loader_init loaded a guest", 0); return -1; } if (!vmm_is_ready()) { log_error("[LINUX] VMM not ready"); + panic_full("LNX-E21 VMM NOT READY", "linux_launch invoked before vmm_init succeeded", 0); return -2; } @@ -487,10 +490,12 @@ int linux_launch(void) { * 内容不受影响:VMCLEAR 只回写内存并改状态,VMPTRLD 再挂载。 */ if (vmx_vmcs_clear(vmm_get_vmcs_phys()) != 0) { log_error("[LINUX] vmclear failed"); + panic_full("LNX-E22 VMCLEAR FAILED", "vmclear failed on the linux guest vmcs before launch", 0); return -4; } if (vmx_vmcs_load(vmm_get_vmcs_phys()) != 0) { log_error("[LINUX] vmptrld after vmclear failed"); + panic_full("LNX-E23 VMPTRLD FAILED", "vmptrld failed after vmclear on the linux guest vmcs", 0); return -5; } @@ -621,6 +626,7 @@ int linux_launch(void) { } log_hex64("[LINUX] vmlaunch failed, error=", error); g_linux_guest_active = 0; + panic_full("LNX-E24 VMLAUNCH FAILED", "vmlaunch failed for the linux guest", 0); return -3; } @@ -632,6 +638,7 @@ int linux_launch(void) { log_hex64("[LINUX] vmexit count=", vmexit_get_count()); if (!g_guest_parked) { log_error("[LINUX] guest terminated before daemon park"); + panic_full("LNX-E25 GUEST TERMINATED BEFORE PARK", "linux guest terminated before the daemon parked", 0); return -6; } @@ -653,6 +660,7 @@ int linux_launch(void) { if (!got_ready) { g_guest_parked = 0; log_error("[LINUX] HLT without EXEC_READY handshake"); + panic_full("LNX-E26 HLT WITHOUT EXEC READY", "guest parked without the daemon publishing exec_ready", 0); return -7; } } diff --git a/CODE/UTSM/vmm/linux_boot.d b/CODE/UTSM/vmm/linux_boot.d new file mode 100644 index 0000000..f18b989 --- /dev/null +++ b/CODE/UTSM/vmm/linux_boot.d @@ -0,0 +1,17 @@ +vmm/linux_boot.o: vmm\linux_boot.c include\utsm\linux_loader.h \ + include\utsm\types.h include\utsm\panic.h include\utsm\linux_xsave.h \ + include\utsm\vmx.h include\utsm\ept.h include\utsm\vmm.h \ + include\utsm\virtio_mmio.h include\utsm\ipc_shm.h \ + ..\utsm-ipc\ipc_proto.h include\utsm\log.h vmm\..\arch\x86_64\limine.h +include\utsm\linux_loader.h: +include\utsm\types.h: +include\utsm\panic.h: +include\utsm\linux_xsave.h: +include\utsm\vmx.h: +include\utsm\ept.h: +include\utsm\vmm.h: +include\utsm\virtio_mmio.h: +include\utsm\ipc_shm.h: +..\utsm-ipc\ipc_proto.h: +include\utsm\log.h: +vmm\..\arch\x86_64\limine.h: diff --git a/CODE/UTSM/vmm/linux_compat.c b/CODE/UTSM/vmm/linux_compat.c index 6d48764..effd982 100644 --- a/CODE/UTSM/vmm/linux_compat.c +++ b/CODE/UTSM/vmm/linux_compat.c @@ -15,6 +15,7 @@ */ #include +#include #include #include /* VSCode Phase 5: linux_find_vscode_module */ #include @@ -196,6 +197,7 @@ static int lxc_exec_internal(const char *path, int argc, /* 2. 发送 EXEC_REQUEST */ if (ipc_shm_send(UTSM_MSG_EXEC_REQUEST, &req, sizeof(req)) != 0) { log_warn("[LNXC] exec: failed to enqueue request"); + panic_full("LNX-E10 EXEC ENQUEUE FAILED", "ipc_shm_send rejected the exec request", 0); return -2; } @@ -287,6 +289,7 @@ static int lxc_file_roundtrip(u32 msg_type, const char *path, u64 offset, if (ipc_shm_send(msg_type, &req, sizeof(req)) != 0) { log_warn("[LNXC] file: failed to enqueue request"); + panic_full("LNX-E11 FILE ENQUEUE FAILED", "ipc_shm_send rejected the file request", 0); return -2; } @@ -798,11 +801,13 @@ int lxc_sync_lib_dir(const char *guest_lib_path) { if (!guest_lib_path) return -1; if (!lxc_is_available()) { log_warn("[LNXC] sync_lib_dir: service not available"); + panic_full("LNX-E12 SYNC LIB SERVICE UNAVAILABLE", "lib sync invoked while the compat service is unavailable", 0); return -1; } int rc = lxc_f32_ensure(); if (rc != 0) { log_warn("[LNXC] sync_lib_dir: FAT32 not available"); + panic_full("LNX-E13 SYNC LIB FAT32 UNAVAILABLE", "lib sync invoked without a usable fat32 block device", 0); return rc; } @@ -811,6 +816,7 @@ int lxc_sync_lib_dir(const char *guest_lib_path) { if (f32_find_path_dir_lfn(g_compat_lib_path, &lib_clus) != 0) { log_warn("[LNXC] sync_lib_dir: lib dir not found:"); log_warn(g_compat_lib_path); + panic_full("LNX-E14 LIB DIR NOT FOUND", "fat32 lib directory for the guest is missing on the system disk", 0); return -2; /* 目录不存在(容忍:可能是首次启动未放库) */ } log_info("[LNXC] sync_lib_dir: lib dir found"); @@ -862,6 +868,7 @@ static int lxc_guest_path_exists(const char *path) { int lxc_vscode_install(void) { if (!lxc_is_available()) { log_warn("[LNXC] vscode install: service not available"); + panic_full("LNX-E15 VSCODE SERVICE UNAVAILABLE", "vscode install invoked while the compat service is unavailable", 0); return -1; } log_info("[LNXC] vscode: probe /opt/vscode/bin/code"); @@ -894,6 +901,7 @@ int lxc_vscode_install(void) { if (rc != 0 || written != chunk) { log_warn("[LNXC] vscode: tarball push failed"); log_hex64("[LNXC] vscode: push off=", off); + panic_full("LNX-E16 VSCODE TARBALL PUSH FAILED", "streaming the vscode tarball into the guest failed", 0); return -12; } off += written; @@ -910,6 +918,7 @@ int lxc_vscode_install(void) { int rc = lxc_exec("/bin/mkdir", 3, argv, 0, 0, 0, &ec); if (rc != 0 || ec != 0) { log_warn("[LNXC] vscode: mkdir /opt/vscode failed"); + panic_full("LNX-E17 VSCODE MKDIR FAILED", "mkdir -p /opt/vscode failed inside the guest", 0); return -13; } } @@ -956,12 +965,14 @@ int lxc_vscode_install(void) { if (!unpacked) { log_warn("[LNXC] vscode: extract failed"); + panic_full("LNX-E18 VSCODE EXTRACT FAILED", "tar extraction of the vscode tarball failed in the guest", 0); return -13; } /* 7. 验证:/opt/vscode/bin/code 存在即可启动 */ if (!lxc_guest_path_exists("/opt/vscode/bin/code")) { log_warn("[LNXC] vscode: verify failed (bin/code missing)"); + panic_full("LNX-E19 VSCODE VERIFY FAILED", "/opt/vscode/bin/code missing after the install", 0); return -14; } diff --git a/CODE/UTSM/vmm/linux_compat.d b/CODE/UTSM/vmm/linux_compat.d new file mode 100644 index 0000000..ee4fad1 --- /dev/null +++ b/CODE/UTSM/vmm/linux_compat.d @@ -0,0 +1,20 @@ +vmm/linux_compat.o: vmm\linux_compat.c include\utsm\linux_compat.h \ + include\utsm\types.h include\utsm\panic.h include\utsm\linux_resume.h \ + include\utsm\linux_loader.h include\utsm\ipc_shm.h \ + ..\utsm-ipc\ipc_proto.h include\utsm\vmm.h include\utsm\virtio_mmio.h \ + include\utsm\log.h include\utsm\block.h vmm\..\..\tools\fat32_io.h \ + vmm\..\..\tools\fat32_lfn.h vmm\..\..\tools\fat32_part.h +include\utsm\linux_compat.h: +include\utsm\types.h: +include\utsm\panic.h: +include\utsm\linux_resume.h: +include\utsm\linux_loader.h: +include\utsm\ipc_shm.h: +..\utsm-ipc\ipc_proto.h: +include\utsm\vmm.h: +include\utsm\virtio_mmio.h: +include\utsm\log.h: +include\utsm\block.h: +vmm\..\..\tools\fat32_io.h: +vmm\..\..\tools\fat32_lfn.h: +vmm\..\..\tools\fat32_part.h: diff --git a/CODE/UTSM/vmm/linux_loader.c b/CODE/UTSM/vmm/linux_loader.c index 73fd2b9..3677a9a 100644 --- a/CODE/UTSM/vmm/linux_loader.c +++ b/CODE/UTSM/vmm/linux_loader.c @@ -14,6 +14,7 @@ */ #include +#include #include #include #include @@ -472,6 +473,7 @@ int linux_parse_bzimage(const void *bzimage, u64 size, if (size < 0x300) { log_error("[LINUX] bzImage too small"); + panic_full("LIN-E01 BZIMAGE TOO SMALL", "bzImage smaller than the real-mode setup header", 0); return -1; } @@ -494,6 +496,7 @@ int linux_parse_bzimage(const void *bzimage, u64 size, log_hex64("[LINUX] boot protocol version=", version); if (version < 0x020c) { log_error("[LINUX] boot protocol too old"); + panic_full("LIN-E02 BOOT PROTOCOL TOO OLD", "bzImage boot protocol older than 2.12", 0); return -4; } @@ -502,6 +505,7 @@ int linux_parse_bzimage(const void *bzimage, u64 size, log_hex64("[LINUX] xloadflags=", xloadflags); if (!(xloadflags & XLF_KERNEL_64)) { log_error("[LINUX] not a 64-bit kernel"); + panic_full("LIN-E03 NOT A 64-BIT KERNEL", "bzImage xloadflags lacks the 64-bit kernel flag", 0); return -5; } @@ -514,6 +518,7 @@ int linux_parse_bzimage(const void *bzimage, u64 size, u64 setup_size = ((u64)setup_sects + 1) * 512; if (setup_size >= size) { log_error("[LINUX] setup sectors exceed bzImage"); + panic_full("LIN-E04 SETUP SECTORS EXCEED BZIMAGE", "setup sector count extends beyond the bzImage size", 0); return -6; } @@ -523,6 +528,7 @@ int linux_parse_bzimage(const void *bzimage, u64 size, if (payload_file_offset > size || payload_length > size - payload_file_offset) { log_error("[LINUX] compressed payload exceeds bzImage"); + panic_full("LIN-E05 PAYLOAD EXCEEDS BZIMAGE", "compressed payload extends beyond the bzImage size", 0); return -7; } log_hex64("[LINUX] payload_offset(in protected image)=", payload_offset); @@ -642,6 +648,7 @@ int linux_loader_init(void) { &kernel_offset, &kernel_length, &init_size, &entry_offset) != 0) { log_error("[LINUX] bzImage parse failed"); + panic_full("LIN-E06 BZIMAGE PARSE FAILED", "linux_parse_bzimage rejected the bzImage header", 0); return -2; } @@ -653,6 +660,7 @@ int linux_loader_init(void) { dkm_dma_buffer kernel_buf; if (dma_alloc_pages(kernel_alloc_size / 4096, 2 * 1024 * 1024, 0, &kernel_buf) != 0) { log_error("[LINUX] failed to alloc kernel memory"); + panic_full("LIN-E07 ALLOC KERNEL MEMORY FAILED", "dma_alloc_pages failed for the guest kernel image", 0); return -3; } log_hex64("[LINUX] kernel HPA=", kernel_buf.phys); @@ -662,6 +670,7 @@ int linux_loader_init(void) { dkm_dma_buffer bp_buf; if (dma_alloc_pages(1, 4096, 0, &bp_buf) != 0) { log_error("[LINUX] failed to alloc boot_params"); + panic_full("LIN-E08 ALLOC BOOT PARAMS FAILED", "dma_alloc_pages failed for boot_params", 0); return -4; } @@ -669,6 +678,7 @@ int linux_loader_init(void) { dkm_dma_buffer pgt_buf; if (dma_alloc_pages(PGT_TOTAL_PAGES, 4096, 0, &pgt_buf) != 0) { log_error("[LINUX] failed to alloc page tables"); + panic_full("LIN-E09 ALLOC PAGE TABLES FAILED", "dma_alloc_pages failed for guest page tables", 0); return -5; } @@ -676,6 +686,7 @@ int linux_loader_init(void) { dkm_dma_buffer gdt_buf; if (dma_alloc_pages(1, 4096, 0, &gdt_buf) != 0) { log_error("[LINUX] failed to alloc GDT"); + panic_full("LIN-E10 ALLOC GDT FAILED", "dma_alloc_pages failed for the guest gdt", 0); return -6; } @@ -683,6 +694,7 @@ int linux_loader_init(void) { dkm_dma_buffer stack_buf; if (dma_alloc_pages(1, 4096, 0, &stack_buf) != 0) { log_error("[LINUX] failed to alloc stack"); + panic_full("LIN-E11 ALLOC STACK FAILED", "dma_alloc_pages failed for the guest boot stack", 0); return -7; } @@ -690,6 +702,7 @@ int linux_loader_init(void) { dkm_dma_buffer cmdline_buf; if (dma_alloc_pages(1, 4096, 0, &cmdline_buf) != 0) { log_error("[LINUX] failed to alloc cmdline"); + panic_full("LIN-E12 ALLOC CMDLINE FAILED", "dma_alloc_pages failed for the kernel command line", 0); return -8; } @@ -708,6 +721,7 @@ int linux_loader_init(void) { ram_size = 512 * 1024 * 1024; /* 512MB floor for Phase 3 MVP */ if (dma_alloc_pages(ram_size / 4096, 2 * 1024 * 1024, 0, &ram_buf) != 0) { log_error("[LINUX] failed to alloc guest RAM (512MB minimum)"); + panic_full("LIN-E13 ALLOC GUEST RAM MINIMUM FAILED", "dma_alloc_pages failed even for the 512mb guest ram floor", 0); return -9; } } @@ -759,12 +773,14 @@ int linux_loader_init(void) { dkm_dma_buffer initrd_buf; if (dma_alloc_pages(initrd_pages, 4096, 0, &initrd_buf) != 0) { log_error("[LINUX] failed to alloc initrd memory"); + panic_full("LIN-E14 ALLOC INITRD MEMORY FAILED", "dma_alloc_pages failed for the initrd image", 0); return -17; } mem_copy(initrd_buf.virt, initrd, initrd_size); if (ept_map_range(LINUX_GUEST_INITRD_GPA, initrd_buf.phys, initrd_pages * 4096, EPT_READ | EPT_WRITE) != 0) { log_error("[LINUX] EPT map initrd failed"); + panic_full("LIN-E15 EPT MAP INITRD FAILED", "ept_map_range failed for the initrd image", 0); return -18; } g_guest.initrd_gpa = LINUX_GUEST_INITRD_GPA; @@ -790,6 +806,7 @@ int linux_loader_init(void) { if (ept_map_range(g_guest.kernel_gpa, kernel_buf.phys, kernel_alloc_size, EPT_RWX) != 0) { log_error("[LINUX] EPT map kernel failed"); + panic_full("LIN-E16 EPT MAP KERNEL FAILED", "ept_map_range failed for the guest kernel image", 0); return -10; } @@ -797,6 +814,7 @@ int linux_loader_init(void) { if (ept_map_range(g_guest.bootparams_gpa, bp_buf.phys, 4096, EPT_READ | EPT_WRITE) != 0) { log_error("[LINUX] EPT map boot_params failed"); + panic_full("LIN-E17 EPT MAP BOOT PARAMS FAILED", "ept_map_range failed for boot_params", 0); return -11; } @@ -804,6 +822,7 @@ int linux_loader_init(void) { if (ept_map_range(g_guest.pgt_gpa, pgt_buf.phys, PGT_TOTAL_SIZE, EPT_READ | EPT_WRITE) != 0) { log_error("[LINUX] EPT map page tables failed"); + panic_full("LIN-E18 EPT MAP PAGE TABLES FAILED", "ept_map_range failed for guest page tables", 0); return -12; } @@ -811,6 +830,7 @@ int linux_loader_init(void) { if (ept_map_range(g_guest.gdt_gpa, gdt_buf.phys, 4096, EPT_READ | EPT_WRITE) != 0) { log_error("[LINUX] EPT map GDT failed"); + panic_full("LIN-E19 EPT MAP GDT FAILED", "ept_map_range failed for the guest gdt", 0); return -13; } @@ -818,6 +838,7 @@ int linux_loader_init(void) { if (ept_map_range(LINUX_GUEST_STACK_GPA, stack_buf.phys, 4096, EPT_READ | EPT_WRITE) != 0) { log_error("[LINUX] EPT map stack failed"); + panic_full("LIN-E20 EPT MAP STACK FAILED", "ept_map_range failed for the guest boot stack", 0); return -14; } @@ -825,6 +846,7 @@ int linux_loader_init(void) { if (ept_map_range(g_guest.cmdline_gpa, cmdline_buf.phys, 4096, EPT_READ) != 0) { log_error("[LINUX] EPT map cmdline failed"); + panic_full("LIN-E21 EPT MAP CMDLINE FAILED", "ept_map_range failed for the kernel command line", 0); return -15; } @@ -840,6 +862,7 @@ int linux_loader_init(void) { u64 ram_gpa = LINUX_GUEST_RAM_GPA; if (ept_map_range(ram_gpa, ram_buf.phys, ram_size, EPT_RWX) != 0) { log_error("[LINUX] EPT map guest RAM failed"); + panic_full("LIN-E22 EPT MAP GUEST RAM FAILED", "ept_map_range failed for guest ram", 0); return -16; } log_hex64("[LINUX] guest RAM mapped GPA=", ram_gpa); @@ -890,10 +913,12 @@ int linux_loader_init(void) { dkm_dma_buffer hole; if (dma_alloc_pages(1, EPT_PAGE_SIZE, 0, &hole) != 0) { log_warn("[LINUX] low-RAM hole fill OOM"); + panic_full("LIN-E23 LOW RAM HOLE FILL OOM", "dma_alloc_pages failed while filling low ram ept holes", 0); break; } if (ept_map_range(gpa, hole.phys, EPT_PAGE_SIZE, EPT_RWX) != 0) { log_warn("[LINUX] low-RAM hole fill map failed"); + panic_full("LIN-E24 LOW RAM HOLE FILL MAP FAILED", "ept_map_range failed while filling low ram ept holes", 0); break; } filled++; diff --git a/CODE/UTSM/vmm/linux_loader.d b/CODE/UTSM/vmm/linux_loader.d new file mode 100644 index 0000000..58a3686 --- /dev/null +++ b/CODE/UTSM/vmm/linux_loader.d @@ -0,0 +1,12 @@ +vmm/linux_loader.o: vmm\linux_loader.c include\utsm\linux_loader.h \ + include\utsm\types.h include\utsm\panic.h include\utsm\vmx.h \ + include\utsm\ept.h include\utsm\log.h include\utsm\dma.h \ + vmm\..\arch\x86_64\limine.h +include\utsm\linux_loader.h: +include\utsm\types.h: +include\utsm\panic.h: +include\utsm\vmx.h: +include\utsm\ept.h: +include\utsm\log.h: +include\utsm\dma.h: +vmm\..\arch\x86_64\limine.h: diff --git a/CODE/UTSM/vmm/virtio_blk.c b/CODE/UTSM/vmm/virtio_blk.c index 1dd6178..23807ee 100644 --- a/CODE/UTSM/vmm/virtio_blk.c +++ b/CODE/UTSM/vmm/virtio_blk.c @@ -15,6 +15,7 @@ */ #include +#include #include #include #include @@ -690,6 +691,7 @@ static int xrootfs_map_esp_file(void) { if (nclus == 0 || nclus > XROOTFS_MAX_CLUSTERS) { log_error("[VBLK] extra-rootfs cluster map too large"); log_hex64("[VBLK] nclus=", nclus); + panic_full("VVB-E10 EXTRA ROOTFS CLUSTER MAP TOO LARGE", "extra rootfs image cluster count exceeds the static map limit", 0); return -7; } @@ -697,6 +699,7 @@ static int xrootfs_map_esp_file(void) { for (i = 0; i < nclus; i++) { if (fc_cur < 2 || fc_cur >= 0x0FFFFFF8u) { log_error("[VBLK] extra-rootfs FAT chain short"); + panic_full("VVB-E11 EXTRA ROOTFS FAT CHAIN SHORT", "fat chain of the extra rootfs image ended before covering the file", 0); return -8; } g_xrootfs_clus_lba[i] = (u32)vol + data_start + (fc_cur - 2u) * spc; diff --git a/CODE/UTSM/vmm/virtio_blk.d b/CODE/UTSM/vmm/virtio_blk.d index 9826b17..de9def7 100644 --- a/CODE/UTSM/vmm/virtio_blk.d +++ b/CODE/UTSM/vmm/virtio_blk.d @@ -1,9 +1,10 @@ vmm/virtio_blk.o: vmm\virtio_blk.c include\utsm\virtio_mmio.h \ - include\utsm\types.h include\utsm\linux_loader.h include\utsm\block.h \ - include\utsm\log.h vmm\..\..\tools\fat32_lfn.h \ + include\utsm\types.h include\utsm\panic.h include\utsm\linux_loader.h \ + include\utsm\block.h include\utsm\log.h vmm\..\..\tools\fat32_lfn.h \ vmm\..\..\tools\fat32_part.h include\utsm\virtio_mmio.h: include\utsm\types.h: +include\utsm\panic.h: include\utsm\linux_loader.h: include\utsm\block.h: include\utsm\log.h: diff --git a/CODE/UTSM/vmm/virtio_net.c b/CODE/UTSM/vmm/virtio_net.c index 7676186..cb11cc5 100644 --- a/CODE/UTSM/vmm/virtio_net.c +++ b/CODE/UTSM/vmm/virtio_net.c @@ -14,6 +14,7 @@ */ #include +#include #include #include #include diff --git a/CODE/UTSM/vmm/virtio_net.d b/CODE/UTSM/vmm/virtio_net.d new file mode 100644 index 0000000..42db745 --- /dev/null +++ b/CODE/UTSM/vmm/virtio_net.d @@ -0,0 +1,9 @@ +vmm/virtio_net.o: vmm\virtio_net.c include\utsm\virtio_mmio.h \ + include\utsm\types.h include\utsm\panic.h include\utsm\linux_loader.h \ + include\utsm\net.h include\utsm\log.h +include\utsm\virtio_mmio.h: +include\utsm\types.h: +include\utsm\panic.h: +include\utsm\linux_loader.h: +include\utsm\net.h: +include\utsm\log.h: diff --git a/CODE/UTSM/vmm/vmexit.c b/CODE/UTSM/vmm/vmexit.c index b1fa03e..ec45423 100644 --- a/CODE/UTSM/vmm/vmexit.c +++ b/CODE/UTSM/vmm/vmexit.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -98,10 +99,12 @@ static int ept_map_guest_ram_page(u64 gpa_page) { dkm_dma_buffer buf; if (dma_alloc_pages(1, EPT_PAGE_SIZE, 0, &buf) != 0) { log_error("[VMEXIT] OOM for guest RAM page"); + panic_full("VMX-E10 OOM FOR GUEST RAM PAGE", "dma_alloc_pages failed for a demand mapped guest ram page", 0); return -1; } if (ept_map_range(gpa_page, buf.phys, EPT_PAGE_SIZE, EPT_RWX) != 0) { log_error("[VMEXIT] EPT map guest RAM page failed"); + panic_full("VMX-E11 EPT MAP GUEST RAM PAGE FAILED", "ept_map_range failed for a demand mapped guest ram page", 0); return -1; } return 0; @@ -1091,6 +1094,7 @@ static int handle_virtio_mmio_access(u64 gpa, u64 rip, int *out_resume) { log_error("[VMEXIT] virtio-mmio: cannot decode access insn"); log_hex64("[VMEXIT] rip=", rip); *out_resume = 0; + panic_full("VMX-E12 CANNOT DECODE VIRTIO MMIO INSN", "instruction fetch or decode failed for a virtio mmio access", 0); return -1; } @@ -1146,6 +1150,7 @@ static int handle_ept_violation(u64 qualification, u64 rip, int *out_resume) { log_error("[VMEXIT] EPT upgrade existing page failed"); log_hex64("[VMEXIT] gpa=", gpa); *out_resume = 0; + panic_full("VMX-E13 EPT UPGRADE EXISTING PAGE FAILED", "ept_map_range failed while upgrading an existing ept leaf", 0); return -1; } ept_flush_ept(); @@ -1161,6 +1166,7 @@ static int handle_ept_violation(u64 qualification, u64 rip, int *out_resume) { log_error("[VMEXIT] EPT violation: guest RAM map failed"); log_hex64("[VMEXIT] gpa=", gpa); *out_resume = 0; + panic_full("VMX-E14 EPT VIOLATION GUEST RAM MAP FAILED", "demand mapping a guest ram page on ept violation failed", 0); return -1; } *out_resume = 1; @@ -1322,6 +1328,7 @@ static int handle_exception(u64 qualification, u64 rip, int *out_resume) { log_hex64("[VMEXIT] df idtr=", vmx_vmcs_read(VMCS_GUEST_IDTR_BASE)); log_hex64("[VMEXIT] df idtl=", vmx_vmcs_read(VMCS_GUEST_IDTR_LIMIT)); *out_resume = 0; + panic_full("VMX-E15 GUEST DOUBLE FAULT", "guest took a double fault which will not be reinjected", 0); return 0; } if (g_linux_guest_active) { @@ -1461,6 +1468,7 @@ int vmexit_dispatch(void) { if (ept_map_guest_ram_page(page) != 0) { log_error("[VMEXIT] EPT misconfig repair failed"); resume = 0; + panic_full("VMX-E16 EPT MISCONFIG REPAIR FAILED", "both ept_repair_leaf and a fresh page alloc failed on ept misconfig", 0); break; } if (misconfig_logs <= 16) @@ -1484,6 +1492,7 @@ int vmexit_dispatch(void) { log_hex64("[VMEXIT] triple idtr=", vmx_vmcs_read(VMCS_GUEST_IDTR_BASE)); log_hex64("[VMEXIT] triple idtl=", vmx_vmcs_read(VMCS_GUEST_IDTR_LIMIT)); resume = 0; + panic_full("VMX-E17 GUEST TRIPLE FAULT", "guest cpu entered a triple fault", 0); break; case EXIT_EXTERNAL_INTERRUPT: INSTR_STAT_INC(ext_irq); diff --git a/CODE/UTSM/vmm/vmexit.d b/CODE/UTSM/vmm/vmexit.d new file mode 100644 index 0000000..9557df0 --- /dev/null +++ b/CODE/UTSM/vmm/vmexit.d @@ -0,0 +1,22 @@ +vmm/vmexit.o: vmm\vmexit.c include\utsm\vmx.h include\utsm\types.h \ + include\utsm\panic.h include\utsm\ept.h include\utsm\vmm.h \ + include\utsm\hypercall.h include\utsm\ipc_shm.h \ + ..\utsm-ipc\ipc_proto.h include\utsm\log.h include\utsm\dma.h \ + include\utsm\linux_loader.h include\utsm\linux_xsave.h \ + include\utsm\virtio_mmio.h include\utsm\instr.h \ + vmm\..\arch\x86_64\limine.h +include\utsm\vmx.h: +include\utsm\types.h: +include\utsm\panic.h: +include\utsm\ept.h: +include\utsm\vmm.h: +include\utsm\hypercall.h: +include\utsm\ipc_shm.h: +..\utsm-ipc\ipc_proto.h: +include\utsm\log.h: +include\utsm\dma.h: +include\utsm\linux_loader.h: +include\utsm\linux_xsave.h: +include\utsm\virtio_mmio.h: +include\utsm\instr.h: +vmm\..\arch\x86_64\limine.h: diff --git a/CODE/UTSM/vmm/vmm.c b/CODE/UTSM/vmm/vmm.c index c398774..608161c 100644 --- a/CODE/UTSM/vmm/vmm.c +++ b/CODE/UTSM/vmm/vmm.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -412,23 +413,28 @@ int vmm_init(void) { log_info("[VMM] init begin"); if (vmx_enable() != 0) { - log_error("[VMM] VMX enable failed"); + /* 【插桩白名单】设计内环境探测:WHPX/无嵌套 VMX 等 VMX 不可用属 + * CLAUDE.md §3 白名单"VMX/bzImage/kernel.krl 未配置跳过"。 */ + log_error("[VMM] VMX enable failed (environment probe, skipping)"); return -1; } if (ept_init() != 0) { - log_error("[VMM] EPT init failed"); + /* 【插桩白名单】同上:EPT 不可用走 shadow paging 回退,由外层门跳过 guest 段。 */ + log_error("[VMM] EPT init failed (environment probe, skipping)"); return -2; } if (vmx_vmcs_alloc(&g_vmcs_phys) != 0) { - log_error("[VMM] VMCS alloc failed"); + /* 【插桩白名单】同上:init 期资源探测失败,非运行期语义错误。 */ + log_error("[VMM] VMCS alloc failed (environment probe, skipping)"); return -3; } log_hex64("[VMM] VMCS phys=", g_vmcs_phys); if (vmx_vmcs_load(g_vmcs_phys) != 0) { - log_error("[VMM] VMCS load failed"); + /* 【插桩白名单】同上。 */ + log_error("[VMM] VMCS load failed (environment probe, skipping)"); return -4; } @@ -436,7 +442,8 @@ int vmm_init(void) { vmx_vmcs_write(VMCS_VPID, 0x1234); u64 vpid_readback = vmx_vmcs_read(VMCS_VPID); if (vpid_readback != 0x1234) { - log_error("[VMM] VMCS read/write verify failed"); + /* 【插桩白名单】同上:init 期硬件回读探测,异常环境交外层门跳过。 */ + log_error("[VMM] VMCS read/write verify failed (environment probe, skipping)"); log_hex64("[VMM] wrote=0x1234 read=", vpid_readback); return -5; } @@ -550,6 +557,7 @@ static void vmm_dump_guest_state(void) { int vmm_self_test(void) { if (!g_vmm_ready) { log_error("[VMM] not ready"); + panic_full("VMM-E15 VMM NOT READY", "self test invoked before vmm_init succeeded", 0); return -1; } @@ -573,18 +581,22 @@ int vmm_self_test(void) { if (ept_map_range(0x1000, guest_code_phys, 4096, EPT_RWX) != 0) { log_error("[VMM] map guest code failed"); + panic_full("VMM-E16 MAP GUEST CODE FAILED", "ept_map_range failed for the self test code page", 0); return -3; } if (ept_map_range(0x8000, guest_stack_phys, 4096, EPT_RWX) != 0) { log_error("[VMM] map guest stack failed"); + panic_full("VMM-E17 MAP GUEST STACK FAILED", "ept_map_range failed for the self test stack page", 0); return -4; } if (ept_map_range(0x3000, guest_gdt_phys, 4096, EPT_READ | EPT_WRITE) != 0) { log_error("[VMM] map guest GDT failed"); + panic_full("VMM-E18 MAP GUEST GDT FAILED", "ept_map_range failed for the self test gdt page", 0); return -5; } if (ept_map_range(0x4000, guest_tss_phys, 4096, EPT_READ | EPT_WRITE) != 0) { log_error("[VMM] map guest TSS failed"); + panic_full("VMM-E19 MAP GUEST TSS FAILED", "ept_map_range failed for the self test tss page", 0); return -6; } /* P8.4: Map IDT page for KVM nested VMX (IDTR base = 0x5000) */ @@ -593,6 +605,7 @@ int vmm_self_test(void) { for (int i = 0; i < 4096; i++) g_guest_idt[i] = 0; if (ept_map_range(0x5000, guest_idt_phys, 4096, EPT_READ | EPT_WRITE) != 0) { log_error("[VMM] map guest IDT failed"); + panic_full("VMM-E20 MAP GUEST IDT FAILED", "ept_map_range failed for the self test idt page", 0); return -9; } } @@ -616,6 +629,7 @@ int vmm_self_test(void) { ept_map_range(0x7000, pdpt_phys, 4096, EPT_READ | EPT_WRITE) != 0 || ept_map_range(0x9000, pd_phys, 4096, EPT_READ | EPT_WRITE) != 0) { log_error("[VMM] map guest page tables failed"); + panic_full("VMM-E21 MAP GUEST PAGE TABLES FAILED", "ept_map_range failed for the self test page tables", 0); return -12; } } @@ -629,10 +643,12 @@ int vmm_self_test(void) { * Without this, VMLAUNCH fails (error 4 or silent failure under KVM). */ if (vmx_vmcs_clear(g_vmcs_phys) != 0) { log_error("[VMM] vmclear failed"); + panic_full("VMM-E22 VMCLEAR FAILED", "vmclear failed on the self test vmcs", 0); return -10; } if (vmx_vmcs_load(g_vmcs_phys) != 0) { log_error("[VMM] vmptrld after vmclear failed"); + panic_full("VMM-E23 VMPTRLD FAILED", "vmptrld failed after vmclear on the self test vmcs", 0); return -11; } @@ -725,6 +741,7 @@ int vmm_self_test(void) { log_hex64("[VMM] CR4 missing(need)=", cr4_missing); log_hex64("[VMM] CR4 extra(forbid)=", cr4_extra); } + panic_full("VMM-E24 VMLAUNCH FAILED", "vmlaunch failed during the self test launch", 0); return -7; } @@ -735,6 +752,7 @@ int vmm_self_test(void) { if (g_last_exit_reason != EXIT_HLT) { log_warn("[VMM] expected HLT exit"); + panic_full("VMM-E25 UNEXPECTED EXIT REASON", "self test guest exited with a reason other than hlt", 0); return -8; } diff --git a/CODE/UTSM/vmm/vmm.d b/CODE/UTSM/vmm/vmm.d new file mode 100644 index 0000000..6480222 --- /dev/null +++ b/CODE/UTSM/vmm/vmm.d @@ -0,0 +1,11 @@ +vmm/vmm.o: vmm\vmm.c include\utsm\vmm.h include\utsm\types.h \ + include\utsm\panic.h include\utsm\vmx.h include\utsm\ept.h \ + include\utsm\log.h include\utsm\dma.h vmm\..\arch\x86_64\limine.h +include\utsm\vmm.h: +include\utsm\types.h: +include\utsm\panic.h: +include\utsm\vmx.h: +include\utsm\ept.h: +include\utsm\log.h: +include\utsm\dma.h: +vmm\..\arch\x86_64\limine.h: diff --git a/CODE/UTSM/vmm/vmx.c b/CODE/UTSM/vmm/vmx.c index 97dd40c..786ddbb 100644 --- a/CODE/UTSM/vmm/vmx.c +++ b/CODE/UTSM/vmm/vmx.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -41,10 +42,12 @@ u64 vmx_kernel_virt_to_phys(const void *address) { if (!response) { log_error("[VMX] Limine kernel-address response missing"); + panic_full("VMX-E01 KERNEL ADDRESS RESPONSE MISSING", "limine did not return a kernel address response", 0); return 0; } if (virt < response->virtual_base) { log_error("[VMX] address is below kernel virtual base"); + panic_full("VMX-E02 ADDRESS BELOW KERNEL VIRTUAL BASE", "kernel virtual to physical conversion got an address below the kernel base", 0); return 0; } @@ -235,6 +238,7 @@ int vmx_enable(void) { dkm_dma_buffer vmxon_buf; if (dma_alloc_pages(1, EPT_PAGE_SIZE, 0x100000000ULL, &vmxon_buf) != 0) { log_error("[VMX] failed to alloc VMXON region"); + panic_full("VMX-E03 ALLOC VMXON REGION FAILED", "dma_alloc_pages failed for the vmxon region", 0); return -2; } g_vmxon_phys = vmxon_buf.phys; @@ -276,6 +280,7 @@ int vmx_enable(void) { /* 第二次尝试:读 vmx instruction error 通过 VMCS 不适用 vmxon; * 简化:返回失败。 */ log_error("[VMX] vmxon failed"); + panic_full("VMX-E04 VMXON FAILED", "the vmxon instruction failed to enter vmx root mode", 0); return -3; } @@ -301,6 +306,7 @@ int vmx_vmcs_alloc(u64 *phys_out) { dkm_dma_buffer buf; if (dma_alloc_pages(1, EPT_PAGE_SIZE, 0x100000000ULL, &buf) != 0) { log_error("[VMX] failed to alloc VMCS region"); + panic_full("VMX-E05 ALLOC VMCS REGION FAILED", "dma_alloc_pages failed for the vmcs region", 0); return -2; } /* 偏移 0 写入 VMCS revision ID */ @@ -328,6 +334,7 @@ int vmx_vmcs_load(u64 phys) { ); if (err) { log_error("[VMX] vmptrld failed"); + panic_full("VMX-E06 VMPTRLD FAILED", "the vmptrld instruction failed to load the vmcs", 0); return -1; } return 0; @@ -352,6 +359,7 @@ int vmx_vmcs_clear(u64 phys) { ); if (err) { log_error("[VMX] vmclear failed"); + panic_full("VMX-E07 VMCLEAR FAILED", "the vmclear instruction failed on the vmcs", 0); return -1; } return 0; diff --git a/CODE/UTSM/vmm/vmx.d b/CODE/UTSM/vmm/vmx.d new file mode 100644 index 0000000..717a0bc --- /dev/null +++ b/CODE/UTSM/vmm/vmx.d @@ -0,0 +1,10 @@ +vmm/vmx.o: vmm\vmx.c include\utsm\vmx.h include\utsm\types.h \ + include\utsm\panic.h include\utsm\ept.h include\utsm\log.h \ + include\utsm\dma.h vmm\..\arch\x86_64\limine.h +include\utsm\vmx.h: +include\utsm\types.h: +include\utsm\panic.h: +include\utsm\ept.h: +include\utsm\log.h: +include\utsm\dma.h: +vmm\..\arch\x86_64\limine.h: diff --git a/CODE/UTSM/vmm/xj380_loader.c b/CODE/UTSM/vmm/xj380_loader.c index 645172e..1842736 100644 --- a/CODE/UTSM/vmm/xj380_loader.c +++ b/CODE/UTSM/vmm/xj380_loader.c @@ -15,6 +15,7 @@ */ #include +#include #include #include #include @@ -86,24 +87,29 @@ static int xj380_parse_elf(const void *img, u64 size, u64 *entry_out, u64 *span_out) { if (size < sizeof(xj_elf64_ehdr)) { log_error("[XJ380] kernel.krl too small"); + panic_full("XJ3-E01 KRL IMAGE TOO SMALL", "kernel.krl image smaller than an elf64 header", 0); return -1; } const xj_elf64_ehdr *eh = (const xj_elf64_ehdr *)img; if (*(u32 *)eh->e_ident != (u32)ELF_MAGIC) { log_error("[XJ380] bad ELF magic"); + panic_full("XJ3-E02 BAD ELF MAGIC", "kernel.krl elf magic mismatch", 0); return -2; } if (eh->e_ident[4] != 2) { /* ELFCLASS64 */ log_error("[XJ380] not a 64-bit ELF"); + panic_full("XJ3-E03 NOT A 64-BIT ELF", "kernel.krl is not a 64-bit elf image", 0); return -3; } if (eh->e_type != ELF_ET_EXEC) { log_error("[XJ380] kernel.krl not ET_EXEC"); + panic_full("XJ3-E04 KRL NOT ET_EXEC", "kernel.krl is not an ET_EXEC elf image", 0); return -4; } if (eh->e_phnum == 0 || eh->e_phentsize != sizeof(xj_elf64_phdr) || eh->e_phoff + (u64)eh->e_phnum * sizeof(xj_elf64_phdr) > size) { log_error("[XJ380] bad program header table"); + panic_full("XJ3-E05 BAD PROGRAM HEADER TABLE", "kernel.krl program header table is invalid", 0); return -5; } @@ -114,21 +120,25 @@ static int xj380_parse_elf(const void *img, u64 size, if (ph[i].p_vaddr < XJ380_KERNEL_VADDR) { log_error("[XJ380] PT_LOAD below kernel base"); log_hex64("[XJ380] vaddr=", ph[i].p_vaddr); + panic_full("XJ3-E06 PT_LOAD BELOW KERNEL BASE", "pt_load segment mapped below the xj380 kernel base", 0); return -6; } u64 off = ph[i].p_vaddr - XJ380_KERNEL_VADDR; if (off + ph[i].p_memsz > XJ380_GUEST_KERNEL_MAX) { log_error("[XJ380] kernel exceeds reserved window (32MB)"); + panic_full("XJ3-E07 KERNEL EXCEEDS RESERVED WINDOW", "kernel span exceeds the 32mb reserved window", 0); return -7; } if (ph[i].p_offset + ph[i].p_filesz > size) { log_error("[XJ380] PT_LOAD filesz beyond image"); + panic_full("XJ3-E08 PT_LOAD FILESZ BEYOND IMAGE", "pt_load file size extends beyond the kernel.krl image", 0); return -8; } if (off + ph[i].p_memsz > span) span = off + ph[i].p_memsz; } if (span == 0) { log_error("[XJ380] no PT_LOAD segments"); + panic_full("XJ3-E09 NO PT_LOAD SEGMENTS", "kernel.krl contains no pt_load segments", 0); return -9; } @@ -474,6 +484,7 @@ static int xj380_build_boot_config(u64 hpa, u64 mtrr_hpa, u64 stack_gpa, u64 fbc void *xj380_find_kernel_module(u64 *size_out) { if (!g_module_request.response) { log_error("[XJ380] no Limine module response"); + panic_full("XJ3-E10 NO LIMINE MODULE RESPONSE", "limine did not return a boot module response", 0); return (void *)0; } @@ -525,34 +536,37 @@ int xj380_loader_init(void) { u64 entry, span; if (xj380_parse_elf(krl, krl_size, &entry, &span) != 0) { log_error("[XJ380] kernel.krl parse failed"); + panic_full("XJ3-E11 KRL PARSE FAILED", "xj380_parse_elf rejected the kernel.krl image", 0); return -2; } if (entry < XJ380_KERNEL_VADDR || entry >= XJ380_KERNEL_VADDR + span) { log_error("[XJ380] entry outside kernel window"); + panic_full("XJ3-E12 ENTRY OUTSIDE KERNEL WINDOW", "kernel entry point lies outside the reserved kernel window", 0); return -3; } /* 3. 分配 boot area 缓冲(按页) */ dkm_dma_buffer pgt_buf, gdt_buf, madt_buf, fadt_buf, mcfg_buf, hpet_buf; dkm_dma_buffer memmap_buf, bootcfg_buf, mtrr_buf, stack_buf, fakeefi_buf, fbc_buf; - if (dma_alloc_pages(8, 4096, 0, &pgt_buf) != 0) { log_error("[XJ380] alloc pgt failed"); return -4; } - if (dma_alloc_pages(1, 4096, 0, &gdt_buf) != 0) { log_error("[XJ380] alloc gdt failed"); return -5; } - if (dma_alloc_pages(1, 4096, 0, &madt_buf) != 0) { log_error("[XJ380] alloc madt failed"); return -6; } - if (dma_alloc_pages(1, 4096, 0, &fadt_buf) != 0) { log_error("[XJ380] alloc fadt failed"); return -7; } - if (dma_alloc_pages(1, 4096, 0, &mcfg_buf) != 0) { log_error("[XJ380] alloc mcfg failed"); return -8; } - if (dma_alloc_pages(1, 4096, 0, &hpet_buf) != 0) { log_error("[XJ380] alloc hpet failed"); return -9; } - if (dma_alloc_pages(1, 4096, 0, &memmap_buf) != 0) { log_error("[XJ380] alloc memmap failed"); return -10; } - if (dma_alloc_pages(1, 4096, 0, &bootcfg_buf) != 0) { log_error("[XJ380] alloc bootcfg failed"); return -11; } - if (dma_alloc_pages(1, 4096, 0, &mtrr_buf) != 0) { log_error("[XJ380] alloc mtrr failed"); return -12; } - if (dma_alloc_pages(2, 4096, 0, &stack_buf) != 0) { log_error("[XJ380] alloc stack failed"); return -13; } - if (dma_alloc_pages(1, 4096, 0, &fakeefi_buf) != 0) { log_error("[XJ380] alloc fake efi failed"); return -14; } - if (dma_alloc_pages(1, 4096, 0, &fbc_buf) != 0) { log_error("[XJ380] alloc fbc failed"); return -15; } + if (dma_alloc_pages(8, 4096, 0, &pgt_buf) != 0) { log_error("[XJ380] alloc pgt failed"); panic_full("XJ3-E13 ALLOC PGT FAILED", "dma_alloc_pages failed for guest page tables", 0); return -4; } + if (dma_alloc_pages(1, 4096, 0, &gdt_buf) != 0) { log_error("[XJ380] alloc gdt failed"); panic_full("XJ3-E14 ALLOC GDT FAILED", "dma_alloc_pages failed for the guest gdt page", 0); return -5; } + if (dma_alloc_pages(1, 4096, 0, &madt_buf) != 0) { log_error("[XJ380] alloc madt failed"); panic_full("XJ3-E15 ALLOC MADT FAILED", "dma_alloc_pages failed for the madt stub", 0); return -6; } + if (dma_alloc_pages(1, 4096, 0, &fadt_buf) != 0) { log_error("[XJ380] alloc fadt failed"); panic_full("XJ3-E16 ALLOC FADT FAILED", "dma_alloc_pages failed for the fadt stub", 0); return -7; } + if (dma_alloc_pages(1, 4096, 0, &mcfg_buf) != 0) { log_error("[XJ380] alloc mcfg failed"); panic_full("XJ3-E17 ALLOC MCFG FAILED", "dma_alloc_pages failed for the mcfg stub", 0); return -8; } + if (dma_alloc_pages(1, 4096, 0, &hpet_buf) != 0) { log_error("[XJ380] alloc hpet failed"); panic_full("XJ3-E18 ALLOC HPET FAILED", "dma_alloc_pages failed for the hpet stub", 0); return -9; } + if (dma_alloc_pages(1, 4096, 0, &memmap_buf) != 0) { log_error("[XJ380] alloc memmap failed"); panic_full("XJ3-E19 ALLOC MEMMAP FAILED", "dma_alloc_pages failed for the efi memmap page", 0); return -10; } + if (dma_alloc_pages(1, 4096, 0, &bootcfg_buf) != 0) { log_error("[XJ380] alloc bootcfg failed"); panic_full("XJ3-E20 ALLOC BOOTCFG FAILED", "dma_alloc_pages failed for the boot_config page", 0); return -11; } + if (dma_alloc_pages(1, 4096, 0, &mtrr_buf) != 0) { log_error("[XJ380] alloc mtrr failed"); panic_full("XJ3-E21 ALLOC MTRR FAILED", "dma_alloc_pages failed for the mtrr buffer", 0); return -12; } + if (dma_alloc_pages(2, 4096, 0, &stack_buf) != 0) { log_error("[XJ380] alloc stack failed"); panic_full("XJ3-E22 ALLOC STACK FAILED", "dma_alloc_pages failed for the guest boot stack", 0); return -13; } + if (dma_alloc_pages(1, 4096, 0, &fakeefi_buf) != 0) { log_error("[XJ380] alloc fake efi failed"); panic_full("XJ3-E23 ALLOC FAKE EFI FAILED", "dma_alloc_pages failed for the fake efi table", 0); return -14; } + if (dma_alloc_pages(1, 4096, 0, &fbc_buf) != 0) { log_error("[XJ380] alloc fbc failed"); panic_full("XJ3-E24 ALLOC FBC FAILED", "dma_alloc_pages failed for the framebuffer config page", 0); return -15; } /* 4. 分配内核缓冲并装入 PT_LOAD 段 */ u64 kernel_alloc = (span + 4095) & ~4095ULL; dkm_dma_buffer kernel_buf; if (dma_alloc_pages(kernel_alloc / 4096, 2 * 1024 * 1024, 0, &kernel_buf) != 0) { log_error("[XJ380] failed to alloc kernel memory"); + panic_full("XJ3-E25 ALLOC KERNEL MEMORY FAILED", "dma_alloc_pages failed for the loaded kernel image", 0); return -16; } { @@ -573,6 +587,7 @@ int xj380_loader_init(void) { dkm_dma_buffer fb_buf; if (dma_alloc_pages((XJ380_FB_SIZE + 4095) / 4096, 4096, 0, &fb_buf) != 0) { log_error("[XJ380] failed to alloc framebuffer"); + panic_full("XJ3-E26 ALLOC FRAMEBUFFER FAILED", "dma_alloc_pages failed for the guest framebuffer", 0); return -17; } { @@ -591,6 +606,7 @@ int xj380_loader_init(void) { ram_size = XJ380_GUEST_RAM_MIN; if (dma_alloc_pages(ram_size / 4096, 2 * 1024 * 1024, 0, &ram_buf) != 0) { log_error("[XJ380] failed to alloc guest RAM (256MB minimum)"); + panic_full("XJ3-E27 ALLOC GUEST RAM MINIMUM FAILED", "dma_alloc_pages failed even for the 256mb guest ram floor", 0); return -18; } } @@ -630,65 +646,80 @@ int xj380_loader_init(void) { * boot area 各缓冲独立分配,逐个按自身 GPA 映射。 */ if (ept_map_range(XJ380_PGT_GPA, pgt_buf.phys, XJ380_PGT_SIZE, EPT_READ | EPT_WRITE) != 0) { log_error("[XJ380] EPT map page tables failed"); + panic_full("XJ3-E28 EPT MAP PAGE TABLES FAILED", "ept_map_range failed for guest page tables", 0); return -19; } if (ept_map_range(XJ380_GDT_GPA, gdt_buf.phys, 4096, EPT_READ | EPT_WRITE) != 0) { log_error("[XJ380] EPT map GDT failed"); + panic_full("XJ3-E29 EPT MAP GDT FAILED", "ept_map_range failed for the guest gdt", 0); return -20; } if (ept_map_range(XJ380_MADT_GPA, madt_buf.phys, 4096, EPT_READ | EPT_WRITE) != 0) { log_error("[XJ380] EPT map MADT failed"); + panic_full("XJ3-E30 EPT MAP MADT FAILED", "ept_map_range failed for the madt stub", 0); return -21; } if (ept_map_range(XJ380_FADT_GPA, fadt_buf.phys, 4096, EPT_READ | EPT_WRITE) != 0) { log_error("[XJ380] EPT map FADT failed"); + panic_full("XJ3-E31 EPT MAP FADT FAILED", "ept_map_range failed for the fadt stub", 0); return -22; } if (ept_map_range(XJ380_MCFG_GPA, mcfg_buf.phys, 4096, EPT_READ | EPT_WRITE) != 0) { log_error("[XJ380] EPT map MCFG failed"); + panic_full("XJ3-E32 EPT MAP MCFG FAILED", "ept_map_range failed for the mcfg stub", 0); return -23; } if (ept_map_range(XJ380_HPET_GPA, hpet_buf.phys, 4096, EPT_READ | EPT_WRITE) != 0) { log_error("[XJ380] EPT map HPET failed"); + panic_full("XJ3-E33 EPT MAP HPET FAILED", "ept_map_range failed for the hpet stub", 0); return -24; } if (ept_map_range(XJ380_MEMMAP_GPA, memmap_buf.phys, 4096, EPT_READ | EPT_WRITE) != 0) { log_error("[XJ380] EPT map memory map failed"); + panic_full("XJ3-E34 EPT MAP MEMMAP FAILED", "ept_map_range failed for the efi memmap", 0); return -25; } if (ept_map_range(XJ380_BOOTCFG_GPA, bootcfg_buf.phys, 4096, EPT_READ | EPT_WRITE) != 0) { log_error("[XJ380] EPT map BOOT_CONFIG failed"); + panic_full("XJ3-E35 EPT MAP BOOT CONFIG FAILED", "ept_map_range failed for the boot_config page", 0); return -26; } if (ept_map_range(XJ380_MTRR_GPA, mtrr_buf.phys, 4096, EPT_READ | EPT_WRITE) != 0) { log_error("[XJ380] EPT map MTRR buffer failed"); + panic_full("XJ3-E36 EPT MAP MTRR BUFFER FAILED", "ept_map_range failed for the mtrr buffer", 0); return -27; } if (ept_map_range(XJ380_STACK_GPA, stack_buf.phys, 8192, EPT_READ | EPT_WRITE) != 0) { log_error("[XJ380] EPT map stack failed"); + panic_full("XJ3-E37 EPT MAP STACK FAILED", "ept_map_range failed for the guest boot stack", 0); return -28; } if (ept_map_range(XJ380_FAKEEFI_GPA, fakeefi_buf.phys, 4096, EPT_READ | EPT_WRITE) != 0) { log_error("[XJ380] EPT map fake EFI table failed"); + panic_full("XJ3-E38 EPT MAP FAKE EFI FAILED", "ept_map_range failed for the fake efi table", 0); return -29; } if (ept_map_range(XJ380_FBC_GPA, fbc_buf.phys, 4096, EPT_READ | EPT_WRITE) != 0) { log_error("[XJ380] EPT map FrameBufferConfig failed"); + panic_full("XJ3-E39 EPT MAP FRAMEBUFFER CONFIG FAILED", "ept_map_range failed for the framebuffer config page", 0); return -30; } if (ept_map_range(g_guest.fb_gpa, fb_buf.phys, XJ380_FB_SIZE, EPT_READ | EPT_WRITE) != 0) { log_error("[XJ380] EPT map framebuffer failed"); + panic_full("XJ3-E40 EPT MAP FRAMEBUFFER FAILED", "ept_map_range failed for the guest framebuffer", 0); return -31; } if (ept_map_range(g_guest.kernel_gpa, kernel_buf.phys, kernel_alloc, EPT_RWX) != 0) { log_error("[XJ380] EPT map kernel failed"); + panic_full("XJ3-E41 EPT MAP KERNEL FAILED", "ept_map_range failed for the loaded kernel image", 0); return -32; } if (ept_map_range(g_guest.ram_gpa, ram_buf.phys, ram_size, EPT_RWX) != 0) { log_error("[XJ380] EPT map guest RAM failed"); + panic_full("XJ3-E42 EPT MAP GUEST RAM FAILED", "ept_map_range failed for guest ram", 0); return -33; } /* 低 1MB 恒等映射(BIOS 区,与 linux_loader 一致;<1MB 无需按需分配) */ diff --git a/CODE/UTSM/vmm/xj380_loader.d b/CODE/UTSM/vmm/xj380_loader.d new file mode 100644 index 0000000..1293b15 --- /dev/null +++ b/CODE/UTSM/vmm/xj380_loader.d @@ -0,0 +1,12 @@ +vmm/xj380_loader.o: vmm\xj380_loader.c include\utsm\xj380_loader.h \ + include\utsm\types.h include\utsm\panic.h include\utsm\vmx.h \ + include\utsm\ept.h include\utsm\log.h include\utsm\dma.h \ + vmm\..\arch\x86_64\limine.h +include\utsm\xj380_loader.h: +include\utsm\types.h: +include\utsm\panic.h: +include\utsm\vmx.h: +include\utsm\ept.h: +include\utsm\log.h: +include\utsm\dma.h: +vmm\..\arch\x86_64\limine.h: diff --git a/SYSTEM/boot/utsm.elf b/SYSTEM/boot/utsm.elf index 522a73f1e45e0ed540385389ba8a84287a5e052b..1b805ca502386f0f9b6b5bdf079bc79bfde6c4fa 100755 GIT binary patch delta 177160 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 delta 157376 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 z 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 Ntn?7^WSh{t{s$#2%{c%7