This commit is contained in:
xyou
2026-07-28 12:00:02 +08:00
parent efa626ed17
commit 17a577f2ed
51 changed files with 8446 additions and 787 deletions
+262
View File
@@ -706,4 +706,266 @@ static inline du_u32 du_theme_accent(du_theme t) {
return (t == DU_THEME_DARK) ? DS_DARK_ACCENT : DS_LIGHT_ACCENT;
}
/* ===================================================================
* L0+ — Winux-Kate 调色板 (eDEX-UI Neon Cyber Theme)
*
* 源自 D:\Code\Winux-Kate\src\styles\theme.css
* 风格:深蓝黑底 + 青色霓虹 + 绿色辅助 + 扫描线纹理
* =================================================================== */
/* --- 主色调:深空蓝黑 (Deep Space Black) --- */
#define DP_KATE_BG 0xFF02040Au /* --bg: #02040a */
#define DP_KATE_BG2 0xFF050A18u /* --bg2: #050a18 */
#define DP_KATE_PANEL 0xB20A1228u /* --panel: rgba(10,18,40,0.72) 半透明 */
#define DP_KATE_PANEL_SOLID 0xFF0A1228u /* 不透明版本(用于无 alpha 混合场景) */
/* --- 强调色:霓虹青 (Neon Cyan) --- */
#define DP_KATE_ACCENT 0xFF00E5FFu /* --accent: #00e5ff */
#define DP_KATE_ACCENT_DIM 0x2E00E5FFu /* --accent-dim: rgba(0,229,255,0.18) */
#define DP_KATE_ACCENT_DIM_SOLID 0xFF1A3A4Au /* 不透明近似 */
#define DP_KATE_PANEL_BORDER 0x5900E5FFu /* --panel-border: rgba(0,229,255,0.35) */
#define DP_KATE_PANEL_BORDER_SOLID 0xFF005A6Au /* 不透明近似 */
/* --- 辅助色:霓虹绿 (Neon Green) --- */
#define DP_KATE_ACCENT2 0xFF39FF14u /* --accent2: #39ff14 */
/* --- 文本色 --- */
#define DP_KATE_TEXT 0xFFCFEFFBu /* --text: #cfeffb */
#define DP_KATE_TEXT_DIM 0xFF6F8AA8u /* --text-dim: #6f8aa8 */
/* --- 状态色 --- */
#define DP_KATE_WARN 0xFFFFCC00u /* --warn: #ffcc00 */
#define DP_KATE_DANGER 0xFFFF4D6Du /* --danger: #ff4d6d */
/* ===================================================================
* L1 — Winux-Kate 语义色值
* =================================================================== */
#define KS_BG_PRIMARY DP_KATE_BG
#define KS_BG_SECONDARY DP_KATE_PANEL_SOLID
#define KS_BG_TERTIARY DP_KATE_BG2
#define KS_TEXT_PRIMARY DP_KATE_TEXT
#define KS_TEXT_DIM DP_KATE_TEXT_DIM
#define KS_TEXT_INVERT DP_KATE_BG
#define KS_ACCENT DP_KATE_ACCENT
#define KS_ACCENT2 DP_KATE_ACCENT2
#define KS_ACCENT_DIM DP_KATE_ACCENT_DIM_SOLID
#define KS_BORDER DP_KATE_PANEL_BORDER_SOLID
#define KS_BORDER_FOCUS DP_KATE_ACCENT
#define KS_BORDER_DIM 0xFF1A2840u /* 暗边框 */
#define KS_DANGER DP_KATE_DANGER
#define KS_WARN DP_KATE_WARN
/* ===================================================================
* Winux-Kate 布局常量(源自 theme.css / pages.css)
* =================================================================== */
#define KATE_TOPBAR_H 34 /* .topbar height */
#define KATE_STATUSBAR_H 32 /* .statusbar height */
#define KATE_TASKBAR_H 40 /* .taskbar height */
#define KATE_PANEL_HEADER_H 24 /* .panel-header */
#define KATE_TITLEBAR_H 28 /* 窗口标题栏 */
#define KATE_ICON_W 104 /* .desktop-icon width */
#define KATE_ICON_H 90 /* .desktop-icon height (含 label) */
#define KATE_ICON_IMG 40 /* .di-img / .di-fallback */
#define KATE_ICON_GAP 18 /* .desktop-grid gap */
#define KATE_ICON_PAD 24 /* .desktop-canvas padding */
#define KATE_TB_ITEM_MAX_W 200 /* .tb-item max-width */
#define KATE_PAGE_PAD 8 /* 页面 padding */
/* ===================================================================
* Winux-Kate 特效函数
* =================================================================== */
/* 绘制扫描线纹理( repeating-linear-gradient 0deg, 3px 周期)
* 在指定矩形区域内叠加半透明青色水平细线 */
static inline void du_kate_scanlines(du_context *ctx, du_i64 x, du_i64 y,
du_i64 w, du_i64 h) {
for (du_i64 ry = 0; ry < h; ry++) {
du_i64 yy = y + ry;
if (yy < 0 || (du_u64)yy >= ctx->height) continue; /* 每 3 像素一条线 */
du_u32 *line = (du_u32 *)((du_u8 *)ctx->fb + (du_u64)yy * ctx->pitch);
for (du_i64 rx = 0; rx < w; rx++) {
du_i64 xx = x + rx;
if (xx < 0 || (du_u64)xx >= ctx->width) continue;
/* 叠加极淡青色(alpha ~0.03 ≈ 8/255)*/
du_u32 cur = line[(du_u64)xx];
du_u32 b = (cur >> 16) & 0xFF;
du_u32 g = (cur >> 8) & 0xFF;
du_u32 r = cur & 0xFF;
b = (b + 2 < 255) ? b + 2 : 255;
g = (g + 4 < 255) ? g + 4 : 255;
r = (r + 2 < 255) ? r + 2 : 255;
line[(du_u64)xx] = 0xFF000000u | (b << 16) | (g << 8) | r;
}
}
}
/* 绘制带光晕的矩形边框(box-shadow 效果)
* 外发光:在矩形外围绘制渐变青色光晕 */
static inline void du_kate_glow_border(du_context *ctx, du_i64 x, du_i64 y,
du_i64 w, du_i64 h, du_u32 glow_color) {
/* 2px 渐变光晕,alpha 混合到实际背景(逐像素读-混合-写) */
for (du_i64 i = 2; i >= 1; i--) {
du_u32 alpha = (i == 2) ? 50 : 100;
/* 上下边 */
for (du_i64 c = -i; c < w + i; c++) {
du_i64 xt = x + c;
du_pixel(ctx, xt, y - i,
du_blend(du_pixel_read(ctx, xt, y - i), glow_color, alpha));
du_pixel(ctx, xt, y + h + i - 1,
du_blend(du_pixel_read(ctx, xt, y + h + i - 1), glow_color, alpha));
}
/* 左右边 */
for (du_i64 r = -i; r < h + i; r++) {
du_i64 yt = y + r;
du_pixel(ctx, x - i, yt,
du_blend(du_pixel_read(ctx, x - i, yt), glow_color, alpha));
du_pixel(ctx, x + w + i - 1, yt,
du_blend(du_pixel_read(ctx, x + w + i - 1, yt), glow_color, alpha));
}
}
}
/* 绘制 Winux-Kate 面板(.panel 样式)
* - 半透明深蓝背景
* - 青色边框
* - 内外光晕
* - 扫描线纹理
* - 可选标题栏 */
static inline void du_kate_panel(du_context *ctx, du_i64 x, du_i64 y,
du_i64 w, du_i64 h, const char *header) {
/* 1. 背景 */
du_fill_rounded_rect(ctx, x, y, w, h, KS_BG_SECONDARY, 2);
/* 2. 边框 */
du_rect_outline(ctx, x, y, w, h, KS_BORDER, 2);
/* 3. 外光晕 */
du_kate_glow_border(ctx, x, y, w, h, KS_ACCENT);
/* 4. 扫描线纹理 */
du_kate_scanlines(ctx, x + 1, y + 1, w - 2, h - 2);
/* 5. 标题栏 */
if (header) {
du_fill_rect(ctx, x, y, w, KATE_PANEL_HEADER_H, 0xFF062838u); /* 深青色标题栏 */
du_divider_h(ctx, x, y + KATE_PANEL_HEADER_H, w, KS_BORDER);
/* 标题文字:青色,大写,letter-spacing */
du_draw_string(ctx, header, x + 10, y + (KATE_PANEL_HEADER_H - DU_ASCII_LINE_H) / 2 + 2,
KS_ACCENT, 0xFF062838u, DU_ASCII_STEP);
/* 标题前的小绿点 */
du_fill_rect(ctx, x + 4, y + KATE_PANEL_HEADER_H / 2 - 3, 6, 6, KS_ACCENT2);
}
}
/* 绘制 Winux-Kate 顶部栏(.topbar 样式)
* - 34px 高
* - 渐变背景
* - 底部边框
* - 品牌名 + 时钟槽位 */
static inline void du_kate_topbar(du_context *ctx, du_i64 w,
const char *brand, const char *clock) {
/* 渐变背景:左青色微亮 → 右深色 */
du_fill_rect_gradient(ctx, 0, 0, w, KATE_TOPBAR_H,
0xFF0A3050u, 0xFF02040Au);
/* 底部分隔线 */
du_divider_h(ctx, 0, KATE_TOPBAR_H, w, KS_BORDER);
/* 品牌名(青色,加粗,letter-spacing 4px)*/
if (brand) {
du_draw_string(ctx, brand, 12, (KATE_TOPBAR_H - DU_ASCII_LINE_H) / 2 + 1,
KS_ACCENT, 0, DU_ASCII_STEP);
}
/* 时钟(右侧,绿色)*/
if (clock) {
du_i64 cl = 0;
while (clock[cl]) cl++;
du_draw_string(ctx, clock, w - 12 - cl * DU_ASCII_STEP,
(KATE_TOPBAR_H - DU_ASCII_LINE_H) / 2 + 1,
KS_ACCENT2, 0, DU_ASCII_STEP);
}
}
/* 绘制 Winux-Kate 状态栏(.statusbar 样式)
* - 32px 高
* - 顶部边框
* - 半透明青色背景 */
static inline void du_kate_statusbar(du_context *ctx, du_i64 x, du_i64 y,
du_i64 w, const char *status_text) {
du_fill_rect(ctx, x, y, w, KATE_STATUSBAR_H, 0xFF051828u);
du_divider_h(ctx, x, y, w, KS_BORDER);
if (status_text) {
du_draw_string(ctx, status_text, x + 12,
y + (KATE_STATUSBAR_H - DU_ASCII_LINE_H) / 2 + 1,
KS_TEXT_DIM, 0, DU_ASCII_STEP);
}
}
/* 绘制 Winux-Kate 桌面图标(.desktop-icon 样式)
* - 104px 宽
* - 40x40 图标区域
* - 下方文字标签
* - 选中态:青色边框 + 光晕 */
static inline void du_kate_desktop_icon(du_context *ctx, du_i64 x, du_i64 y,
const char *label, int selected) {
/* 悬停/选中背景 */
if (selected) {
du_fill_rect(ctx, x, y, KATE_ICON_W, KATE_ICON_H, KS_ACCENT_DIM);
du_rect_outline(ctx, x, y, KATE_ICON_W, KATE_ICON_H, KS_ACCENT, 1);
du_kate_glow_border(ctx, x, y, KATE_ICON_W, KATE_ICON_H, KS_ACCENT);
}
/* 图标占位区域(40x40 居中)*/
du_i64 ix = x + (KATE_ICON_W - KATE_ICON_IMG) / 2;
du_i64 iy = y + 10;
du_rect_outline(ctx, ix, iy, KATE_ICON_IMG, KATE_ICON_IMG, KS_BORDER, 1);
/* 标签 */
if (label) {
du_i64 ll = 0;
while (label[ll]) ll++;
du_i64 lx = x + (KATE_ICON_W - ll * DU_ASCII_STEP) / 2;
if (lx < x + 2) lx = x + 2;
du_draw_string(ctx, label, lx, y + KATE_ICON_IMG + 18,
KS_TEXT_PRIMARY, 0, DU_ASCII_STEP);
}
}
/* 绘制 Winux-Kate 任务栏项(.tb-item 样式) */
static inline void du_kate_tb_item(du_context *ctx, du_i64 x, du_i64 y,
const char *title, int active) {
du_i64 tl = 0;
while (title[tl]) tl++;
du_i64 w = tl * DU_ASCII_STEP + 24;
if (w > KATE_TB_ITEM_MAX_W) w = KATE_TB_ITEM_MAX_W;
du_u32 fg = active ? KS_ACCENT : KS_TEXT_PRIMARY;
if (active) {
du_fill_rect(ctx, x, y, w, 28, KS_ACCENT_DIM);
}
du_rect_outline(ctx, x, y, w, 28, KS_BORDER, 1);
if (active) {
du_kate_glow_border(ctx, x, y, w, 28, KS_ACCENT);
}
du_draw_string(ctx, title, x + 8, y + (28 - DU_ASCII_LINE_H) / 2 + 1,
fg, 0, DU_ASCII_STEP);
}
/* 绘制 Winux-Kate 按钮 (.btn 样式) */
static inline void du_kate_button(du_context *ctx, du_i64 x, du_i64 y,
du_i64 w, du_i64 h, const char *label,
int hover) {
du_u32 fg = KS_ACCENT;
if (hover) {
du_fill_rect(ctx, x, y, w, h, KS_ACCENT_DIM);
}
du_rect_outline(ctx, x, y, w, h, KS_BORDER, 1);
if (hover) {
du_kate_glow_border(ctx, x, y, w, h, KS_ACCENT);
}
du_i64 ll = 0;
while (label[ll]) ll++;
du_i64 lx = x + (w - ll * DU_ASCII_STEP) / 2;
du_draw_string(ctx, label, lx, y + (h - DU_ASCII_LINE_H) / 2 + 1,
fg, hover ? KS_ACCENT_DIM : KS_BG_SECONDARY, DU_ASCII_STEP);
}
#endif /* DESHAB_UI_H */
+33
View File
@@ -0,0 +1,33 @@
#ifndef UTSM_EPT_H
#define UTSM_EPT_H
#include <utsm/types.h>
/* EPT 页表结构:4 级页表(PML4 / PDPT / PD / PT),每级 512 项,每页 4KB。 */
#define EPT_PAGE_SIZE 4096ULL
#define EPT_ENTRIES 512ULL
/* EPTP 构造:bits [5:0]=memory type, bits [7:6]=walk length-1, bits [51:12]=PML4 HPA */
#define EPTP_WALK_LEN_4 (3ULL << 6) /* 4 级页表 */
#define EPTP_MEMTYPE_WB (EPT_MEMORY_TYPE_WB)
/* 初始化 EPT:分配 PML4,置零。返回 0 成功。 */
int ept_init(void);
/* 构造 EPTP 值(用于 VMCS EPT_POINTER 字段)。 */
u64 ept_get_eptp(void);
/* 在 EPT 中映射一段 GPA→HPA 区间,权限由 flags 决定(EPT_READ/WRITE/EXECUTE)。
* 自动按 4KB 分配中间页表页。返回 0 成功。 */
int ept_map_range(u64 gpa, u64 hpa, u64 size, u64 flags);
/* 便利函数:1:1 映射(GPA==HPA)。 */
int ept_identity_map(u64 gpa, u64 size, u64 flags);
/* Walk the EPT to translate a GPA to its mapped HPA.
* Returns the HPA on success, 0 if the GPA is not mapped.
* Handles 4KB pages and 2MB large pages. */
u64 ept_gpa_to_hpa(u64 gpa);
#endif
+39
View File
@@ -0,0 +1,39 @@
#ifndef UTSM_HYPERCALL_H
#define UTSM_HYPERCALL_H
/* UTSM-side VMCALL hypercall handler.
*
* When the Linux guest executes a VMCALL instruction, it triggers a VM-Exit
* with exit reason EXIT_VMCALL (18). The guest places:
* RAX = UTSM_HCALL_MAGIC | op (identifies this as a UTSM hypercall)
* RDI = arg0
* RSI = arg1
* RDX = arg2
*
* The handler validates the magic, dispatches to the operation handler,
* writes the return value into GUEST_RAX, and advances GUEST_RIP past
* the VMCALL instruction so the guest resumes normally.
*
* If the magic doesn't match, the handler returns a VMFAIL indication
* (by setting the VMCS vm-exit instruction error), which causes the guest
* to see VMCALL fail. Phase 1.3: we just return -UTSM_HCALL_NOSYS.
*
* Protocol details in CODE/utsm-ipc/ipc_proto.h.
*/
#include <utsm/types.h>
/* VM-Exit handler for VMCALL (exit reason 18).
*
* Reads guest RAX/RDI/RSI/RDX from the VMCS save area (passed in by the
* assembly exit stub), dispatches the hypercall, writes the result to
* GUEST_RAX, and advances GUEST_RIP.
*
* Returns 1 to resume the guest, 0 to terminate. */
int hypercall_handle(u64 guest_rax, u64 guest_rdi, u64 guest_rsi, u64 guest_rdx,
u64 guest_rip, u64 instr_len);
/* Statistics */
u64 hypercall_get_count(void);
#endif /* UTSM_HYPERCALL_H */
+68
View File
@@ -0,0 +1,68 @@
#ifndef UTSM_IPC_SHM_H
#define UTSM_IPC_SHM_H
/* UTSM-side IPC shared memory manager.
*
* Allocates a 1MB contiguous physical region, initializes the
* utsm_ipc_shm structure (header + two ring buffers + payload pool),
* and EPT-maps it at LINUX_GUEST_IPC_SHM_GPA so the Linux guest can
* access it after querying the GPA via UTSM_HCALL_SHM_INFO.
*
* The shared protocol structures are defined in CODE/utsm-ipc/ipc_proto.h,
* which is included by both UTSM and the Linux utsm-ipc driver.
*
* Ring buffer discipline:
* utsm_to_linux: UTSM produces (ipc_shm_send), Linux consumes
* linux_to_utsm: Linux produces, UTSM consumes (ipc_shm_recv)
*/
#include <utsm/types.h>
#include <ipc_proto.h> /* shared UTSM↔Linux IPC protocol (struct utsm_ipc_msg, etc.) */
/* ===== Initialization ===== */
/* Allocate, initialize, and EPT-map the IPC shared memory region.
* Must be called after vmm_init() (EPT is required) and before linux_launch().
* Returns 0 on success, negative on error. */
int ipc_shm_init(void);
/* Shut down IPC: mark UTSM as not ready.
* Does not free the shared memory (it may still be referenced by EPT). */
void ipc_shm_shutdown(void);
/* Query state */
int ipc_shm_is_ready(void);
/* Get the HPA of the shared memory region (for EPT mapping).
* Returns 0 if not initialized. */
u64 ipc_shm_get_hpa(void);
/* Get the GPA of the shared memory region (passed to Linux via hypercall). */
u64 ipc_shm_get_gpa(void);
/* Get the size of the shared memory region. */
u64 ipc_shm_get_size(void);
/* ===== Message API (UTSM-side) ===== */
/* Send a message from UTSM to Linux (enqueues into utsm_to_linux ring).
* Returns 0 on success, -1 if the ring is full. */
int ipc_shm_send(u32 msg_type, const void *data, u32 data_len);
/* Receive a message from Linux to UTSM (dequeues from linux_to_utsm ring).
* Returns 0 on success (msg filled in), -1 if the ring is empty. */
int ipc_shm_recv(struct utsm_ipc_msg *msg_out);
/* Check if there are pending messages from Linux. */
int ipc_shm_has_pending(void);
/* Notify Linux that a message is waiting (placeholder for IPI injection).
* Phase 1.3: logs the event; Phase 1.4+ will inject a guest IRQ. */
void ipc_shm_notify_linux(void);
/* ===== Debug ===== */
/* Dump ring buffer statistics to the UTSM serial console. */
void ipc_shm_dump_stats(void);
#endif /* UTSM_IPC_SHM_H */
+170
View File
@@ -0,0 +1,170 @@
#ifndef UTSM_LINUX_LOADER_H
#define UTSM_LINUX_LOADER_H
#include <utsm/types.h>
/* ===== Linux boot protocol structures (Documentation/x86/boot.rst) ===== */
/* bzImage setup_header — lives at offset 0x1f1 inside bzImage and boot_params.
* Only the fields we actually use are listed; gaps are reserved/padding. */
struct linux_setup_header {
u8 setup_sects; /* 0x1f1: number of setup sectors */
u16 root_flags; /* 0x1f2 */
u32 syssize; /* 0x1f4: protected-mode code size / 16 */
u16 ram_size; /* 0x1f8 */
u16 vid_mode; /* 0x1fa */
u16 boot_flag; /* 0x1fe: 0xAA55 */
u16 jump; /* 0x200: jump insn */
u32 header; /* 0x202: "HdrS" magic */
u16 version; /* 0x206: boot protocol version */
u32 realmode_swtch; /* 0x208 */
u16 start_sys_seg; /* 0x20c */
u16 kernel_version; /* 0x20e: offset to version string */
u8 type_of_loader; /* 0x210 */
u8 loadflags; /* 0x211 */
u16 setup_move_size; /* 0x212 */
u32 code32_start; /* 0x214: 32-bit entry (also 64-bit entry base) */
u32 ramdisk_image; /* 0x218 */
u32 ramdisk_size; /* 0x21c */
u32 bootsect_kludge; /* 0x220 */
u16 heap_end_ptr; /* 0x224 */
u8 ext_loader_ver; /* 0x226 */
u8 ext_loader_type; /* 0x227 */
u32 cmd_line_ptr; /* 0x228: command line physical address */
u32 init_size; /* 0x22c: total init memory needed */
u32 acpi_rsdp_addr; /* 0x230 */
u8 _pad0[4]; /* 0x234: relocatable_kernel + min_alignment */
u16 xloadflags; /* 0x236: bit0=XLF_KERNEL_64 */
u32 cmdline_size; /* 0x238 */
u32 _pad1; /* 0x23c */
u64 setup_data; /* 0x240: linked list of setup_data */
u64 pref_address; /* 0x248 → wait, this is payload_offset */
/* NOTE: The real layout continues with payload_offset at 0x248.
* However, pref_address is at 0x258 and init_size at 0x260.
* The struct above is intentionally simplified — we read fields
* by offset rather than relying on this struct for the full layout. */
} __attribute__((packed));
/* boot_params is 4096 bytes. The setup_header is at offset 0x1f1. */
#define BOOT_PARAMS_SIZE 4096
#define SETUP_HEADER_OFFSET 0x1f1
/* Key field offsets within bzImage / boot_params */
#define BZ_BOOT_FLAG_OFF 0x1fe
#define BZ_HEADER_MAGIC 0x53726448 /* "HdrS" */
#define BZ_HEADER_OFF 0x202
#define BZ_VERSION_OFF 0x206
#define BZ_TYPE_OF_LOADER_OFF 0x210
#define BZ_LOADFLAGS_OFF 0x211
#define BZ_CODE32_START_OFF 0x214
#define BZ_RAMDISK_IMAGE_OFF 0x218
#define BZ_RAMDISK_SIZE_OFF 0x21c
#define BZ_CMD_LINE_PTR_OFF 0x228
#define BZ_INIT_SIZE_OFF 0x22c /* wait — actually init_size is at 0x260 */
#define BZ_XLOADFLAGS_OFF 0x236
#define BZ_CMDLINE_SIZE_OFF 0x238
#define BZ_PAYLOAD_OFFSET_OFF 0x248
#define BZ_PAYLOAD_LENGTH_OFF 0x24c
#define BZ_PREF_ADDRESS_OFF 0x258
#define BZ_INIT_SIZE_ACTUAL_OFF 0x260
/* xloadflags bits */
#define XLF_KERNEL_64 0x0001
#define XLF_CAN_BE_LOADED_ABOVE 0x0002
#define XLF_EFI_HANDOVER 0x0010
#define XLF_EFI_KEXEC 0x0020
/* loadflags bits */
#define LOADFLAG_LOADED_HIGH 0x01
#define LOADFLAG_KEEP_ROOT 0x02
#define LOADFLAG_CAN_USE_HEAP 0x80
/* e820 entry types */
#define E820_TYPE_RAM 1
#define E820_TYPE_RESERVED 2
#define E820_TYPE_ACPI 3
#define E820_TYPE_NVS 4
#define E820_TYPE_UNUSABLE 5
#define E820_TYPE_PMEM 7
/* e820_table entry in boot_params at offset 0x2e0 (actually 0x2d0 in older,
* 0x2e0 in newer). We use 0x2e0 and the e820_entries count at 0x1e8.
* Each entry is 20 bytes: u64 addr, u64 size, u32 type. */
#define E820_ENTRIES_OFFSET 0x1e8
#define E820_TABLE_OFFSET 0x2e0
#define E820_MAX_ENTRIES 128
#define E820_ENTRY_SIZE 20
/* ===== Guest memory layout (GPA) =====
* Based on utsm-linux-dual-kernel-architecture.md.
* 0x00000000-0x003FFFFF : UTSM reserved (denied to Linux)
* 0x00400000-0x004FFFFF : boot_params / cmdline / GDT / page tables / stack
* 0x01000000-0x02FFFFFF : Linux kernel image
* 0x03000000-0x03FFFFFF : Linux initrd
* 0x04000000-0x040FFFFF : IPC shared memory (1MB, both kernels RW)
* 0x05000000-MAX : Linux general RAM
*/
#define LINUX_GUEST_KERNEL_GPA 0x01000000ULL /* 16 MB, 2MB-aligned */
#define LINUX_GUEST_BOOTPARAMS_GPA 0x00400000ULL /* 4 MB */
#define LINUX_GUEST_CMDLINE_GPA 0x00500000ULL /* 5 MB */
#define LINUX_GUEST_INITRD_GPA 0x03000000ULL /* 48 MB (within kernel+initrd region) */
#define LINUX_GUEST_STACK_GPA 0x00800000ULL /* 8 MB (stack grows down) */
#define LINUX_GUEST_GDT_GPA 0x00600000ULL /* 6 MB (guest GDT) */
#define LINUX_GUEST_PGT_GPA 0x00700000ULL /* 7 MB (guest page tables) */
#define LINUX_GUEST_CMDLINE_MAX 4096
/* IPC shared memory GPA (must match CODE/utsm-ipc/ipc_proto.h) */
#define LINUX_GUEST_IPC_SHM_GPA 0x04000000ULL /* 64 MB */
#define LINUX_GUEST_IPC_SHM_SIZE (1024 * 1024) /* 1MB */
/* General RAM starts after IPC region */
#define LINUX_GUEST_RAM_GPA 0x05000000ULL /* 80 MB */
/* ===== Linux loader API ===== */
/* Loaded Linux guest state */
struct linux_guest_info {
u64 kernel_gpa; /* GPA where kernel was loaded */
u64 kernel_entry; /* 64-bit entry point GPA */
u64 kernel_size; /* Size of loaded kernel image */
u64 bootparams_gpa; /* GPA of boot_params */
u64 cmdline_gpa; /* GPA of command line */
u64 cmdline_size; /* Command line length (with NUL) */
u64 initrd_gpa; /* GPA of initrd (0 = none) */
u64 initrd_size; /* Size of initrd */
u64 pgt_gpa; /* GPA of guest page tables */
u64 gdt_gpa; /* GPA of guest GDT */
int loaded; /* 1 = successfully loaded */
};
/* Find the Linux bzImage boot module among Limine modules.
* Returns pointer to the module data, or NULL if not found.
* Sets *size_out to the module size. */
void *linux_find_bzimage_module(u64 *size_out);
/* Parse bzImage header and extract key parameters.
* Returns 0 on success, negative on error. */
int linux_parse_bzimage(const void *bzimage, u64 size,
u64 *payload_offset_out, u64 *payload_length_out,
u64 *init_size_out, u64 *entry_offset_out);
/* Initialize the Linux guest: parse bzImage, allocate guest memory,
* set up boot_params, page tables, GDT, and EPT mappings.
* Returns 0 on success, negative on error. */
int linux_loader_init(void);
/* Get the loaded Linux guest info (NULL if not loaded). */
const struct linux_guest_info *linux_get_guest_info(void);
/* Configure VMCS for Linux guest and perform vmlaunch.
* Must be called after vmm_init() + linux_loader_init().
* Returns 0 on successful guest termination, negative on error. */
int linux_launch(void);
/* Default Linux command line (can be overridden). */
#define LINUX_DEFAULT_CMDLINE \
"console=ttyS0,115200 earlyprintk=serial nokaslr " \
"no_timer_check loglevel=7"
#endif
+4
View File
@@ -9,6 +9,10 @@
#include <utsm/segment.h>
#include <utsm/capability.h>
#include <utsm/utrw.h>
#include <utsm/vmm.h>
#include <utsm/linux_loader.h>
#include <utsm/ipc_shm.h>
#include <utsm/hypercall.h>
void utsm_init(void);
int utsm_selftest_run(void);
+63
View File
@@ -0,0 +1,63 @@
#ifndef UTSM_VMM_H
#define UTSM_VMM_H
#include <utsm/types.h>
/* VMM 顶层 API:协调 VMX/EPT/VMCS/VMEXIT,启动 guest。
*
* Phase 1.1(当前):vmm_init() 完成 VMX root 启用 + EPT 初始化,
* vmm_self_test() 启动一个最小 guest(HLT 指令)验证 VMEXIT 路径。
*
* Phase 1.2+:vmm_launch_linux() 加载并启动 Linux 6.6 LTS guest。
*/
/* ===== Guest register save area =====
*
* VMCS does NOT save guest GPRs (RAX-R15) on VM-Exit. The assembly VM-Exit
* handler (vmexit_asm.S) saves all 16 GPRs into this structure before
* calling the C dispatcher, and restores them before vmresume.
*
* C handlers (e.g. hypercall.c) can read guest arguments from this structure
* and write return values (e.g. g_guest_regs.rax = retval) which will be
* loaded into the CPU before vmresume resumes the guest. */
struct vmexit_guest_regs {
u64 rax;
u64 rbx;
u64 rcx;
u64 rdx;
u64 rsi;
u64 rdi;
u64 rbp;
u64 r8;
u64 r9;
u64 r10;
u64 r11;
u64 r12;
u64 r13;
u64 r14;
u64 r15;
};
/* Global guest register save area (referenced by vmexit_asm.S).
* Non-static: shared between vmm.c, vmexit.c, hypercall.c, and vmexit_asm.S. */
extern volatile struct vmexit_guest_regs g_guest_regs;
/* ===== VMM API ===== */
/* 初始化 VMM:VMX root 模式 + EPT 表 + 分配 VMCS。
* 返回 0 成功,负值失败。 */
int vmm_init(void);
/* 关闭 VMM:vmxoff。 */
void vmm_shutdown(void);
/* Phase 1.1 自检:启动最小 guest 验证 VMX 路径。
* guest 代码为内嵌的 HLT 指令,预期触发 HLT VMEXIT。
* 返回 0 成功。 */
int vmm_self_test(void);
/* VMM 状态查询 */
int vmm_is_ready(void);
u64 vmm_get_eptp(void);
#endif
+268
View File
@@ -0,0 +1,268 @@
#ifndef UTSM_VMX_H
#define UTSM_VMX_H
#include <utsm/types.h>
/* ===== VMX MSRs ===== */
#define IA32_VMX_BASIC 0x480
#define IA32_VMX_PINBASED_CTLS 0x481
#define IA32_VMX_PROCBASED_CTLS 0x482
#define IA32_VMX_EXIT_CTLS 0x483
#define IA32_VMX_ENTRY_CTLS 0x484
#define IA32_VMX_PROCBASED_CTLS2 0x48B
#define IA32_VMX_EPT_VPID_CAP 0x48C
#define IA32_VMX_TRUE_PINBASED_CTLS 0x48D
#define IA32_VMX_TRUE_PROCBASED_CTLS 0x48E
#define IA32_VMX_TRUE_EXIT_CTLS 0x48F
#define IA32_VMX_TRUE_ENTRY_CTLS 0x490
/* ===== CR4 / CR0 bits ===== */
#define CR4_VMXE_BIT 13ULL
#define CR4_VMXE (1ULL << CR4_VMXE_BIT)
#define CR4_PAE (1ULL << 5)
#define CR4_PGE (1ULL << 7)
#define CR4_PSE (1ULL << 4)
#define CR0_PE (1ULL << 0)
#define CR0_NE (1ULL << 5)
#define CR0_WP (1ULL << 16)
#define CR0_PG (1ULL << 31)
/* ===== VMCS field encodings (Intel SDM Vol 3, Appendix H) ===== */
/* Field encoding: bit 13=1 -> host root, bit 12=1 -> guest, bits [11:10] = type, bits [9:1] = index */
#define VMCS_FIELD_HOST 0x2000ULL
#define VMCS_FIELD_GUEST 0x1000ULL
#define VMCS_FIELD_CTRL 0x4000ULL
#define VMCS_FIELD_READ 0x6000ULL
/* Control fields */
#define VMCS_VPID 0x0000
#define VMCS_GUEST_ES_ADDR 0x0006
#define VMCS_GUEST_CS_ADDR 0x0008
#define VMCS_GUEST_SS_ADDR 0x000A
#define VMCS_GUEST_DS_ADDR 0x000C
#define VMCS_GUEST_FS_ADDR 0x000E
#define VMCS_GUEST_GS_ADDR 0x0010
#define VMCS_GUEST_LDTR_ADDR 0x0012
#define VMCS_GUEST_TR_ADDR 0x0014
#define VMCS_GUEST_INTR_STATUS 0x0009
#define VMCS_IO_BITMAP_A 0x2000
#define VMCS_IO_BITMAP_B 0x2002
#define VMCS_MSR_BITMAP 0x2004
#define VMCS_TSC_OFFSET 0x2010
#define VMCS_EPT_POINTER 0x201A
/* Read-only data fields */
#define VMCS_GUEST_PHYSICAL_ADDR 0x2400
#define VMCS_EXIT_REASON 0x4402
#define VMCS_EXIT_QUALIFICATION 0x6400
#define VMCS_IO_RCX 0x6404
#define VMCS_IO_RSI 0x6406
#define VMCS_IO_RDI 0x6408
#define VMCS_IO_RIP 0x640A
#define VMCS_GUEST_LINEAR_ADDR 0x640A
#define VMCS_INSTRUCTION_LENGTH 0x440C
#define VMCS_VMX_INSTRUCTION_ERROR 0x4406
/* Guest-state fields */
#define VMCS_GUEST_ES_SELECTOR 0x0800
#define VMCS_GUEST_CS_SELECTOR 0x0802
#define VMCS_GUEST_SS_SELECTOR 0x0804
#define VMCS_GUEST_DS_SELECTOR 0x0806
#define VMCS_GUEST_FS_SELECTOR 0x0808
#define VMCS_GUEST_GS_SELECTOR 0x080A
#define VMCS_GUEST_LDTR_SELECTOR 0x080C
#define VMCS_GUEST_TR_SELECTOR 0x080E
#define VMCS_GUEST_CS_LIMIT 0x4800
#define VMCS_GUEST_SS_LIMIT 0x4804
#define VMCS_GUEST_DS_LIMIT 0x4806
#define VMCS_GUEST_ES_LIMIT 0x4801
#define VMCS_GUEST_FS_LIMIT 0x4808
#define VMCS_GUEST_GS_LIMIT 0x480A
#define VMCS_GUEST_LDTR_LIMIT 0x480C
#define VMCS_GUEST_TR_LIMIT 0x480E
#define VMCS_GUEST_CS_ACCESS 0x4816
#define VMCS_GUEST_SS_ACCESS 0x481A
#define VMCS_GUEST_DS_ACCESS 0x4818
#define VMCS_GUEST_ES_ACCESS 0x4814
#define VMCS_GUEST_FS_ACCESS 0x481C
#define VMCS_GUEST_GS_ACCESS 0x481E
#define VMCS_GUEST_LDTR_ACCESS 0x4820
#define VMCS_GUEST_TR_ACCESS 0x4822
#define VMCS_GUEST_INTERRUPTIBILITY 0x4824
#define VMCS_GUEST_ACTIVITY_STATE 0x4826
#define VMCS_GUEST_SYSENTER_CS 0x482A
#define VMCS_GUEST_PREEMPTION_TIMER 0x482E
/* 64-bit guest-state fields(与 PDPTR 共享编码,仅在 EPT 启用时为 EFER/PAT) */
#define VMCS_GUEST_IA32_EFER 0x2806
#define VMCS_GUEST_IA32_PAT 0x2804
#define VMCS_GUEST_IA32_PERF_GLOBAL_CTRL 0x2808
#define VMCS_GUEST_CR0 0x6800
#define VMCS_GUEST_CR3 0x6802
#define VMCS_GUEST_CR4 0x6804
#define VMCS_GUEST_ES_BASE 0x6806
#define VMCS_GUEST_CS_BASE 0x6808
#define VMCS_GUEST_SS_BASE 0x680A
#define VMCS_GUEST_DS_BASE 0x680C
#define VMCS_GUEST_FS_BASE 0x680E
#define VMCS_GUEST_GS_BASE 0x6810
#define VMCS_GUEST_LDTR_BASE 0x6812
#define VMCS_GUEST_TR_BASE 0x6814
#define VMCS_GUEST_GDTR_BASE 0x6816
#define VMCS_GUEST_GDTR_LIMIT 0x4810
#define VMCS_GUEST_IDTR_BASE 0x6818
#define VMCS_GUEST_IDTR_LIMIT 0x4812
#define VMCS_GUEST_DR7 0x681A
#define VMCS_GUEST_RSP 0x681C
#define VMCS_GUEST_RIP 0x681E
#define VMCS_GUEST_RFLAGS 0x6820
#define VMCS_GUEST_SYSENTER_ESP 0x6824
#define VMCS_GUEST_SYSENTER_EIP 0x6826
/* Host-state fields (Intel SDM Vol 3D, Appendix H, Table H-6) */
#define VMCS_HOST_CR0 0x6C00
#define VMCS_HOST_CR3 0x6C02
#define VMCS_HOST_CR4 0x6C04
#define VMCS_HOST_ES_SELECTOR 0x0C00
#define VMCS_HOST_CS_SELECTOR 0x0C02
#define VMCS_HOST_SS_SELECTOR 0x0C04
#define VMCS_HOST_DS_SELECTOR 0x0C06
#define VMCS_HOST_FS_SELECTOR 0x0C08
#define VMCS_HOST_GS_SELECTOR 0x0C0A
#define VMCS_HOST_TR_SELECTOR 0x0C0C
#define VMCS_HOST_FS_BASE 0x6C06
#define VMCS_HOST_GS_BASE 0x6C08
#define VMCS_HOST_TR_BASE 0x6C0A
#define VMCS_HOST_GDTR_BASE 0x6C0C
#define VMCS_HOST_IDTR_BASE 0x6C0E
#define VMCS_HOST_SYSENTER_CS 0x4C00
#define VMCS_HOST_RSP 0x6C14
#define VMCS_HOST_RIP 0x6C16
#define VMCS_HOST_SYSENTER_ESP 0x6C10
#define VMCS_HOST_SYSENTER_EIP 0x6C12
/* 64-bit host-state fields */
#define VMCS_HOST_IA32_EFER 0x2C02
#define VMCS_HOST_IA32_PAT 0x2C00
#define VMCS_HOST_IA32_PERF_GLOBAL_CTRL 0x2C04
/* IA32_EFER MSR (0xC0000080) bits */
#define EFER_SCE (1ULL << 0)
#define EFER_LME (1ULL << 8)
#define EFER_LMA (1ULL << 10)
#define EFER_NXE (1ULL << 11)
#define EFER_SVME (1ULL << 12)
#define EFER_LMSLE (1ULL << 13)
#define EFER_FFXSR (1ULL << 14)
#define EFER_TCE (1ULL << 15)
/* VM-execution control fields */
#define VMCS_PIN_BASED_VM_EXEC_CONTROL 0x4000
#define VMCS_CPU_BASED_VM_EXEC_CONTROL 0x4002
#define VMCS_EXCEPTION_BITMAP 0x4004
#define VMCS_VM_EXIT_CONTROLS 0x400C
#define VMCS_VM_ENTRY_CONTROLS 0x4012
#define VMCS_VM_ENTRY_INTERRUPT_INFO 0x4016
#define VMCS_SECONDARY_VM_EXEC_CONTROL 0x401E
/* ===== Pin-based controls ===== */
#define PIN_EXT_INTERRUPT_EXITING (1ULL << 0)
#define PIN_NMI_EXITING (1ULL << 3)
/* ===== Primary processor-based controls ===== */
#define CPU_BASED_HLT_EXITING (1ULL << 7)
#define CPU_BASED_INVLPG_EXITING (1ULL << 9)
#define CPU_BASED_MWAIT_EXITING (1ULL << 10)
#define CPU_BASED_RDPMC_EXITING (1ULL << 11)
#define CPU_BASED_RDTSC_EXITING (1ULL << 12)
#define CPU_BASED_CR8_LOAD_EXITING (1ULL << 19)
#define CPU_BASED_CR8_STORE_EXITING (1ULL << 20)
#define CPU_BASED_MOV_DR_EXITING (1ULL << 23)
#define CPU_BASED_UNCOND_IO_EXITING (1ULL << 24)
#define CPU_BASED_USE_IO_BITMAPS (1ULL << 25)
#define CPU_BASED_PAUSE_EXITING (1ULL << 30)
#define CPU_BASED_ACTIVATE_SECONDARY (1ULL << 31)
#define CPU_BASED_USE_MSR_BITMAPS (1ULL << 28)
/* ===== Secondary processor-based controls ===== */
#define SEC_EXEC_ENABLE_EPT (1ULL << 1)
#define SEC_EXEC_ENABLE_VPID (1ULL << 5)
#define SEC_EXEC_UNRESTRICTED_GUEST (1ULL << 7)
/* ===== VM-exit controls ===== */
#define VM_EXIT_SAVE_DEBUG_CONTROLS (1ULL << 2)
#define VM_EXIT_HOST_ADDR_SPACE_SIZE (1ULL << 9)
#define VM_EXIT_LOAD_PERF_GLOBAL_CTRL (1ULL << 12)
#define VM_EXIT_ACK_INTR_ON_EXIT (1ULL << 15)
#define VM_EXIT_SAVE_GUEST_EFER (1ULL << 20)
#define VM_EXIT_LOAD_HOST_EFER (1ULL << 21)
/* ===== VM-entry controls ===== */
#define VM_ENTRY_LOAD_DEBUG_CONTROLS (1ULL << 2)
#define VM_ENTRY_IA32E_MODE_GUEST (1ULL << 9)
#define VM_ENTRY_LOAD_GUEST_EFER (1ULL << 15)
/* ===== Exit reasons ===== */
#define EXIT_EXCEPTION_NMI 0
#define EXIT_EXTERNAL_INTERRUPT 1
#define EXIT_TRIPLE_FAULT 2
#define EXIT_INIT_SIGNAL 3
#define EXIT_CPUID 10
#define EXIT_INVD 13
#define EXIT_RDMSR 31
#define EXIT_WRMSR 32
#define EXIT_MONITOR 39
#define EXIT_MWAIT 36
#define EXIT_VMCALL 18
#define EXIT_VMCLEAR 19
#define EXIT_VMLAUNCH 20
#define EXIT_VMPTRLD 21
#define EXIT_VMPTRST 22
#define EXIT_VMREAD 23
#define EXIT_VMRESUME 24
#define EXIT_VMWRITE 25
#define EXIT_VMXOFF 26
#define EXIT_VMXON 27
#define EXIT_CONTROL_ACCESS 28
#define EXIT_IO_INSTRUCTION 30
#define EXIT_RDPMC 15
#define EXIT_RDTSC 16
#define EXIT_HLT 12
#define EXIT_INVLPG 14
#define EXIT_EPT_VIOLATION 48
#define EXIT_EPT_MISCONFIG 49
#define EXIT_APIC_ACCESS 44
/* ===== EPT memory types ===== */
#define EPT_MEMORY_TYPE_UC 0ULL
#define EPT_MEMORY_TYPE_WC 1ULL
#define EPT_MEMORY_TYPE_WT 4ULL
#define EPT_MEMORY_TYPE_WP 5ULL
#define EPT_MEMORY_TYPE_WB 6ULL
/* ===== EPT entry bits ===== */
#define EPT_READ (1ULL << 0)
#define EPT_WRITE (1ULL << 1)
#define EPT_EXECUTE (1ULL << 2)
#define EPT_RWX (EPT_READ | EPT_WRITE | EPT_EXECUTE)
#define EPT_LARGE_PAGE (1ULL << 7)
/* ===== VMX instruction errors ===== */
#define VMXERR_VMCALL_INVALID 1
/* ===== Public API ===== */
int vmx_supported(void);
int vmx_enable(void);
int vmx_disable(void);
int vmx_vmcs_alloc(u64 *phys_out);
int vmx_vmcs_load(u64 phys);
u64 vmx_vmcs_read(u64 field);
void vmx_vmcs_write(u64 field, u64 value);
int vmx_vmlaunch(void);
int vmx_vmresume(void);
u64 vmx_read_msr(u32 msr);
u64 vmx_get_host_cr3(void);
#endif