Gilbraltar is a version of the OCaml compiler to be able to build a MirageOS for RaspberryPi 4.

Related tags

Compilers gilbraltar
Overview

Gilbraltar, the MirageOS retreat is not so far

 _____ _ _ _           _ _           
|   __|_| | |_ ___ ___| | |_ ___ ___ 
|  |  | | | . |  _| .'| |  _| .'|  _|
|_____|_|_|___|_| |__,|_|_| |__,|_|  

gilbraltar is a version of the OCaml compiler to be able to build a MirageOS for RaspberryPi 4. It's a work in progress repository to provide a dune's toolchain (as ocaml-freestanding) specialized for Raspberry Pi 4.

The project is split into 2 packages:

  • kernel which contains the C kernel
  • caml which is a copy of ocaml-freestanding for our kernel

The goal of this repository is to bootstrap a caml runtime from nothing. The caml runtime is linked to nolibc and openlibm statically. Then, it provides a new ocamlfind/dune toolchain to be able to craft a full operating system with dune (as far as your context is rpi4).

A full example of an Hello World bare-metal OS is available into test where a small ceremony is needed to compile the program for your Raspberry Pi 4 - be aware that you must take the rpi4 artifact (and not the default one which is compiled with kernel/lib/stub.c).

This project by its conception is mainly inspired by:

How to launch the example

First, you must have opam as the OCaml package manager. Then, you need to install Gilbraltar:

$ opam pin add git+https://github.com/dinosaure/gilbraltar -y
...

Then, with dune, you are able to craft a full operating system:

$ cd test
$ dune build kernel8.elf

With qemu and a patch to be able to simulate a Raspberry Pi 4 system, you are able to launch the kernel8.elf with (Ctrl a + x to terminate):

$ qemu-system-aarch64 -M raspi4 \
  -nographic -no-reboot \
  -serial null -serial mon:stdio \
  -kernel kernel8.elf
 _____ _ _ _           _ _           
|   __|_| | |_ ___ ___| | |_ ___ ___ 
|  |  | | | . |  _| .'| |  _| .'|  _|
|_____|_|_|___|_| |__,|_|_| |__,|_|  
RPi4: Memory map: 768 MB addressable:
RPi4:   reserved @ (0x0 - 0xffffffffffffffff)
RPi4:       text @ (0x0 - 0x3dfff)
RPi4:     rodata @ (0x3e000 - 0x45fff)
RPi4:       data @ (0x46000 - 0x52fff)
RPi4:       heap >= 0x53000 < stack < 0x30000000
Hello World from OCaml!
QEMU: Terminated

And voilà!

And physically?

Gilbraltar use UART to puts some text and if you have an USB to Serial TTL link, you should be able to see this text if you follow this tutorial.

The main difference between the tutorial and our example is: OCaml! So, as far as an OCaml library does not link with a C stubs, you should be able to use it in your new RPi4 MirageOS!

TODO

This is a non-exhaustive list about what Gilbraltar does not do:

  • GPIO
  • MMU
  • yield
  • Multicore?
