当前位置: 首页 > news >正文

Linux kvmtool Kernel Virtual Machine Tool and ramfs Loading

Linux kvmtool Kernel Virtual Machine Tool and ramfs Loading

kvmtool(也称为lkvm或kvm-tool)是比QEMU轻量得多的KVM用户态VMM,源码位于tools/kvm/目录。它的核心设计哲学是直接使用KVM API,避免QEMU的完整设备模型,专注于快速启动Guest Linux内核。ramfs(initramfs/rootfs)加载是kvmtool启动流程的关键环节,决定了Guest内核完成初始化的根文件系统来源。

kvmtool的主入口在kvm.c的kvm__init和kvm__start:

```c
int kvm__init(struct kvm *kvm)
{
int ret;

/* 打开/dev/kvm获取KVM文件描述符 */
kvm->sys_fd = open("/dev/kvm", O_RDWR);
if (kvm->sys_fd < 0)
return -errno;

/* 通过KVM_API_VERSION检查接口版本兼容性 */
ret = ioctl(kvm->sys_fd, KVM_GET_API_VERSION, 0);
if (ret != KVM_API_VERSION)
die("KVM API version mismatch");

/* 创建VM fd */
kvm->vm_fd = ioctl(kvm->sys_fd, KVM_CREATE_VM, 0);

/* 获取KVM支持的能力 */
ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION, KVM_CAP_IRQCHIP);
ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION, KVM_CAP_USER_MEMORY);

return 0;
}

int kvm__start(struct kvm *kvm)
{
/* 加载内核elf镜像 */
if (kvm->cfg.firmware_filename)
load_bzimage(kvm, kvm->cfg.firmware_filename);

/* 加载initramfs */
if (kvm->cfg.initrd_filename)
load_ramdisk(kvm, kvm->cfg.initrd_filename);

/* 设置启动参数 */
kvm__setup_bootargs(kvm);

/* 创建VCPU并启动 */
kvm__create_vcpus(kvm);
kvm__run(kvm);

return 0;
}
```

ramfs加载通过load_ramdisk函数实现,将initramfs或rootfs镜像加载到Guest物理内存中的指定位置:

```c
int load_ramdisk(struct kvm *kvm, const char *filename)
{
int fd;
ssize_t file_size;
struct stat st;
unsigned long addr;
const char *p;

/* 打开ramdisk文件 */
fd = open(filename, O_RDONLY);
if (fd < 0)
return -errno;

/* 获取文件大小 */
if (fstat(fd, &st) < 0) {
close(fd);
return -errno;
}
file_size = st.st_size;

/* 计算ramdisk在Guest物理内存中的地址
* 通常放在内核加载地址之后,紧接内核末尾
*/
addr = kvm->arch.kern_start + kvm->arch.kern_size;
/* 4KB对齐 */
addr = (addr + 0xfff) & ~0xfff;

/* 使用KVM_SET_USER_MEMORY_REGION映射 */
if (!kvm->ram_size_enough(addr, file_size)) {
/* 扩展Guest物理内存映射 */
kvm__register_mem(kvm, addr, ALIGN(file_size, PAGE_SIZE),
NULL);
}

/* 使用mmap映射文件到Guest地址空间 */
p = mmap(NULL, file_size, PROT_READ,
MAP_PRIVATE | MAP_POPULATE, fd, 0);
if (p == MAP_FAILED) {
close(fd);
return -errno;
}

/* 拷贝ramdisk内容到Guest内存 */
memcpy(guest_flat_to_host(kvm, addr), p, file_size);

munmap((void *)p, file_size);
close(fd);

/* 更新内核启动参数中的ramdisk地址和大小 */
kvm->arch.ramdisk_addr = addr;
kvm->arch.ramdisk_size = file_size;

pr_debug(" RAM disk: %s, @ 0x%lx, size %ld bytes\n",
filename, addr, file_size);

return 0;
}
```

加载完成后,kvmtool通过setup_bootargs在boot_params结构中填充initrd_start和initrd_size字段。x86架构下,boot_params由Linux boot protocol定义,位于实模式启动代码段(0x90000偏移处)。kvmtool使用kvm__setup_boot_args直接在Guest物理内存的boot_params结构体上写入:

```c
void kvm__setup_boot_args(struct kvm *kvm)
{
struct boot_params *boot;
unsigned long bp_addr = 0x90000;

/* 获取boot_params的Host指针 */
boot = guest_flat_to_host(kvm, bp_addr);

/* 填充initrd地址和大小 */
boot->hdr.ramdisk_image = kvm->arch.ramdisk_addr;
boot->hdr.ramdisk_size = kvm->arch.ramdisk_size;

/* 设置启动参数行 */
if (kvm->cfg.real_cmdline)
strncpy((char *)boot->hdr.cmd_line_ptr,
kvm->cfg.real_cmdline, 255);

/* 设置header标志 */
boot->hdr.type_of_loader = 0xFF;
boot->hdr.loadflags |= CAN_USE_HEAP | LOAD_HIGH;
}
```

