↓ Skip to main content

01 - Introducing my AArch64 bare-metal kernel on QEMU virt

·572 words·3 mins
Elouan Charbonnier
Author
Elouan Charbonnier
AArch64 Bare-Metal Kernel - This article is part of a series.
Part 1: This Article

Welcome to this new series on my blog! It’ll serve as a development journal for a small bare-metal AArch64 kernel, written entirely in assembly and running on QEMU’s virt machine.

The project can be found in this repository: aarch64-baremetal-kernel.


What is this project about?
#

This project is supposed to be simple, I have to build a small kernel capable of:

  • booting on a virtual AArch64 board (QEMU virt)
  • talking to the outside world through UART
  • handling exceptions and interrupts
  • setting up a timer and multitasking
  • and, eventually, looking like a (very small) working operating system

I’m keeping my expectations in check about this operating system. I started this project without really knowing where it’s going to end up :)

On top of that, I’m only going to use assembly (no C).


Why this project?
#

The main reason that pushed me to start this project is to learn ARM assembly language as well as to understand in depth the AArch64 architecture and how it works at a low level (registers, exception levels, MMU, etc.).

Note that v0.1 is already done at the time I’m writing this article: the kernel boots and already prints a message over UART.


Target environment
#

EmulatorQEMU
Machinevirt
ArchitectureAArch64 (ARMv8-A)
CPUcortex-a57
LanguageAArch64 assembly
Toolchainaarch64-none-elf

QEMU virt exposes a minimal but sufficient board for this project: some RAM, an AArch64 CPU, and a PL011-compatible UART, mapped in MMIO at address 0x09000000.


Prerequisites
#

To follow this series comfortably, I’d recommend already having some basic notions of assembly (any architecture works). No prior knowledge of AArch64 is required: I’m starting from scratch myself and I’ll explain every instruction used as we go.


Detailed development plan
#

Here’s the current roadmap of the project, version by version:

VersionFeature
v0.1Boot and UART
v0.2Exceptions and interrupts
v0.3ARM timer
v0.4Memory management and MMU
v0.5Exception levels and user mode
v0.6Multitasking and scheduler
v0.7Drivers and peripherals
v1.0Minimal operating system

Upcoming articles
#

Here are, in order, the articles planned for this series:

ArticleVersion(s)TitleMain content
01-IntroductionPresentation of the project, its goals and its target environment.
02v0.1First boot: linker script, stack and first UART messageSetting up the linker script, the boot code, stack initialization and the first UART driver to print a message.
03v0.2Exceptions: building the vector tableBuilding the exception vector table, configuring VBAR_EL1, handling synchronous exceptions and IRQs.
04v0.3Setting up the ARM timerConfiguring the ARM generic timer, setting up periodic interrupts and the basics of timekeeping.
05v0.4Managing physical and virtual memorySetting up a simple physical allocator, page tables, MMU configuration and the switch to virtual addressing.
06v0.5First program in user modeDetecting and handling exception levels, transitioning to EL0 and running the first user-mode program.
07v0.6Running several tasksContext save/restore, task structure, round-robin scheduler and running multiple kernel tasks.
08v0.7New drivers and peripheralsImproving the UART driver, adding GPIO support and additional peripherals from the virt machine.
09v1.0Wrap-upConsolidating all the previous components into a small usable operating system.

Thanks in advance to everyone who follows this series. If you have questions, feedback, or just want to chat about the project, feel free to reach out.

See you in the next article, where we’ll really dive into the code: boot and the first UART driver!

AArch64 Bare-Metal Kernel - This article is part of a series.
Part 1: This Article