Skip to content

Instantly share code, notes, and snippets.

@olegslavkin
Last active June 9, 2019 09:29
Show Gist options
  • Save olegslavkin/47c71512f35630e032461e31cee65c8a to your computer and use it in GitHub Desktop.
Save olegslavkin/47c71512f35630e032461e31cee65c8a to your computer and use it in GitHub Desktop.
QEMU ARM Lab in docker

prepare host (docker host)

export EALAB=~/Projects/qemu-arm-lab/
mkdir -p ${EALAB} && cd "$_"

# This's for rootfs booted by NFS 
# install nfs server. For ubuntu apt install -y nfs-kernel-server
echo "${EALAB}/rootfs *(rw,sync,no_root_squash,no_subtree_check)" | sudo tee --append /etc/exports
sudo systemctl restart nfs-kernel-server.service

docker run -it --rm -v $(pwd):/mnt --privileged -w /mnt --net host -h qemu-arm-lab --name qemu-arm-lab ubuntu:18.10

prepare env container

export EALAB=/mnt
export EALABSRC=${EALAB}/src
export EALABDWN=${EALAB}/downloads
export EALABBOOT=${EALAB}/boot
export EALABBLD=${EALAB}/build
export EALABRFS=${EALAB}/rootfs
mkdir -p ${EALABSRC} && cd "$_"
apt update && apt upgrade -y
apt install -y gcc wget xz-utils python libglib2.0-dev pkg-config libpixman-1-dev libncurses-dev bison flex git bc gcc-arm-linux-gnueabihf iproute2 dnsmasq
cd ${EALAB}
mkdir -p {downloads,boot,build,rootfs}

Export package version and vars

export QEMUVER=4.0.0
export UBOOTVER=2019.04
export LINUXVER=5.0.10
export BUSYBOXVER=1.30.1
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-

Download and compile qemu

wget https://download.qemu.org/qemu-${QEMUVER}.tar.xz -P ${EALABDWN}
tar xf ${EALABDWN}/qemu-${QEMUVER}.tar.xz -C ${EALABBLD}
cd ${EALABBLD}/qemu-${QEMUVER}
./configure \
--target-list=arm-softmmu,arm-linux-user \
--enable-debug \
--extra-cflags="-g3 -pg -fno-omit-frame-pointer" \
--extra-cxxflags="-g3 -pg -fno-omit-frame-pointer" \
--extra-ldflags="-g3" \
--disable-strip --disable-pie
make -j $(nproc) && make install

Download and compile u-boot

Machine: vexpress_ca9x4

wget https://github.com/u-boot/u-boot/archive/v${UBOOTVER}.tar.gz -P ${EALABDWN}
tar xf ${EALABDWN}/v${UBOOTVER}.tar.gz -C ${EALABBLD}
cd ${EALABBLD}/u-boot-${UBOOTVER}
ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} make vexpress_ca9x4_defconfig O=${EALABBLD}/u-boot-${UBOOTVER}-build
ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} make -j $(nproc) O=${EALABBLD}/u-boot-${UBOOTVER}-build
cp ${EALABBLD}/u-boot-${UBOOTVER}-build/{u-boot,u-boot.bin} ${EALABBOOT}

Download and compile Linux Kernel

