一、PCIE config空间
pci设备的config空间只有256字节,X86架构下是通过两个IO端口访问的,0xCF8/0xCFC端口,分别用于选通地址和传输数据。当前大部分设备都是pcie设备,config空间扩展到了4KB,而对于[256-4096)的扩展config空间,X86是通过memory映射的方式访问,并非IO端口的形式。也就是X86会把pcie的config空间映射到一片memory空间,访问这片空间的时候RC就会发出config tlp报文。
这是真实的硬件设计,而对于QEMU+KVM的虚机场景,显然是要基于硬件实现和虚拟化的需求设计虚机访问config空间的完整流程。
文章对于qemu的虚机memory管理机制不单独介绍。
二、config空间(前256B)的模拟
这一部分的模拟,首先从hw/pci-host/q35.c查看。q35是一种常用的X86机型,当前qemu里的X86机型都是使用q35来模拟。
qemu-system-x86_64 -machine q35,accel=kvm -cpu host -smp sockets=2,cores=2,threads=1 -m 4096
具体的q35的machine模拟初始化接口,里面代码很多,我们只关注pci host主桥的初始化。在pc_q35_init接口里直接调用qdev_new()接口(非命令行显式创建)实例化一个host主桥,设备类型为TYPE_Q35_HOST_DEVICE,这个设备的驱动定义在hw/pci-host/q35.c里。
/* PC hardware initialisation */
static void pc_q35_init(MachineState *machine)
{
/* create pci host bus */
q35_host = Q35_HOST_DEVICE(qdev_new(TYPE_Q35_HOST_DEVICE));
}
在TYPE_Q35_HOST_DEVICE的realize接口中,对0xCF8/0xCFC两个端口进行了注册,注册到conf_mem和data_mem两个MemoryRegion里。
static void q35_host_realize(DeviceState *dev, Error **errp)
{
sysbus_add_io(sbd, MCH_HOST_BRIDGE_CONFIG_ADDR, &pci->conf_mem);
sysbus_init_ioports(sbd, MCH_HOST_BRIDGE_CONFIG_ADDR, 4);
sysbus_add_io(sbd, MCH_HOST_BRIDGE_CONFIG_DATA, &pci->data_mem);
sysbus_init_ioports(sbd, MCH_HOST_BRIDGE_CONFIG_DATA, 4);
}
在TYPE_Q35_HOST_DEVICE的instance_init接口中,添加了0xCF8/0xCFC端口对应的MemoryRegion的处理函数。
479




被折叠的 条评论
为什么被折叠?



