{"id":13512351,"url":"https://github.com/sorpaas/rux","last_synced_at":"2025-04-08T04:19:35.704Z","repository":{"id":74187345,"uuid":"51561646","full_name":"sorpaas/rux","owner":"sorpaas","description":"A hobbyist microkernel written in Rust, featuring a capability-based system similar to seL4.","archived":false,"fork":false,"pushed_at":"2019-12-02T01:05:44.000Z","size":511,"stargazers_count":301,"open_issues_count":3,"forks_count":15,"subscribers_count":16,"default_branch":"master","last_synced_at":"2025-03-24T10:11:10.246Z","etag":null,"topics":["kernel","microkernel"],"latest_commit_sha":null,"homepage":"https://source.that.world/source/rux/","language":"Rust","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sorpaas.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2016-02-12T01:58:28.000Z","updated_at":"2025-03-24T03:59:22.000Z","dependencies_parsed_at":null,"dependency_job_id":"de110609-c3e6-45f0-a9c7-cc0d019c6363","html_url":"https://github.com/sorpaas/rux","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sorpaas%2Frux","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sorpaas%2Frux/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sorpaas%2Frux/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sorpaas%2Frux/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sorpaas","download_url":"https://codeload.github.com/sorpaas/rux/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247773727,"owners_count":20993639,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["kernel","microkernel"],"created_at":"2024-08-01T03:01:45.952Z","updated_at":"2025-04-08T04:19:35.684Z","avatar_url":"https://github.com/sorpaas.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"## Rux, a microkernel written in Rust\n\nRux is a hobbyist microkernel written in Rust, featuring a\ncapability-based system similar to [seL4](https://sel4.systems/).\n\n- [Repository](https://source.that.world/source/rux/)\n- [Documentation](https://that.world/~docs/rux/kernel/)\n\n## Overview\n\nRux's goal is to become a safe general-purpose microkernel. It tries to\ntake advantage of Rust's memory model -- ownership and lifetime. While\nthe kernel will be small, unsafe code should be kept minimal. This makes\nupdating functionalities of the kernel hassle-free.\n\nRux uses a design that is similar to seL4. While there won't be formal\nverification in the short term, it tries to address some design issues\nof seL4, for example, capability allocation.\n\n## Contributing\n\nWe use [Phabricator](https://source.that.world/source/rux/) to manage\ncode reviews and collabration. To submit a patch, install\n[arcanist](https://secure.phabricator.com/book/phabricator/article/arcanist_quick_start/). After\nyou finished coding, run `arc diff` and it will guide you to create a\nnew patch in Phabricator.\n\nIf you don't like arcanist, you can also submit raw diff directly\nthrough the [web\ninterface](https://source.that.world/differential/diff/create/). Refer\nto guide in [this page](https://llvm.org/docs/Phabricator.html) for\ndetails on how to do this.\n\n## Quickstart\n\nCurrently, due to packaging problem, the kernel is only tested to\ncompile and run on Linux with `x86_64`. Platforms with qemu and compiler\ntarget of `x86_64` should all be able to run this kernel, but do it at\nyour own risk.\n\nTo run the kernel, first install `Rust`, `qemu`, and cross-compiled\nGNU's `binutils`. The easiest way to do it is through the\n`default.nix` file provided in the source code. Install\n[Nix](http://nixos.org/nix/), then go to the source code root and run\nthe following command:\n\n```lang=bash\nnix-shell\n```\n\nAfter that, run:\n\n```lang=bash\nmake run\n```\n\nYou should see the kernel start to run with a qemu VGA buffer. The\nbuffer, after the kernel successfully booted, should show a simple\ncommand-line interface controlled by `rinit` program launched by the\nkernel. Several commands can be used to test things out.\n\n```lang=bash\necho [message]\n```\n\nEcho messages and print them back to the VGA buffer.\n\n```lang=bash\nlist\n```\n\nPrint the current `CPool` slots into the kernel message buffer.\n\n```lang=bash\nretype cpool [source slot id] [target slot id]\n```\n\nRetype an Untyped capability into a CPool capability. `[source slot id]`\nshould be a valid slot index of an Untyped capability. `[target slot id]`\nshould be an empty slot for holding the retyped CPool capability.\n\n### Example: Talk With a Child Task\n\nThe rinit program will start the command line interface when it is the\nfirst to run. For all subsequent rinit programs, they will wait on a\nchannel (using the root CPool of index 255), and print out the value\nto the serial buffer.\n\nWhen you see the command line in the qemu VGA buffer, the \"parent\"\nrinit program has been successfully started. We can then create a\n\"child\" program using the same memory layout (sharing one page table),\nand make them talk.\n\nWhen the \"parent\" rinit program is started, you should see something\nlike below in the VGA buffer:\n\n```\nChild entry should be at: 0x88b0 (34992)\nChild stack pointer should be at: 0x70003ffc (1879064572)\n```\n\nThose messages are useful if we want to create a \"child\".\n\nTo do this, we first retype a new task from an untyped capability.\n\n```lang=bash\nretype task 2 249\n```\n\nThis creates a new task in \"inactive\" state, which allows us to do\nfurther settings. We then set its stack pointer and instruction\npointer to the valid value:\n\n```lang=bash\nset stack 249 1879064572\nset instruction 249 34992\n```\n\nThen we set the task's root CPool and top page table the same as the\n\"parent\":\n\n```lang=bash\nset cpool 249 0\nset table 249 3\n```\n\nThe task buffer is used for system calls, thus we need a new one for\nthe child. Fortunately, in the kernel `kmain`, we have already created\none at index 250, so we can set that as the \"child\"'s buffer.\n\n```lang=bash\nset buffer 249 250\n```\n\nAfter that, we can set the state of the task to active. This will\nstart the task.\n\n```lang=bash\nset active 249 1\n```\n\nIf you are lazy and don't want to create the task from scratch. The\ncommand below automates the task from retyping tasks from untyped to\nactivating the task.\n\n```lang=bash\nstart child\n```\n\nAfter the child has started, we can send numbers to channel (with\nCPool index 255).\n\n```lang=bash\nsend raw 5\n```\n\nYou should see `[kernel] Userspace print: Received from master: 5` in\nthe serial message buffer.\n\nYou can also send capabilities over the channel. Rux uses different\nsystem calls to send raw values, payloads and capabilities through\nchannels. If you wish to send capabilities, modify `let value: u64 =\nsystem::channel_take(CAddr::from(255));` in `child_main` of\n`rinit/src/lib.rs` to `let value: CAddr =\nsystem::channel_take_cap(CAddr::from(255));`.\n\n```lang=bash\nsend cap 0\n```\n\nAnd the top-level capability pool capability (CPoolCap) is copied\nagain from parent to child.\n\n## Source Code Structure\n\nThe development of Rux happen in the `master` branch in the source code\ntree. The kernel resides in the `kernel` folder, with platform-specific\ncode in `kernel/src/arch`. For the `x86_64` platform, the kernel is\nbooted from `kernel/src/arch/x86_64/start.S`. The assembly code them\njumps to the `kinit` function in `kernel/src/arch/x86_64/init/mod.rs`.\n\nAfter the kernel is bootstrapped, it will initialize a user-space\nprogram called `rinit`, which resides in the `rinit` folder. The\nuser-space program talks with the kernel through system calls, with ABI\ndefined in the package `abi`, and wrapped in `system`.\n\n## Kernel Design\n\n### Capabilities\n\nCapabilities are used in kernel to manage Kernel Objects. Those\nCapabilities are reference-counted pointers that provide management for\nobject lifecycles.\n\nCapabilities in user-space can be accessed using so-called `CAddress`,\nrefered through the root capability of the user-space task. This helps\nto handle all permission managements for the kernel, and thus no\npriviliged program or account is needed.\n\nCurrent implemented capabilities are:\n\n- Untyped memory capability (UntypedCap)\n- Capability pool capability (CPoolCap)\n- Paging capability\n  - PML4Cap, PDPTCap, PDCap, PTCap\n  - RawPageCap, TaskBufferPageCap\n  - VGA buffer\n- CPU time sharing capability (TaskCap)\n- Inter-process communication capability (ChannelCap)\n\n#### Example: Initialize a New Task\n\nThis example shows how to initialize a new task using the capability\nsystem.\n\n- Create an empty TaskCap.\n- Create an empty CPoolCap.\n- Initialize paging capabilities (One PML4Cap, Several PDPTCap, PDCap,\n  PTCap and RawPageCap)\n- Assign the stack pointer in TaskCap.\n- Load the program into those RawPageCap.\n- Assign the PML4Cap to TaskCap.\n- Assign the CPoolCap to TaskCap.\n- Switch to the task!\n\n#### Implementation\n\nImplementing reference-counted object is a little bit tricky in kernel,\nas objects need to be immediately freed, and all weak pointers need to\nbe cleared after the last strong pointer goes out. Rux's implementation\nuses something called `WeakPool` to implement this. The original\nreference counted object (called `Inner`), form a double-linked list\ninto the nodes in multiple WeakPools.\n\n### Capability Pools\n\nCapability Pools (or `CPool`) are used to hold multiple capability\ntogether. This is useful for programs to pass around permissions, and is\nessential for `CPool` addressing. In implementation, capability pools\nare implemented as a `WeakPool`.\n\n### Tasks\n\nA task capability has a pointer to a capability pool (the root for\n`CPool` addressing), a task buffer (for kernel calls), and a top-level\npage table. When switching to a task, the kernel switches to the page\ntable specified.\n\nThe `switch_to` function implemented uses several tricks to make it\n\"safe\" as in Rust's sense. When an interrupt happens in userspace, the\nkernel makes it as if the `switch_to` function has returned.\n\nIn kernel-space, interrupts are disabled.\n\n### Channels\n\nTasks communicate with each other through channels. A channel has a\nshort buffer holding messages sent from a task, and will respond this to\nthe first task that calls `wait` on the channel.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsorpaas%2Frux","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsorpaas%2Frux","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsorpaas%2Frux/lists"}