The Stupid Operating System

Overview

Stupid Operating System

Build Status MIT License Latest RustDoc Gitter

SOS is a simple, tiny toy OS implemented in Rust.

I'm writing this mostly for fun, to learn more about OS design and kernel hacking, so don't expect anything new or exciting out of this project.

Inspiration, and a reasonable amount of code, taken from @phil-opp's great series of blog posts on the subject, Charlie Somerville's rustboot, and Samy Pessé's How to Make an Operating System.

design goals

  • POSIX compliance is not a goal (though it would be cool)
  • Hybrid/loosely microkernel (i.e., move code to user space when convenient/practical)
  • Possibly provide the Rust stdlib at the OS level.
  • JVM-style memory allocation?
  • Possibly experiment with a Plan 9-esque networking stack eventually?

building & running

I've included a simple Makefile to automate building and running SOS. This README lists most of the important make targets, but there's also a $ make help command, which will print a list of all available targets.

setting up your build environment

In order to build SOS, you'll need to properly configure your build environment. Since this process is fairly complex, I've provided some automatic installation shell scripts to make it a bit more painless.

  • $ make env will install and configure build dependencies

If you don't trust the scripts, or if you're curious to know what they're doing, you can also follow the manual install instructions in BUILDING.md.

building & running the OS

  • $ make kernel compiles & links the kernel binary
  • $ make iso makes the kernel and builds a bootable ISO image
  • $ make run compiles the kernel, makes the ISO, and boots QEMU from the ISO