export LNXMAJ=$(echo ${LINUXVER} | cut -c1)
wget https://mirror.yandex.ru/pub/linux/kernel/v${LNXMAJ}.x/linux-${LINUXVER}.tar.xz -P ${EALABDWN}
tar xf ${EALABDWN}/linux-${LINUXVER}.tar.xz -C ${EALABBLD}
cd ${EALABBLD}/linux-${LINUXVER}
ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} make vexpress_defconfig  O=${EALABBLD}/linux-${LINUXVER}-build 
ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} make -j $(nproc) O=${EALABBLD}/linux-${LINUXVER}-build zImage dtbs
ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} make -j $(nproc) O=${EALABBLD}/linux-${LINUXVER}-build INSTALL_MOD_PATH=${EALABRFS} modules modules_install
cp ${EALABBLD}/linux-${LINUXVER}-build/arch/arm/boot/{Image,zImage} ${EALABBOOT}
cp ${EALABBLD}/linux-${LINUXVER}-build/arch/arm/boot/dts/*.dtb ${EALABBOOT}

Download and compile Busybox

wget https://www.busybox.net/downloads/busybox-${BUSYBOXVER}.tar.bz2 -P ${EALABDWN}
tar xf ${EALABDWN}/busybox-${BUSYBOXVER}.tar.bz2 -C ${EALABBLD}
mkdir -p ${EALABBLD}/busybox-${BUSYBOXVER}-build
cd ${EALABBLD}/busybox-${BUSYBOXVER}
ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} make defconfig O=${EALABBLD}/busybox-${BUSYBOXVER}-build
cd ${EALABBLD}/busybox-${BUSYBOXVER}-build
ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} make -j $(nproc) install CONFIG_STATIC=y CONFIG_PREFIX=${EALABRFS} O=${EALABBLD}/busybox-${BUSYBOXVER}-build

Test qemu

Linux kernel (Cortex A9)

qemu-system-arm -M vexpress-a9 -m 256 -dtb ${EALABBOOT}/vexpress-v2p-ca9.dtb \
-kernel ${EALABBOOT}/zImage -nographic

Linux kernel (Cortex A15)

qemu-system-arm -M vexpress-a15 -m 256 -dtb ${EALABBOOT}/vexpress-v2p-ca15-tc1.dtb \
-kernel ${EALABBOOT}/zImage -nographic

u-boot (Cortex A9)

qemu-system-arm -M vexpress-a9 -m 256 -kernel ${EALABBOOT}/u-boot -nographic -dtb ${EALABBOOT}/vexpress-v2p-ca9.dtb

Prepare network

ip link add qemu-arm-lab type bridge
ip link set dev qemu-arm-lab up
ip a a 192.168.1.250/24 dev qemu-arm-lab
dnsmasq -p 1053 -F 192.168.1.100,192.168.1.200,12h --enable-tftp --tftp-root=${EALABBOOT}
mkdir -p /usr/local/etc/qemu
echo 'allow all' > /usr/local/etc/qemu/bridge.conf

Boot

qemu-system-arm -M vexpress-a9 -m 256 -kernel ${EALABBOOT}/u-boot -nographic -dtb ${EALABBOOT}/vexpress-v2p-ca9.dtb -net nic -net bridge,br=qemu-arm-lab

u-boot

setenv ipaddr 192.168.1.100
setenv serverip 192.168.1.250
setenv netmask 255.255.255.0
tftpboot 0x61000000 vexpress-v2p-ca9.dtb
tftpboot 0x62000000 zImage
bootz 0x62000000 - 0x61000000

mkdir -p ${EALABRFS}/dev

Note Please see nfs path

setenv ipaddr 192.168.1.100
setenv serverip 192.168.1.250
setenv netmask 255.255.255.0
setenv bootargs 'root=/dev/nfs rw nfsroot=192.168.1.250:<path>/Projects/qemu-arm-lab/rootfs,v3,tcp console=ttyAMA0 ip=dhcp rw'
tftpboot 0x61000000 vexpress-v2p-ca9.dtb
tftpboot 0x62000000 zImage
bootz 0x62000000 - 0x61000000

Boot kernel

qemu-system-arm -M vexpress-a9 -m 256 -kernel ${EALABBOOT}/zImage -nographic -dtb ${EALABBOOT}/vexpress-v2p-ca9.dtb -append "loglevel=8 root=/dev/nfs rw nfsroot=192.168.1.250:/<path>/Projects/qemu-arm-lab/rootfs/,v3,tcp nfsrootdebug console=ttyAMA0 ip=dhcp rw rootwait" -net nic -net bridge,br=qemu-arm-lab

Debug

Prepare Linux Kernel

cd ${EALABBLD}/linux-${LINUXVER}
ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} make menuconfig  O=${EALABBLD}/linux-${LINUXVER}-build
Kernel hacking  ---> Compile-time checks and compiler options  ---> Compile the kernel with debug info
Kernel hacking  ---> KGDB: kernel debugger  ---> KGDB: use kgdb over the serial console
Kernel hacking  ---> KGDB: kernel debugger  ---> KGDB_KDB: include kdb frontend for kgdb
ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} make -j $(nproc) O=${EALABBLD}/linux-${LINUXVER}-build zImage dtbs
ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} make -j $(nproc) O=${EALABBLD}/linux-${LINUXVER}-build INSTALL_MOD_PATH=${EALABRFS} modules modules_install
cp ${EALABBLD}/linux-${LINUXVER}-build/arch/arm/boot/{Image,zImage} ${EALABBOOT}
cp ${EALABBLD}/linux-${LINUXVER}-build/arch/arm/boot/dts/*.dtb ${EALABBOOT}
cp ${EALABBLD}/linux-${LINUXVER}-build/vmlinux ${EALABBOOT}

boot with debug

qemu-system-arm -M vexpress-a9 -m 256 -kernel ${EALABBOOT}/zImage -nographic -dtb ${EALABBOOT}/vexpress-v2p-ca9.dtb -append "loglevel=8 root=/dev/nfs rw nfsroot=192.168.1.250:/home/olegsl/Projects/qemu-arm-lab/rootfs/,v3,tcp nfsrootdebug console=ttyAMA0 init=/bin/busybox ip=dhcp rw rootwait" -net nic -net bridge,br=qemu-arm-lab -s -S

docker run -it --rm --privileged --name ealab-gdb --net host -w /mnt -v ${EALAB}:/mnt ubuntu:18.10 bash -c 'apt update && apt install -y python gdb-multiarch wget && wget -O /etc/gdb/gdbinit git.io/.gdbinit && gdb-multiarch -q /mnt/boot/vmlinux'
set architecture armv5tej
target extended-remote :1234
b do_mount_root
c
Breakpoint 1, do_mount_root (name=0x80a58910 <nfs_root_device> "192.168.1.250:/home/olegsl/Projects/qemu-arm-lab/rootfs/", fs=0x808d6b68 "nfs", flags=32768, data=0x80a58408 <nfs_root_options>) at /mnt/build/linux-5.0.10/init/do_mounts.c:388
388             int err = ksys_mount(name, "/root", fs, flags, data);
─── Assembly ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
0x80a012a8 do_mount_root+0  push    {r4, r5, r6, lr}
0x80a012ac do_mount_root+4  sub    sp, sp, #8
0x80a012b0 do_mount_root+8  str    r3, [sp]
0x80a012b4 do_mount_root+12 mov    r3, r2
─── Expressions ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
─── History ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
─── Memory ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
─── Registers ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
              r0 0x80a58910                         r1 0x808d6b68                         r2 0x00008000                         r3 0x80a58408                         r4 0x80b08c08          
              r5 0x00000005                         r6 0x80b0ba00                         r7 0x80b69530                         r8 0x00000006                         r9 0x808d6b68          
             r10 0x000003e8                        r11 0x00000000                        r12 0x8efc7a00                         sp 0x8e83ff60                         lr 0x80a01700          
              pc 0x80a012a8                       cpsr 0x60000013                      fpscr 0x00000000                      fpsid 0x41033090                      fpexc 0x00000000          
             PAR 0x00000000                      PAR_S 0x00000000                  ID_PFR0_S 0x00001031                  ID_AFR0_S 0x00000000                 ID_MMFR0_S 0x00100103          
        ID_ISAR2 0x21232041                   ID_ISAR3 0x11112131                    ID_PFR0 0x00001031                   ID_MMFR0 0x00100103                   ID_ISAR5 0x00000000          
      ID_ISAR1_S 0x13112111                    ID_DFR0 0x00000000                    ID_AFR0 0x00000000                   ID_MMFR1 0x20000000                   ID_MMFR2 0x01230000          
        ID_MMFR3 0x00002111                   ID_ISAR4 0x00111142                 ID_ISAR0_S 0x00101111                   ID_ISAR6 0x00000000                 ID_ISAR2_S 0x21232041          
      ID_ISAR3_S 0x11112131                  ID_DFR0_S 0x00000000                 ID_ISAR5_S 0x00000000                 ID_MMFR4_S 0x00000000                 ID_MMFR1_S 0x20000000          
        ID_ISAR1 0x13112111                   TPIDRPRW 0x00000000                     WFAR_S 0x00000000                     IFAR_S 0x00000000                   ID_ISAR0 0x00101111          
      ID_ISAR4_S 0x00111142                 ID_ISAR6_S 0x00000000                   ID_MMFR4 0x00000000                      CLIDR 0x09000003                       WFAR 0x00000000          
      ID_MMFR2_S 0x01230000                 ID_MMFR3_S 0x00002111                    MAIR0_S 0xff0a81a8                       AIDR 0x00000000                     CSSELR 0x00000000          
          PMCR_S 0x41002000                       PMCR 0x41002000                     PMSELR 0x00000000                    CLIDR_S 0x09000003                      MAIR1 0x00000000          
        DBGBVR_S 0x00000000                PMUSERENR_S 0x00000000                       IFAR 0x00000000               PMINTENCLR_S 0x00000000                      CPACR 0x00f00000          
         MAIR1_S 0x40e040e0                     DBGBCR 0x00000000                  PMCCNTR_S 0x00000000                  OSLSR_EL1 0x0000000a                     DBGBVR 0x00000000          
    PMCNTENSET_S 0x00000000               PMCNTENCLR_S 0x00000000                   PMOVSR_S 0x00000000                   TPIDRURW 0x00000000                   TPIDRURO 0x00000000          
          DBGBVR 0x00000000                     DBGBCR 0x00000000                     DBGBVR 0x00000000                 MDCCSR_EL0 0x00000000                   DBGBCR_S 0x00000000          
       DBGDIDR_S 0x35141000               MDCCSR_EL0_S 0x00000000                  DBGDSAR_S 0x00000000                  MDSCR_EL1 0x00000000                  PMUSERENR 0x00000000          
         PMCCNTR 0x00000000                   DBGBVR_S 0x00000000                   DBGBCR_S 0x00000000                     AIDR_S 0x00000000                   CSSELR_S 0x00000000          
      PMCNTENSET 0x00000000                 PMCNTENCLR 0x00000000                     PMOVSR 0x00000000                    VTTBR_S 0x0000000000000000            FAR_EL2 0x00000000          
          DBGBCR 0x00000000                  AFSR0_EL1 0x00000000                  AFSR1_EL1 0x00000000                     DBGBVR 0x00000000                     DBGBCR 0x00000000          
    PMINTENSET_S 0x00000000                      MAIR0 0x00000000                     DBGWCR 0x00000000                   PMSELR_S 0x00000000                    DBGDIDR 0x35141000          
        DBGBVR_S 0x00000000                    DBGDSAR 0x00000000                     DBGBVR 0x00000000                   DBGWVR_S 0x00000000                 PMINTENSET 0x00000000          
      PMINTENCLR 0x00000000                 VBAR_EL2_S 0x00000000                   DBGWVR_S 0x00000000                   DBGWCR_S 0x00000000                   CPTR_EL2 0x00000000          
       AFSR0_EL2 0x00000000                   HACR_EL2 0x00000000                     DBGBVR 0x00000000                     DBGBCR 0x00000000                     DBGWVR 0x00000000          
        DBGBVR_S 0x00000000                   DBGWVR_S 0x00000000                   DBGBVR_S 0x00000000                VPIDR_EL2_S 0x410fc090                     DBGBCR 0x00000000          
          DBGWCR 0x00000000                     DBGWVR 0x00000000                   DBGBCR_S 0x00000000                   DBGWVR_S 0x00000000                MDSCR_EL1_S 0x00000000          
        DBGBVR_S 0x00000000                   DBGBCR_S 0x00000000                   DBGWCR_S 0x00000000                    HAMAIR1 0x00000000                   DBGBCR_S 0x00000000          
          DBGWVR 0x00000000                  HPFAR_EL2 0x00000000              CNTHCTL_EL2_S 0x00000000             CNTHP_TVAL_EL2 0x00000000                     DBGWCR 0x00000000          
      MAIR_EL2_S 0x00000000                   DBGBCR_S 0x00000000                     DBGWVR 0x00000000                   DBGWCR_S 0x00000000                      MVBAR 0x00000000          
         HTTBR_S 0x0000000000000000            ESR_EL2 0x00000000                  VPIDR_EL2 0x410fc090                   MAIR_EL2 0x00000000                     DBGWCR 0x00000000          
        HSTR_EL2 0x00000000                   DBGWCR_S 0x00000000                  AFSR1_EL2 0x00000000                       DFAR 0x00000000                PMEVCNTR3_S 0x00000000          
           TEECR 0x00000001                        CTR 0x80038003                      TCMTR 0x00000000                PMEVCNTR0_S 0x00000000                PMEVCNTR1_S 0x00000000          
     PMEVCNTR2_S 0x00000000                   VBAR_EL2 0x00000000                     HMAIR1 0x00000000                  SCTLR_EL2 0x00000000                  AFSR0_EL3 0x00000000          
        HMAIR1_S 0x00000000                  AMAIR_EL2 0x00000000              CNTHP_CTL_EL2 0x00000000                      HTTBR 0x0000000000000000   CNTHP_TVAL_EL2_S 0x00000000          
     TTBR0_EL1_S 0x60004059                TTBR1_EL1_S 0x60004059                AMAIR_EL2_S 0x00000000                  HAMAIR1_S 0x00000000                     DFAR_S 0x00000000          
           DUMMY 0x00000000                  TPIDR_EL2 0x00000000                        SCR 0x00000000                      VTTBR 0x0000000000000000            TCR_EL2 0x00000000          
           HIFAR 0x00000000                  TTBR0_EL1 0x00000000                  TTBR1_EL1 0x00000000                      TTBCR 0x00000000                 VTCR_EL2_S 0x00000000          
        VTCR_EL2 0x00000000                  TCR_EL2_S 0x00000000                     TEEHBR 0x00000000                      DUMMY 0x00000000                  FAR_EL2_S 0x00000000          
 CNTHP_CTL_EL2_S 0x00000000                  ESR_EL2_S 0x00000000                HPFAR_EL2_S 0x00000000                    HCR_EL2 0x00000000                   MDCR_EL2 0x00000000          
           CTR_S 0x80038003                    TCMTR_S 0x00000000                    TLBTR_S 0x00000000                    TTBCR_S 0x00000000                      DUMMY 0x00000000          
            MIDR 0x410fc090                      DUMMY 0x00000000                      TLBTR 0x00000000                    MVBAR_S 0x00000000                    DUMMY_S 0x00000000          
         DUMMY_S 0x00000000                      DUMMY 0x00000000                CNTHCTL_EL2 0x00000000                    DUMMY_S 0x00000000                    HIFAR_S 0x00000000          
           NSACR 0x00000000                    DUMMY_S 0x00000000                    TEECR_S 0x00000001                    DUMMY_S 0x00000000                       DFSR 0x00000000          
            IFSR 0x00000000                  AFSR1_EL3 0x00000000                     MIDR_S 0x410fc090                  ACTLR_EL2 0x00000000                     VBAR_S 0x00000000          
            SDER 0x00000000                       CBAR 0x1e000000                      SCTLR 0x00c50078                  ACTLR_EL1 0x00000000                  PMEVCNTR3 0x00000000          
       PMEVCNTR0 0x00000000                  PMEVCNTR1 0x00000000                  PMEVCNTR2 0x00000000                       VBAR 0x00000000               PMEVTYPER0_S 0x00000000          
    PMEVTYPER1_S 0x00000000               PMEVTYPER2_S 0x00000000               PMEVTYPER3_S 0x00000000                 PMEVTYPER0 0x00000000                 PMEVTYPER1 0x00000000          
      PMEVTYPER2 0x00000000                 PMEVTYPER3 0x00000000                  CNTVOFF_S 0x0000000000000000       CNTHP_CVAL_S 0x0000000000000000        PMCCFILTR_S 0x00000000          
       DBGDRAR_S 0x00000000                   TEEHBR_S 0x00000000                ACTLR_EL1_S 0x00000000                    CPACR_S 0x00f00000                     DACR_S 0x00000051          
       A9_DIAG_S 0x00000000               A9_PWRDIAG_S 0x00000000                     DFSR_S 0x00000005                  FCSEIDR_S 0x00000000               CONTEXTIDR_S 0x00000000          
     A9_PWRCTL_S 0x00000000                TPIDR_EL2_S 0x00000000                     CBAR_S 0x1e000000                OSLSR_EL1_S 0x0000000a                     IFSR_S 0x00000000          
      TPIDRURW_S 0x00000000                 TPIDRURO_S 0x00000000                    CNTVOFF 0x0000000000000000            SCTLR_S 0x10c5387d                SCTLR_EL2_S 0x00000000          
     ACTLR_EL2_S 0x00000000                 TPIDRPRW_S 0x0e340000                 CNTHP_CVAL 0x0000000000000000              SCR_S 0x00000000                     SDER_S 0x00000000          
     AFSR0_EL1_S 0x00000000                AFSR1_EL1_S 0x00000000                AFSR0_EL2_S 0x00000000                 NEONBUSY_S 0x00000000                 CPTR_EL2_S 0x00000000          
      HSTR_EL2_S 0x00000000                  PMCCFILTR 0x00000000                AFSR0_EL3_S 0x00000000                AFSR1_EL3_S 0x00000000                 HACR_EL2_S 0x00000000          
       HCR_EL2_S 0x00000000                    NSACR_S 0x00000000                AFSR1_EL2_S 0x00000000                 MDCR_EL2_S 0x00000000                    DBGDRAR 0x00000000          
            DACR 0x00000000                  A9_PWRCTL 0x00000000                    A9_DIAG 0x00000000                    FCSEIDR 0x00000000             CONTEXTIDR_EL1 0x00000000          
      A9_PWRDIAG 0x00000000                   NEONBUSY 0x00000000                   TLB_VA_S 0x00000000                   TLB_PA_S 0x00000000                     TLB_VA 0x00000000          
      TLB_ATTR_S 0x00000000                     TLB_PA 0x00000000                   TLB_ATTR 0x00000000          
─── Source ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
383 }
384 
385 static int __init do_mount_root(char *name, char *fs, int flags, void *data)
386 {
387     struct super_block *s;
388     int err = ksys_mount(name, "/root", fs, flags, data);
389     if (err)
390         return err;
391 
392     ksys_chdir("/root");
393     s = current->fs->pwd.dentry->d_sb;
─── Stack ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
[0] from 0x80a012a8 in do_mount_root+0 at /mnt/build/linux-5.0.10/init/do_mounts.c:388
arg name = 0x80a58910 <nfs_root_device> "192.168.1.250:/home/olegsl/Projects/qemu-arm-lab/rootfs/"
arg fs = 0x808d6b68 "nfs"
arg flags = 32768
arg data = 0x80a58408 <nfs_root_options>
[1] from 0x80a01700 in mount_nfs_root at /mnt/build/linux-5.0.10/init/do_mounts.c:486
(no arguments)
[+]
─── Threads ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
[1] id 1 from 0x80a012a8 in do_mount_root+0 at /mnt/build/linux-5.0.10/init/do_mounts.c:388
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
>>> 
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment