A Rust-based userland which also adds compile-time assurances to seL4 development.

Overview

ferros

Overview

A Rust library to add extra assurances to seL4 development.

ferros provides smart type-safe wrappers around seL4 features with an emphasis on compile-time resource tracking.

ferros builds on top of the selfe-sys library.

Build

Install cargo-xbuild then run cargo xbuild --target armv7-unknown-linux-gnueabihf from the root project directory.

Integration test execution is as simple as cd qemu-test && cargo test and requires the installation of qemu-system-arm.

Usage

Add ferros as a cargo dependency.

[dependencies]
ferros = { git = "https://github.com/auxoncorp/ferros" }

Quick Start

The following code walkthrough assumes execution selfe with the example sel4_start library, and introduces some aspects of ferros.

use selfe_sys;
use ferros::alloc::{self, micro_alloc, smart_alloc};
use ferros::userland::{root_cnode, BootInfo};

// The raw boot info is provided by the sel4_start library
let raw_boot_info: &'static selfe_sys::seL4_BootInfo = unsafe { &*selfe_start::BOOTINFO };


// Utility for finding and claiming `Untyped` instances supplied by the boot info.
let mut allocator = micro_alloc::Allocator::bootstrap(&raw_boot_info)?;
let initial_untyped = allocator
    .get_untyped::<U20>() // The size of the Untyped instance, as bits
    .expect("Couldn't find an untyped instance of the desired size");

// Create the top-level CNode wrapper with type-level-tracked remaining slot capacity
let (root_cnode, local_slots) = root_cnode(&raw_boot_info);

// Once we have an initial Untyped instance, memory distribution from it
// can be tracked with compile-time checks. The smart_alloc macro synthesizes
// the allocation code, and the capacity bounds are statically verified by
// the type checker. The effect is that you can write 'slots' in the macro body 
// anywhere you need some slots, and you'll get the right number allocated
// with type inference. A reference to 'ut' does the same for untyped memory. 
smart_alloc!(|slots from local_slots, ut from uts| {

    // Create a page table seL4 kernel object and return a capability pointer to it.
    // Here we use a variable binding type annotation and Rust's type system can figure out
    // if it can allocate a large enough Untyped instance and enough cnode slots
    // to represent this particular kernel object.
    let example_page_table: LocalCap<UnmappedPageTable> = retype(ut, slots)?;

    // Create a resource-tracking wrapper around the raw boot info to assist in
    // virtual memory related operations.
    let boot_info  = BootInfo::wrap(raw_boot_info, ut, slots);
    let (root_page_table, boot_info) = boot_info.map_page_table(root_page_table)?;
});

Features

Context-Aware Automatic Capability Management

Capabilities are the mechanism by which seL4 applications manage their access to useful kernel objects, like notifications, endpoints, and pages.

Capabilities are stored in specialized collections of capability-holding-capacity, called CNodes. In basic seL4 development, knowledge of a complex addressing scheme (CPointers) is required to generate and manipulate capabilities. In C seL4 development there are few guard-rails against misinterpreting what type of kernel object is referenced by a CPointer, let alone whether that CPointer is even valid in the current execution context.

ferros solves these problems by tracking capabilities with a smart pointer type, Cap.

Cap pointers are parameterized at the type level by the kernel object kind they point at, as well as by whether the pointer is valid in the local execution context (or in the context of a child process); e.g. Cap<Endpoint, Local> , Cap<Notification, Child>

The ferros APIs

Compile Time Resource Management

seL4 offers several resources worth tracking -- available free slots in a CNode, raw memory in Untyped instances, the portions of virtual memory space yet unclaimed, and so forth. ferros tracks these resources at compile time.

CNodes have a self-explanatory FreeSlots type parameter, Untypeds have a BitSize type parameter that shows how many bits of memory they could store, and VSpace's PageDirFreeSlots and PageTableFreeSlots params collaborate to show which portions of virtual address space have yet to be claimed or mapped.

