QEMU入门5:为virt板引入一个sd-card

文章目录

  • 前言
    • 环境
  • qemu设备仿真流程
  • qemu 命令行帮助
  • qemu monitor帮助
  • sd卡相关概念
  • 添加sd-card
  • create_sdbus
  • 修改设备树
  • 启动脚本
  • mmc检测成功
  • 额外说明

前言

virt默认不支持mmc设备,如果只是想引入一个sd/mmc设备,那直接在启动脚本里增加一个sdhci-pci,再在内核里新增sdhci-pci的驱动就可以了。
本篇记录的是,通过修改virt板代码,引入一个pl181(sdhci),从而引入sdcard的流程。

系列文章:

QEMU入门1:ubuntu22.04搭建QEMU运行环境
QEMU入门2:使用qemu简单的运行一个aarch64 linux内核
QEMU入门3:制作initrd、根文件系统
QEMU入门4:aarch64虚拟机安装grub

环境

ubuntu22.04
qemu-8.1.5
本文所用内容已上传github,文章全部内容均在arco-qemu/arco-virt路径下
github仓库地址:https://github.com/ARCO-D/arco-qemu

qemu设备仿真流程

设备实现(如果需要自己仿真设备
总线连接(将设备挂载到虚拟机
设备配置(内存映射、中断连接
设备树添加

qemu 命令行帮助

qemu -device help
# 查看某个虚拟机支持的所有设备
qemu -device nvme,help
# 查看指定的某设备的配置
ctrl+a c
# 进入/退出 qemu monitor
ctrl+a h
# 查看所有的ctrl+a系列帮助(包括监视器
qemu -trace xx
# 跟踪xx的调用(-trace help列出可以trace的调用

qemu monitor帮助

info block
# 查看块设备
qom-list
# 查看对象(组织结构像目录
qom-get $path $name
# 查看对象属性, 例:
(qemu) qom-get /machine/unattached/device[7]/ card-inserted[0]
"/machine/unattached/device[4]/unnamed-gpio-in[4]"

sd卡相关概念

sd-card:sd卡和emmc都是nand flash设备,因为qemu已经有了sd-card,所以仿真emmc设备可以通过sd-card来替代(/dev下都是mmcblk*
sd-bus:sd卡的电气总线,规定Vcc、Vss、CLK、命令线、数据线DAT0-3,是一种规范(就是sd卡槽的引脚
sdhci:主机上的sd控制器,通过访问这个控制器与sd卡通信(就像spi控制器那样的控制器
sdhci-pci:有时会使用 sd卡-sd读卡器-pci接口-主机 这样的连接方式,sdhci-pci就是实现sd读卡器-pci这一段路的控制器(cpld-spi-iic
pci:并行总线,pcie是它的串行升级版本
pl181:arm实现的一个公版sdhci控制器

添加sd-card

create_sdbus

在machvirt_init函数中添加 create_sdbus(vms, sysmem);
create_bus函数内容如下:

/* create_sdbus总线说明:
 * mmin_map   : 内存起始地址是0x40000000 + 0x40000000(1G), 为了不冲突就从0x80000000开始了
 * connect_irq: a15irqmap里占用了1-9,16+ 所以这里选了没占用的10和11; 0和1是pl181设备里声明的两根中断线
 * cd-inserted: 不需要像vexpress那样配qdev_connect_gpio_out_named, 配了反而不行
 */
static void create_sdbus(const VirtMachineState *vms, MemoryRegion *mem)
{
    DeviceState *dev = qdev_new("pl181");
    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x80000000);
    // interrupt
    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(vms->gic, 10));
    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, qdev_get_gpio_in(vms->gic, 11));
}

修改设备树

virt板中的设备是通过qemu_fdt函数生成的设备树节点,这里我们直接修改dts文件:

/*
regulator-name随便配, 但需要有这个供电mmc才能用
*/
vmmc_supply: regulator {
	compatible = "regulator-fixed";
	regulator-name = "3V3";
	regulator-min-microvolt = <3300000>;
	regulator-max-microvolt = <3300000>;
	regulator-always-on;
};

/*
interrupts需要配两个, 注意冲突
cd-gpios可以不配
时钟不配两个似乎也行
*/
mmc@80000000 {
	compatible = "arm,pl181", "arm,primecell";
	reg = <0x00 0x80000000 0x00 0x1000>;
	interrupts = <0x00 0x0a 0x04>, <0x00 0x0b 0x04>;
	clocks = <0x8000>;
	clock-names = "apb_pclk";
	bus-width = <4>;
	max-frequency = <5000000>;
	vmmc-supply = <&vmmc_supply>;
	wp-gpios = <0x8007 6 0>;
	cd-gpios = <0x8007 7 1>;
};

启动脚本

../build/qemu-system-aarch64 \
-nographic \
-M virt \
-cpu cortex-a55 \
-smp 4 \
-m 1G \
-dtb arco.dtb \
-kernel Image-6.6.57 \
-initrd initrd.cpio.gz \
-append "root=/dev/ram0 console=ttyAMA0 init=/linuxrc ignore_loglevel nokaslr" \
-drive file=arco.img,if=none,id=sdc,format=raw \
-device sd-card,drive=sdc,bus=sd-bus

mmc检测成功

arco-virt ~ # dmesg |grep mmc
[    0.250995] mmci-pl18x 80000000.mmc: Got CD GPIO
[    0.251170] mmci-pl18x 80000000.mmc: Got WP GPIO
[    0.252818] mmci-pl18x 80000000.mmc: mmc0: PL181 manf 41 rev0 at 0x80000000 irq 20,21 (pio)
[    0.290216] mmc0: new SD card at address 4567
[    0.291567] mmcblk0: mmc0:4567 QEMU! 2.00 GiB
[    0.297904]  mmcblk0: p1 p2

输出类似信息,说明检测成功了

额外说明

关于启动脚本里指定的console=ttyAMA0
这个和virt板的外设无关,是pl011默认使用的终端名,声明在内核的amba-pl011.c驱动里

你可能感兴趣的:(QEMU,驱动开发)