QEMU AArch64 Virt Bare Bones
From OSDev Wiki
QEMU is a free and open source hardware emulator that supports multiple architecture, including ARM. QEMU has its own generic board mainly for virtualization usages, called virt. virt supports ARM and RISC-V architecture.
In this tutorial, we'll write a basic kernel for QEMU virt board, specifically Aarch64.
Contents |
Prerequisites
For this tutorial, you'll need
- An ARM cross-compiler toolchain
- QEMU, of course you'll need QEMU because this tutorial designed for QEMU virt.
Code
Now we'll need to write some code for our little kernel.
boot.s
.global _start _start: ldr x30, =stack_top mov sp, x30 bl kmain b .
kernel.c
#include <stdint.h> volatile uint8_t *uart = (uint8_t *) 0x09000000; void putchar(char c) { *uart = c; } void print(const char *s) { while(*s != '\0') { putchar(*s); s++; } } void kmain(void) { print("Hello world!\n"); }
linker.ld
ENTRY(_start) SECTIONS { . = 0x40100000; /* RAM starts at 0x40000000 but if we ask to load the kernel there, QEMU will not load a DTB */ .startup . : { boot.o(.text) } .text : { *(.text) } .data : { *(.data) } .bss : { *(.bss COMMON) } . = ALIGN(8); . += 0x1000; /* 4kB of stack memory */ stack_top = .; }
Compiling the kernel
Now, we'll need to compile our kernel so we can boot it.
$ aarch64-elf-as boot.s -o boot.o $ aarch64-elf-gcc -ffreestanding -c kernel.c -o kernel.o $ aarch64-elf-ld -nostdlib -Tlinker.ld boot.o kernel.o -o kernel.elf
Booting our kernel
Since our kernel is now compiled, we'll boot it with QEMU
$ qemu-system-aarch64 -machine virt -cpu cortex-a57 -kernel kernel.elf -nographic Hello world!