Whenever a function needs to take some subset of resources from these objects, the function consumes the object as a whole and returns an instance of that object with the necessary type parameters decremented to track the resources expended. If a resource container's contents aren't sufficient to a given task at hand, the developer will experience a compile time failure (as opposed to a runtime one).

Following initialization the ferros framework renders accidental resource exhaustion in production deployment impossible by making correct usage mandatory during design and development.

Isolation and Communication

Atop the basic building blocks of capability creation and storage, ferros provides higher-level primitives for creating fully isolated subprocesses (see vspace.rs) as well as several options for well-typed synchronous and asynchronous communication between processes (see multi_consumer.rs, ipc.rs, and shared_memory_ipc.rs).

License

See LICENSE for more details.

Copyright 2021 Auxon Corporation

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Comments
  • Add an index to VSpace to denote

    Add an index to VSpace to denote "for child management" usage

    Not unlike the distinction between Child and Local for capabilities, we should also include a VSpace state which denotes that it is being prepared for a child's usage.

    Consider as an example the creation of a child process in a child process: https://github.com/auxoncorp/ferros/blob/ad3807bcd7a98bfc1f487a24339a7d2670ad4f3c/qemu-test/test-project/src/grandkid_process_runs.rs#L65-L72

    It is of course standard to be operating on a child's VSpace; what is not standard here, is that this child intends to create a child of its own. That's why we map pages into its address space and move the capabilities to the child's CSpace. The child will use this mapped region as scratch for creating its own child's stack. ~It is for this use case that we'd like to have a state in vspace_state for a process's VSpace whose intent is to beget children.~1 This state shall also add type-level guardrails to prevent a developer from mixing local and child capabilities, &c.

    1. See comment below regarding a CNodeRole index.

    opened by pittma 6
  • Rethink bootstrapping allocation

    Rethink bootstrapping allocation

    Summary

    Now that we have WUTBuddy::alloc_strong, we can provide the same API that Allocator::get_untyped gives us, but we can do it with WUTBuddy underneath! We can also use something buddy-like for tracking device memory, however, it will need to be supplemented with the ability to look things up by physical address which I'll get into later in this issue.

    Implementation details

    I. Allocation is Janus-like

    Where one face looks at general memory, the other at device memory. This results in the effective erasure of Allocator as we know it and from its ashes rises a WUTBuddy backed general memory allocator and a split-based allocator for device memory.

    pub struct UntypedAllocator {
        uts: WUTBuddy<role::Local, memory_kind::General>,
    }
    
    pub struct DeviceUntypedAllocator {
        device_uts: ArrayVec<[WUntyped<memory_kind::Device>; MAX_DEVICE_UTS]>,
    }
    

    Both of these allocators could join the BootInfo family, making there be a single bootstrap call which returns these two objects as part of the boot info structure1.

    Work that this entails

    1. WUntypeds do not have memory kinds associated with them. This will likely be the most amount of work as it'll result in threading it into all of the WUntyped usages.
    2. A change to allow the construction of the two types above which uses the memory_kind sorting hat to separate device from general memory.
    3. For weak_ut_buddy to be able to be constructed around a set of untypeds rather than just one.

    II. get_untyped

    Its API could remain the same, but I think it will want to return the error from WUTbuddy::alloc_strong for cases where splitting is involved and we get into syscall-land.

    Work this entails

    1. Delete a lot of code in micro_alloc.rs and make get_untyped delegate to alloc_strong.

    III. Device Memory

    For device memory, we need something like a buddy allocator, but our lookups aren't about sizes exclusively; they're also about physical addresses. We also have the desire to take only the relevant chunk of some oversized "device region", as mentioned in #30. For this use case, we want our implementation to do 4 things:

    1. Find the region in which the device resides.
    2. Find the granule(s) in that region in which the device resides.
    3. Split that thing up so we can have at that device.
    4. Hold on to the caps that come out the other end of those splits and update their respective physical addresses.

    Our existing buddy allocator implementations use size as the sorting criterion; we want a slightly different implementation which uses physical addresses as the search criterion, where size only comes into play after we've located the target region.

    Before I get into a suggested implementation I'd like to mention a conjecture w/r/t the salience of the type-level tracking of the size of device untypeds: I don't think it matters. We need size like an afterthought so we know how to split—we're not trying to prevent an over-allocation on device memory. Its depletion as a resource is binary, not gradual; the capability to the desired device is there or it is not.

    How I imagine this works is as a simple ArrayVec holding WUntypeds whose paddr we're also tracking a lá seL4_UntypedDesc. Lookups search through the vector and find the region the desired device resides in and it's extracted from the list. If it needs to be split, it is—buddy style, and then the new caps are pushed into the vector2.

    Work this entails

    1. Adding paddrs to WUntypeds3.
    2. The implementation of the algorithm described above.

    Footnotes

    1. This I am still unsure of and could be persuaded either way.
    2. This is of course pretty memory-thrashy, particularly the drop-and-put-back-together part. This naive implementation's viability is currently pending a response from @jonlamb-gh w/r/t whether this is ever used in the fault path.
    3. Only on memory_kind::Device untypeds to reduce intrusion?
    opened by pittma 5
  • Separate

    Separate "simultaneous" usage of `map_region_at_addr` and `map_region`

    By "simultaneous" I mean that VSpace should not provide both modes of mapping at the same time. When it does, we must keep track of the regions created in uses of map_region_at_addr to prevent overlaps in usages of map_region.

    Regarding the VMM's use of this: The VM's VSpace should always be in the map_region_at_addr mode. This is counter to a typical process which starts in map_region_at_addr mode to service the user image mapping but then transitions to the mode of "map a region, I don't care where". A future_next_addr member could be added to the "map at" state which gets moved when any region exceeds it.

    opened by pittma 4
  • Add ARMv8-A architecture support, running in AArch64

    Add ARMv8-A architecture support, running in AArch64

    The seL4 kernel supports running on an ARMv8 ISA, application profile, so should ferros.

    It's worth noting that the AAarch32 execution state of ARMv8-A is compatible with an ARMv7-A implementation that includes the Visualization Extensions. This allows us to run 32-bit guest at EL0/EL1 in a 64-bit vmm at EL2 (assuming the exception handling path exist).

    Also note that GNU and Linux documentation (except for Redhat and Fedora distributions) sometimes refers to AArch64 as ARM64.

    Hardware virtual memory objects

    AArch64 supports three different translation granules. These define the block size at the lowest level of translation table and control the size of translation tables in use.

    seL4 has picked a translation granule of 4 KB, with the following page sizes:

    • seL4_PageBits = 4 KB at level 3
    • seL4_LargePageBits = 2 MB at level 2
    • seL4_HugePageBits = 1 GB at level 1

    In the AArch64 state, there are four levels of paging structures:

    • PageGlobalDirectory at level 0
    • PageUpperDirectory at level 1
    • PageDirectory at level 2
    • PageTable at level 3

    Where a the VSpace is realized as a PageGlobalDirectory.

    All paging structures are indexed by 9 bits of the virtual address, therefore each level can address 2^9 = 512 slots.

    Virtual address translation table lookup with 4 KB pages

    In the case of a 4 KB granule, the hardware can use a 4-level look up process. The 48-bit address has nine address bits for each level translated (that is, 512 entries each), with the final 12 bits selecting a byte within the 4 KB coming directly from the original address.

    Bits [47:39] of the virtual address index into the 512 entry L0 table. Each of these table entries spans a 512 GB range and points to an L1 table. Within that 512 entry L1 table, bits [38:30] are used as index to select an entry and each entry points to either a 1 GB block or an L2 table.

    Bits [29:21] index into a 512 entry L2 table and each entry points to a 2 MB block or next table level. At the last level, bits [20:12] index into a 512 entry L3 table and each entry points to a 4 KB block.

    +--------+--------+--------+--------+--------+--------+--------+--------+
    |63    56|55    48|47    40|39    32|31    24|23    16|15     8|7      0|
    +--------+--------+--------+--------+--------+--------+--------+--------+
     |                 |         |         |         |         |
     |                 |         |         |         |         v
     |                 |         |         |         |   [11:0]  in-page offset
     |                 |         |         |         +-> [20:12] L3 index
     |                 |         |         +-----------> [29:21] L2 index
     |                 |         +---------------------> [38:30] L1 index
     |                 +-------------------------------> [47:39] L0 index
     +-------------------------------------------------> [63] TTBR0/1
    

    Virtual memory attributes

    When mapping memory, consider the cacheability:

    • If cacheable == true, use seL4_ARCH_Default_VMAttributes
    • If cacheable == false, use seL4_ARCH_Uncached_VMAttributes

    Work tasks

    • Add arm64 module with all of the respective architecture const's
    • Add aarch64 specific translation and paging constructors
    • Move architecture specific TCB manipulation into a module

    References

    opened by jonlamb-gh 4
  • Construction of a self hosted process

    Construction of a self hosted process

    Summary

    The VMM process will be self-hosted in the sense that it is managing its own memory. The main goal of this work is to separate the creation of a process from the use of that process's VSpace. In the existing process creation, ReadyProcess::new takes a mutable reference to the process's VSpace, this borrow prevents placing a VSpace into a child's process parameters.

    This issue proposes a new type of process, one that is self-hosted.


    Implementation Details

    Logistics

    in userland/process, the existing implementation becomes StandardProcess and a new process type, SelfHosted, is added to the module.

    SelfHosted

    ~SelfHosted's constructor takes a stack addr for the child and the local region for stack setup:~

    pub fn new<T: RetypeForSetup>(
        child_stack_addr: usize,
        cspace: LocalCap<ChildCNode>,
        parent_mapped_region: MappedMemoryRegion<StackPageCount, shared_status::Exclusive>,
        parent_cnode: &LocalCap<LocalCNode>,
        function_descriptor: extern "C" fn(T) -> (),
        process_parameter: SetupVer<T>,
        ipc_buffer_ut: LocalCap<Untyped<PageBits>>,
        tcb_ut: LocalCap<Untyped<<ThreadControlBlock as DirectRetype>::SizeBits>>,
        slots: LocalCNodeSlots<PrepareThreadCNodeSlots>,
        priority_authority: &LocalCap<ThreadPriorityAuthority>,
        fault_source: Option<crate::userland::FaultSource<role::Child>>,
    ) -> Result<Self, ProcessSetupError>;
    

    ~At its call site, the stack regions should already be configured:~

    let (unmapped_stack_pages, _) =
        parent_mapped_region.share(page_slots, parent_cnode, CapRights::RW)?;
    let mapped_stack_pages =
        vspace.map_shared_region_and_consume(unmapped_stack_pages, CapRights::RW)?;
    let stack_pointer =
        mapped_stack_pages.vaddr() + mapped_stack_pages.size() - param_size_on_stack;
    
    let params = SelfHostedParams { vspace };
    
    // Now we setup the process _without_ using the vspace.
    let proc = SelfHosted::new(
        stack_pointer,
        child_cnode,
        local_mapped_region,
        &cnode,
        child_main,
        params,
        ut,
        ut,
        slots,
        tpa,
        Some(fault_source),
    )?;
    

    See comment below for an update to this API.

    ProcType (optional)

    There's likely some code reuse both in the funneling into some overlap with standard process creation but also in the common behavior. Consider a

    impl<P: ProcType> P {
         // Common things
    }
    

    solution to capture some of the overlap where SelfHosted and StandardProcess both implement ProcType.

    blocker 
    opened by pittma 3
  • Device memory support for WUTBuddy

    Device memory support for WUTBuddy

    ... or make a different struct to do the same thing. We need to take a large device untyped and carve it up on demand to get a single page device untyped at a requested address.

    duplicate 
    opened by mullr 2
  • Expose virtual CPU capability

    Expose virtual CPU capability

    A seL4 VCPU object enables a thread to perform instructions and operations as if it were running at a higher privilege level. Higher privilege levels typically have access to additional machine registers and other pieces of state, the VCPU object acts as storage for that state.

    Note that the VCpuRegister variants are different for each architecture.

    There is some opportunity to have distinct Bound and Unbound VCPU types, where the process of binding an unbound VCPU to a TCB yields a bound VCPU type.

    We should wrap the underlying capability to expose these methods:

    /// Bind a TCB to a virtual CPU.
    ///
    /// When a TCB has a bound VCpu it is allowed to
    /// have the mode field of the cpsr register set
    /// to values other than user.
    /// It is allowed to have any value other than hypervisor.
    pub fn bind_tcb(&mut self, tcb: &mut LocalCap<ThreadControlBlock>) -> Result<(), SeL4Error>;
    
    /// Inject an IRQ to a virtual CPU.
    pub fn inject_irq(
            &mut self,
            virq: u16,
            priority: u8,
            group: u8,
            index: u8,
    ) -> Result<(), SeL4Error>;
    
    /// Read a virtual CPU register.
    pub fn read_register(&self, reg: VCpuRegister) -> Result<usize, SeL4Error>;
    
    /// Write a virtual CPU register.
    pub fn write_register(&mut self, reg: VCpuRegister, value: usize) -> Result<(), SeL4Error>;
    
    opened by jonlamb-gh 2
  • VSpace: Map at specific address

    VSpace: Map at specific address

    The VMM will need to map specific regions into the IPA for the guest, so VSpace will need something akin to VSpace::map_region_at_addr:

    pub fn map_region_at_addr<SizeBits: Unsigned>(
        &mut self,
        vaddr: Vaddr,
        region: UnmappedRegion<SizeBits>,
        rights: CapRights,
    ) -> Result<(), VSpaceError> {
        if self.overlaps_with_previously_mapped(vaddr) {
            return Err(VSpaceError::RegionOverlaps);
        } else {
            self.map_layer(...)
        }
    }
    

    Where VSpace::overlaps_with_previously_mapped uses a bit of new state added to VSpace:

    // Maybe this comes from a configuration item in sel4.toml?
    const NUM_SPECIFIC_REGIONS: usize = ...;
    
    struct VSpace<VSS> {
        //....
        mapped_regions: [(Vaddr, Vaddr); NUM_SPECIFIC_REGIONS],
    }
    
    impl VSpace<...> {
        fn overlaps_with_previously_mapped(&self, vaddr: Vaddr) -> bool {
            for (head, size) in self.mapped_regions {
                if vaddr > head && vaddr < head + size {
                    return true
                }
            }
            false
        }
    }
    

    Some caveats:

    1. There is a performance cost here and map_region_at_specific_addr is in the fault-path for the VMM, the hottest part w.r.t. to meeting a guest's expectations on memory accesses. It is likely that we don't want to do the overlapping check on every call, but instead to elide it in our code altogether, allowing the map_region_at_specific_addr call to fail in the kernel, amortizing that cost.
    2. We'll need to update the existing map_region functions to make use of the new state, as it is likely that the cost of letting the kernel tell us about an overlap, one page at a time, is in its worst case more than what could be reasonably amortized. Imagine failing through a region of a few hundred megabytes, or even a gigabyte, one page at a time.

    This rolls up into https://github.com/auxoncorp/engineering-planning/issues/3 and is blocked by #9.

    opened by pittma 2
  • Fix unused Results

    Fix unused Results

    warning: unused `core::result::Result` that must be used
       --> ferros/src/userland/multi_consumer.rs:705:5
        |
    705 |     consumer_vspace.skip_pages(1);
        |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        |
        = note: `#[warn(unused_must_use)]` on by default
        = note: this `Result` may be an `Err` variant, which should be handled
    
    warning: unused `core::result::Result` that must be used
       --> ferros/src/userland/multi_consumer.rs:713:5
        |
    713 |     consumer_vspace.skip_pages(1);
        |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        |
        = note: this `Result` may be an `Err` variant, which should be handled
    
    opened by jonlamb-gh 1
  • IRQControl needs to be splittable

    IRQControl needs to be splittable

    We need to hand a lot, but not all, of the irqcontrol slots to the VMM process, but still maintain some of them for local device drivers (uart to talk to the control plane, for example)

    opened by mullr 1
  • Access flag fault?

    Access flag fault?

    In an aarch64 build, the child processes don't seem to be able to use their VSpaces. The access for the pc faults before the process even starts, and it also cannot dump its stack:

    vm fault on code at address 0x44ae98 with status 0x82000006
    in thread 0xff800fff2c00 "child of: 'rootserver'" at address 0x44ae98
    With stack:
    0x312000: INVALID
    0x312008: INVALID
    0x312010: INVALID
    0x312018: INVALID
    0x312020: INVALID
    0x312028: INVALID
    0x312030: INVALID
    0x312038: INVALID
    0x312040: INVALID
    0x312048: INVALID
    0x312050: INVALID
    0x312058: INVALID
    0x312060: INVALID
    0x312068: INVALID
    0x312070: INVALID
    0x312078: INVALID
    

    My best effort at translating what that status means (0x82000006) I gather from some arm documentation on the instruction fault status register:

    b000110 access flag fault, page

    This leads me to wonder if there are some broken details w/r/t rights? flags? settings for paging mapping when using aarch64.

    Here's some information on the meaning of access flags: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0211k/Caceaije.html

    However, I'm unsure what or how those tie into the use of CapRight in seL4.

    opened by pittma 1
  • Make the example system run on real hardware

    Make the example system run on real hardware

    The example system added in #87 currently does not run on real hardware yet, it requires additional configuration around IOMUXing, clocks and ENET phy initialization.

    opened by jonlamb-gh 0
  • Migrate away from cargo-xbuild

    Migrate away from cargo-xbuild

    As of nightly 2020–07–15, cargo has its own feature for cross compiling the sysroot (see build-std) in a .cargo/config.toml

    [unstable]
    build-std = ["core", "compiler_builtins"]
    build-std-features = ["compiler-builtins-mem"]
    

    We no longer need to use cargo-xbuild to do this.

    opened by jonlamb-gh 0
  • Fix Badge bit masking

    Fix Badge bit masking

    opened by jonlamb-gh 1
