qemu模拟arm64平台

599 阅读3分钟

配置busybox

下载busybox

https://github.com/mirror/busybox/releases/tag/1_36_0

配置busybox编译参数

make defconfig ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-
make menuconfig ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-

勾选编译静态库

Settings  --->
    [*] Build static binary (no shared libs)

编译busybox

make -j4 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-
make install

busybox快速构建_install脚本

构建完整的根文件系统需要在_install目录下创建各类文件,因此直接将这些重复的动作写成一个脚本。

#!/bin/bash
set -x

BUSYBOX_PATH=$PWD
BUSYBOX_INSTALL_PATH=$PWD/_install

function add_info_to_busybox_rcS() {
    pushd $BUSYBOX_INSTALL_PATH
cat << EOF > ./etc/init.d/rcS
mkdir -p /sys
mkdir -p /tmp
mkdir -p /proc
mkdir -p /mnt
/bin/mount -a
mkdir -p /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
EOF
    popd
}

function copy_lib_to_busybox_lib() {
    pushd $BUSYBOX_INSTALL_PATH
    sudo cp -rf /usr/aarch64-linux-gnu/lib/* ./lib
    sudo cp -rf /usr/aarch64-linux-gnu/lib64/* ./lib
    popd
}

function mknod_for_busybox_lib() {
    pushd $BUSYBOX_INSTALL_PATH
    pushd ./dev
    sudo mknod -m 664 tty1 c 4 1
    sudo mknod -m 664 tty2 c 4 2
    sudo mknod -m 664 tty3 c 4 3
    sudo mknod -m 664 tty4 c 4 4
    sudo mknod -m 664 console c 5 1
    sudo mknod -m 664 null c 1 3
    popd
    popd
}

function add_info_to_profile() {
    pushd $BUSYBOX_INSTALL_PATH
cat << EOF > ./etc/profile
#!/bin/sh
export HOSTNAME=idle
export USER=timelessxp
export HOME=/home
export PS1="[timelessxp@qemu_arm64 \W]# "
PATH=/bin:/sbin:/usr/bin:/usr/sbin
LD_LIBRARY_PATH=/lib:/usr/lib:$LD_LIBRARY_PATH
export PATH LD_LIBRARY_PATH
EOF
    popd
}

function add_info_to_inittab() {
    pushd $BUSYBOX_INSTALL_PATH
cat << EOF > ./etc/inittab
::sysinit:/etc/init.d/rcS
::respawn:-/bin/sh
::askfirst:-/bin/sh
::ctrlaltdel:/bin/umount -a -r
EOF
    popd
}

function add_info_to_fstab() {
    pushd $BUSYBOX_INSTALL_PATH
cat << EOF > ./etc/fstab
#device  mount-point    type     options   dump   fsck order
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
debugfs /sys/kernel/debug debugfs defaults 0 0
#kmod_mount /mnt 9p trans=virtio 0 0
EOF
    popd
}

function init_base_dir() {
    pushd $BUSYBOX_INSTALL_PATH
    mkdir data dev etc home lib mnt proc root sys tmp var
    mkdir -p ./etc/init.d
    pushd ./etc
    # 下面这句可能导致init卡住
    touch fstab inittab profile
    popd
    pushd $BUSYBOX_INSTALL_PATH/etc/init.d
    touch rcS
    chmod a+x rcS
    popd
}

function main_function() {
    pushd $BUSYBOX_INSTALL_PATH
    init_base_dir
    add_info_to_busybox_rcS
    copy_lib_to_busybox_lib
    mknod_for_busybox_lib
    add_info_to_fstab
    add_info_to_inittab
    add_info_to_profile
    popd
}

main_function

busybox快速制作rootfs脚本

上述的文件目录搭建完成后,可以通过以下脚本完成rootfs镜像的生成,需要使用root权限。

#!/bin/bash
if [ -f rootfs_ext4.img ];then
    rm rootfs_ext4.img
fi

# 拷贝ko文件到指定的目录下,方便驱动代码的验证。
find ./my_code/drv_code -name "*.ko" | xargs -I {} cp -vf {} _install/my_drv/

dd if=/dev/zero of=rootfs_ext4.img bs=1M count=256
mkfs.ext4 rootfs_ext4.img
mkdir -p tmpfs
mount -t ext4 rootfs_ext4.img tmpfs/ -o loop
cp -af _install/* tmpfs/
umount tmpfs
rm -rf tmpfs
chmod 777 rootfs_ext4.img

cp rootfs_ext4.img ../linux

配置kernel

sudo apt-get install build-essential zlib1g-dev pkg-config libglib2.0-dev binutils-dev libboost-all-dev autoconf libtool libssl-dev libpixman-1-dev libpython-dev python-pip python-capstone virtualenv
# 编译
make defconfig ARCH=arm64
make ARCH=arm64 Image -j8  CROSS_COMPILE=aarch64-linux-gnu-
qemu-system-aarch64 -machine virt -cpu cortex-a57 -machine type=virt -m 512 -smp 1 -nographic -kernel arch/arm64/boot/Image -drive format=raw,file=../busybox-1.35.0/rootfs_ext4.img -append "noinitrd root=/dev/vda rw console=ttyAMA0 loglevel=8" -fsdev local,id=kmod_dev,path=$PWD/kmodules,security_model=none -device virtio-9p-device,fsdev=kmod_dev,mount_tag=kmod_mount

使用 echo +30 > /sys/class/rtc/rtc0/wakealarm 可以触发休眠唤醒 echo "mem" > /sys/power/state

使用gdb调试kernel

gdb-multiarch vmlinux
target remote localhost:1234
c

dump QEMU的设备树

qemu-system-aarch64 -machine virt,dumpdtb=file.dtb -cpu cortex-a57 -machine type=virt -m 1024 -smp 4 -nographic -kernel arch/arm64/boot/Image -drive format=raw,file=./rootfs_ext4.img -append "noinitrd root=/dev/vda rw console=ttyAMA0 loglevel=8 nokasrl" -fsdev local,id=kmod_dev,path=$PWD/kmodules,security_model=none -device virtio-9p-device,fsdev=kmod_dev,mount_tag=kmod_mount

在-machine选项后面加上dumpdtb=file.dtb,就可以把设备树文件dump到file.dtb中。

dtb转dts

dtc -I dtb file.dtb -O dts -o file.dts

dts转dtb,并指定

dtc -O dtb  -I dts file.dts -o file.dtb

指定的方法为:在启动qemu的时候,添加上-dtb file.dtb即可。

qemu-system-aarch64 -machine virt -cpu cortex-a57 -machine type=virt -m 1024 -smp 4 -nographic -kernel arch/arm64/boot/Image -dtb file.dtb -drive format=raw,file=../../busybox-1.36.1/rootfs
_ext4.img -append "noinitrd root=/dev/vda rw console=ttyAMA0 loglevel=8 nokasrl" -fsdev local,id=kmod_dev,path=$PWD/kmodules,security_model=none -device virtio-9p-device,fsdev=kmod_dev,mount_ta
g=kmod_mount

问题记录

  1. 报modprobe binfmt-464c cannot be processed, kmod busy with 50 threads for more than 5 seconds now错误 解决方案:lib库缺失导致,确保copy的lib文件成功。

  2. gdb停不住的问题 解决方案1:在-append选项中加上nokaslr 解决方案2:更换gdb版本。

  3. cannot create /proc/sys/kernel/hotplug: nonexistent directory make menuconfig的时候,打开以下选项。 Device Drivers > Generic Driver Options > Support for uevent helper

参考链接: www.cnblogs.com/phoebus-ma/… juejin.cn/post/711312…