feat: add support for aarch64 timer/interrupts, port MontaukOS userspace

This commit is contained in:
daniel committed 2026-10-25 08:27:09 +01:00
1 parent 8b6379fb7e
commit 8c09ccef66
101 files changed
+1720 -629

No files matched your search

+15 -3
View File
@@ -13,6 +13,18 @@
namespace gui {
// Drain write-combining stores to the scanout buffer before it is flipped
// or composited by someone else.
inline void wc_store_fence() {
#if defined(__x86_64__)
asm volatile("sfence" ::: "memory");
#elif defined(__aarch64__)
asm volatile("dsb st" ::: "memory");
#else
#error "unsupported architecture"
#endif
}
class Framebuffer {
uint32_t* hw_fb;
uint32_t* hw_fb2; // second scanout buffer (page flip), nullptr if unsupported
@@ -322,12 +334,12 @@ public:
montauk::memcpy(mirror, src, row_bytes);
}
}
if (hw_mirror) asm volatile("sfence" ::: "memory");
if (hw_mirror) wc_store_fence();
if (hw_fb2) {
// Wait for the latch (vsync): the buffer we just left becomes
// safe to draw into only once the new one is actually scanning.
asm volatile("sfence" ::: "memory");
wc_store_fence();
int64_t presented = montauk::fb_flip(hw_next, 1);
if (presented == hw_next) {
hw_next ^= 1;
@@ -359,7 +371,7 @@ public:
montauk::memcpy(mirror, src, row_bytes);
}
}
asm volatile("sfence" ::: "memory");
wc_store_fence();
}
}
}
+62
View File
@@ -419,6 +419,8 @@ typedef struct {
Raw syscall wrappers
==================================================================== */
#if defined(__x86_64__)
static inline long _mtk_syscall0(long nr) {
long ret;
__asm__ volatile("syscall" : "=a"(ret) : "a"(nr)
@@ -491,6 +493,66 @@ static inline long _mtk_syscall5(long nr, long a1, long a2, long a3, long a4, lo
return ret;
}
#elif defined(__aarch64__)
// AArch64: number in x8, arguments in x0-x5, `svc #0`; the kernel
// preserves every register except x0, which carries the result.
static inline long _mtk_syscall0(long nr) {
register long x8 __asm__("x8") = nr;
register long x0 __asm__("x0");
__asm__ volatile("svc #0" : "=r"(x0) : "r"(x8) : "memory");
return x0;
}
static inline long _mtk_syscall1(long nr, long a1) {
register long x8 __asm__("x8") = nr;
register long x0 __asm__("x0") = a1;
__asm__ volatile("svc #0" : "+r"(x0) : "r"(x8) : "memory");
return x0;
}
static inline long _mtk_syscall2(long nr, long a1, long a2) {
register long x8 __asm__("x8") = nr;
register long x0 __asm__("x0") = a1;
register long x1 __asm__("x1") = a2;
__asm__ volatile("svc #0" : "+r"(x0) : "r"(x8), "r"(x1) : "memory");
return x0;
}
static inline long _mtk_syscall3(long nr, long a1, long a2, long a3) {
register long x8 __asm__("x8") = nr;
register long x0 __asm__("x0") = a1;
register long x1 __asm__("x1") = a2;
register long x2 __asm__("x2") = a3;
__asm__ volatile("svc #0" : "+r"(x0) : "r"(x8), "r"(x1), "r"(x2) : "memory");
return x0;
}
static inline long _mtk_syscall4(long nr, long a1, long a2, long a3, long a4) {
register long x8 __asm__("x8") = nr;
register long x0 __asm__("x0") = a1;
register long x1 __asm__("x1") = a2;
register long x2 __asm__("x2") = a3;
register long x3 __asm__("x3") = a4;
__asm__ volatile("svc #0" : "+r"(x0) : "r"(x8), "r"(x1), "r"(x2), "r"(x3) : "memory");
return x0;
}
static inline long _mtk_syscall5(long nr, long a1, long a2, long a3, long a4, long a5) {
register long x8 __asm__("x8") = nr;
register long x0 __asm__("x0") = a1;
register long x1 __asm__("x1") = a2;
register long x2 __asm__("x2") = a3;
register long x3 __asm__("x3") = a4;
register long x4 __asm__("x4") = a5;
__asm__ volatile("svc #0" : "+r"(x0) : "r"(x8), "r"(x1), "r"(x2), "r"(x3), "r"(x4) : "memory");
return x0;
}
#else
#error "unsupported architecture"
#endif
/* ====================================================================
Process management
==================================================================== */
+5 -1
View File
@@ -7,7 +7,11 @@
extern "C" {
#endif
typedef unsigned long jmp_buf[8];
#if defined(__aarch64__)
typedef unsigned long jmp_buf[21]; /* x19-x30, sp, d8-d15 */
#else
typedef unsigned long jmp_buf[8]; /* rbx, rbp, r12-r15, rsp, rip */
#endif
int setjmp(jmp_buf env);
void longjmp(jmp_buf env, int val) __attribute__((noreturn));
+76 -1
View File
@@ -1,6 +1,6 @@
/*
* syscall.h
* MontaukOS program-side syscall wrappers using SYSCALL instruction
* MontaukOS program-side syscall wrappers (x86_64 SYSCALL, AArch64 SVC)
* Copyright (c) 2025 Daniel Hammer
*/
@@ -13,6 +13,8 @@ namespace montauk {
// ---- Raw SYSCALL wrappers ----
#if defined(__x86_64__)
// The SYSCALL handler does not restore RDI, RSI, RDX, R10, R8, R9
// (they are skipped on the return path). We move arguments into the
// correct registers inside the asm block and list ALL argument
@@ -108,6 +110,79 @@ namespace montauk {
return ret;
}
#elif defined(__aarch64__)
// AArch64: number in x8, arguments in x0-x5, `svc #0`; the kernel
// preserves every register except x0, which carries the result.
inline int64_t syscall0(uint64_t nr) {
register uint64_t x8 asm("x8") = nr;
register uint64_t x0 asm("x0");
asm volatile("svc #0" : "=r"(x0) : "r"(x8) : "memory");
return (int64_t)x0;
}
inline int64_t syscall1(uint64_t nr, uint64_t a1) {
register uint64_t x8 asm("x8") = nr;
register uint64_t x0 asm("x0") = a1;
asm volatile("svc #0" : "+r"(x0) : "r"(x8) : "memory");
return (int64_t)x0;
}
inline int64_t syscall2(uint64_t nr, uint64_t a1, uint64_t a2) {
register uint64_t x8 asm("x8") = nr;
register uint64_t x0 asm("x0") = a1;
register uint64_t x1 asm("x1") = a2;
asm volatile("svc #0" : "+r"(x0) : "r"(x8), "r"(x1) : "memory");
return (int64_t)x0;
}
inline int64_t syscall3(uint64_t nr, uint64_t a1, uint64_t a2, uint64_t a3) {
register uint64_t x8 asm("x8") = nr;
register uint64_t x0 asm("x0") = a1;
register uint64_t x1 asm("x1") = a2;
register uint64_t x2 asm("x2") = a3;
asm volatile("svc #0" : "+r"(x0) : "r"(x8), "r"(x1), "r"(x2) : "memory");
return (int64_t)x0;
}
inline int64_t syscall4(uint64_t nr, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4) {
register uint64_t x8 asm("x8") = nr;
register uint64_t x0 asm("x0") = a1;
register uint64_t x1 asm("x1") = a2;
register uint64_t x2 asm("x2") = a3;
register uint64_t x3 asm("x3") = a4;
asm volatile("svc #0" : "+r"(x0) : "r"(x8), "r"(x1), "r"(x2), "r"(x3) : "memory");
return (int64_t)x0;
}
inline int64_t syscall5(uint64_t nr, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) {
register uint64_t x8 asm("x8") = nr;
register uint64_t x0 asm("x0") = a1;
register uint64_t x1 asm("x1") = a2;
register uint64_t x2 asm("x2") = a3;
register uint64_t x3 asm("x3") = a4;
register uint64_t x4 asm("x4") = a5;
asm volatile("svc #0" : "+r"(x0) : "r"(x8), "r"(x1), "r"(x2), "r"(x3), "r"(x4) : "memory");
return (int64_t)x0;
}
inline int64_t syscall6(uint64_t nr, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5, uint64_t a6) {
register uint64_t x8 asm("x8") = nr;
register uint64_t x0 asm("x0") = a1;
register uint64_t x1 asm("x1") = a2;
register uint64_t x2 asm("x2") = a3;
register uint64_t x3 asm("x3") = a4;
register uint64_t x4 asm("x4") = a5;
register uint64_t x5 asm("x5") = a6;
asm volatile("svc #0" : "+r"(x0) : "r"(x8), "r"(x1), "r"(x2), "r"(x3), "r"(x4), "r"(x5) : "memory");
return (int64_t)x0;
}
#else
#error "unsupported architecture"
#endif
// ---- Typed wrappers ----
// Process