feat: add support for aarch64 timer/interrupts, port MontaukOS userspace
This commit is contained in:
1 parent
8b6379fb7e
commit
8c09ccef66
101 files changed
+1720
-629
No files matched your search
+45
-10
@@ -105,29 +105,64 @@ dispatch table (`ArchIrqDispatch`), panic-frame printing, and:
|
||||
between them (device space on ARM). MAIR: 0 Normal WB, 1 Normal NC
|
||||
(`MapWC`), 2 Device-nGnRE (`MapMMIO`).
|
||||
|
||||
- GICv2 (`Interrupts.cpp`, from the MADT): IRQ slots map onto INTIDs --
|
||||
`IRQ_TIMER` onto the generic timer's PPI, the MSI slots (24-45) onto the
|
||||
SPIs of a GICv2m MSI frame (`ComposeMsi`), the IPI slots onto SGIs 0/1.
|
||||
Interrupts are completed (EOI) before the handler runs, as on x86; a
|
||||
level-triggered source drops its line first in an ack hook.
|
||||
- Generic timer tick (`Timer.cpp`): the EL1 virtual timer at
|
||||
`CNTFRQ_EL0`, its PPI from the GTDT, re-armed from the ack hook.
|
||||
- PSCI `SYSTEM_RESET` / `SYSTEM_OFF` (`Arch::Reboot` / `Arch::PowerOff`)
|
||||
through the conduit the FADT's ARM_BOOT_ARCH names. Hardware-reduced
|
||||
ACPI has no PM1 block, so `AcpiShutdown` leaves power-off to the port.
|
||||
- `Arch::SyncInstructionCache` after the ELF loader writes code: ARM
|
||||
instruction fetch does not snoop data writes (QEMU hides this; real
|
||||
cores do not). EL0 may maintain caches itself (`SCTLR_EL1.UCI`).
|
||||
|
||||
Not yet written (each is marked `TODO(aarch64)`):
|
||||
|
||||
- GIC driver: SPI routing, SGIs for IPIs, MSIs via ITS/GICv2m
|
||||
(`ComposeMsi` returns false, so drivers fall back to INTx/polling). IRQs
|
||||
reach `ArchIrqException`, which only logs them.
|
||||
- Generic timer tick (`Arch::Timer::InitializeBsp` returns false). Boot
|
||||
currently stops in the first driver that waits on `GetMilliseconds()`
|
||||
(xHCI port power-up).
|
||||
- Secondary CPU start-up, PSCI reset and suspend.
|
||||
- Secondary CPU start-up (`Smp::BootAPs`).
|
||||
- PCI INTx: the PC interrupt lines (slots 1-23) have no ARM meaning, so
|
||||
`RouteLegacyIrq` refuses them. Routing a PCI pin needs its `_PRT`
|
||||
entry and a GSI-based routing call; until then PCI drivers use MSI
|
||||
(GICv2m) or polling.
|
||||
|
||||
The generic kernel is compiled `-fsigned-char` for AArch64: it was written
|
||||
for x86's signed plain `char`.
|
||||
|
||||
Building it needs `clang` and `ld.lld`; without a system `ld.lld` the
|
||||
kernel makefile uses the one rustup ships
|
||||
(`~/.rustup/toolchains/*/lib/rustlib/*/bin/gcc-ld/ld.lld`), and `KERNEL_LD=`
|
||||
overrides both. `make run ARCH=aarch64` boots a kernel-only image (userspace
|
||||
is x86_64-only so far) on QEMU `virt` with a GICv2 and Cortex-A72 cores, the
|
||||
overrides both. `make run ARCH=aarch64` boots the full image (desktop, apps,
|
||||
USB keyboard and mouse) on QEMU `virt` with a GICv2 and Cortex-A72 cores, the
|
||||
Raspberry Pi 4/400's configuration; it needs `qemu-system-aarch64` and
|
||||
`qemu-efi-aarch64`.
|
||||
`qemu-efi-aarch64`, and the userspace compiler
|
||||
(`./toolchain/build-montauk-toolchain.sh aarch64`). `KERNEL_ONLY=1` builds an
|
||||
image without userspace.
|
||||
|
||||
The kernel console is mirrored to the serial port the ACPI SPCR table names
|
||||
(PL011, SBSA UART, 16550 or the BCM2835 mini UART; `Drivers/Serial/Uart.cpp`),
|
||||
including the log written before the port was found. On QEMU that is
|
||||
`-serial stdio`.
|
||||
|
||||
## Userspace
|
||||
|
||||
The programs are architecture-neutral C/C++ built by `<arch>-montauk-gcc`
|
||||
(see `toolchain/README.md`). `programs/mk/arch.mk` holds everything
|
||||
architecture-specific in the build: the toolchain prefix, FP/SIMD flag sets
|
||||
(`ARCH_FP_FLAGS` for GUI apps, `ARCH_NOFP_FLAGS` for system programs) and the
|
||||
output layout. x86_64 keeps `bin/`, `obj/` and libraries next to their
|
||||
sources; other architectures build beside them into `bin-<arch>/`,
|
||||
`obj-<arch>/` and `lib/<name>/build-<arch>/`, so both can be built from one
|
||||
tree. The few architecture-specific sources are the raw system-call
|
||||
wrappers (`#if defined(__x86_64__)` / `__aarch64__` blocks in
|
||||
`montauk/syscall.h`, `libc/montauk.h`, `lib/libc/libc.c` and
|
||||
`lib/libc/crt/crt1.c`), `lib/libc/arch/setjmp-<arch>.S` and the scanout
|
||||
store fence in `gui/framebuffer.hpp`.
|
||||
|
||||
Not built for AArch64: tcc (it generates x86 code), the on-OS SDK and the
|
||||
Rust programs (their `x86_64-unknown-montauk` target).
|
||||
|
||||
## Adding another architecture
|
||||
|
||||
1. Create `kernel/src/Arch/<arch>/` with the six inline headers listed above
|
||||
|
||||
Reference in new issue
Block a user