Owner
Auxon Corporation
Critical Insights for Critical Systems
Auxon Corporation
Adds a uf2 header Microsofts HID Flashing Format (UF2) for copying over to UF2 bootloader mass storage devices

uf2conv Adds a uf2 header Microsofts HID Flashing Format (UF2) for copying over to UF2 bootloader mass storage devices. UF2 is factory programmed exte

Paul Sajna 22 Oct 16, 2022
A lightweight microkernel/IPC based operating system built with Rust which is not a clone of any existing operating system

Noble Operating System Noble is a lightweight microkernel and IPC based operating system built with Rust which is not a clone of any existing operatin

Revolution Xenon 3 Jan 10, 2022
RCore-Tutorial-v3 - Let's write an OS which can run on RISC-V in Rust from zero!

rCore-Tutorial-v3 rCore-Tutorial version 3.5. See the Documentation in Chinese. Official QQ group number: 735045051 news 2021.11.20: Now we are updati

rCore OS 786 Jan 2, 2023
Let's write an OS which can run on ARM in Rust from scratch

rCore-Tutorial-v3 rCore-Tutorial version 3.5. See the Documentation in Chinese. news 2021.11.20: Now we are updating our labs. Please checkout chX-dev

rCore OS 10 Dec 17, 2022
Let's write an OS which can run on x86_64 in Rust from scratch