kvmtool的ramfs加载路径与QEMU有显著区别。QEMU通过fw_cfg将initramfs传递给SeaBIOS或OVMF,而kvmtool直接在内核启动参数中设置initrd地址,由内核本身在启动过程中解压并挂载initramfs。这种方式减少了启动链中的中间环节。

kvmtool的Guest内存映射使用kvm__register_mem创建KVM_SET_USER_MEMORY_REGION slot,每个slot对应一段连续的Guest物理地址范围。ramfs加载完成后,内核解压initramfs时通过arch/x86/kernel/setup.c中的populate_initrd_image访问这些地址。如果ramfs大于可用slot大小,kvmtool会合并或扩展已有slot来容纳。

内存映射的核心数据结构为:

```c
struct kvm_mem_bank {
struct list_head list;
u64 guest_phys_addr;
u64 size;
void *host_addr;
struct kvm_userspace_memory_region region;
};
```

每个mem_bank对应一个KVM memory slot,kvmtool通过KVM_SET_USER_MEMORY_REGION将host_addr线性映射到guest_phys_addr供Guest内核直接访问。

http://www.jsqmd.com/news/1020176/

相关文章:

  • 2026舆情服务市场格局:十大公司榜单发布,玖叁鹿全链路能力成行业新标准 - 936品牌测评网
  • MultiLogin:如何高效解决Minecraft多认证源共存难题?
  • Java毕业设计-面向学生竞赛的团队组建与信息管控系统设计 SpringBoot 架构下高校竞赛团队管理系统的设计与实践(源码+LW+部署文档+全bao+远程调试+代码讲解等)
  • 北京 16 区上门收酒权威榜单|专业鉴酒、当场结算,靠谱商家排名一览 - 光耀华夏品牌榜
  • 2026专业的后塍办理公司注册业务公司推荐 - 品牌排行榜
  • AMD平台内存升级避坑指南:实测微星B550M迫击炮+三根内存的兼容性真相
  • 高效跨平台资源下载神器:res-downloader实战指南
  • 2026蒲鞋市街道专业的空调拆装服务商有哪些 - 品牌排行榜
  • 2026年 插板阀/插板门/翻板门/挡板门厂家排行榜:电动烟气脱硫热风隔绝门精品品牌与选购指南 - 品牌发掘
  • CANN ops-nn神经网络算子库概念拆解:从矩阵运算到昇腾NPU指令映射的算子注册与内核调度机制类比解读
  • 计算机毕业设计之jsp“速餐”校园订餐系统的设计与实现
  • 2026年京东云萌新指南:怎么集成OpenClaw?Token Plan配置及大模型Skill接入
  • 2026年 风机消音器/蒸汽消音器/排汽消音器/锅炉消音器十大厂家推荐:多场景降噪技术与源头工厂实力深度解析 - 品牌发掘
  • 北京上门回收茅台、老酒机构权威排名|全域免费上门,附官方预约电话 - 光耀华夏品牌榜
  • GBase 8s数据库安装包安装部署类脚本讲解
  • 2026德阳全屋整装哪家专业?本土6家装修公司深度分析(含真实案例与联系方式) - 优质品牌商家
  • GZDOOM联机模组避坑指南:如何快速判断你的WAD/PK3文件能不能多人玩
  • Windows内存清理终极指南:Mem Reduct让你的电脑告别卡顿的简单方法
  • WASM AI 推理性能优化:浏览器端模型推理的工程实践
  • OpenClaw v2.7.9 完整部署步骤 附问题排查与实操指令
  • NXP EdgeLock Enclave HSM API实战:安全数据存储与设备认证详解
  • 2026年 高级家庭教育指导师证书推荐:人社部/电教馆/教育部认证,北京家庭教育指导师报考指南与口碑解析 - 品牌发掘
  • 2026年成都直饮水系统选购指南:从方案设计到售后运维的全面解析 - 优质品牌商家
  • 避坑指南|2026 北京上门收酒正规商家实力排行,藏家交易首选 - 光耀华夏品牌榜
  • 收藏!AI时代,别再做“什么都会一点”的浅层通才,这才是真正的复合型人才!
  • 2026 海外移动广告素材监测工具选型白皮书:六大核心评估维度与落地指南 - 短商
  • 提示工程不是话术,是可复用的AI交互工程体系
  • 2026 北京老酒回收口碑排行榜|上门收酒正规实体商家,藏家实测打分 - 光耀华夏品牌榜
  • 中国水文站矢量点位分布数据(近1万个站点)|属性齐全|WGS84坐标|SHP格式
  • 遗传算法调试实战:监控种群演化轨迹与早熟诊断