Comments
  • `make env` raises error [OS X Sierra]

    `make env` raises error [OS X Sierra]

    install-mac: Adding target linker to /Users/shea/.cargo/config...

    install-env: Installing xargo.

    error: Couldn't load Cargo configuration

    Caused by: could not parse TOML configuration in /Users/shea/.cargo/config

    Caused by: could not parse input as TOML /Users/shea/.cargo/config:1:4-2:1 expected =, but found

    make: *** [env] Error 101

    kind/bug area/build 
    opened by SnailShea 5
  • Double fault as of 1f9b6cd2d67f6b0c0004b8fd1ff5678c0338be2b

    Double fault as of 1f9b6cd2d67f6b0c0004b8fd1ff5678c0338be2b

    Something I changed between 1f9b6cd2d67f6b0c0004b8fd1ff5678c0338be2b and 19d09785340e1d49ba70100c1766aa3fe59db9d1 seems to be causing a double fault (or triple fault?).

    I need to figure out where the fault is occurring and which commit caused it before I can pinpoint the cause of the issue. I'm assuming that the interrupt handling refactor in commits 621f40dd6e6731092043f4b3826f44dbb8f51235 and ec14c269f4ea9140ba5983a26d09464266345ddb, or the changes to DTable::get_ptr() are probably what's causing the problem.

    kind/bug critical arch/x86_32 arch/x86_all arch/x86_64 area/kernel 
    opened by hawkw 5
  • Install more dev dependencies with Homebrew on macOS

    Install more dev dependencies with Homebrew on macOS

    It'd be nice if we could use Homebrew to install more of the macOS dev dependencies (like x86_64-pc-elf binutils and gcc, and objconv), so that they can be installed from the Brewfile rather than forcing everyone who wants to build SOS to run the install scripts.

    kind/feature area/build 
    opened by hawkw 4
  • Add `mtools` to build dependencies

    Add `mtools` to build dependencies

    This PR adds mtools to the list of build dependencies on Linux and adds it to the packages installed on Arch/Manjaro and Debian/Ubuntu. Closes #52.

    Thanks @rachlmac for fixing this issue.

    area/build 
    opened by hawkw 3
  • Populate IDT statically?

    Populate IDT statically?

    If we know the location of ISR functions in the compiled binary statically (which we do), then it seems to me that we should be able to create interrupt gates for them statically as well, at compile-time. This way, we could have our IDT already populated with kernel ISRs at compile-time, rather than having to fill it with Gate::absent() and then loop through a different array of ISRs and insert them into the IDT as part of the init process, like we currently do.

    kind/feature arch/x86_all area/kernel 
    opened by hawkw 3
  • Make interrupt handlers less stupid (a.k.a.

    Make interrupt handlers less stupid (a.k.a. "`handle_interrupt` considered harmful")

    Our current interrupt handling architecture certainly works, but it is a bit of a mess. We have an assembly language file that makes an array of interrupt handler functions, but they all just call the same Rust function which then matches the interrupt ID and dispatches again. This is a mess.

    The current approach has way too many moving parts, with ASM interrupt handlers getting dispatched to by the IDT but then all just jumping to the same God function (handle_interrupt) in Rust-land, which dispatches again based on the interrupt ID. It also doesn't help us to achieve our goal of using files ending in .asm only in the boot sequence.

    Also, even though we have separate handle_interrupt and handle_cpu_exception functions, and separate macros in the assembly file for generating ASM handlers for exceptions and normal interrupts, we still dispatch CPU exceptions through handle_interrupt. Even the name handle_interrupt is a problem: a function with a name that broad is probably a God function that needs to be broken apart.

    It seems to me we have several options. We could keep the current architecture, but try to do away with the assembly handlers by just sticking handle_interrupt and handle_cpu_exception directly into the IDT. In @phil-opp's recent blog post on interrupt handling, he just writes a separate Rust handler function for each interrupt and sticks them into his IDT. This might be a better way to go - it's simpler and gets rid of the handle_interrupt God function.

    kind/refactor arch/x86_32 arch/x86_all arch/x86_64 area/kernel 
    opened by hawkw 3
  • feat(x86_64::paging): Implement paging & kernel remap

    feat(x86_64::paging): Implement paging & kernel remap

    This PR adds a working implementation of paging and remapping the kernel into the high address space on x86_64! 🍾

    Note that interrupts had to be re-disabled temporarily because of issues from #78 that I'm still looking into.

    This PR also includes a number of changes to the elf and alloc crates that were necessary to get paging working correctly. It doesn't finish the whole "allocator rewrite" project, but it brings us further along.

    Paging issues:

    • Closes #18
    • Closes #19
    • Closes #20

    Allocator issues:

    • Closes #64
    • Closes #65
    • Closes #66
    • Closes #72

    Also makes some progress on issues #31, #73, #76, and #84.

    screen shot 2017-05-28 at 12 41 04 pm

    kind/feature arch/x86_64 area/kernel area/elf area/alloc 
    opened by hawkw 2
  • Pure-Rust boot sequence

    Pure-Rust boot sequence

    This PR adds the pure-Rust boot sequence for x86_64.

    This closes #17, closes #67, closes #68, closes #69, and closes #70.

    There is now a page fault when we try to set up the kernel heap, but this is likely because we are trying to create the heap before we've remapped the kernel into the higher address space. Since this is already slated to be more or less completely rewritten anyway (see #73 and so on), I think we can go ahead and merge this.

    kind/feature kind/refactor area/kernel 
    opened by hawkw 2
  • Can the return type of an allocation be changed to Option<Unique<u8>>?

    Can the return type of an allocation be changed to Option>?

    Rather than representing a pointer to an allocation as *mut u8, can we represent it as an Option<Unique<u8>>?

    Using Unique might allow the compiler to do more reasoning about an allocation result...

    kind/feature kind/question kind/refactor from TODO 
    opened by hawkw 2
  • iter::Step trait functions have changed

    iter::Step trait functions have changed

    build errors:

       Compiling memory v0.0.1 (file:///Users/eliza/Code/sos-kernel/memory)
    error[E0407]: method `step` is not a member of trait `core::iter::Step`
       --> memory/src/macros.rs:229:13
        |
    229 | /             fn step(&self, by: &Self) -> Option<Self> {
    230 | |                 self.number
    231 | |                     .step(&by.number)
    232 | |                     .map(|s| $ty { number: s})
    233 | |             }
        | |_____________^ not a member of trait `core::iter::Step`
        |
       ::: memory/src/arch/x86_64/mod.rs
        |
    34  |       #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Page!(PAddr) )]
        |  ___________________________________________________________-
    35  | |     pub struct PhysicalPage { pub number: u64 }
    36  | | }
    37  | | impl fmt::Debug for PhysicalPage {
    ...   |
    
    error[E0407]: method `steps_between_by_one` is not a member of trait `core::iter::Step`
       --> memory/src/macros.rs:247:13
        |
    247 | /             fn steps_between_by_one(start: &$ty, end: &$ty) -> Option<usize> {
    248 | |                 use ::core::iter::Step;
    249 | |                 <<$addr as Addr>::Repr as Step>::steps_between( &start.number
    250 | |                                                               , &end.number
    251 | |                                                               , &1
    252 | |                                                               )
    253 | |             }
        | |_____________^ not a member of trait `core::iter::Step`
        |
       ::: memory/src/arch/x86_64/mod.rs
        |
    34  |       #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Page!(PAddr) )]
        |  ___________________________________________________________-
    35  | |     pub struct PhysicalPage { pub number: u64 }
    36  | | }
    37  | | impl fmt::Debug for PhysicalPage {
    ...   |
    
    error[E0407]: method `is_negative` is not a member of trait `core::iter::Step`
       --> memory/src/macros.rs:263:23
        |
    263 |               #[inline] fn is_negative(&self) -> bool { unimplemented!(); }
        |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `core::iter::Step`
        |
       ::: memory/src/arch/x86_64/mod.rs
        |
    34  |       #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Page!(PAddr) )]
        |  ___________________________________________________________-
    35  | |     pub struct PhysicalPage { pub number: u64 }
    36  | | }
    37  | | impl fmt::Debug for PhysicalPage {
    ...   |
    
    error[E0407]: method `step` is not a member of trait `core::iter::Step`
       --> memory/src/macros.rs:229:13
        |
    229 | /             fn step(&self, by: &Self) -> Option<Self> {
    230 | |                 self.number
    231 | |                     .step(&by.number)
    232 | |                     .map(|s| $ty { number: s})
    233 | |             }
        | |_____________^ not a member of trait `core::iter::Step`
        |
       ::: memory/src/lib.rs
        |
    160 |       #[derive( Copy, Clone, Eq, Ord, PartialEq, PartialOrd, Page!(VAddr) )]
        |  ____________________________________________________________-
    161 | |     pub struct VirtualPage { pub number: usize }
    162 | | }
    163 | |
    ...   |
    222 | |
    223 | |     /// Remove `n` pages from the beginning of this `PageRange`
        | |___________________________________- in this macro invocation
    
    error[E0407]: method `steps_between_by_one` is not a member of trait `core::iter::Step`
       --> memory/src/macros.rs:247:13
        |
    247 | /             fn steps_between_by_one(start: &$ty, end: &$ty) -> Option<usize> {
    248 | |                 use ::core::iter::Step;
    249 | |                 <<$addr as Addr>::Repr as Step>::steps_between( &start.number
    250 | |                                                               , &end.number
    251 | |                                                               , &1
    252 | |                                                               )
    253 | |             }
        | |_____________^ not a member of trait `core::iter::Step`
        |
       ::: memory/src/lib.rs
        |
    160 |       #[derive( Copy, Clone, Eq, Ord, PartialEq, PartialOrd, Page!(VAddr) )]
        |  ____________________________________________________________-
    161 | |     pub struct VirtualPage { pub number: usize }
    162 | | }
    163 | |
    ...   |
    222 | |
    223 | |     /// Remove `n` pages from the beginning of this `PageRange`
        | |___________________________________- in this macro invocation
    
    error[E0407]: method `is_negative` is not a member of trait `core::iter::Step`
       --> memory/src/macros.rs:263:23
        |
    263 |               #[inline] fn is_negative(&self) -> bool { unimplemented!(); }
        |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `core::iter::Step`
        |
       ::: memory/src/lib.rs
        |
    160 |       #[derive( Copy, Clone, Eq, Ord, PartialEq, PartialOrd, Page!(VAddr) )]
        |  ____________________________________________________________-
    161 | |     pub struct VirtualPage { pub number: usize }
    162 | | }
    163 | |
    ...   |
    222 | |
    223 | |     /// Remove `n` pages from the beginning of this `PageRange`
        | |___________________________________- in this macro invocation
    
    error[E0050]: method `steps_between` has 3 parameters but the declaration in trait `core::iter::Step::steps_between` has 2
       --> memory/src/macros.rs:237:58
        |
    237 |               fn steps_between(start: &$ty, end: &$ty, by: &$ty)
        |                                                            ^^^^ expected 2 parameters, found 3
        |
       ::: memory/src/arch/x86_64/mod.rs
        |
    34  |       #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Page!(PAddr) )]
        |  ___________________________________________________________-
    35  | |     pub struct PhysicalPage { pub number: u64 }
    36  | | }
    37  | | impl fmt::Debug for PhysicalPage {
    ...   |
        |
        = note: `steps_between` from trait: `fn(&Self, &Self) -> core::option::Option<usize>`
    
    error[E0046]: not all trait items implemented, missing: `add_usize`
       --> memory/src/macros.rs:227:9
        |
    227 |           impl ::core::iter::Step for $ty {
        |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `add_usize` in implementation
        |
       ::: memory/src/arch/x86_64/mod.rs
        |
    34  |       #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Page!(PAddr) )]
        |  ___________________________________________________________-
    35  | |     pub struct PhysicalPage { pub number: u64 }
    36  | | }
    37  | | impl fmt::Debug for PhysicalPage {
    ...   |
        |
        = note: `add_usize` from trait: `fn(&Self, usize) -> core::option::Option<Self>`
    
    error[E0050]: method `steps_between` has 3 parameters but the declaration in trait `core::iter::Step::steps_between` has 2
       --> memory/src/macros.rs:237:58
        |
    237 |               fn steps_between(start: &$ty, end: &$ty, by: &$ty)
        |                                                            ^^^^ expected 2 parameters, found 3
        |
       ::: memory/src/lib.rs
        |
    160 |       #[derive( Copy, Clone, Eq, Ord, PartialEq, PartialOrd, Page!(VAddr) )]
        |  ____________________________________________________________-
    161 | |     pub struct VirtualPage { pub number: usize }
    162 | | }
    163 | |
    ...   |
    222 | |
    223 | |     /// Remove `n` pages from the beginning of this `PageRange`
        | |___________________________________- in this macro invocation
        |
        = note: `steps_between` from trait: `fn(&Self, &Self) -> core::option::Option<usize>`
    
    error[E0046]: not all trait items implemented, missing: `add_usize`
       --> memory/src/macros.rs:227:9
        |
    227 |           impl ::core::iter::Step for $ty {
        |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `add_usize` in implementation
        |
       ::: memory/src/lib.rs
        |
    160 |       #[derive( Copy, Clone, Eq, Ord, PartialEq, PartialOrd, Page!(VAddr) )]
        |  ____________________________________________________________-
    161 | |     pub struct VirtualPage { pub number: usize }
    162 | | }
    163 | |
    ...   |
    222 | |
    223 | |     /// Remove `n` pages from the beginning of this `PageRange`
        | |___________________________________- in this macro invocation
        |
        = note: `add_usize` from trait: `fn(&Self, usize) -> core::option::Option<Self>`
    
    error: aborting due to 10 previous errors
    
    error: Could not compile `memory`.
    
    kind/bug critical contrib/good first issue 
    opened by hawkw 1
  • Consistent notation for VAddr/PAddr

    Consistent notation for VAddr/PAddr

    Currently, we tend to format both virtual (VAddr) and physical (PAddr) addresses using the "{:#p}" format specifier for pointers. This works fine, but makes telling whether an address is physical or virtual difficult when reading through logs, et cetera.

    It'd be nice if we could have a consistent notation for these. I suggest possibly replacing "0xff00" with "Pxff00 for physical addresses and Vxff00 for virtual addresses, or appending a P/V to the end of the hex address, like 0xff00_p.

    kind/feature contrib/help wanted contrib/easy 
    opened by hawkw 1
  • Figure out how to get non-kernel binaries into the SOS ISO

    Figure out how to get non-kernel binaries into the SOS ISO

    This can be hard-coded to the hello-world test elf for now, but eventually we'll want to generalise this for including userspace stuff in the OS distribution.

    contrib/help wanted area/build 
    opened by hawkw 0
  • Add a Gitter chat badge to README.md

    Add a Gitter chat badge to README.md

    sos-os/kernel now has a Chat Room on Gitter

    @hawkw has just created a chat room. You can visit it here: https://gitter.im/sos-os/kernel.

    This pull-request adds this badge to your README.md:

    Gitter

    If my aim is a little off, please let me know.

    Happy chatting.

    PS: Click here if you would prefer not to receive automatic pull-requests from Gitter in future.

    opened by gitter-badger 0
  • Error compiling when re-referencing ptr::Unique to ptr::NonNull

    Error compiling when re-referencing ptr::Unique to ptr::NonNull

    ┌─╼[~/Projects/sos-kernel] [master*]
    └────╼ make kernel
       Compiling vga v0.1.0 (file:///Users/shea/Projects/sos-kernel/vga)
    error[E0277]: the trait bound `core::ptr::NonNull<[[Char; 80]; 25]>: core::marker::Send` is not satisfied in `Terminal`
      --> vga/src/lib.rs:91:1
       |
    91 | / pub static CONSOLE: Mutex<Terminal>
    92 | |     = Mutex::new(unsafe { Terminal::new(
    93 | |          Palette::new(Color::LightGrey, Color::Black )
    94 | |        , 0xB8000
    95 | |     )});
       | |________^ `core::ptr::NonNull<[[Char; 80]; 25]>` cannot be sent between threads safely
       |
       = help: within `Terminal`, the trait `core::marker::Send` is not implemented for `core::ptr::NonNull<[[Char; 80]; 25]>`
       = note: required because it appears within the type `Terminal`
       = note: required because of the requirements on the impl of `core::marker::Sync` for `spin::Mutex<Terminal>`
       = note: shared static variables must have a type that implements `Sync`
    
    error: aborting due to previous error
    
    error: Could not compile `vga`.
    
    To learn more, run the command again with --verbose.
    make: *** [target/x86_64-sos-kernel-gnu/debug/sos_kernel] Error 101
    
    opened by SnailShea 1
Owner
SOS
the SOS operating system
SOS
Writing an OS in Rust, To Study Operating System and Computer System

Hun Os Writing an OS in Rust, To Study Operating System and Computer System Reference Os Written In Rust https://github.com/seonghun-dev/blog_os https

Jung Seonghun 2 Dec 15, 2022
A secure embedded operating system for microcontrollers

Tock is an embedded operating system designed for running multiple concurrent, mutually distrustful applications on Cortex-M and RISC-V based embedded

Tock Embedded OS 4.1k Jan 5, 2023
A secure embedded operating system for microcontrollers

Tock is an embedded operating system designed for running multiple concurrent, mutually distrustful applications on Cortex-M and RISC-V based embedded

Tock Embedded OS 4k Jan 2, 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
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
A new operating system kernel with Linux binary compatibility written in Rust.

Kerla Kerla is a monolithic operating system kernel from scratch in Rust which aims to be compatible with the Linux ABI, that is, runs Linux binaries

Seiya Nuta 3.1k Jan 1, 2023
Operating system written in Rust for NumWorks calculator (model n0110)

RustWorks An OS (eventually) for the Numworks calculator (model n0110). Setup First install Rust by following these instuctions then: rustup target ad

null 30 Nov 10, 2022
The official kernel for Popcorn OS, and operating system designed for handheld devices.

About Popkern is the kernel for Popcorn OS, an operating system designed for handheld devices. As such, the kernel is (to be) optimised at all levels

Team Scena 3 Sep 19, 2021
Geng wanzheng ([a] more complete) asynchronous operating system

更完整系统(GWZOS) 更完整系统的目的是编写一个异步功能完整的异步操作系统。我们希望尽可能完整地实现异步内核的核心概念,提供相应的驱动、软件生态系统,为未来内核的设计探索可能的实现方案。对比不同解决方案的性能开销,得到较详细的内核验证结论。 感谢大家对项目的支持!接龙链接 设计文档请参考: 无相

Luo Jia 10 Aug 26, 2021
SteinsOS is an operating system written in Rust

SteinsOS is an operating system featuring non-preemptive kernel targeting on single-core armv8 architecture.

Sheng 84 Dec 15, 2022
Xrs is a POSIX-subset operating system kernel written in Rust.

XRS-OS ( ?? WIP) Xrs is a POSIX-subset operating system kernel written in Rust. Current project team members 0x5459 core developer (he/him) 0x5457 cor

null 7 Nov 16, 2022
A simples rust operating system that prints hello world.

rust-os-helloworld A simples rust operating system that prints hello world. Just run: cargo install bootimage and: cargo bootimage Install QEMU and: q

null 3 Nov 24, 2021
An attempt at an operating system written in Rust

Rust Operating System An attempt at a simple operating system in Rust and a semester project for the Operating Systems course at CS@UCU. Documentation

Andriy Sultanov 10 Jan 15, 2022
A small operating system, for my own learning

taos This project is the result of following Philipp Oppermann's series of tutorials in building a small operating system kernel targeting x86-64, alo

null 0 Nov 7, 2021
Cute tiny operating system for RISC-V. ฅ•ω•ฅ

MoeOS ⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄ ٩(^ᴗ^)۶欢迎参观MoeOS的仓库,MoeOS是一个小巧可爱(并不)的操作系统,目前全力支持RISC-V中。 (*≧▽≦)因为还只是一个玩具操作系统,就别要求她能做太多事情啦!现在功能还不完善,会慢慢加的! 编译 呐,你想给我找个家么? 目前MoeOS

Rui Li 30 Nov 11, 2022
Rux - An x86_64 toy operating system kernel written in Rust

Rux - An x86_64 toy operating system kernel written in Rust. Rux is a port of the Hux kernel, my x86 32-bit single-CPU toy kernel written in C, following the OSTEP book structure and terminology.

Guanzhou Jose Hu 6 Feb 26, 2022
A RISC-V and unix-like operating system developed just for fun.

Orca 虎鲸 A RISC-V and unix-like operating system developed just for fun. Schedule [*] bootloader (use RustSBI-qemu) [ ] linker & stack [ ] memory alloc

Mr.Z 4 May 29, 2022
A Rust Operating System, written from the ground up

ThornOS A Rust Operating System, written from the ground up Build Dependencies Bootimage TODO: Document build process in more detail Acknowledgements

Stuart Reid 1 Mar 31, 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