Comments
  • Better boot.S and link script

    Better boot.S and link script

    /cc @TheLortex may be a nicer boot.S and link script. However, a bug persists. I think this layout solve the issue about bss nicely. The remaining bug is about the Sys.argv.(0) and its usage. Indeed, a main.ml such as:

    let () = Format.printf "Hello %s!" Sys.argv.(0)
    

    But this code does not show anything:

    let () = Format.printf "Hello %S!" Sys.argv.(0)
    
    help wanted 
    opened by dinosaure 6
  • Interrupt mapped to OCaml signals

    Interrupt mapped to OCaml signals

    Main changes

    In this PR, the 64 interrupts referenced in the BCM2711 ARM Peripherals manual (6.2.4. VideoCore interrupts) are mapped to signals. Sys.set_signal can be used to setup a handler on one particular interrupt line. Currently, the interrupt process is the following:

    • signal_init is called to register a handler to the kernel
    • an interrupt is thrown, jump to the handler in the kernel, which in turn jumps to the handler in nolibc/signal.c
    • handler dispatch the interruption to the ocaml runtime
    • interruption returns, but they stay globally disabled
    • at some point, the signal handler is called by OCaml
    • the signal handler acknowledges the interrupt and enables them back globally.

    Idea

    Maybe it's possible to disable only the triggered interruption, but that would mean that double interruptions could occur, I don't know how OCaml handles that (what happens if another signal is triggered while handling a signal ?)

    Miscellanous changes

    kernel_old=1 is used because otherwise some breaking configuration is done in the interrupt controller (see https://github.com/raspberrypi/tools/blob/13474ee775d0c5ec8a7da4fb0a9fa84187abfc87/armstubs/armstub8.S#L214). I wanted to dune build caml/libnolibc.a and did some fixes for that.

    opened by TheLortex 3
  • gilbraltar does not work anymore with GCC 11 & GCC 12.

    gilbraltar does not work anymore with GCC 11 & GCC 12.

    With a deep look, the help of @TheLortex and @pitag-ha. many beers and a MirageOS retreat, we figure out that the compilation of variadic arguments with GCC 11 and GCC 12 produces a bad assembly for a RPi4. At least, that the only real difference we noticed.

    opened by dinosaure 1
  • Fix interrupts mapping to signals for interrupts ID >= 32

    Fix interrupts mapping to signals for interrupts ID >= 32

    For interrupts ID >= 32, the OCaml signal handler wouldn't be called.

    That's because 1 << sig is a 32-bit value, it equals to zero when overflowing. Instead we have to do 1L << sig to work with a 64-bit value and get the correct behavior.

    opened by TheLortex 1
  • Fix gcc11

    Fix gcc11

    It seems that since GCC 11, the compilateur is able to use some 128 bits registers and they are specially used on variadic arguments. Even if we allowed the RPi4 to use these registers, we are trapped by a non-aligned access. We enforce GCC to produce this assembly code and be sure that everything is aligned.

    I believe that on the real world operating system, such behavior are trapped and fixed(?) by the kernel.

    opened by dinosaure 0
  • Interrupts handler and MMU

    Interrupts handler and MMU

    Changes:

    • build system: add dune
    • interrupts: add a default handler that prints the exception register
    • change default exception level to EL1 (kernel)
    • mmu: add a flat mapping to enable cache
    opened by TheLortex 0
  • Delete the `kernel_old=1` option from the `config.txt`

    Delete the `kernel_old=1` option from the `config.txt`

    Currently, our unikernel is available at 0x0 into our image and we specify to the firmware that we use the old memory layout with kernel_old=1. However, from an @palainp's advise, it will be nice to have a reserved area before the kernel where it will be "safe" to manipulate the NULL pointer (which will be equal to 0x0).

    opened by dinosaure 0
  • nolibc/memcpy + memmove

    nolibc/memcpy + memmove

    I'm fine with the same memcpy+memmove as the ones in ocaml-freestanding/nolibc. My current testing is:

    $ opam pin
    gilbraltar.~dev                   git  git+https://github.com/palainp/gilbraltar#nolibc
    gilbraltar-linux.~dev             git  git+https://github.com/palainp/gilbraltar#nolibc
    gilbraltar-toolchain.~dev         git  git+https://github.com/palainp/gilbraltar#nolibc
    mirage-console-gilbraltar.~dev    git  git+https://github.com/palainp/gilbraltar#nolibc
    mirage-gilbraltar.~dev            git  git+https://github.com/palainp/gilbraltar#nolibc
    $ dune clean && dune build kernel8.img
    $ md5sum kernel8.img 
    8a83b4fe753409c01e298cd0beb3a6e3  kernel8.img
    $ sudo mount /dev/mmcblk0p1 /mnt/
    $ cat /mnt/config.txt 
    core_freq_min=500
    #enable_uart=1
    kernel_old=1
    $ sudo cp kernel8.img /mnt/
    $ sudo umount /mnt
    $ sudo minicom -D /dev/ttyUSB0 -b 115200
     _____ _ _ _           _ _                                                      
    |   __|_| | |_ ___ ___| | |_ ___ ___                                            
    |  |  | | | . |  _| .'| |  _| .'|  _|                                           
    |_____|_|_|___|_| |__,|_|_| |__,|_|                                             
    EL:1                                                                            
    Interrupts: up                                                                  
    MMU: ON                                                                         
    RPi4: Memory map: 752 MB addressable:                                           
    RPi4:   reserved @ (0x0 - 0xffffffffffffffff)                                   
    RPi4:       text @ (0x0 - 0x40e5f)                                              
    RPi4:     rodata @ (0x40e60 - 0x4738f)                                          
    RPi4:       data @ (0x47390 - 0x1012f4f)                                        
    RPi4:       heap >= 0x1013000 < stack < 0x2f000000                              
    Hello World from OCaml!                                                         
    IRQ                                                                             
    
    
    opened by palainp 2
  • multiple CPUs?

    multiple CPUs?

    So, any idea what the other cores should be doing while one is executing one MirageOS unikernel?

    One idea would be to have one unikernel per CPU - thus a dedicated network unikernel etc. -- but then there needs to be some communication channel between the unikernels (shared memory? who'd set this up?). I'm thinking mostly in terms of muen policy and channels (i.e. decided at compile time, not at runtime, where code is executed and which communication is setup).

    What do you think?

    opened by hannesm 1
  • Fill the gap between MirageOS and Gilbraltar

    Fill the gap between MirageOS and Gilbraltar

    a mirage-gilbraltar, as a mirage-solo5 should exists and we should extend targets inside the mirage/mirage project. However, I think we must implement yield before to be able to launch lwt.

    opened by dinosaure 1
Owner
Calascibetta Romain
Calascibetta Romain
Compiler Design Project: Simulation of front-end phase of C Compiler involving switch-case construct.

CSPC41 Compiler Design Project Assignment Compiler Design Project: Simulation of front-end phase of C Compiler involving switch-case construct. Using

Adeep Hande 1 Dec 15, 2021
A Small C Compiler

8cc C Compiler Note: 8cc is no longer an active project. The successor is chibicc. 8cc is a compiler for the C programming language. It's intended to

Rui Ueyama 5.8k Jan 8, 2023
A C compiler for LLVM. Supports C++11/14/1z C11

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies

LLVM 17.5k Jan 8, 2023
GNU Prolog is a native Prolog compiler

GNU Prolog is a native Prolog compiler with constraint solving over finite domains (FD)

Daniel Diaz 64 Dec 13, 2022
Take your first step in writing a compiler.

first-step Take your first step in writing a compiler. Building from Source Before building first-step, please make sure you have installed the follow

PKU Compiler Course 28 Aug 20, 2022
NCC is an ANSI/ISO-compliant optimizing C compiler.

The compiler is retargetable by design, but, at present, it only produces binaries for Linux/x86_64. As the compiler ABI differs somewhat from the System V ABI used by Linux, its code cannot be linked against Linux system libraries. It does, however, provide its own (incomplete) standard ANSI/Posix C library.

Charles E. Youse 0 Apr 1, 2022
nanoc is a tiny subset of C and a tiny compiler that targets 32-bit x86 machines.

nanoc is a tiny subset of C and a tiny compiler that targets 32-bit x86 machines. Tiny? The only types are: int (32-bit signed integer) char (8-

Ajay Tatachar 19 Nov 28, 2022
Smaller C is a simple and small single-pass C compiler

Smaller C is a simple and small single-pass C compiler, currently supporting most of the C language common between C89/ANSI C and C99 (minus some C89 and plus some C99 features).

Alexey Frunze 1.2k Jan 7, 2023
Microvm is a virtual machine and compiler

The aim of this project is to create a stack based language and virtual machine for microcontrollers. A mix of approaches is used. Separate memory is used for program and variable space (Harvard architecture). An interpreter, virtual machine and compiler are available. A demostration of the interpreter in action is presented below.

null 10 Aug 14, 2022
yadcc - Yet Another Distributed C++ Compiler

Yet Another Distributed C++ Compiler. yadcc是一套腾讯广告自研的分布式编译系统,用于支撑腾讯广告的日常开发及流水线。相对于已有的同类解决方案,我们针对实际的工业生产环境做了性能、可靠性、易用性等方面优化。

Tencent 276 Dec 29, 2022
Aheui JIT compiler for PC and web

아희짓 개요 아희짓은 아희 언어를 위한 JIT (Just in Time) 컴파일러입니다. 어셈블러와 유틸 라이브러리외에 외부 라이브러리에 전혀 의존하지 않고 JIT을 바닥부터 구현합니다. 지원 환경 64비트 windows, mac, linux (x86 아키텍쳐) 웹어셈

Sunho Kim 28 Sep 23, 2022
C implementation of the Tiny BASIC compiler found in an article by Dr. Austin Henley

Teeny Tiny Basic A C implementation of the Tiny BASIC compiler found in this article and this github repo by Dr. Austin Henley. I did pretty well in A

Gavin Morris 7 Oct 4, 2022
bcc is an interactive compiler of a language called b.

bcc is an interactive compiler of a language called b.

kparc 18 Nov 7, 2022
This is a compiler written from scratch in C

C Compiler This is a compiler written from scratch in C, with fully supporting C18 as a goal. It can currently compile itself, and most simple program

null 29 Jan 6, 2023
mrcceppc is a reimplementation project for the Metrowerks mwcceppc compiler.

Compiler | mrcceppc mrcceppc is a reimplementation project for the Metrowerks mwcceppc compiler. Compiling Run generate_{version}.bat for which versio

null 9 Nov 21, 2022
A C header that allow users to compile brainfuck programs within a C compiler.

brainfuck.h A C header that allow users to compile brainfuck programs within a C compiler. You can insert the header into the top of your brainfuck so

null 1 Dec 30, 2022
NaiveCC: a compiler frontend for a subset of C

NaiveCC: a compiler frontend for a subset of C This is a toy compiler frontend for a subset of the C programming language based on the LR(1) parsing t

Yuxiang Wei 1 Nov 15, 2021
A LLVM and Clang compiler toolchain built for kernel development

Cosmic-Clang Toolchain This is a LLVM and Clang compiler toolchain built for kernel development. Builds are always made from the latest LLVM sources r

Ǥђ๏ຮ₮⌁Ⲙครtє࿐ 0 Apr 12, 2022
A compiler written in C++ to convert .hoi code to hoi4 code

What is HC4? HC4 is a compiler that converts .hoic filenames to Hearts of Iron IV's .txt. Usage Use hc4 in the terminal (./hc4 if on Unix) and it will

SaCode 1 Jul 31, 2022