It’s possible (and easy) to develop software for ARM based platforms without having physical ARM based hardware on your desk – there are many ways to do this such as using the QEMU emulator. However by using something known as a Fixed Virtual Platform (FVP) it’s possible to run software on a simulation of some of the very latest ARM architectures. The FVP models, which are based upon SystemC can be downloaded from the ARM website at no cost. In this post we’ll go through the steps needed to boot Linux on an ARMv8 model.
The first step to obtain the FVP is to register an account on the ARM website here and then login to Arm Self Service. You’ll find the download under Development Tools | ESL: Fast Models | Fast Models and Fixed Virtual Platforms under the name “ARMv8-A Base Platform Binary (Lin) FOC”. There is also a Download link on the main ARM FVP page. After clicking through a license agreement you’ll be able to download and extract the FVP. It includes some PDFs that give an overview of what you’ve downloaded and how to use it.
Now let’s build a Linux kernel image, we can do this via the following commands:
$ wget https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/snapshot/linux-4.20.tar.gz $ tar -xf linux-4.20.tar.gz $ cd linux-4.20 $ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- defconfig $ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j 40 Image
We’ll need a device tree, there isn’t one for the FVP model in mainline but we can get one from the Arm Trusted Firmware Github repo as follows:
$ wget https://github.com/ARM-software/arm-trusted-firmware/archive/9a207532f8216bf83fed0891fed9ed0bc72ca450.zip $ unzip 9a207532f8216bf83fed0891fed9ed0bc72ca450.zip $ cd arm-trusted-firmware-9a207532f8216bf83fed0891fed9ed0bc72ca450/ $ dtc fdts/fvp-base-gicv3-psci.dts -I dts -O dtb > fvp-base-gicv3-psci.dtb
We also need a bootloader, the simplest option here is to use ‘boot-wrapper‘ – this provides the minimum needed steps to boot a Linux image. We can tell it about our kernel image and device tree and it will bundle them together into an ELF file (with .axf extension) that the simulator can boot. As follows…
$ wget https://git.kernel.org/pub/scm/linux/kernel/git/mark/boot-wrapper-aarch64.git/snapshot/boot-wrapper-aarch64-ed60963595855e66ffc06a8a543cbb429c7ede03.tar.gz $ tar -xf boot-wrapper-aarch64-ed60963595855e66ffc06a8a543cbb429c7ede03.tar.gz $ cd boot-wrapper-aarch64-ed60963595855e66ffc06a8a543cbb429c7ede03/ $ autoreconf -i $ ./configure --enable-psci --enable-gicv3 --with-kernel-dir=../linux-4.20 --with-dtb=../arm-trusted-firmware-9a207532f8216bf83fed0891fed9ed0bc72ca450/fdts/fvp-base-gicv3-psci.dtb --host=aarch64-linux-gnu $ make
We can now use our FVP model to boot our Linux image, as follows:
$ cd Base_RevC_AEMv8A_pkg $ ./models/Linux64_GCC-4.9/FVP_Base_RevC-2xAEMv8A -C cache_state_modelled=0 -C bp.refcounter.non_arch_start_at_default=1 -C bp.secure_memory=false ../boot-wrapper-aarch64-ed60963595855e66ffc06a8a543cbb429c7ede03/linux-system.axf
After a brief moment of suspense you’ll see your kernel boot output in a xterm window bringing you sheer excitement and joy.
Trying ::1... Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. Boot-wrapper v0.2 [ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd0f0] [ 0.000000] Linux version 4.20.0 (andmur01@e119886-lin) (gcc version 7.3.1 20180425 [linaro-7.3-2018.05 revision d29120a424ecfbc167ef90065c0eeb7f91977701] (Linaro GCC 7.3-2018.05)) #1 SMP PREEMPT Sat Jan 5 17:04:15 GMT 2019 [ 0.000000] Machine model: FVP Base [ 0.000000] efi: Getting EFI parameters from FDT: [ 0.000000] efi: UEFI not found. [ 0.000000] cma: Reserved 32 MiB at 0x00000000fd000000 [ 0.000000] NUMA: No NUMA configuration found [ 0.000000] NUMA: Faking a node at [mem 0x0000000080000000-0x00000008ffffffff] [ 0.000000] NUMA: NODE_DATA [mem 0x8fffe7840-0x8fffe8fff] [ 0.000000] Zone ranges: [ 0.000000] DMA32 [mem 0x0000000080000000-0x00000000ffffffff] [ 0.000000] Normal [mem 0x0000000100000000-0x00000008ffffffff] [ 0.000000] Movable zone start for each node [ 0.000000] Early memory node ranges [ 0.000000] node 0: [mem 0x0000000080000000-0x00000000feffffff] [ 0.000000] node 0: [mem 0x0000000880000000-0x00000008ffffffff] [ 0.000000] Initmem setup node 0 [mem 0x0000000080000000-0x00000008ffffffff] [ 0.000000] psci: probing for conduit method from DT. [ 0.000000] psci: Using PSCI v0.1 Function IDs from DT [ 0.000000] random: get_random_bytes called from start_kernel+0xa8/0x418 with crng_init=0
We didn’t bother providing a rootfs so you won’t get as far as userspace. If you wanted to get a userspace you could create one with Buildroot and add it to the axf image via the boot-wrapper configure option ‘–with-initrd’.
We’ve only just scratched the surface of the FVP models – there is more to explore, for eaxmple the FVP package also comes included with ‘modeldebugger‘ which allows you to debug code. As always refer to the documentation for more details. Happy coding.