From 6fb97937f7bbc16c53f1ff4d926a80eabdc6aaf1 Mon Sep 17 00:00:00 2001 From: Sunrisepeak Date: Fri, 30 Oct 2026 18:31:31 +0900 Subject: [PATCH] 0.19.0 --- openkal.map: a part of a file in the address space, by mmap, msync and munmap (openkal 0.18) The file's length and kind are read with fstat first: the kernel maps beyond a file's end and maps some devices, and the specification refuses both at the call. kal_map_sync is msync(MS_ASYNC), the visibility the specification asks for and not durability. No PROT_EXEC. Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com> --- README.md | 2 +- mcpp.toml | 5 ++-- src/map.cpp | 65 +++++++++++++++++++++++++++++++++++++++++++++++++ src/sys.h | 7 +++--- src/version.cpp | 3 ++- 5 files changed, 75 insertions(+), 7 deletions(-) create mode 100644 src/map.cpp diff --git a/README.md b/README.md index 910b5dc..4e7d276 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ for Linux, written on the kernel's own system-call interface. openkal = "0.17.0" [target.'cfg(os = "linux")'.dependencies] -openkal-linux = "0.18.3" +openkal-linux = "0.19.0" ``` ## Why it does not use a C library diff --git a/mcpp.toml b/mcpp.toml index 23f7b6b..11326a5 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -1,7 +1,7 @@ [package] namespace = "mcpplibs" name = "openkal-linux" -version = "0.18.3" +version = "0.19.0" description = "The reference implementation of openkal for Linux, written on the kernel's own system-call interface so that it can be placed beneath a C library as well as above one." license = "Apache-2.0" @@ -60,10 +60,11 @@ provides-interfaces = [ "openkal.datagram", "openkal.space", "openkal.timeout", + "openkal.map", ] [dependencies] -openkal = "0.17.1" +openkal = "0.18.0" # The package contributes definitions and no modules. The interface it # implements is declared by the specification package, which this package diff --git a/src/map.cpp b/src/map.cpp new file mode 100644 index 0000000..30ce4af --- /dev/null +++ b/src/map.cpp @@ -0,0 +1,65 @@ +#include "sys.h" +#include "handle.h" +#include + +// openkal.map on this kernel (openkal 0.18). +// +// One system call each way: mmap, msync, munmap. The region is the address the +// kernel returned and the length the caller passed, so there is nothing to +// record; a handle would have needed a table from handles to mappings, which +// clause 7.1 excludes. +// +// THE FILE'S LENGTH IS ASKED FIRST. The kernel maps beyond the end of a file +// and lets an access there fault; the specification refuses such a region at +// the call (map.h), so the length is read with fstat and compared. The same +// fstat says whether the file is a regular one: the kernel maps some devices, +// and a device's contents are not a file's. +// +// NO PROT_EXEC. Instructions run only from memory openkal.exec published. + +extern "C" { + +int kal_map_file(kal_file f, kal_u64 offset, kal_uintptr length, kal_uintptr how, void** out) { + if (out == nullptr) return kal_err_invalid; + *out = nullptr; + const int fd = okl::unpack(f.h); + if (fd < 0 || length == 0 || offset % KAL_MAP_ALIGNMENT != 0 + || (how & ~(KAL_MAP_WRITE | KAL_MAP_SHARED)) != 0) + return kal_err_invalid; + okl::kstat st{}; + const okl_long s = okl::sys(okl::nr_fstat, fd, reinterpret_cast(&st)); + if (okl::failed(s)) return okl::translate(s); + if ((st.mode & okl::s_ifmt) != okl::s_ifreg) return kal_err_not_supported; + const kal_u64 size = st.size > 0 ? static_cast(st.size) : 0; + if (offset > size || static_cast(length) > size - offset) return kal_err_invalid; + const okl_long prot = okl::prot_read | ((how & KAL_MAP_WRITE) ? okl::prot_write : 0); + const okl_long flags = (how & KAL_MAP_SHARED) ? okl::map_shared : okl::map_private; + const okl_long r = okl::sys(okl::nr_mmap, 0, static_cast(length), prot, flags, fd, + static_cast(offset)); + if (okl::failed(r)) { + // ENODEV: the file system does not map. The resource, not the + // implementation, refuses (map.h). + if (-r == okl::e_nodev) return kal_err_not_supported; + return okl::translate(r); + } + *out = reinterpret_cast(r); + return kal_ok; +} + +int kal_map_sync(void* region, kal_uintptr length) { + if (region == nullptr || length == 0) return kal_err_invalid; + // MS_ASYNC: a shared mapping is the page cache, which a read of the file + // already reads; what the specification asks of this call is that + // visibility, not durability, and asking for durability here would make + // every caller wait for the medium. + const okl_long r = okl::sys(okl::nr_msync, reinterpret_cast(region), + static_cast(length), okl::ms_async); + return okl::failed(r) ? okl::translate(r) : kal_ok; +} + +void kal_map_release(void* region, kal_uintptr length) { + if (region == nullptr || length == 0) return; + (void)okl::sys(okl::nr_munmap, reinterpret_cast(region), static_cast(length)); +} + +} diff --git a/src/sys.h b/src/sys.h index c995553..e1a01a3 100644 --- a/src/sys.h +++ b/src/sys.h @@ -95,7 +95,7 @@ inline okl_long sys(okl_long n, okl_long a, okl_long b, okl_long c, okl_long d, enum : okl_long { nr_read = 0, nr_write = 1, nr_close = 3, nr_fstat = 5, nr_lseek = 8, - nr_mmap = 9, nr_mprotect = 10, nr_munmap = 11, nr_ioctl = 16, + nr_mmap = 9, nr_mprotect = 10, nr_munmap = 11, nr_ioctl = 16, nr_msync = 26, nr_readv = 19, nr_writev = 20, nr_sched_yield = 24, nr_nanosleep = 35, nr_getpid = 39, nr_clone = 56, nr_execve = 59, nr_exit = 60, nr_wait4 = 61, nr_kill = 62, nr_ftruncate = 77, nr_getcwd = 79, nr_fsync = 74, @@ -197,7 +197,7 @@ enum : okl_long { nr_exit = 93, nr_exit_group = 94, nr_set_tid_address = 96, nr_futex = 98, nr_nanosleep = 101, nr_clock_gettime = 113, nr_clock_getres = 114, nr_sched_yield = 124, nr_kill = 129, nr_tgkill = 131, nr_gettid = 178, - nr_getpid = 172, nr_mmap = 222, nr_munmap = 215, nr_mprotect = 226, + nr_getpid = 172, nr_mmap = 222, nr_munmap = 215, nr_mprotect = 226, nr_msync = 227, nr_clone = 220, nr_execve = 221, nr_wait4 = 260, nr_renameat = 38, nr_dup3 = 24, nr_execveat = 281, nr_close_range = 436, nr_prlimit64 = 261, nr_dup2 = -1, nr_fcntl = 25, @@ -323,7 +323,8 @@ enum : okl_long { #endif at_fdcwd = -100, at_removedir = 0x200, at_symlink_nofollow = 0x100, prot_read = 1, prot_write = 2, prot_exec = 4, prot_none = 0, - map_private = 2, map_anonymous = 0x20, map_stack = 0x20000, + map_shared = 1, map_private = 2, map_anonymous = 0x20, map_stack = 0x20000, + ms_async = 1, clock_monotonic = 1, clock_realtime = 0, futex_wait = 0, futex_wake = 1, futex_private = 128, }; diff --git a/src/version.cpp b/src/version.cpp index 9102e34..ba04fdd 100644 --- a/src/version.cpp +++ b/src/version.cpp @@ -23,7 +23,8 @@ kal_u64 kal_interfaces(void) { | KAL_IFACE_ENV | KAL_IFACE_TIME | KAL_IFACE_RANDOM | KAL_IFACE_FS | KAL_IFACE_PROCESS | KAL_IFACE_TASK | KAL_IFACE_EXEC | KAL_IFACE_TERMINAL | KAL_IFACE_NET - | KAL_IFACE_DATAGRAM | KAL_IFACE_SPACE | KAL_IFACE_TIMEOUT; + | KAL_IFACE_DATAGRAM | KAL_IFACE_SPACE | KAL_IFACE_TIMEOUT + | KAL_IFACE_MAP; } }