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
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
#include <utsm/ept.h>
|
||||
#include <utsm/panic.h>
|
||||
#include <utsm/vmx.h>
|
||||
#include <utsm/log.h>
|
||||
#include <utsm/types.h>
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
@@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
#include <utsm/ipc_shm.h>
|
||||
#include <utsm/panic.h>
|
||||
#include <utsm/vmx.h>
|
||||
#include <utsm/ept.h>
|
||||
#include <utsm/log.h>
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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:
|
||||
@@ -13,6 +13,7 @@
|
||||
*/
|
||||
|
||||
#include <utsm/linux_loader.h>
|
||||
#include <utsm/panic.h>
|
||||
#include <utsm/linux_xsave.h>
|
||||
#include <utsm/vmx.h>
|
||||
#include <utsm/ept.h>
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include <utsm/linux_compat.h>
|
||||
#include <utsm/panic.h>
|
||||
#include <utsm/linux_resume.h>
|
||||
#include <utsm/linux_loader.h> /* VSCode Phase 5: linux_find_vscode_module */
|
||||
#include <utsm/ipc_shm.h>
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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:
|
||||
@@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
#include <utsm/linux_loader.h>
|
||||
#include <utsm/panic.h>
|
||||
#include <utsm/vmx.h>
|
||||
#include <utsm/ept.h>
|
||||
#include <utsm/log.h>
|
||||
@@ -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++;
|
||||
|
||||
@@ -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:
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include <utsm/virtio_mmio.h>
|
||||
#include <utsm/panic.h>
|
||||
#include <utsm/linux_loader.h>
|
||||
#include <utsm/block.h>
|
||||
#include <utsm/log.h>
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
#include <utsm/virtio_mmio.h>
|
||||
#include <utsm/panic.h>
|
||||
#include <utsm/linux_loader.h>
|
||||
#include <utsm/net.h>
|
||||
#include <utsm/log.h>
|
||||
|
||||
@@ -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:
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <utsm/vmx.h>
|
||||
#include <utsm/panic.h>
|
||||
#include <utsm/ept.h>
|
||||
#include <utsm/vmm.h>
|
||||
#include <utsm/hypercall.h>
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
+23
-5
@@ -1,4 +1,5 @@
|
||||
#include <utsm/vmm.h>
|
||||
#include <utsm/panic.h>
|
||||
#include <utsm/vmx.h>
|
||||
#include <utsm/ept.h>
|
||||
#include <utsm/log.h>
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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:
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <utsm/vmx.h>
|
||||
#include <utsm/panic.h>
|
||||
#include <utsm/ept.h>
|
||||
#include <utsm/log.h>
|
||||
#include <utsm/types.h>
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include <utsm/xj380_loader.h>
|
||||
#include <utsm/panic.h>
|
||||
#include <utsm/vmx.h>
|
||||
#include <utsm/ept.h>
|
||||
#include <utsm/log.h>
|
||||
@@ -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 无需按需分配) */
|
||||
|
||||
@@ -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:
|
||||
Reference in New Issue
Block a user