rCore-Tutorial-v3 rCore-Tutorial version 3.5. See the Documentation in Chinese. news 2021.11.20: Now we are updating our labs. Please checkout chX-dev

rCore OS 6 Apr 1, 2022
A Real Time Operating System in Rust for Cortex M3 embedded systems

A Real Time Operating System in Rust for Cortex M3 embedded systems

Manuel Forcén Muñoz 5 Jun 1, 2022
Real Time For the Masses (RTFM), a framework for building concurrent applications, for MSP430 MCUs

msp430-rtfm Real Time For the Masses (RTFM), a framework for building concurrent applications, for MSP430 MCUs License Licensed under either of Apache

Jorge Aparicio 9 Sep 10, 2022
A concurrency framework for building real-time systems

Real-Time Interrupt-driven Concurrency A concurrency framework for building real-time systems. Formerly known as Real-Time For the Masses. Features Ta

Real-Time Interrupt-driven Concurrency (RTIC) 1k Dec 31, 2022
A language-based OS to run Rust on bare metal

RustOS A simple, language-based OS. Current features: Simple VGA for seeing output Some Rust libraries (core, alloc, collections) already in Working (

null 402 Dec 8, 2022
A language-based OS to run Rust on bare metal

RustOS A simple, language-based OS. Current features: Simple VGA for seeing output Some Rust libraries (core, alloc, collections) already in Working (

null 79 Dec 3, 2022
This project is based on code from freertos.rs and some additions to simplify the usage of FreeRTOS in embedded applications written in Rust

FreeRTOS-rust This project is based on code from freertos.rs and some additions to simplify the usage of FreeRTOS in embedded applications written in

Lobaro 196 Jan 4, 2023
Aero is a new modern, unix based operating system. It is being developed for educational purposes.

Areo Aero is a new modern, unix based operating system written in Rust and is being developed for educational purposes. Aero follows the monolithic ke

Anhad Singh 623 Dec 24, 2022
suidsnoop is a tool based on eBPF LSM programs that logs whenever a suid binary is executed and implements custom allow/deny lists.

suidsnoop Log suid binaries and enforce per-uid suid policy. suidsnoop is a tool for logging whenever a suid binary is executed on your system and opt

William Findlay 11 Dec 22, 2022
A fresh FRAME-based Substrate node, ready for hacking

Substrate Node Template A fresh FRAME-based Substrate node, ready for hacking ?? Getting Started Follow the steps below to get started with the Node T

Worlddev5007 13 Aug 26, 2022
A comparison of operating systems written in Rust

Rust OS comparison A comparison of operating systems written in Rust. There are several open source operating systems written in Rust. Most of them ar

Markus Kohlhase 492 Jan 8, 2023
An OS kernel written in rust. Non POSIX

"Tifflin" Experimental Kernel (and eventually Operating System) This is an experiment in writing an OS Kernel in rust (http://rust-lang.org). Mostly t

John Hodge (Mutabah) 618 Jan 8, 2023
A hobby operating system, in Rust

intermezzOS: kernel intermezzOS is a hobby operating system. This repository is for its kernel. See the website for more. License This project is dual

intermezzOS 1.3k Jan 1, 2023
A Rust version of the Weenix OS

Reenix This is the start of a unix like operating system written in Rust. It is based on the Weenix Operating system written for Brown's CS167/9. At t

Alex Light 311 Dec 22, 2022
A tiny 32 bit kernel written in Rust

rustboot A tiny 32 bit kernel written in Rust. I was inspired to download Rust and try to do this after seeing zero.rs - a stub that lets Rust program

Charlie Somerville 1.5k Dec 30, 2022