Skip to content

Use dune to build the unikernel#1153

Closed
samoht wants to merge 12 commits intomirage:masterfrom
samoht:dune
Closed

Use dune to build the unikernel#1153
samoht wants to merge 12 commits intomirage:masterfrom
samoht:dune

Conversation

@samoht
Copy link
Copy Markdown
Member

@samoht samoht commented May 5, 2020

MirageOS 4

What is MirageOS?

MirageOS is a library operating system that can build standalone unikernels on various platforms. More precisely, the architecture can be divided into:

  1. operating system libraries that implement kernel and protocol functionality, ranging from low-level network card drivers to a full reimplementation of the TLS protocol, through to a reimplementation of the Git protocol to store versioned data.

  2. A set of typed signatures to make sure these libraries are consistent and can interoperate. As all the library are almost all pure OCaml code, we have defined a set of OCaml module types that encode these conventions in a statically enforcable way. We make no compatibility guarantees at the C level, but compile those on a best-effort basis.

  3. Finally, MirageOS is also a metaprogramming compiler that generates OCaml code. It takes as input: the OCaml source code of a program and all of its dependencies, the full description of
    the deployment target, including configuration values (like the HTTP port to listen too, or the private key or the service being deployed). The mirageCLI tool uses all of these to generate a executable unikernel: a specialised binary artefact containing only the code what is needed to run on the given deployment platform and no more.

It is possible to write high-level MirageOS applications, such as HTTPS, email or CalDAV servers which can be deployed on very heterogenous and embedded platforms by changing only a few compilation parameters. The supported platforms range from ESP32 micro-controllers, minimal virtual machines running on a cloud providers, or processes running inside a Docker container configured with a tight security profile. In general, these platform do not have a full POSIX environment; MirageOS does not try to emulate POSIX and focuses on providing a small, well-defined, typed interface with the system components. The nearest equivalent to the MirageOS approach is the WASI (wasi.dev) set of interfaces for WebAssembly.

  1. and 2. are relatively well-defined in MirageOS 3. MirageOS 4 is focusing on 3.

Is everything really written in OCaml

While most of the code is written in OCaml, a typed, high-level language with many good safety properties, there are pieces of MirageOS which are still written in unsafe C. These bits can be
separated in three categories:

  1. The OCaml runtime is written in C. It needs to be ported to the platform that MirageOS is trying to target, which do not support POSIX. Hence, the first component to port to a new platform is the OCaml runtime.

  2. The low-level device drivers (network, console, clock, etc) also need some C bits.

  3. The base usual C bindings; some libraries are widely used and (unfortunately) very hard (but not impossible) to replace them completely without taking a big performance hit or having to trust code without much real-world usages. This is the case for low-level bit handling for crypto code (even if we try to make sure allocation is alway handled by the OCaml runtime) as well as arbitrary precision numeric computation (e.g. gmp). Ideally we could image rewriting all of these libraries in OCaml if we had an infinite amount of time in our hands.

MirageOS as a cross-compilator

The MirageOS compiler is basically a cross-compiler, where the host and target toolchain are identical, but with different flags for the C bindings: for instance, it is necessary to pass -freestanding to all C bindings to not use POSIX headers. The MirageOS compiler also uses a custom linker: eg. not only it needs a custom OCaml's runtime libasmrun.a, but it also needs to run a different linker to generate specialised executable images.

Historically, the OCaml ecosystem always had partial support for cross-compilation: for instance, the ocaml-cross way of doing it is to duplicate all existing opam pacakges by adding a -windows suffix to their names and dependencies; this allows normal packages and windows packages can be co-installed in the same opam switch.

MirageOS 3 resolved that by duplicating only the packages defining C bindings and (ab)using ocamlfind predicates to resolve link time depencencies for C archives and on relying on the now deprecated --output-obj option of the OCaml compiler.

The proposal for MirageOS 4 is to solve this issue via the built-in support for cross-compilation of dune. This is done by gathering all the sourceslocally, creating a dune-workspace file describing the C flags to use in each cross-compilation "context" and then call dune once.

An example: solo5

The current prototype is using duniverse to gather all sources and can be tested as follows:

$ opam pin add https://github.com/samoht/mirage.git#dune
$ opam pin add https://github.com/ocamllabs/duniverse.git
$ cd <your app>
$ mirage configure -t hvt
$ duniverse init --opam-repo https://github.com/samoht/opam-repository.git#duniverse
$ duniverse pull
$ dune build <app>.hvt
$ dune exec -- solo5-hvt <app.hvt>

Current limitations:

Possible improvements:

  • do we want mirage exec to replace the last line?
  • use dune to generate opam files

