FEMU环境配置

本文主要参考FEMU仓库README

0x00 Intro

FEMU架构图

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
                        +--------------------+
                        |    VM / Guest OS   |
                        |                    |
                        |                    |
                        |  NVMe Block Device |
                        +--------^^----------+
                                 ||
                              PCIe/NVMe
                                 ||
  +------------------------------vv----------------------------+
  |  +---------+ +---------+ +---------+ +---------+ +------+  |
  |  | Blackbox| |  OCSSD  | | ZNS-SSD | |  NoSSD  | | ...  |  |
  |  +---------+ +---------+ +---------+ +---------+ +------+  |
  |                    FEMU NVMe SSD Controller                |
  +------------------------------------------------------------+

FEMU是弗吉尼亚理工学院的Huaicheng LI教授团队开发的一款SSD模拟器,FEMU的论文此前进行过总结[[FAST'18] FEMU闪存模拟系统介绍](https://blog.ipandai.club/p/fast18-femu%E9%97%AA%E5%AD%98%E6%A8%A1%E6%8B%9F%E7%B3%BB%E7%BB%9F%E4%BB%8B%E7%BB%8D/)

综合来说,FEMU是通过修改QEMU的基础框架,实现了对SSD性能的监控、控制,同时支持自行对FTL进行设计,对于VM而言,FEMU就是一个NVMe协议块设备,支持多种SSD研究模式:

  • 白盒模式 Open Chanel SSD:例如软件定义闪存SDF,OCSSD,主机端运行FTL
  • 黑盒模式 BBSSD:FTL位于存储设备,实现了内部映射表,模拟目前的消费级SSD
  • ZNS SSD:向OS暴露NVMe Zone接口,便于OS直接发起read/write请求
  • NoSSD:模拟超低延迟的NVMe设备,例如SCM、Optane、Z-NAND SSD

FEMU使用的一些注意事项:

  1. 尽量让FEMU单独运行,以便有较低的误差

  2. FEMU默认使用8个核心来轮训NVMe队列,FTL额外使用一个核心,VM使用少量的虚拟CPU,默认配置会为VM保留4个宿主机CPU。FEMU对轮询线程的数量可以自行配置,使用-device femu,queues=1,devsz_mb=xxx,femu_mode=xxx进行设置,即:

    FEMU轮询线程+1个FTL线程+FEMU虚拟机虚拟CPU数量+宿主机使用1-2个CPU<=宿主机中的CPU核心数

  3. FEMU会将整个SSD存储到DRAM中来确保精准的延迟和对闪存的模拟,必须确保有大于存储设备容量的空闲内存,宿主机和VM需要保留2-4GB的内存,一个比较直观的公式表达就是:

    FEMU SSD大小+虚拟机DRAM大小+宿主机DRAM大小<=总DRAM大小

    $\rm FEMU \ \ SSD\ \ Size + VM\ \ DRAM\ \ Size+Host\ \ DRAM\ \ Size \leq Total\ \ DRAM \ \ Size$

  4. FEMU只支持4.14及以上的Linux内核版本

更多详细信息可以参考FEMU wiki

0x01 Usage

Image

Get From Maintainer

首先是要制作系统镜像,如果不想的话,可以直接使用作者提供的镜像,起初我打算在macOS上制作,但是貌似macOS没有给QEMU使用HyperVisor的权限,因此想去装一个Ubuntu双系统,结果Windows在硬盘末尾写了一点数据,导致SSD不能分出足够的空间来安装,最后折腾了一下磁盘碎片整理,关闭虚拟内存、使用win自带的硬盘碎片整理工具,最终还是没能成功分出足够的空间,世界名画:

最后只能借助WSL,制作出来了Ubuntu Server的镜像,几经周折上传到服务器之后,发现启动失败,用md5sum看了一下,结果上传过程中发生了错误,于是压缩了镜像重新上传,此时学长告知可以直接使用作者提供的镜像(ubuntu 20.04.1 server版本,内核版本5.4),看了一下README发现填写问卷即可,镜像下载Google 问卷,只有邮箱中就会收到下载地址

下载地址为:

1
2
wget http://people.cs.uchicago.edu/~huaicheng/femu/femu-vm.tar.xz
tar xJvf femu-vm.tar.xz

下载后解压,然后记得检查一下md5,不然会变得不幸

1
2
md5sum u20s.qcow2 > tmp.md5sum
diff md5sum u20s.md5sum

虚拟机的用户名和密码为

1
2
username: femu
passwd: femu

Make It Yourself

在ubuntu官网或者各大高校镜像站下载live-server即可,然后使用qemu-system-x86启动VM安装程序,这里作者要求是最好使用GUI模式来操作,我尝试了nographic发现并不能正确的进入安装程序,顺便提一下,退出QEMU的方式是

1
修饰键:Ctrl+A 命令键:x

也就是先按下Ctrl+A,再按下x,类似tmux~~

启动指令:

1
2
3
4
5
6
7
8
9
sudo qemu-system-x86_64 \
-cdrom ubuntu-22.04.1-live-server-amd64.iso \
-hda femu.qcow2 \
-boot d \
-net nic -net user \
-m 8192 \
-rtc base=localtime -smp 8 \
-cpu host \
-enable-kvm

作者文档中使用的为-localtime,目前的QEMU版本已经移除了该方式,改为了-rtc base=localtime

一路安装下来之后,使用如下指令进入VM中(去掉挂载iso的参数)

1
2
3
4
5
6
7
8
sudo qemu-system-x86_64 \
-hda femu.qcow2 \
-boot d \
-net nic -net user \
-m 8192 \
-rtc base=localtime -smp 8 \
-cpu host \
-enable-kvm

进入VM后,编辑/etc/default/grub,写入以下启动选项:

1
2
3
GRUB_CMDLINE_LINUX="ip=dhcp console=ttyS0,115200 console=tty console=ttyS0"
GRUB_TERMINAL=serial
GRUB_SERIAL_COMMAND="serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1"

通过以上指令设置-nographic模式的启动选项,同时设置了ip的获取方式

保存退出后,更新grub,并退出vm

1
2
sudo update-grub
sudo shutdown -h now

此时镜像就制作成功了,可以通过FEMU来启动进行

Run Qemu

针对不同的研究方向,可以通过运行不同的启动脚本来运行FEMU

例如:

运行黑盒模式

1
./run-blackbox.sh

运行白盒模式

1
./run-whitebox.sh

运行NoSSD模式

1
./run-nossd.sh

运行ZNSSD模式

1
./run-zns.sh

以黑盒模式的运行为例,脚本主要内容即FEMU的运行,这里使用的qemu-system-x86_64是FEMU的编译产物,可以通过修改脚本的配置来使FEMU适配自己的机器,参数修改参考上文或者FEMU Wiki

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/bin/bash
# Huaicheng Li <huaicheng@cs.uchicago.edu>
# Run FEMU as a black-box SSD (FTL managed by the device)

# image directory
IMGDIR=$HOME/images
# Virtual machine disk image
OSIMGF=$IMGDIR/u20s.qcow2

if [[ ! -e "$OSIMGF" ]]; then
	echo ""
	echo "VM disk image couldn't be found ..."
	echo "Please prepare a usable VM image and place it as $OSIMGF"
	echo "Once VM disk image is ready, please rerun this script again"
	echo ""
	exit
fi

sudo x86_64-softmmu/qemu-system-x86_64 \
    -name "FEMU-BBSSD-VM" \
    -enable-kvm \
    -cpu host \
    -smp 4 \
    -m 4G \
    -device virtio-scsi-pci,id=scsi0 \
    -device scsi-hd,drive=hd0 \
    -drive file=$OSIMGF,if=none,aio=native,cache=none,format=qcow2,id=hd0 \
    -device femu,devsz_mb=4096,femu_mode=1 \
    -net user,hostfwd=tcp::8080-:22 \
    -net nic,model=virtio \
    -nographic \
    -qmp unix:./qmp-sock,server,nowait 2>&1 | tee log

后续进行一些具体实验后再补充一些FEMU在实际研究过程中的使用步骤

Reference

  1. https://github.com/vtess/FEMU
  2. https://github.com/vtess/FEMU/wiki
  3. https://www.qemu.org/docs/master/about/removed-features.html#localtime-removed-in-3-1
0%