feat(kernel): add Stage 1 bare-metal hypervisor skeleton for QEMU ARM virt
- Add kernel/arch/arm/boot.S with ARMv7 assembly entry, stack setup, BSS clear - Add kernel/arch/arm/linker.ld for QEMU virt memory layout (load at 0x40000000) - Add kernel/arch/arm/uart.c/uart.h for PL011 serial output - Add kernel/kernel.c with kernel_main() idle loop - Add kernel/Makefile for arm-none-eabi-gcc cross-compile and QEMU launch - Add kernel/README.md with build/run instructions - Ignore kernel build artifacts in .gitignore
This commit is contained in:
parent
e6ec3881af
commit
173b2c3330
8 changed files with 250 additions and 0 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -55,6 +55,12 @@ test/results/
|
|||
test/coverage/
|
||||
*.log
|
||||
|
||||
# Universalisos kernel build artifacts
|
||||
kernel/*.o
|
||||
kernel/*.elf
|
||||
kernel/*.bin
|
||||
kernel/arch/arm/*.o
|
||||
|
||||
# Temporary files
|
||||
*.tmp
|
||||
*.temp
|
||||
|
|
|
|||
52
kernel/Makefile
Normal file
52
kernel/Makefile
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
# Universalisos kernel build for QEMU ARM virt
|
||||
|
||||
CROSS_COMPILE ?= arm-none-eabi-
|
||||
CC := $(CROSS_COMPILE)gcc
|
||||
LD := $(CROSS_COMPILE)ld
|
||||
OBJCOPY := $(CROSS_COMPILE)objcopy
|
||||
OBJDUMP := $(CROSS_COMPILE)objdump
|
||||
|
||||
CFLAGS := \
|
||||
-mcpu=cortex-a15 \
|
||||
-marm \
|
||||
-O2 \
|
||||
-ffreestanding \
|
||||
-nostdlib \
|
||||
-nostartfiles \
|
||||
-Wall \
|
||||
-Wextra \
|
||||
-Werror \
|
||||
-Iinclude \
|
||||
-g
|
||||
|
||||
LDFLAGS := -T arch/arm/linker.ld
|
||||
|
||||
OBJS := \
|
||||
arch/arm/boot.o \
|
||||
arch/arm/uart.o \
|
||||
kernel.o
|
||||
|
||||
.PHONY: all clean run dump
|
||||
|
||||
all: kernel.bin kernel.elf
|
||||
|
||||
kernel.elf: $(OBJS) arch/arm/linker.ld
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS)
|
||||
|
||||
kernel.bin: kernel.elf
|
||||
$(OBJCOPY) -O binary $< $@
|
||||
|
||||
%.o: %.S
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
dump: kernel.elf
|
||||
$(OBJDUMP) -d $<
|
||||
|
||||
run: kernel.elf
|
||||
qemu-system-arm -M virt -cpu cortex-a15 -nographic -kernel kernel.elf
|
||||
|
||||
clean:
|
||||
rm -f $(OBJS) kernel.elf kernel.bin
|
||||
58
kernel/README.md
Normal file
58
kernel/README.md
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
# Universalisos Kernel — Stage 1 Bare-Metal Skeleton
|
||||
|
||||
This is the first bootable type-1 hypervisor milestone for Universalisos: a
|
||||
minimal bare-metal kernel that runs on QEMU's ARM `virt` machine and prints to
|
||||
the PL011 UART.
|
||||
|
||||
## Building
|
||||
|
||||
Requires `arm-none-eabi-gcc` and `qemu-system-arm`.
|
||||
|
||||
```bash
|
||||
cd kernel
|
||||
make
|
||||
```
|
||||
|
||||
Outputs:
|
||||
- `kernel.elf` — ELF image for debugging
|
||||
- `kernel.bin` — raw binary for QEMU `-kernel`
|
||||
|
||||
## Running in QEMU
|
||||
|
||||
```bash
|
||||
make run
|
||||
```
|
||||
|
||||
This runs `qemu-system-arm` with the ELF image so that QEMU loads the kernel
|
||||
at the address specified in the linker script.
|
||||
|
||||
Expected output:
|
||||
|
||||
```
|
||||
Universalisos type-1 hypervisor booted.
|
||||
Stage 1: bare-metal skeleton running on QEMU ARM virt.
|
||||
```
|
||||
|
||||
Press `Ctrl+A` then `X` to exit QEMU.
|
||||
|
||||
## Inspecting the binary
|
||||
|
||||
```bash
|
||||
make dump
|
||||
```
|
||||
|
||||
## Layout
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `arch/arm/boot.S` | Assembly entry point, stack/BSS setup |
|
||||
| `arch/arm/linker.ld` | Memory layout for QEMU virt (load at 0x40000000) |
|
||||
| `arch/arm/uart.c` | PL011 UART driver |
|
||||
| `arch/arm/uart.h` | UART interface |
|
||||
| `kernel.c` | `kernel_main()` entry point |
|
||||
|
||||
## Design notes
|
||||
|
||||
- The kernel is loaded by QEMU at RAM base `0x40000000`.
|
||||
- A 64 KiB stack is reserved immediately after the BSS section.
|
||||
- Interrupts are disabled in the boot stub; the kernel idles with `wfi`.
|
||||
34
kernel/arch/arm/boot.S
Normal file
34
kernel/arch/arm/boot.S
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Universalisos ARMv7 boot code for QEMU virt machine.
|
||||
*
|
||||
* This is the first code executed after QEMU loads the kernel image.
|
||||
* It sets up the stack, zeroes the BSS, and jumps to kernel_main().
|
||||
*/
|
||||
|
||||
.syntax unified
|
||||
.arch armv7-a
|
||||
|
||||
.section .text.boot
|
||||
.global _start
|
||||
_start:
|
||||
/* Disable interrupts until the kernel is ready. */
|
||||
cpsid if
|
||||
|
||||
/* Set up the stack at the top of the reserved boot region. */
|
||||
ldr sp, =_stack_top
|
||||
|
||||
/* Clear the BSS section. */
|
||||
ldr r0, =_bss_start
|
||||
ldr r1, =_bss_end
|
||||
mov r2, #0
|
||||
1:
|
||||
cmp r0, r1
|
||||
bge 2f
|
||||
str r2, [r0], #4
|
||||
b 1b
|
||||
2:
|
||||
/* Enter the C kernel. */
|
||||
bl kernel_main
|
||||
|
||||
/* Halt if kernel_main ever returns. */
|
||||
b .
|
||||
39
kernel/arch/arm/linker.ld
Normal file
39
kernel/arch/arm/linker.ld
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Universalisos linker script for QEMU ARM virt machine.
|
||||
*
|
||||
* QEMU loads the raw kernel image at the start of RAM (0x40000000)
|
||||
* when using -kernel.
|
||||
*/
|
||||
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x40000000;
|
||||
|
||||
.text : {
|
||||
*(.text.boot)
|
||||
*(.text .text.*)
|
||||
}
|
||||
|
||||
.rodata : {
|
||||
*(.rodata .rodata.*)
|
||||
}
|
||||
|
||||
.data : {
|
||||
*(.data .data.*)
|
||||
}
|
||||
|
||||
.bss : {
|
||||
_bss_start = .;
|
||||
*(.bss .bss.*)
|
||||
*(COMMON)
|
||||
_bss_end = .;
|
||||
}
|
||||
|
||||
/* 64 KiB boot stack placed immediately after BSS, 8-byte aligned. */
|
||||
_stack_bottom = .;
|
||||
. = ALIGN(8);
|
||||
. = . + 0x10000;
|
||||
_stack_top = ALIGN(8);
|
||||
}
|
||||
32
kernel/arch/arm/uart.c
Normal file
32
kernel/arch/arm/uart.c
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* PL011 UART driver for QEMU ARM virt machine.
|
||||
*
|
||||
* The virt machine exposes a PL011 UART at 0x09000000.
|
||||
*/
|
||||
|
||||
#include "uart.h"
|
||||
|
||||
#define UART0_BASE 0x09000000U
|
||||
#define UART_DR (*(volatile unsigned int *)(UART0_BASE + 0x00U))
|
||||
#define UART_FR (*(volatile unsigned int *)(UART0_BASE + 0x18U))
|
||||
#define UART_FR_TXFF (1U << 5)
|
||||
|
||||
void uart_init(void)
|
||||
{
|
||||
/* QEMU initializes the UART for us. */
|
||||
}
|
||||
|
||||
void uart_putc(char c)
|
||||
{
|
||||
while ((UART_FR & UART_FR_TXFF) != 0U) {
|
||||
/* Wait until the transmit FIFO is not full. */
|
||||
}
|
||||
UART_DR = (unsigned int)c;
|
||||
}
|
||||
|
||||
void uart_puts(const char *s)
|
||||
{
|
||||
while (*s != '\0') {
|
||||
uart_putc(*s++);
|
||||
}
|
||||
}
|
||||
12
kernel/arch/arm/uart.h
Normal file
12
kernel/arch/arm/uart.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* PL011 UART driver header for QEMU ARM virt machine.
|
||||
*/
|
||||
|
||||
#ifndef UNIVERSALISOS_UART_H
|
||||
#define UNIVERSALISOS_UART_H
|
||||
|
||||
void uart_init(void);
|
||||
void uart_putc(char c);
|
||||
void uart_puts(const char *s);
|
||||
|
||||
#endif /* UNIVERSALISOS_UART_H */
|
||||
17
kernel/kernel.c
Normal file
17
kernel/kernel.c
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Universalisos kernel entry point.
|
||||
*/
|
||||
|
||||
#include "arch/arm/uart.h"
|
||||
|
||||
void kernel_main(void)
|
||||
{
|
||||
uart_init();
|
||||
uart_puts("Universalisos type-1 hypervisor booted.\r\n");
|
||||
uart_puts("Stage 1: bare-metal skeleton running on QEMU ARM virt.\r\n");
|
||||
|
||||
/* Idle loop. */
|
||||
for (;;) {
|
||||
__asm__ __volatile__("wfi");
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue