Skip to content

ThatMishakov/pmOS

Repository files navigation

pmOS

A small (hobby) operating for RISC-V, LoongArch and x86 (i686 and x86_64), using a homemade microkernel, C library and userspace, partially developed as my end of degree project. The goal of the project is to make a general purpose operating system, with the objective of learning and being suitable for development and exploration of the RISC-V and X86 platforms. The microkernel is mostly written in C++, and the userspace is in a mixture of C, C++ and Rust (and ASM where needed). The limine bootloader and Hyper bootloader are used for booting the system, depending on the architecture.

Screenshots

RISC-V Execution: RISC-V execution

Baremetal execution on an old x86 (AMD E450) laptop, discovering an internal SATA HDD: Baremetal execution

Architecture

The OS is based on a microkernel architecture, with the idea of running drivers and services in userspace. The kernel currently has physical and virtual memory managers, scheduling, interrupts, IPC and permissions managed inside it. Of the process management, the kernel only knows about threads (called "tasks" in the code), with (POSIX) processes and threads being an abstraction on top of it, managed in userspace. The rest is implemented in userspace, communicating through IPC message queues.

The executables use ELF format.

The system supports booting by the limine protocol. In the past, multiboot2 was used with a stage 2 bootloader, but it was replaced by limine, since it works on both x86_64 and RISC-V. The kernel is loaded by limine, which initializes itself and starts the first user space task from a module called "bootstrap". It then recieves some info from the kernel and list of modules, moved to memory objects and starts those up, and maps itself as a root filesystem.

As such, the kernel directory contains the kernel, the lib contains userspace C libraries, sysroot contains system headers, limine contains the bootloader configs, and the rest of the directories contain different userspace programs, which make up the system. All of the drivers (including framebuffer) are run in userspace.

The i686 port is using Hyper bootloader and its Ultra protocol.

Project structure

The project is rougly structured as follows:

  • kernel/ - The microkernel
  • lib/ - Different libraries (C, Rust and so on)
  • userspace/ - Different userspace servers/programs
  • host-recipes/, source-recipes/, recipes/, patches/, Jinxfile - Jinx build system stuff
  • scripts/ - Build support scripts

Compilation and execution

The Jinx build system is used for building the system. A Makfile is provided in the root of this project, which downloads Jinx and uses it to build the system images for different architectures. The qemu, qemu-x86, qemu-i686 and qemu-loongarch64 makefile targets are provided to build and run RISC-V, amd64, ia32 and LoongArch64 images in qemu, respectively.

If you would like to use jinx directly, you can run

export source_dir=<path to this repository>

cd ${source_dir} && git submodule update --init --recursive # Prepare submodules
make -C ${source_dir} jinx # Download jinx

cd <your build directory>
${source_dir}/jinx init ${source_dir} ARCH=<desired architecture, e.g. riscv64, x86_64, i686, loongarch64>
${source_dir}/jinx build limine-disk-image

Immediate plans

  1. Implement working set for virtual memory (swap and page replacement)
  2. Implement AHCI driver reading and writing
  • Work on doccumentation
  • Improve project structure

Features

These are the features that are planned to be had in the OS:

Kernel

Arch-independent features:

  • Processes and threads

    • Processes - The kernel has tasks, but POSIX processes and execlp/spawn is not yet implemented
    • Task switching
    • Preemptive multitasking
    • Threads - basic pthread implementation in userspace building on kernel interfaces
    • Kernel threads
    • User space
  • Memory

    • Page frame allocator
      • Zone allocator - currently only splits memory into <4GB and >=4GB zones (for legacy devices)
    • Kernel virtual memory manager
    • kmalloc
    • Allocating memory to userspace
    • Userspace memory regions
      • Mapping (anonymous mmap)
      • Lazy allocations
      • Full unmapping
      • Partial and overlaping unmapping (munmap)
      • memprotect and changing permissions
      • Acccess to physical memory
      • Mapping of memory objects
      • Copy-on-write
    • Memory mapping
    • Releasing used pages
    • Memory objects
      • Memory object creation from kernel
      • Memory object access from kernel
      • Blocking tasks on memory object access in kernel
        • Need to make changes in scheduler
      • Memory object mapping to userspace
      • Memory object creation and management from userspace
    • Delayed allocation
    • Memory protections
    • TLB shootdowns
    • Swapping
    • Accessing userspace memory
      • Implemented (and surprisingly works well), but is very slow, needs rewriting
  • Interrupts and exceptions

    • Very basic exception handling
    • Syscalls
    • Interrupt dispatching to drivers
    • Interrupt sharing
  • IPC and messaging

    • Buffered string messages
    • Ports
    • Kernel messages
    • Quick user memory access - catching exceptions on userspace memory access
    • Handles/capabilities - would make API a lot nicer and fix a lot of issues with current design
      • Handles for ports
      • Handles for other stuff
      • Notification of closed handles
  • Permissions -> capabilities would solve that

  • Multi CPU support

RISC-V specific features:

  • Virtual memory - 3 to 5 level page tables
  • Exceptions
  • Timer interrupt
  • Userspace/U mode
  • Multi hart support

x86 features:

  • Virtual memory
  • Exceptions
  • Time
    • ACPI PM Timer (clock source and calibration)
    • HPET (clock source and calibration)
      • HPET timer interrupt source (in absence of LAPIC timer)
    • LAPIC timer
    • TSC
    • TSC deadline
    • KVM clock
  • APIC
    • xAPIC
    • x2APIC
    • LAPIC
    • IOMMU
  • Userspace/Ring 3
  • Multi CPU support

x86_64 specific features:

  • 5 level paging

i686 specific features:

  • Virtual memory
    • 2 level page tables
    • PAE - supports and uses up to 16GB of RAM, if available

LoongArch64 specific features:

  • Virtual memory
  • Exceptions
  • Timer interrupt - haven't noticed there was a TSC-like global timer, needs fixing
  • External interrupts - using EIO PIC and BIO PIC over HT
  • Userspace
  • Multi CPU support

Core utilities and daemons

  • Process management (processd) - Mostly unfinished, I plan it to route signals
  • Networking (networkd)
  • Filesystems
    • FAT32
    • FUSE
    • USTAR filesystem daemon - Archive parsing works, but it is very incomplete
    • VFSd
      • Mounting filesystems
      • Opening files
      • Traversing trees
  • pmbus - a bus for drivers and services in Rust
    • Publishing objects
    • Requesting objects
    • C++ bindings
    • C bindings
    • Rust bindings
  • Drawing on screen (screend)
    • Framebuffer
      • Showing text with framebuffer
  • Human input
  • Native executables
  • POSIX compatibility layer - Many functions are implemented and working, but a lot more are yet to be done

Drivers

  • PS/2
    • Keyboard - works, but needs something to funnel the input to
    • Mouse
  • i8042
  • ATA/Bulk storage
    • AHCI
      • Controller detection and initialization
      • Device detection
      • DMA
      • interrupts handling
      • Reading
      • Writing - no filesystems yet
    • NVMe
    • Virtio block
  • USB
  • Serial/Parallel - ns16550 using interrupts for receiving and sending. Works on RISC-V, missing IO ports stuff and untested on x86.
  • PCI/PCIe
    • Device detection
    • Legacy interrupt routing - Works on x86, broken on RISC-V, likely easy to fix
    • MSI/MSI-X
  • Network cards
  • virtio
    • virtio-user-input
  • ACPI (using uACPI)
    • Initialization
    • IRQ routing
    • Power button (interrupt) and shutting down
    • EC driver
    • AMD GPIO driver
    • S3 sleep - kinda works, but doesn't have a proper interface for drivers

Userland

  • Terminal
  • GUI
  • C/POSIX Library - a buch of functions are implemented, but a lot more are missing
  • Init server
    • Launching servers
    • Matching pmbus objects

Languages/Runtimes

  • LLVM/Clang patch
  • Hosted GCC cross-compiler
  • C and its runtime (using homemade C/POSIX library)
  • C++ and libstdc++ (and other) runtime(s) - Compiling and working but a lot of C library functions are missing
  • Go and libgo runtime with GCC - Compiling, but untested and probably broken for now. Also, exec-stuff is missing

Known issues

Documentation

In works!

Dependencies

The following libraries have been used in the project, possibly containing their own licenses:

License

Unless otherwise stated (see the dependencies), the project is licensed under the BSD 3-Clause license. See the LICENSE file for more information.

About

Small operating system for x86 and RISC-V

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors