QEMU内存后端文件与FUSE兼容性问题及其定位
最近想要将文件系统和 QEMU 模拟器结合起来做一些实验性的工作,需要使用 QEMU 内存后端文件的特性。前面的进展都很顺利,但是待准备工作都完成后,却遇到了模拟器无法启动的问题,好在最终还是解决了,接下来便一一细说。 环境准备我的基本开发环境为 QEMU 6.2 版本,Linux 5.10 版本内核,面向架构为 x86_64。这部分环境的准备没有遇到什么大问题,只是需要注意我选用的版本相对较老,在使用较新的编译器编译时可能会报出警告,因此需要在编译前的 configure 阶段将 Werror 的 flag 禁用,以免在编译时将警告当作错误来对待。 例如对于 QEMU 来说,configure 的命令为: 1$ ./configure --target-list=x86_64-softmmu --disable-docs --disable-werror 这里最好也加上 --disable-docs,因为编译文档的工具链同样容易由于版本问题导致编译失败。 文件系统方面,我当前的需求是需要实现一个最简的堆叠式加密文件系统,无需关注具体的加密算法是什么。一般来说,有两种方案:...
QEMU内存后端文件的用法及分析
本文将介绍 QEMU 中内存后端文件参数用法和代码实现,基于的版本为 QEMU 6.2。 参数用法首先是参数的用法,下面是 官方文档 中对此的说明: memory-backend=’id’ An alternative to legacy -mem-path and mem-prealloc options. Allows to use a memory backend as main RAM. For example: 123-object memory-backend-file,id=pc.ram,size=512M,mem-path=/hugetlbfs,prealloc=on,share=on-machine memory-backend=pc.ram-m 512M 接下来我们做一个测试,首先创建一个空文件 mem,使用 du 查看其空间占用大小: 12$ du -sh mem0 mem 然后利用参数指定该文件为内存后端文件,并启动一个模拟器,启动参数如下: 12345678910qemu-system-riscv64 \ -cpu rv64 \ ...
关于Linux信号的一些思考
今天偶然间看到一个介绍 Linux 信号的视频:别再杀进程了!让 Ctrl+C 变成“喵”…(用信号实现)哔哩哔哩_bilibili ,虽然讲的东西很基础,但也引发了我思考一些之间没有很关注的问题。在与 LLM “讨论” 一番过后,便想将这些思考记录下来,算是查漏补缺吧。 信号的一面有关信号的具体用法,不是本文关注的重点,这部分内容可以翻看《深入理解计算机系统》(CSAPP)的异常控制流章节,这也是我最早建立对“信号”认识的地方。 先下定义:信号的本质是操作系统提供的一种进程间通信(IPC)机制,其他两种主要的进程间通信进制为共享内存和消息传递。 其中管道通常也被认为是一种特殊的消息传递机制,它们的核心设计都是不依赖于两个进程(以下称作 A 和 B)共享一段内存空间,而是将内核作为一个中间层,将数据代为转发,即 A -> kernel -> B。只不过常规的消息传递转发的是结构化的数据,而管道通常直接进行数据流的传递。 与共享内存和消息传递不同,信号通常并不直接传送数据,而是传达一系列预设编号的通知,进程在收到通知后,根据通知类别的不同,进行分发处理。简单类比就...
AMD SEV机密虚拟机ASID管理
本文将介绍 Linux 内核中,AMD SEV 机密虚拟机对虚拟机号 ASID 的管理设计,基于的内核版本为 Linux 5.10。 数据结构AMD SEV 中对 ASID 管理的核心代码位于 arch/x86/kvm/svm/sev.c 中,以下是与之相关的数据结构定义: 1234567891011121314/* 定义保护位图的互斥锁 */static DEFINE_MUTEX(sev_bitmap_lock);/* SEV 同时支持的最大 ASID */unsigned int max_sev_asid;/* SEV 应该使用的最小的 ASID */static unsigned int min_sev_asid;/* 待分配的 ASID 位图 */static unsigned long *sev_asid_bitmap;/* 回收的 ASID 位图 */static unsigned long *sev_reclaim_asid_bitmap; AMD SEV 的 ASID 管理采用了 双位图 的设计,包含一张分配位图 sev_asid_bitmap 和一张回收位图 ...
Linux内核initcall初始化机制
本文将介绍 Linux 内核的初始化函数结构,其通过 initcall 机制来实现,其核心是一系列优先级不同的宏,用于控制初始化函数的执行顺序。本文的实验的内核环境基于 Linux 5.10。 initcall 的级别与执行顺序Linux 内核定义了多个初始化级别(按照执行顺序从高到低排列): 宏定义 级别名 优先级值 用途说明 early_initcall(fn) early - 早期的初始化,在 SMP 初始化之前 pure_initcall(fn) pure 0 用于初始化不能被静态初始化的变量 core_initcall(fn) core 1 核心子系统初始化 postcore_initcall(fn) postcore 2 核心子系统之后的初始化 arch_initcall(fn) arch 3 架构相关初始化 subsys_initcall(fn) subsys 4 子系统初始化 fs_initcall(fn) fs 5 文件系统初始化 rootfs_initcall(fn) rootfs - 根文件系统初始化 dev...
使用QEMU TCG模拟一个硬件虚拟化环境
本文将介绍如何使用 QEMU TCG 模拟的方式,构建一个支持硬件虚拟化的环境,使得能够在该模拟器环境下启动一个 KVM 虚拟机。 编译最新 QEMU首先需要下载并编译 QEMU,我们以 x86_64 架构为例,QEMU 选择使用最新版本。 123456789# 下载最新仓库$ git clone https://git.qemu-project.org/qemu.git$ cd qemu# 配置编译目标$ ./configure --target-list=x86_64-softmmu# 编译$ make -j$(nproc) 准备 Linux 内核(选用 6.12.0)接下来,需要准备 Linux 内核,我这里选用的是 6.12.0 版本。硬件虚拟化技术使用 AMD-V,需要在 menuconfig 中启用 KVM for AMD processor support。 1234567891011121314# 下载 6.12 版本内核$ wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.12.tar.xz$ ...
QEMU softmmu模型
本文将分析 QEMU TCG 模式下的访存模型,也就是 softmmu 的设计,基于的版本为 QEMU 6.2,架构则以 RISC-V 为例。 基本调用链1234561. target/riscv/translate.c 访存指令翻译。2. accel/tcg/cputlb.c 调用 helper 加载函数(如 helper_le_ldq_mmu)。3. 调用 load_helper 函数 1. 查 TLB,若未命中,则 tlb_fill 进行填充。 2. 处理各种特殊情况(MMIO、不对界访问等)。 3. 计算得到对应的宿主机虚拟地址 haddr = addr + entry->addend,并根据字长进行访问。 TLB 数据结构QEMU 的 softmmu 模型的核心数据结构为其 TLB 的设计,结构如下: CPUTLB12345typedef struct CPUTLB { CPUTLBCommon c; // 存储 TLB 的一系列元数据。 CPUTLBDesc d[NB_MMU_MODES]; // 慢速(二级) TLB,主要用于存储从...
OS功能挑战赛2025总结
随着最近 OS 功能挑战赛 2025 的落幕,既标志着这几个月比赛工作的结束,也标志着本人研一生活的结束。本文将作为一个简单的记录,对本次比赛的过程以及得到的经验教训做一个总结,同时也对未来的学习研究做一个展望。 比赛回顾首先说一下比赛结果—— 三等奖 ,一个稍微有些令人失望的结果。但不管如何,比赛过程中的收获却是实打实的。 项目的源代码已经开放在了 github 中,欢迎参考: LordaeronESZ/SEVFS: A simple encrypted versioning file system. 时间线接下来,我将简单梳理一下本次比赛的整个时间线。 首先是 3 月份,我们完成了比赛的报名和选题工作。其中选题工作并不那么顺利,最开始我们选题备选方案为:(1)proj121-使用哈希页表实现虚拟机的 stage-2 页表 和 (2)proj319-支持 RISC-V 架构的文件级加密文件系统。由于个人科研方向为虚拟化方向,因此两个题目中更偏向于前者。但通过对往年的参赛作品进行调研发现,已经有队伍做过了该题目并且基本完成了题目的所有要求,并最终获得了一等奖——我们再选择...
论文《SVSM-KMS:Safeguarding Keys for Cloud Services with Encrypted Virtualization》总结
本文将介绍 2024 年发表在 arXiv 上的论文《SVSM-KMS:Safeguarding Keys for Cloud Services with Encrypted Virtualization》。 解决的问题密钥管理服务是云环境中最重要的服务之一。集中式密钥管理系统(centralized Key Management System, KMS)通常提供一个统一的平台来进行密钥生成、分发、管理等操作,然而,这会导致可信计算基(TCB)过大,带来单点故障的风险。非集中式的 KMS 是一个方向,但是这会带来为维护多结点一致性的高昂的开销。 云端的安全密钥管理存在许多问题:首先云服务提供商(CSP)拥有对平台的绝对控制权,需要将其视作可信。此外,网络延迟会影响集中式的 KMS 的效率。同时,如果宿主机系统被攻破,还可能导致密钥的泄露。 为了解决这些问题,本文基于 AMD SEV-SNP 所引入的 VMPL 机制和 SVSM 特权软件,设计了 SVSM-KMS,将 KMS 放在 CVM 内的最高 VMPL 特权级,与 host 和 guest 隔离开来。具体来说,本文的贡献如...
RISC-V 架构下的裸金属程序
本文将介绍如何在 RISC-V 环境下,编写一个最简的裸金属(bare-metal)程序,该程序不依赖于操作系统的支持,计算机在启动后直接跳转到该程序开始执行。本文的目的主要是作为一个程序模板,可以对其进行扩展成为一个完整的操作系统或是常驻内存中的固件服务。 实现原理要实现计算机在启动后立马跳转到该程序执行,需要明确一点:计算机启动后执行的第一条指令是什么?或者说,PC 初始值是什么?答案根据平台的不同可能存在差异,我们的测试环境为 qemu-system-riscv64 模拟器的 virt 模型,其初始 PC 为 0x80000000。那么我们便要编写链接脚本,将需要程序的入口点链接到该地址处。 还有第二个问题:程序入口可以直接是 C 程序吗?答案是不行,至少绝大部分情况下不行。C 代码编译之后,局部作用域内变量的保存依赖于栈,因此我们必须准备好一片连续的内存区域(栈空间),并在进入 C 环境前将栈指针寄存器(SP)指向该内存区域的最高地址处(因为栈从高地址向低地址增长)。 至于栈空间的分配,通常有两种方式。首先可以编写链接脚本进行预留: 123456789101112131...















