This commit is contained in:
xyou
2026-07-31 13:53:49 +08:00
parent 5ea84fac97
commit f52157b7af
241 changed files with 26843 additions and 8155 deletions
+24 -5
View File
@@ -1,13 +1,32 @@
#ifndef UTSM_CONFIG_H
#define UTSM_CONFIG_H
#include <utsm/types.h>
/* ---- 编译期固定常量(不暴露给 FUCK 配置) ---- */
#define UTSM_CACHE_LINE_SIZE 64ULL
#define UTSM_PAGE_SIZE 4096ULL
#define UTSM_MAX_SEGMENTS 1024U
#define UTSM_MAX_CAPABILITIES 256U
#define UTSM_MAX_PCKC_KEYS 8U
#define UTSM_ARENA_SIZE (16ULL * 1024ULL * 1024ULL)
#define UTSM_DIRTY_SHARD_PAGES 1024ULL
#define UTSM_KERNEL_STACK_SIZE 16384ULL
/* ---- 编译期默认值宏(用于静态数组大小上限) ---- */
#define UTSM_MAX_SEGMENTS_DEFAULT 1024U
#define UTSM_MAX_CAPABILITIES_DEFAULT 256U
#define UTSM_MAX_PCKC_KEYS_DEFAULT 8U
#define UTSM_ARENA_SIZE_DEFAULT (64ULL * 1024ULL * 1024ULL)
#define UTSM_DIRTY_SHARD_PAGES_DEFAULT 1024ULL
/* ---- 运行期配置变量(由 kernel_main 从 FUCK 文件初始化) ---- */
extern u32 g_utsm_max_segments;
extern u32 g_utsm_max_capabilities;
extern u32 g_utsm_max_pckc_keys;
extern u64 g_utsm_arena_size;
extern u64 g_utsm_dirty_shard_pages;
/* ---- 保留旧宏名(兼容性),映射到默认值 ---- */
#define UTSM_MAX_SEGMENTS UTSM_MAX_SEGMENTS_DEFAULT
#define UTSM_MAX_CAPABILITIES UTSM_MAX_CAPABILITIES_DEFAULT
#define UTSM_MAX_PCKC_KEYS UTSM_MAX_PCKC_KEYS_DEFAULT
#define UTSM_ARENA_SIZE UTSM_ARENA_SIZE_DEFAULT
#define UTSM_DIRTY_SHARD_PAGES UTSM_DIRTY_SHARD_PAGES_DEFAULT
#endif
+5
View File
@@ -5,6 +5,7 @@
#include <utsm/dma.h>
#include <utsm/block.h>
#include <utsm/net.h>
#include <utsm/paging.h>
#define DKM_DRIVER_MAGIC 0x444B4D31u
#define DKM_ABI_VERSION 1u
@@ -95,6 +96,10 @@ typedef struct dkm_kernel_api {
int (*irq_register)(u8 irq, void *handler); /* kernel irq_register */
u64 hhdm_offset; /* physical → virtual */
const dkm_block_api *block; /* block provider registry */
const dkm_mmio_api *mmio; /* 页表/高位 MMIO 映射服务(尾部追加,ABI 兼容) */
/* —— 新增字段只允许追加在末尾(DSK 以 api+0xA8 硬偏移读取 block) —— */
void *(*mm_map_mmio)(u64 phys, u64 size); /* MMIO 独立窗口映射(PCD|PWT),返回虚拟地址,失败返回 0 */
void (*mm_unmap_mmio)(void *virt, u64 size); /* 解除 MMIO 独立窗口映射 */
} dkm_kernel_api;
typedef enum dkm_driver_state {
+17
View File
@@ -9,6 +9,23 @@
#define DSK_BOOT_FLAG_FROM_UTSM (1ULL << 0)
#define DSK_BOOT_FLAG_DKM_READY (1ULL << 1)
#define DSK_BOOT_FLAG_FAT32_PATH (1ULL << 2)
#define DSK_BOOT_FLAG_PROBE_INFO (1ULL << 3)
/* ---- Probe 信息结构(通过 reserved[6] 传递给 shell/desktop) ---- */
#define PROBE_INFO_MAGIC 0x50524F42u /* "PRFB" — Probe inFo Buffer */
typedef struct probe_info {
u32 magic; /* PROBE_INFO_MAGIC */
u32 version; /* ABI 版本,当前 1 */
u64 probe_buf_addr; /* probe_entry 缓冲基地址(物理/HHDM 地址) */
u32 probe_cap; /* 缓冲容量(条目数) */
u32 probe_head; /* 当前写入位置(递增取模) */
u32 probe_count; /* 已写入总条目数 */
u32 probe_dropped; /* 因缓冲满而覆盖的条目数 */
u32 instr_enabled; /* g_instr_enabled 当前值 */
u32 instr_probe_enable; /* g_instr_probe_enable 当前值 */
u64 reserved[4];
} probe_info;
typedef struct dsk_boot_context {
u64 magic;
+15
View File
@@ -30,4 +30,19 @@ int ept_identity_map(u64 gpa, u64 size, u64 flags);
* Handles 4KB pages and 2MB large pages. */
u64 ept_gpa_to_hpa(u64 gpa);
/* Map a 2MB large page in EPT (PD-level direct mapping).
* GPA and HPA must be 2MB-aligned. memtype = EPT_MEMORY_TYPE_*.
* Required for real hardware MTRR compliance. */
int ept_map_2m_page(u64 gpa, u64 hpa, u64 flags, u64 memtype);
/* Check INVVPID/INVEPT support from IA32_VMX_EPT_VPID_CAP MSR.
* Call once after VMX init. */
void ept_check_vpid_support(void);
/* Flush EPT TLB entries (INVEPT). Required after EPT mapping changes on real hardware. */
void ept_flush_ept(void);
/* Flush VPID TLB entries (INVVPID). Required after VPID changes on real hardware. */
void ept_flush_vpid(u16 vpid);
#endif
+11 -3
View File
@@ -5,8 +5,16 @@
void idt_init(void);
/* IRQ handler: return 1 to suppress default ACK, 0 for normal EOI */
typedef int (*irq_handler_t)(u8 irq);
int irq_register(u8 irq, irq_handler_t handler);
/* 将 IDT 所有 256 个条目替换为安全 halt stub (cli; hlt)。
* 用于 UTSM→DSK 跳转前,防止 DSK 运行期间过期 UTSM handler
* 被 spurious IRQ / 异常触发导致三重故障重启。 */
void idt_halt_all(void);
/* IRQ handler: return 1 to suppress default ACK (PIC), 0 for normal EOI.
* 参数为 IDT vector 号 (0x20-0xFF)。
* PIC IRQ (0x20-0x2F): 返回 1 抑制 PIC EOI; 返回 0 自动发送 PIC EOI。
* APIC/IOAPIC/MSI (0x30-0xFF): 返回值当前忽略, EOI 需手动处理 (TODO)。 */
typedef int (*irq_handler_t)(u8 vector);
int irq_register(u8 vector, irq_handler_t handler);
#endif
+181
View File
@@ -0,0 +1,181 @@
/* instr.h — Deshab 统一插桩宏系统
*
* 提供四级插桩原语:
* INSTR_LOG — 带级别和模块过滤的日志输出
* INSTR_STAT — 轻量级计数器 + 周期性摘要
* INSTR_PROBE — 环形探测缓冲写入(结构化事件记录)
* INSTR_TS — 时间戳标注(阶段耗时测量)
*
* 设计原则:
* - 禁用时零开销: g_instr_enabled=0 时所有宏展开为空操作
* - 热路径安全: STAT_INC 仅一条条件自增,PROBE 仅条件写入
* - 统一配置: 通过 FUCK [debug] 段控制开关与粒度
* - 标签编码: 4 字符 ASCII 编码为 u32,避免字符串比较
*
* 使用方式:
* 1. 在 kernel_main() 中调用 instr_init(&g_boot_cfg) 初始化
* 2. 各模块 #include <utsm/instr.h> 后使用 INSTR_* 宏
* 3. 在 FUCK 中设置 [debug] enabled=1 开启插桩
*/
#ifndef UTSM_INSTR_H
#define UTSM_INSTR_H
#include <utsm/types.h>
/* ---- 日志级别 ---- */
#define INSTR_LOG_TRACE 0
#define INSTR_LOG_DEBUG 1
#define INSTR_LOG_INFO 2
#define INSTR_LOG_WARN 3
#define INSTR_LOG_ERROR 4
#define INSTR_LOG_SILENT 5
/* ---- 全局配置变量 (instr.c 定义) ---- */
extern u32 g_instr_enabled; /* 全局插桩开关,FUCK debug.enabled */
extern u32 g_instr_log_level; /* 日志级别阈值,FUCK debug.log_level */
extern u32 g_instr_probe_enable; /* 探测缓冲开关,FUCK debug.probe_enable */
extern u32 g_instr_stat_interval; /* 统计摘要间隔,FUCK debug.stat_summary_interval */
extern u32 g_instr_module_flags; /* 模块级过滤位掩码 */
/* ---- 模块标志位 ---- */
#define INSTR_F_UTSM_TRACE (1u << 0)
#define INSTR_F_VMM_TRACE (1u << 1)
#define INSTR_F_DKM_TRACE (1u << 2)
#define INSTR_F_DSK_TRACE (1u << 3)
#define INSTR_F_BLOCK_TRACE (1u << 4)
#define INSTR_F_NET_TRACE (1u << 5)
#define INSTR_F_INPUT_TRACE (1u << 6)
/* ---- INSTR_LOG: 带级别和模块过滤的日志 ----
* level: INSTR_LOG_TRACE/DEBUG/INFO/WARN/ERROR
* mod_flag: INSTR_F_xxx 或 0(不过滤)
* msg: 常量字符串
*
* 仅当 g_instr_enabled && level >= g_instr_log_level &&
* (mod_flag==0 || mod_flag & g_instr_module_flags) 时输出。
*/
#define INSTR_LOG(level, mod_flag, msg) do { \
if (g_instr_enabled && (level) >= g_instr_log_level && \
((mod_flag) == 0 || (g_instr_module_flags & (mod_flag)))) { \
if ((level) <= INSTR_LOG_ERROR) log_error(msg); \
else if ((level) <= INSTR_LOG_WARN) log_warn(msg); \
else log_info(msg); \
} \
} while(0)
/* ---- INSTR_STAT: 轻量级计数器 (声明+增量+摘要) ----
* INSTR_STAT_DECL(name) — 在函数/文件作用域声明计数器
* INSTR_STAT_INC(name) — 原子性自增 (仅当 enabled)
* INSTR_STAT_SUMMARY(name) — 达到间隔时输出摘要并重置
*/
#define INSTR_STAT_DECL(name) \
static u64 name##_count = 0; \
static u64 name##_last_ts __attribute__((unused)) = 0
#define INSTR_STAT_INC(name) do { \
if (g_instr_enabled) { name##_count++; } \
} while(0)
#define INSTR_STAT_SUMMARY(name) do { \
if (g_instr_enabled && name##_count >= g_instr_stat_interval) { \
u64 _now = instr_rdtsc(); \
u64 _elapsed_ms = (_now - name##_last_ts) / (instr_tsc_per_ms ? instr_tsc_per_ms : 1); \
log_info("[STAT] " #name " count="); \
log_hex64("", name##_count); \
log_info("[STAT] " #name " interval_ms="); \
log_hex64("", _elapsed_ms); \
name##_count = 0; \
name##_last_ts = _now; \
} \
} while(0)
/* ---- INSTR_PROBE: 写入环形探测缓冲 ----
* 标签编码: 4 字符 ASCII,如 "BOOT", "VME0", "EPTV", "IDTI", "AHCI"
* a0-a3: 4 个 u64 参数,语义由标签定义
*
* 仅当 g_instr_enabled && g_instr_probe_enable 时写入。
*/
#define INSTR_PROBE(tag, a0, a1, a2, a3) do { \
if (g_instr_enabled && g_instr_probe_enable) \
probe_write(INSTR_TAG_##tag, (u64)(a0), (u64)(a1), (u64)(a2), (u64)(a3)); \
} while(0)
/* ---- INSTR_TS: 时间戳标注(阶段耗时测量) ----
* INSTR_TS_DECL(name) — 声明时间戳变量
* INSTR_TS_BEGIN(name) — 记录起始 TSC
* INSTR_TS_END(name, label) — 计算耗时并输出(仅当 enabled)
*/
#define INSTR_TS_DECL(name) static u64 name##_ts = 0
#define INSTR_TS_BEGIN(name) do { name##_ts = instr_rdtsc(); } while(0)
#define INSTR_TS_END(name, label) do { \
if (g_instr_enabled) { \
u64 _d = instr_rdtsc() - name##_ts; \
u64 _ms = _d / (instr_tsc_per_ms ? instr_tsc_per_ms : 1); \
log_info("[TS] " label " elapsed_ms="); \
log_hex64("", _ms); \
} \
} while(0)
/* ---- 标签编码常量 ----
* 4 字符 ASCII 编码为大端序 u32:
* 'B'=0x42, 'O'=0x4F, 'O'=0x4F, 'T'=0x54 → 0x424F4F54
*/
#define INSTR_TAG_BOOT 0x424F4F54u /* "BOOT" — 通用启动事件 */
#define INSTR_TAG_IDT0 0x49445430u /* "IDT0" — IDT/中断初始化 */
#define INSTR_TAG_ARE0 0x41524530u /* "ARE0" — Arena 初始化 */
#define INSTR_TAG_DMA0 0x444D4130u /* "DMA0" — DMA 初始化 */
#define INSTR_TAG_NET0 0x4E455430u /* "NET0" — 网络注册 */
#define INSTR_TAG_DRR0 0x44525230u /* "DRR0" — DRR 初始化 */
#define INSTR_TAG_UTS0 0x55545330u /* "UTS0" — UTSM 核心初始化 */
#define INSTR_TAG_DKM0 0x444B4D30u /* "DKM0" — DKM 加载 */
#define INSTR_TAG_DSM0 0x44534D30u /* "DSM0" — 驱动 manifest 加载 */
#define INSTR_TAG_DSK0 0x44534B30u /* "DSK0" — DSK 加载跳转 */
#define INSTR_TAG_SELF 0x53454C46u /* "SELF" — 自检 */
#define INSTR_TAG_VMM0 0x564D4D30u /* "VMM0" — VMM 初始化 */
#define INSTR_TAG_LIN0 0x4C494E30u /* "LIN0" — Linux loader */
#define INSTR_TAG_VME0 0x564D4530u /* "VME0" — VM-Exit 事件 */
#define INSTR_TAG_EPTV 0x45505456u /* "EPTV" — EPT violation */
#define INSTR_TAG_EPTM 0x4550544Du /* "EPTM" — EPT misconfig */
#define INSTR_TAG_AHCI 0x41484349u /* "AHCI" — AHCI 事件 */
#define INSTR_TAG_E1K0 0x45314B30u /* "E1K0" — e1000 事件 */
#define INSTR_TAG_FAT0 0x46415430u /* "FAT0" — FAT32 事件 */
#define INSTR_TAG_NVM0 0x4E564D30u /* "NVM0" — NVMe 事件 */
#define INSTR_TAG_IRQ0 0x49525130u /* "IRQ0" — IRQ 注册/触发 */
#define INSTR_TAG_PIT0 0x50495430u /* "PIT0" — PIT 模拟 */
#define INSTR_TAG_SRL0 0x53524C30u /* "SRL0" — 串口事件 */
#define INSTR_TAG_MMIO 0x4D4D494Fu /* "MMIO" — MMIO 访问 */
#define INSTR_TAG_HCALL 0x4843414Cu /* "HCAL" — Hypercall */
#define INSTR_TAG_EXCP 0x45584350u /* "EXCP" — CPU 异常 */
/* ---- 探测条目结构(与 probe.c 共享) ---- */
typedef struct probe_entry {
u32 tag; /* 4字符ASCII标签 */
u32 tick; /* 低32位TSC(~2s溢出@2GHz,足够诊断) */
u64 args[4]; /* 4个u64参数 */
} probe_entry;
/* ---- 辅助函数声明 (instr.c / probe.c 定义) ---- */
u64 instr_rdtsc(void);
extern u64 instr_tsc_per_ms;
void instr_init(const void *ini_config);
void probe_init(const void *ini_config);
void probe_write(u32 tag, u64 a0, u64 a1, u64 a2, u64 a3);
int probe_read(u32 n, probe_entry *out);
u32 probe_count(void);
u32 probe_capacity(void);
probe_entry *probe_buf_address(void);
u32 probe_head_value(void);
u32 probe_dropped_count(void);
/* 需要前向声明 log 函数 (避免循环 include) */
#ifndef UTSM_LOG_H
void log_info(const char *msg);
void log_warn(const char *msg);
void log_error(const char *msg);
void log_hex64(const char *prefix, u64 value);
#endif
#endif /* UTSM_INSTR_H */
+14
View File
@@ -43,6 +43,20 @@ u64 ipc_shm_get_gpa(void);
/* Get the size of the shared memory region. */
u64 ipc_shm_get_size(void);
/* ===== Payload pool access (bulk data channel) =====
*
* The payload_pool area of the SHM region carries bulk file-transfer data
* (Phase 3 FILE_LIST/FILE_READ). Linux daemon writes into it (via
* UTSM_IOCTL_WRITE_POOL) before sending UTSM_MSG_FILE_RESPONSE; UTSM reads
* it directly through its own HHDM mapping. */
/* Host virtual pointer into payload_pool at byte offset.
* Returns NULL if not initialized or offset out of range. */
void *ipc_shm_payload_ptr(u32 offset);
/* Total capacity of the payload pool in bytes. */
u32 ipc_shm_payload_capacity(void);
/* ===== Message API (UTSM-side) ===== */
/* Send a message from UTSM to Linux (enqueues into utsm_to_linux ring).
+58
View File
@@ -42,10 +42,68 @@ typedef struct linux_compat_service {
char *stdout_buf, u64 stdout_cap, u64 *stdout_len,
u64 *exit_code);
/* 列出 Linux 目录内容(Phase 3 文件传输)。
* path : Linux 绝对路径(如 "/usr/bin")
* buf/cap : 接收列表文本的缓冲区(每行一项,目录名带 '/' 后缀)
* out_len : 实际写入字节数(可为 NULL)
* 返回 0 成功,负值失败(-1=服务不可用, -2=IPC 发送失败,
* -3=linux_resume 失败, -4=无响应, -5=Linux 侧错误,
* -6=缓冲区不足被截断,此时 out_len 仍给出截断长度)。 */
int (*file_list)(const char *path, char *buf, u64 cap, u64 *out_len);
/* 读取 Linux 文件内容(Phase 3 文件传输,支持大文件分块)。
* path : Linux 绝对路径(如 "/etc/hostname")
* offset : 文件内起始偏移(首次读传 0)
* buf/cap : 接收文件数据的缓冲区
* out_len : 本次实际读取字节数(可为 NULL)
* out_total : 文件总大小(可为 NULL)
* 返回 0 成功(含 EOF:out_len=0 且 offset>=total),负值失败
* (错误码同 file_list)。 */
int (*file_read)(const char *path, u64 offset, char *buf, u64 cap,
u64 *out_len, u64 *out_total);
/* 查询 Linux guest 状态字符串(调试用),写入 buf,返回字符串长度。 */
int (*status)(char *buf, u64 cap);
/* 写入 Linux 文件(Phase 3 文件传输,支持大文件分块)。
* 调用方以递增 offset 循环调用即可上传任意大小文件。
* path : Linux 绝对路径(不存在则以 0644 创建;
* offset==0 时先截断,即 push 语义为整文件替换)
* offset : 文件内写入偏移(首次写传 0)
* buf/len : 待写数据(len 会被钳制到 payload pool 容量,
* 实际写入量以 out_written 为准;len=0 仅创建/截断)
* out_written : 本次实际写入字节数(可为 NULL)
* 返回 0 成功,负值失败(错误码同 file_list)。 */
int (*file_write)(const char *path, u64 offset, const char *buf, u64 len,
u64 *out_written);
/* 跨内核文件拉取:Linux 文件 → UTSM FAT32 系统盘根目录(≤256KB,整文件)。
* linux_path : Linux 绝对路径
* fat32_name : UTSM FAT32 根目录文件名(如 "HOSTNAME.TXT",8.3 可转换)
* out_size : 实际传输字节数(可为 NULL)
* 返回 0 成功,负值失败(-7=文件超过 256KB 暂存上限, -9=无块设备,
* -10=非法 FAT32 名, -12=FAT32 写失败,其余同 file_list)。 */
int (*file_pull)(const char *linux_path, const char *fat32_name,
u64 *out_size);
/* 跨内核文件推送:UTSM FAT32 系统盘根目录 → Linux 文件(≤256KB,整文件替换)。
* fat32_name : UTSM FAT32 根目录文件名(8.3 可转换)
* linux_path : Linux 绝对路径
* out_size : 实际传输字节数(可为 NULL)
* 返回 0 成功,负值失败(-11=文件不存在,其余同 file_pull)。 */
int (*file_push)(const char *fat32_name, const char *linux_path,
u64 *out_size);
} linux_compat_service;
/* ===== UTSM 内部接口(不进服务表,供 hypercall.c 等内核代码使用) =====
*
* UTSM FAT32 系统盘根目录文件访问(经 block_get_api() + fat32_io)。
* name 为普通文件名(内部做 8.3 转换)。
* 返回 0 成功;负值:-9 无块设备, -10 非法文件名, -11 文件不存在,
* -12 磁盘 I/O 错误。 */
int lxc_f32_read_file(const char *name, u8 **out_data, u32 *out_size);
int lxc_f32_write_file(const char *name, const u8 *data, u32 size);
/* 获取全局 Linux 兼容层服务实例指针(UTSM 内部使用,
* 外部通过 boot context reserved[5] 获取)。 */
const linux_compat_service *linux_compat_get_service(void);
+8 -2
View File
@@ -135,9 +135,10 @@ struct linux_setup_header {
#define VIRTIO_MMIO_BLK_GPA (VIRTIO_MMIO_GPA_BASE + 0 * VIRTIO_MMIO_GPA_STRIDE) /* 0xF4000000 */
#define VIRTIO_MMIO_NET_GPA (VIRTIO_MMIO_GPA_BASE + 1 * VIRTIO_MMIO_GPA_STRIDE) /* 0xF4001000 */
#define VIRTIO_MMIO_ROOTFS_GPA (VIRTIO_MMIO_GPA_BASE + 2 * VIRTIO_MMIO_GPA_STRIDE) /* 0xF4002000 */
/* 判断 GPA 是否落在 virtio-mmio 设备区(含两端) */
#define VIRTIO_MMIO_GPA_END (VIRTIO_MMIO_GPA_BASE + 2 * VIRTIO_MMIO_GPA_STRIDE)
#define VIRTIO_MMIO_GPA_END (VIRTIO_MMIO_GPA_BASE + 3 * VIRTIO_MMIO_GPA_STRIDE)
#define IS_VIRTIO_MMIO_GPA(gpa) ((gpa) >= VIRTIO_MMIO_GPA_BASE && (gpa) < VIRTIO_MMIO_GPA_END)
/* ===== Linux loader API ===== */
@@ -162,6 +163,10 @@ struct linux_guest_info {
* Sets *size_out to the module size. */
void *linux_find_bzimage_module(u64 *size_out);
/* Find the Arch rootfs image boot module (path contains "rootfs").
* Exposed to Linux guest via memory-backed virtio-blk as /dev/vdb. */
void *linux_find_rootfs_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,
@@ -194,6 +199,7 @@ int linux_launch(void);
"no_timer_check loglevel=7 nohlt idle=poll " \
"noapic nolapic nosmp " \
"virtio_mmio.device=4K@0xF4000000:5 " \
"virtio_mmio.device=4K@0xF4001000:6"
"virtio_mmio.device=4K@0xF4001000:6 " \
"virtio_mmio.device=4K@0xF4002000:7"
#endif
+17
View File
@@ -0,0 +1,17 @@
#ifndef UTSM_MM_H
#define UTSM_MM_H
#include <utsm/types.h>
/* MMIO 映射接口:
* mm_map_mmio 在当前页表(Limine 提供的 CR3)的 MMIO 专用窗口中
* 建立 phys → virt 的 4K 页映射,页属性带 PCD|PWT(等效 UC),
* 适用于任意物理地址(含 4G 以上的 PCI BAR)。
* 返回的虚拟地址包含 phys 的页内偏移;失败返回 0。 */
void *mm_map_mmio(u64 phys, u64 size);
/* 解除 mm_map_mmio 建立的映射(按页清除 PTE + invlpg)。
* 窗口虚拟地址与中间页表页不回收,保留复用。 */
void mm_unmap_mmio(void *virt, u64 size);
#endif
+12
View File
@@ -58,6 +58,16 @@ typedef struct dkm_net_device_info {
u32 flags;
} dkm_net_device_info;
/* 网络设备统计(真机诊断用,驱动层累计)。 */
typedef struct dkm_net_stats {
u64 tx_ok; /* TX 成功帧数 */
u64 tx_err; /* TX 失败帧数 */
u64 rx_ok; /* RX 成功帧数 */
u64 rx_err; /* RX 错误帧数 */
u64 rx_overflow; /* RX buffer 溢出丢包 */
u64 link_changes; /* 链路状态变化次数 */
} dkm_net_stats;
typedef struct dkm_net_api {
int (*register_device)(const dkm_net_device_desc *desc);
u32 (*device_count)(void);
@@ -69,6 +79,8 @@ typedef struct dkm_net_api {
int (*scan_count)(u32 index);
int (*scan_result)(u32 index, u32 n, dkm_net_scan_result *out);
int (*is_wireless)(u32 index);
/* 网络统计查询(返回 0 成功,-1 索引越界)。 */
int (*device_stats)(u32 index, dkm_net_stats *out);
} dkm_net_api;
void net_init(void);
+34
View File
@@ -0,0 +1,34 @@
#ifndef UTSM_PAGING_H
#define UTSM_PAGING_H
#include <utsm/types.h>
/*
* UTSM 页表/MMIO 映射服务
*
* 背景:内核使用 Limine 建立的页表 + HHDM 直映射访问全部 RAM,
* 但 HHDM 只保证覆盖内存映射中的 RAM 区域,不保证覆盖 4G 以上的
* PCI MMIO 空洞(QEMU/OVMF 常把 NVMe 等 64-bit BAR 分配到 48GiB
* 附近)。本模块提供:
* 1. is_mapped —— 四级页表只读 walk,运行时核实某虚拟地址是否可访问,
* 用于在触碰高位 BAR 前先确认 HHDM 覆盖情况(零 #PF 风险)。
* 2. map_mmio —— 在 Limine 页表的 HHDM 空洞处原地补充 4KiB UC 映射
* (P|RW|PCD|PWT),页表页取自 DMA 物理页分配器(低 4G、4K 对齐、清零)。
*
* SAS-R0 单地址空间模型:不新建地址空间,直接扩展当前 CR3 指向的页表,
* 所有 CPU/驱动立即可见,无切换成本。
*/
typedef struct dkm_mmio_api {
/* 四级页表 walk。返回 0=未映射;1=4K PTE 命中;2=2M PDE 命中;3=1G PDPTE 命中 */
int (*is_mapped)(u64 vaddr);
/* 把物理区间 [phys, phys+size) 映射到 hhdm_offset + phys,4KiB UC 页。
* 已被 Limine 覆盖(含 1G/2M 大页)的页自动跳过。返回 0 成功,负数失败。 */
int (*map_mmio)(u64 phys, u64 size);
/* 当前 CR3 物理地址(诊断用) */
u64 (*cr3)(void);
} dkm_mmio_api;
const dkm_mmio_api *paging_get_api(void);
#endif
+9
View File
@@ -153,4 +153,13 @@ int virtio_queue_get_ptrs(u32 device_id, u32 queue_idx,
* 由后端在写 used ring 元素后调用,内部做内存屏障。 */
void virtio_queue_bump_used(struct virtq_used *used, u16 new_idx);
/* 异步触发设备中断(设置 INTERRUPT_STATUS bit0 并向 guest 注入虚拟 IRQ)。
* 用于后端在 QUEUE_NOTIFY 上下文之外完成工作(如周期轮询收到 RX 包)。
* device_id: VIRTIO_ID_*;设备未注册或 irq==0 时为空操作。 */
void virtio_mmio_raise_irq(u32 device_id);
/* 周期轮询 virtio-net RX 路径(填充 guest 已投递的 RX buffer,
* 有填充时自动注入 IRQ)。由 vmexit 的 preemption timer 路径调用。 */
void virtio_net_poll(void);
#endif /* UTSM_VIRTIO_MMIO_H */