Qemu模拟arm cpu运行Linux

ARM 82浏览

Qemu模拟arm cpu运行Linux系统
本文介绍使用qemu虚拟arm cpu来运行和调试Linux系统的一般方法
一.首先需要构建tool-chain
可以使用crosstool-ng构建,从官网下载1.9.3版本,解压后在源代码根目录运行,并假设$CTNG为安装目录
./configure --prefix=$CTNG
make;make install
在源代码目录的samples目录下有一个arm-unknown-linux-gnueabi的目录,该目录下的crosstool.config文件,把文件复制到$CTNG/bin目录下并更名为.config,这是crosstool编译arm工具链的基本配置,我们可以在这个基础上进行修改
执行如下的命令进入配置界面:
cd $CTNG/bin
./ct-ng menuconfig
进行如下的修改:

1. Paths and misc options->Local tarballs directory,这里填写编译toolchain所需要的依赖tarball的下载目录,由于编译工具链可能会反复多次,所以我们最好还是把下载的tarball保存下来,节省时间。

另外,ct-ng会在$CTNG/bin目录下建立.build目录,该目录下的tarball目录中建立了很多的软连接就是指向这个local tarball目录的,另外有一个src目录就是解压缩tarball的目录

2.Prefix directory会指定最后工具链的存放位置,默认是~/x-tools/arm-unknown-linux-gnueabi
3.Target options,确认architecture是arm,确认Use EABI
4.Operating System,这一步很重要,其实不用修改这里的选项,只需要记住这里编译的Linux kernel version,因为后面我们编译内核的时候,需要下载同样版本的内核代码,而且最好选择2.6.32.25,因为这是一个long-term stable ersion,如果使用custom tarballs的话,虽然工具链可以编译通过,但是有可能运行内核的时候会panic

修改完配置之后,执行
./ct-ng build
运行过程中可能出现的问题
主要就是tarball下载失败或者解压缩失败的情况,可以手动下载,然后存放到local tarball目录中,然后到$CTNG/bin/.build/src目录中把前一次解压缩失败的.extracting文件删除,然后继续即可

编译完成后,将在~/x-tools/arm-unknown-linux-gnueabi/bin目录下看到众多的交叉编译器命令,把该目录加入到PATH中,后续会用到这些命令
二.制作root文件系统
1.编译busybox
下载busybox1.21.1,解压缩后,在源代码根目录执行
make defconfig
make menuconfig
需要修改的地方如下:
Busybox settings->Build options->Cross compiler prefix,这里设置交叉编译的前缀,设置为arm-unknown-linux-gnueabi-,注意最后那个‘-’
Busybox settings->Installation options->busybox installation prefix,这里设置最后busybox生成的根文件系统的目录,这里假设该目录为$RFS
其他就没什么修改的了,保存退出,执行
make ; make install
2.root fs
1)创建lib目录,并从~/x-tools/arm-unknown-linux-gnueabi/arm-unknown-linux-gnueabi/sys-root/lib目录中复制ld-linux.so.3,libc.so.6,libm.so.6这三个文件到该目录
2)创建etc目录,并在该目录下创建如下的文件
fstab
none /proc proc   defaults   0 0
none        /dev/pts   devpts mode=0622  0 0
tmpfs       /dev/shm   tmpfs  defaults   0 0

groups
root:x:0

inittab
::respawn:/sbin/getty -L ttyAMA0 115200 xterm
# Stuff to do when restarting the init process                                 
::sysinit:/etc/init.d/rcS                                                      
::restart:/sbin/init                                                                                                      
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a   

passwd
root::0:0:root:/root:/bin/sh
3)创建etc/init.d目录,并在该目录中创建rcS文件
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
/sbin/mdev -s
并设置rcS为可执行
chmod +x rcS
4)创建dev目录,并在该目录下执行
mknod console c 5 1
mknod null c 1 3
mknod ttyAMA0 c 204 64
5)创建mnt,proc,root,tmp目录
6)从sourceforge上下载一个名为genext2fs的程序,用来制作rootfs
genext2fs -b 32768 -d $RFS rootfs.img
该命令将创建32M的名为rootfs.img的根文件系统
gzip -9v rootfs.img
该命令将把rootfs.img压缩为rootfs.img.gz,至此根文件系统就制作完毕了

三.编译内核
1.下载2.6.32.25版本的linux内核,并解压缩,在源代码根目录执行
make ARCH=arm versatile_defconfig
make ARCH=arm menuconfig
2.配置内核参数
1)Kernel Features->Use the ARM EABI to compile the kernel
                    Allow old ABI binaries to run with this kernel
2)ensure General Setup->Inital Ram filesystem and RAM Disk support checked
3)Boot Options->default kernel command string  : console=ttyAMA0
4)Device Drivers->Block devices->Ram block device support->Default ram disk size : 32768
5)如果需要调试内核的话,还要加上kernel hacking->compile the kernel with debug info
3.执行
make zImage ARCH=arm CROSS_COMPILE=arm-unknown-linux-gnueabi-

四.在qemu中加载zImage
apt-get install qemu
执行如下的命令加载
qemu-system-arm -M versatilepb -s -m 256M -serial stdio -kernel {your-compile-dir}/arch/arm/boot/zImage -initrd {your-rfs-dir}/rootfs.img.gz -append "root=/dev/ram rw init=/linuxrc mem=256M console=ttyAMA0"

五.调试内核
在上述命令中加入-S参数,qemu会停下来在1234端口监听
重新开一个terminal,执行
arm-unknown-linux-gnueabi-gdb -x "gdb.cmds" {your-kernel-dir}/vmlinux}
其中gdb.cmds的内容如下:
target remote localhost:1234
如果你喜欢有界面的ddd,可以使用如下命令
ddd --debugger arm-unknown-linux-gnueabi-gdb -x "ddd.cmds" $KERNEL_SRC/vmlinux