note: this PR builds on the amazing work done by @TheLortex @dinosaure who worked on various iterations of this patch over the last 2 years.

@Drup
Copy link
Copy Markdown
Member

Drup commented May 5, 2020

Nice! :O

What's the list of path for in the configure target ? Could we make the definition easier in case where they are no path (which seems common given the diff).

@samoht
Copy link
Copy Markdown
Member Author

samoht commented May 5, 2020

What's the list of path for in the configure target

That's the list of files generated when running config.exe configure (as dune needs a static list of targets). Initially I was trying to guess this list by interpreting the Action.t values, but it's sometimes not very accurate (as it sometimes actually need to run external commands to make progress). I'm still unsure what's the best way forward, I can try to revert https://github.com/mirage/mirage/pull/1151/files#diff-e528ad118df4fd305084a7164eba1d0d but being explicit is taking the safe part.

@Drup
Copy link
Copy Markdown
Member

Drup commented May 5, 2020

Maybe we could only annotate the external commands and infer as much as we can ?

@samoht
Copy link
Copy Markdown
Member Author

samoht commented May 5, 2020

We will also need to check that the list of generated files is static (e.g. doesn't depend on the result/stdout of external commands) which might be a pain. I'll have a look.

@samoht
Copy link
Copy Markdown
Member Author

samoht commented May 5, 2020

I've reverted back to inferring files in configure actions -- most of the time it will just use work so let's make this the default. If for any reason this doesn't work, users can provide their own list of files with ~files.

@Drup
Copy link
Copy Markdown
Member

Drup commented May 5, 2020

Sounds good!

@samoht samoht marked this pull request as ready for review May 5, 2020 17:37
@samoht
Copy link
Copy Markdown
Member Author

samoht commented May 5, 2020

I've added a bit of documentation in the mlis (and in the initial body of that PR).

I think this is now ready to review! Right now I managed to build mirage-skeleton's https.hvt but that's pretty much it; I have more technical notes on how the solo5 target is working that I am trying to polish, but happy to answer any question if needed.

@hannesm
Copy link
Copy Markdown
Member

hannesm commented May 11, 2020

I tried your instructions on a mirage-skeleton hello example. My initial observations:

  • I've no idea and no control where packages are retrieved from (it seems to use your opam-repository overlay, but I've no clue how to extend this) -- this is important for me since I use quite some custom opam repositories on top of the default opam repository
  • NB please change the version number if you use modified source
  • I initially typed mirage configure for the unix target, the duniverse succeeded, but I couldn't find a way to build "hello.exe" / "hello.native"
  • mirage clean does not clean up everything
  • a mirage configure -t hvt in the above, mirage cleaned directory works mostly (duniverse does something)
  • it fails with:
$ dune build hello.hvt
File "duniverse/metrics.0.1.0/dune-project", line 3, characters 11-14:
3 | (using fmt 1.0)
               ^^^
Warning: Version 1.0 of integration with automatic formatters is not
supported until version 1.4 of the dune language.
There are no supported versions of this extension in version 1.1 of the dune
language.

Error: Too many opam files for package "mirage-clock-unix":
- duniverse/mirage-clock-unix.3.0.1/mirage-clock-unix.opam
- duniverse/mirage-clock-freestanding.3.0.1/mirage-clock-unix.opam

and I've no idea how to continue from here -- maybe the way out is git clean -dfx and start over again?

@hannesm
Copy link
Copy Markdown
Member

hannesm commented May 11, 2020

ok, after a manual wipe of the repository - and running mirage configure ; duniverse again, I got to a point where "dune build hello.hvt" does some work, and then fails with "spt/spt_core.c:37:10: fatal error: 'seccomp.h' file not found" (and still no hello.hvt :/)

As unirkernels do not depend on mirage-types inconditionnaly anymore,
every device needs to be more precise about the signatures they
require.
@samoht
Copy link
Copy Markdown
Member Author

samoht commented Feb 4, 2021

@TheLortex do you have an open PR which subsumes this one?

@dinosaure
Copy link
Copy Markdown
Member

As far as I can know, the status of MirageOS is available here: TheLortex#1

@TheLortex
Copy link
Copy Markdown
Member

Hey, I'll make a proper PR tomorrow, the most up to date branch is https://github.com/TheLortex/mirage/tree/mirage-4-upstream based on @dinosaure 's PR on my repo.

@samoht
Copy link
Copy Markdown
Member Author

samoht commented Feb 4, 2021

No hurry -- I'll wait for your PR before closing this one then :-)

@TheLortex
Copy link
Copy Markdown
Member

Closing in favor of #1226

@TheLortex TheLortex closed this May 6, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants