FUCK
This commit is contained in:
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user