minos/README.md
auser 8c44d12357 minos M1: minimal multi-arch kernel (x86 + RISC-V + ARM/Zynq)
Boots under QEMU on all three ISAs from one clang build:
- shared C core (kmain, console) calls a small per-arch contract (arch.h)
- per-arch asm entry + trap/vector table + UART driver
- parallel Makefile (make -j), 'make run-<arch>', 'make sizes'
M1 = boot, UART up, trap vector installed, banner from kmain().
2026-09-25 00:41:24 +03:00

65 lines
2.7 KiB
Markdown

# minos — a minimal multi-arch kernel
One tiny OS core, three ISAs: **x86 (i386)**, **RISC-V (rv64)**, **ARM
(Cortex-A9 / Zynq-7000)**. Built by a single `clang` in parallel so you can
compare how the same C behaves across architectures.
Milestone **M1** (this state): each target boots, brings up its UART, sets its
interrupt/trap vector, and prints a banner from shared C (`kmain`).
## Design
The only boundary is a small per-arch **contract** (`include/arch.h`):
```
arch_early_init() bring up the UART
arch_uart_putc(c) emit one byte
arch_set_trap_vector() install IDT / mtvec / VBAR
arch_name() banner string
arch_halt() hlt / wfi
```
Everything in `common/` is portable C and calls only that contract. Each
`arch/<name>/` supplies the irreducible assembly (`boot.S`, trap/vector table)
plus a C file implementing the contract and a linker script.
```
common/ main.c (kmain), console.c (putc/puts/puthex)
include/ arch.h (the contract), console.h
arch/x86/ boot.S (multiboot) arch.c (COM1 0x3F8, IDT) link.ld (1 MiB)
arch/riscv/ boot.S (_start) trap.S (mtvec) arch.c (UART 0x10000000)
arch/arm/ boot.S (_start) vectors.S (VBAR) arch.c (Cadence UART 0xE0000000)
```
## Build & run
```sh
make -j # build all three in parallel
make run-x86 # boot under QEMU (Ctrl-A X to quit)
make run-riscv
make run-arm
make sizes # compare stripped binary size
make clean
```
## The interesting comparison (M1)
| Aspect | x86 (i386) | RISC-V (rv64) | ARM (Cortex-A9) |
|-------------------|-------------------------|-----------------------|--------------------------|
| Entry protocol | Multiboot1 header | `_start` @ 0x80000000 | `_start` @ DDR |
| Console | port I/O `outb` 0x3F8 | MMIO 16550 0x10000000 | MMIO Cadence 0xE0000000 |
| Trap vector | IDT via `lidt` | `mtvec` CSR | `VBAR` (CP15) |
| Multi-core gate | (single by default) | `mhartid` check | `MPIDR` check |
| Halt | `hlt` | `wfi` | `wfi` |
| Idle byte size | ~890 | ~816 | ~800 |
## Real hardware (next)
- **RISC-V**: the only change is the UART base — `0x10000000` (QEMU virt) →
`0x02500000` (Allwinner D1 / Lichee RV). Loadable via `xfel`.
- **ARM/Zynq**: same Cadence UART base as the real PS; boot via U-Boot/JTAG.
- **x86**: boot the multiboot ELF from GRUB.
## Roadmap
- **M2**: real trap handlers + a timer tick per arch.
- **M3**: expose a tiny syscall-style interface (the "own interface").