I decided to document my journey of writing an OS in Nim. Why Nim? It’s one of the few languages that allow low-level systems programming with deterministic memory management (garbage collector is optional) with destructors and move semantics. It’s also statically typed, which provides greater type safety. It also supports inline assembly, which is a must for OS development. Other options include C, C++, Rust, and Zig. They’re great languages, but I chose Nim for its simplicity, elegance, and performance.
↫ Fusion OS documentation website
I love it when a hobby operating system project not only uses a less common programming language, but the author also details the entire development process in great detail. It’s not a UNIX-like, and the goals are a single 64 bit address space, capability-based security model, and a lot more. It’s targeting UEFI machines, and the code is, of course, open source and available on GitHub.
It reminds me a bit of Singularity OS.
https://en.wikipedia.org/wiki/Singularity_%28operating_system%29
I’d like to ask the author if this goes as far as singularity does in terms of providing memory isolation through strictly enforced static typing and language features rather rather than segments/page tables.
If so that’s awesome. I feel this model is underutilized. I discussed it at length with Neolander here on osnews so long ago 🙂
This sounds more like a less ambitiout version of serenityos or V2. V2 is fairly sucessful and used in millions of devices toda. Designed by the university of Utrech in the netherlands. And no there is no gui afaik to V2. As little as i know about the system, i have ran it on my pentium 2 in 1999, perhaps Thom could enlighten us what “van opnieuw” 2 means. is it some pun? i do not get it.
Author here. While I haven’t started on adding capability-based security yet, the plan is to use capabilities in conjunction with page tables per task to enforce memory protection at the hardware level. Using capabilities alone is not safe, as there’s no hardware support for it (e.g. as in CHERI[0]). Of course, nothing is implemented in this regard yet, so it’s hard to speculate what problems I will run into, but that’s the plan.
[0] https://www.cl.cam.ac.uk/research/security/ctsrd/cheri
khaledh,
That is very informative, I had no idea such a thing existed…
However the approach I was talking about is based on software isolation and does not require special architecture enhancements. Consider. from my link earlier..
These approaches are very different. While CHERI uses hardware to “allow historically memory-unsafe programming languages such as C and C++ to be adapted to provide strong, compatible, and efficient protection”, Singularity uses safe memory semantics to do so.
So consider what it would look like for two different processes to exist in the same memory using memory-safe language operations. Even though the memory of multiple processes exist in the same address space, they remains isolated thanks to language semantics without any special hardware. If a process has no references to the memory of another process, it cannot directly access the other processes’ memory. You could create a novel form of IPC simply having an API that hands the reference over to another processes. All other process-specific references remains isolated without the use of hardware based page tables.
I did not know if perhaps NIM, the language you are using supported this, but it sounds like that’s not the approach you are going with.
Anyway, you have a nice writeup.:) Good on you for doing something that is not yet another unix OS, I feel that creativity gets stifled when unix cloning is the goal.
These comments are why i come here every day. Thank you all for the knowledge.
Alfman, thanks for highlighting the difference. I am familiar with Singularity OS (I read some of the papers). Unfortunately Nim doesn’t have this kind of verifiable software fault isolation. The Singularity team created Sing# specifically for this purpose, and it would be a huge undertaking to build something similar or patch Nim to support this model.
I’m hoping that page table isolation, while sharing the same 64-bit address space, would allow passing of references between tasks through shared memory pages, e.g. a producer task can have write access to certain pages, and can grant a capability to another task to read from those pages. This is kind of similar to Singularity’s exchange heap. The tricky part would be to ensure memory ownership is tracked properly across task boundaries.
khaledh,
Seems like it should work. Shared memory will be most efficient when it stays mapped without having to touch the page tables until close. While permanent mapping is efficient. obviously it’s more vulnerable than only having the mapping when needed. You could build an API to consistently and correctly handle the shared structures and synchronization such that the shared memory does not remain accessible to the program outside of the ABI. Is this what you have in mind?
That would help protect from erroneous pointer access. but my concern is what the performance looks like. Do you know how much overhead there is if every call to the shared object API needs a context switch to escalate it’s access?