這篇文章只是拿來記錄compile Kernel for Cortex-A57, 用於研究PCIe Driver, 其餘的rootfs與busybox請參考附錄
[brook@:~/Projects/qemu/linux-virt]$ sudo apt-get install gcc-aarch64-linux-gnu #for ARM64
[brook@:~/Projects/qemu/linux-virt]$ export ARCH=arm64
[brook@:~/Projects/qemu/linux-virt]$ export CROSS_COMPILE=aarch64-linux-gnu-
[brook@:~/Projects/qemu/linux-virt]$ cp arch/arm64/configs/defconfig .config
[brook@:~/Projects/qemu/linux-virt]$ make olddefconfig
HOSTCC scripts/basic/fixdep
HOSTCC scripts/kconfig/conf.o
HOSTCC scripts/kconfig/confdata.o
HOSTCC scripts/kconfig/expr.o
LEX scripts/kconfig/lexer.lex.c
YACC scripts/kconfig/parser.tab.[ch]
HOSTCC scripts/kconfig/lexer.lex.o
HOSTCC scripts/kconfig/parser.tab.o
HOSTCC scripts/kconfig/preprocess.o
HOSTCC scripts/kconfig/symbol.o
HOSTLD scripts/kconfig/conf
scripts/kconfig/conf --olddefconfig Kconfig
#
# configuration written to .config
#
[brook@:~/Projects/qemu/linux-virt]$ make -j16
[brook@:~/Projects/qemu/linux-virt]$ qemu-system-aarch64 -machine virt -cpu cortex-a57 -smp 8 -m 4096 -kernel ./arch/arm64/boot/Image -append "console=ttyAMA0 root=/dev/vda" -nographic -initrd ../initrd-arm.img
[ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x411fd070]
...
Please press Enter to activate this console.
/ #
/ # lspci -k
00:01.0 Class 0200: 1af4:1000 virtio-pci
00:00.0 Class 0600: 1b36:0008
/ # uname -r
5.4.0
1af4:1000是Virtio network device, 而1b36:0008是QEMU PCIe Host bridge
ETH PCIe driver在"drivers/virtio/virtio_pci_common.c", 其vendor ID是0x1af4, 當device插入時, 就會去比對ID, match後就會載入該module並probe
/* Qumranet donated their vendor ID for devices 0x1000 thru 0x10FF. */
static const struct pci_device_id virtio_pci_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_REDHAT_QUMRANET, PCI_ANY_ID) },
{ 0 }
};
MODULE_DEVICE_TABLE(pci, virtio_pci_id_table);
...
static struct pci_driver virtio_pci_driver = {
.name = "virtio-pci",
.id_table = virtio_pci_id_table,
.probe = virtio_pci_probe,
.remove = virtio_pci_remove,
#ifdef CONFIG_PM_SLEEP
.driver.pm = &virtio_pci_pm_ops,
#endif
.sriov_configure = virtio_pci_sriov_configure,
};
module_pci_driver(virtio_pci_driver);
這裡我把PCI ID移成PCI_DEVICE(PCI_VENDOR_ID_REDHAT_QUMRANET + 1, 再透過echo <vendor_code> <device_code> > /sys/bus/pci/drivers/<pci_device_driver>/new_id動態對PCIe driver新增ID, 讓系統認到網卡
[brook@:~/Projects/qemu/linux-virt]$ git diff .
diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
index f2862f66c2ac..60aef3fea650 100644
--- a/drivers/virtio/virtio_pci_common.c
+++ b/drivers/virtio/virtio_pci_common.c
@@ -492,7 +492,7 @@ static const struct dev_pm_ops virtio_pci_pm_ops = {
/* Qumranet donated their vendor ID for devices 0x1000 thru 0x10FF. */
static const struct pci_device_id virtio_pci_id_table[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_REDHAT_QUMRANET, PCI_ANY_ID) },
+ { PCI_DEVICE(PCI_VENDOR_ID_REDHAT_QUMRANET + 1, PCI_ANY_ID) },
{ 0 }
};
@@ -514,6 +514,7 @@ static int virtio_pci_probe(struct pci_dev *pci_dev,
{
struct virtio_pci_device *vp_dev, *reg_dev = NULL;
int rc;
+ printk("%s(#%d): Brook\n", __FUNCTION__, __LINE__);
/* allocate our structure and fill it out */
vp_dev = kzalloc(sizeof(struct virtio_pci_device), GFP_KERNEL);
lspci會認到1af4:1000, 但是eth driver因為被我跳號, 所以認不到, 再透過/sys/bus/pci/drivers/<pci_device_driver>/new_id將往卡帶起來
/ # lspci
00:01.0 Class 0200: 1af4:1000
00:00.0 Class 0600: 1b36:0008
/ # ifconfig -a
lo Link encap:Local Loopback
LOOPBACK MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
/ # echo 1af4 1000 > /sys/bus/pci/drivers/virtio-pci/new_id
[ 130.728345] virtio_pci_probe(#517): Brook
[ 130.729216] virtio-pci 0000:00:01.0: enabling device (0000 -> 0003)
/ # ifconfig -a
eth0 Link encap:Ethernet HWaddr 52:54:00:12:34:56
BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
lo Link encap:Local Loopback
LOOPBACK MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
透過echo <Domain:Bus:Device.Function> > /sys/bus/pci/drivers/<pci_device_driver>/unbind將driver移除, 也可以透過echo <Domain:Bus:Device.Function> > /sys/bus/pci/drivers/<pci_device_driver>/bind重新將driver帶上
/ # lspci
00:01.0 Class 0200: 1af4:1000
00:00.0 Class 0600: 1b36:0008
/ # echo 0000:00:01.0 > /sys/bus/pci/drivers/virtio-pci/unbind
[ 5163.097254] hrtimer: interrupt took 87350512 ns
/ # ifconfig -a
lo Link encap:Local Loopback
LOOPBACK MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
/ # echo 0000:00:01.0 > /sys/bus/pci/drivers/virtio-pci/bind
[ 5183.251580] virtio_pci_probe(#517): Brook
/ # ifconfig -a
eth0 Link encap:Ethernet HWaddr 52:54:00:12:34:56
BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
lo Link encap:Local Loopback
LOOPBACK MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
參考資料:
- https://blog.csdn.net/zhqh100/article/details/51173275, qemu模拟Cortex-A57运行Linux4.5.1
- Build the Linux Kernel and Busybox for ARM and run them on QEMU
- https://zhuanlan.zhihu.com/p/113467453, qemu PCIe总线结构
- https://pci-ids.ucw.cz/read/PC/1af4, The PCI ID Repository
- https://stackoverflow.com/questions/22901282/hard-time-in-understanding-module-device-tableusb-id-table-usage, Hard time in understanding MODULE_DEVICE_TABLE(usb, id_table) usage