Goal
This post shows how to install aarch64 qemu simulator on x86-64 and run a simple program on aarch64.
Step 1: Installing prerequisites for qemu-system-aarch64.
Basically, you will need to install the following packages into your x86-64-based host system.
- qemu-system-aarch64: For the emulator itself.
- qemu-img for creating virtual disk image files.
- edk2-aarch64 for bios support files for the aarch64 architecture. The qemu for aarch64 needs these BIOS files to boot up.
Just run (pacman is my Archlinux package manager, by the way.):
sudo pacman -S qemu-system-aarch64 qemu-img
Step 2: Download your favor Linux distro iso file.
Note: because Archlinux doesn’t have official support for aarch64, I have chosen Ubuntu. Here is the download link if you need it: https://ubuntu.com/download/server/arm
Because I actually live in China, so I have to download the iso image from Tsinghua University’s mirror site: Tsinghua University’s mirror for ISO
Just wget it:
wget <your iso link here>
Step 3: Creating a virtual disk
I decided to create a new virtual disk because I need to store files in AArch64 virtual machine. If you just want to run it from ISO, you can skip this step.
qemu-img create -f qcow2 arm64.qcow2 40G
This command will create a new virtual disk file in qcow2 format called ‘arm64.qcow2’ and its size is 40G.
Step 4: Install the system.
qemu-system-aarch64 \
-cpu cortex-a53 -smp cores=8 \
-M virt -m 8192 \
-bios /usr/share/edk2/aarch64/QEMU_CODE.fd \
-nographic \
-drive format=qcow2,file=arm64.qcow2 \
-device ramfb \
-cdrom ubuntu.iso \
-nic user,model=virtio \
-rtc base=utc,clock=host
The ubuntu.iso is the filename you just downloaded in step 2.
The bios option tells where is the bios image file is stored in your computer. It comes from the edk2-aarch64 package.
The -m 8192 option tells we want 8G memory for this vm, enabled the multicode CPU simulation (enabled 8 cores) by -smp cores=8 option.
The install guide will launch from the console in text mode, so no graphics are needed.
This step will take some time because the simulation is slow.
Step 5: Run the system.
Just remove the option -cdrom ubuntu.iso from step 4 and re-run the command.
NOTE the simulation will super SLOW because we don’t have any accel available. (Maybe the QEMU’s TCG is used?) (HVF accel only works in aarch64-based host!)
Step 6: Install packages (optional)
This step exists because I want to try compiling a program and disassemble it to find out how ARM ASM works.
Install the compiler:
sudo apt install gcc
The simple code in c:
int func(int a, int b, int c)
{
if (a + b > c)
{
return c;
} else return -c;
}
int main()
{
return func(1, 2, 3);
}
Compile this code into assembly and disable the optimization:
gcc -S -fverbose-asm -o main.s main.c
First we look at the asm of the main function:
main:
.LFB1:
.cfi_startproc
stp x29, x30, [sp, -16]! //,,,
.cfi_def_cfa_offset 16
.cfi_offset 29, -16
.cfi_offset 30, -8
mov x29, sp //,
// main.c:11: return func(1, 2, 3);
mov w2, 3 //,
mov w1, 2 //,
mov w0, 1 //,
bl func //
// main.c:12: }
ldp x29, x30, [sp], 16 //,,,
.cfi_restore 30
.cfi_restore 29
.cfi_def_cfa_offset 0
ret
So first, it uses the stp instruction to allocate some memory from the stack. The stp instruction is used to store the content pairs of registers (x29, x30) into the stack and move the stack pointer (sp) by -16.
Actually, I’m not sure what register x29, x30 are used for? I guess it may just like the ‘callee saved registers’ in x86-64 assembly?
Next, we have seen the w0-w2 registers are used for passing function call arguments. and bl to this function(func). So the bl instruction is similar to the call instruction in x86-64 (?), it seems just jump, so I’m not sure where the ret pointer?
…. so many questions in my mind. So I will resolve the above questions in the next post (How to call/ret a function(or return from a function to the caller)).
Leave a comment