[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [MirageOS-devel] Rust unikernels



On 27 July 2015 at 09:36, Geoffroy Couprie <contact@xxxxxxxxxxxxxxxxxxx> wrote:
> Hi,
>
> On Sat, Jul 25, 2015 at 12:55 PM, Thomas Leonard <talex5@xxxxxxxxx> wrote:
>> On 24 July 2015 at 23:28, Geoffroy Couprie <contact@xxxxxxxxxxxxxxxxxxx> 
>> wrote:
>>> Hi Thomas,
>>>
>>> On Fri, Jul 24, 2015 at 3:02 PM, Thomas Leonard <talex5@xxxxxxxxx> wrote:
>>>> On 24 July 2015 at 13:00, Geoffroy Couprie <contact@xxxxxxxxxxxxxxxxxxx> 
>>>> wrote:
>>>>> Hello!
>>>>>
>>>>> A chat on Twitter showed some interest in unikernels developed in
>>>>> Rust, and I was pointed here for further discussion.
>>>>>
>>>>> First, I want to acknowledge the amazing work done on MirageOS by
>>>>> everybody here. I have followed it from afar for some time, and there
>>>>> has been great progress to make it available and usable.
>>>>>
>>>>> Second, I know making a unikernel system means years of work and a
>>>>> team of developers and testers. I am not planning to attempt it alone.
>>>>> What I want is to sort out the skills needed, the big pitfalls, the
>>>>> important milestones, and know about the unknown unknowns. Then push
>>>>> for that project in the Rust community.
>>>>>
>>>>> From the beginning, people experimented with OS development in Rust
>>>>> (cf https://github.com/ryanra/RustOS
>>>>> https://github.com/thepowersgang/rust-barebones-kernel or
>>>>> https://github.com/charliesome/rustboot ). There is also a very active
>>>>> IRC channel, #rust-osdev on irc.mozilla.org
>>>>>
>>>>> From what I understand, the bare minimum to experiment would be an OS
>>>>> booting and communicating with a network card, scheduling and task
>>>>> switching, remote debugging, a network stack. Also, tools to help in
>>>>> building, deploying and testing applications.
>>>>> The ryanra/RustOS project seems well advanced, but it could use a network 
>>>>> stack.
>>>>
>>>> Hi Geoffroy,
>>>>
>>>> Have you thought about running Mirage on top of a minimal Rust OS
>>>> kernel to start with? Then you could implement new drivers in Rust
>>>> alongside existing Mirage code. As a garbage-collected language, OCaml
>>>> can't be used to implement the very lowest levels of Mirage (e.g.
>>>> malloc) and we currently use (my branch of) Mini-OS [1] for running as
>>>> a unikernel on Xen. A common question is whether we could replace this
>>>> C code with Rust. I'd be interested to help out if so - I've been
>>>> meaning to take another look at Rust now it's stable.
>>>
>>> This is interesting, someone else proposed me that today too. This
>>> would be a good strategy to get something up and running quickly
>>> enough. Basically, Rust can build to a static library which can be
>>> linked to C code, but until there's a memory allocator available,
>>> things can be tricky.
>>> This is how RustOS does it: a small part written in C, which links to
>>> a Rust library that will handle the rest.
>>
>> What does the C code do? Is this for connecting to code in other
>> languages, or something that Rust can't do by itself?
>
> I just checked again, there is no C code, only a few parts in assembly
> to boot and set up the interrupts. Everything else is written in Rust.

Ah, that's good then!

>>> The core parts of MiniOS could probably not be reimplemented right
>>> away, but drivers would be doable. From what I see, the first step is
>>> to communicate with the Xenbus and the Xenstore, right? Then have some
>>> ring buffers and a way for xen to signal that some data is available
>>> (I'm currently looking at netfront.c).
>>
>> The only driver needed for Mirage is the console driver, for early
>> boot messages. Mirage has its own OCaml implementations of Xenbus and
>> Xenstore, so replacing them isn't needed to get rid of the C. Much of
>> Mini-OS is optional and unused (and it would be better to package the
>> optional bits separately really).
>>
>> [...]
>
> So Mirage only needs the console and a way to talk with the Xenbus.

Actually, Mirage doesn't even use Mini-OS's Xenbus, but has its own:

  https://github.com/mirage/shared-memory-ring

> Is the scheduling handled by MiniOS or by Mirage?

Mirage:

https://github.com/mirage/mirage-platform/blob/master/xen/lib/main.ml

Mini-OS does provide preemptive threading, but we don't use it currently.

>>>>> - the system can be monotask at first, but preemtive threading should
>>>>> happen at some point
>>>>
>>>> If you have promises (and make all your low-level APIs non-blocking)
>>>> then you can get a very long way without preemptive threading,
>>>> although it would be good to have it eventually.
>>>
>>> Could you tell me more about this? This approach looks interesting.
>>
>> Every function in Mirage that might need to wait instead immediately
>> returns a promise. e.g. the read function is defined as:
>>
>> val read: flow -> [`Ok of buffer | `Eof | `Error of error ] io
>>
>> (https://github.com/mirage/mirage/blob/d2d4502be0e53de16c915ac72dee008dcaf62991/types/V1.mli#L127)
>>
>> The type "X io" means "promise of an X" or "light-weight thread that
>> will produce an X". Normally Mirage is used with the Lwt library, in
>> which case "io" is defined to be "Lwt.t":
>>
>> https://github.com/mirage/mirage/blob/d2d4502be0e53de16c915ac72dee008dcaf62991/types/V1_LWT.mli#L25
>>
>> Functions processing promises can be chained together in a similar way
>> to non-promise functions, using the >>= operator. It's very useful,
>> and most languages have something similar, though the names vary. A
>> quick Google turned up this (incomplete-looking) Rust library:
>> https://github.com/lucidd/rust-promise
>>
>> See https://mirage.io/wiki/tutorial-lwt for more details.
>>
>
> From what I understand, Lwt is a green threads library. I would have
> thought Mirage needed to emulate OS threads, but it looks like this
> would be enough for most use cases.

Yep. Hardware is easiest to drive with callbacks, but traditional OS
kernels go to a lot of trouble to present a blocking, synchronous API
to userspace. Green threading libraries then have to mess around with
OS threads to recover the asynchronous callback-based API. With
Mini-OS, all that goes away.

> Are multiple cores supported?

No. Currently the recommendation is to spin up multiple VMs if you
need multiple cores. Rust should be good at supporting this though.

>>>>> - a part of Rust standard library is already available, I do not know
>>>>> how much is needed to support the use case of a HTTP server
>>>>> - building monitoring tools inside the kernel
>>>>
>>>> When running under Xen, we share a trace buffer with dom0. This allows
>>>> you to see what the system is doing, even if it is hung or crashed.
>>>> See: https://mirage.io/wiki/profiling
>>>
>>> That visualization tool looks useful! Do you have remote debuggers
>>> too? With a serial port or something similar.
>>
>> Mirage can also be compiled to a Unix process and debugged with gdb
>> and similar in most cases. I believe Xen also provides for debugging
>> of guests from dom0, but I've never used that.
>>
>>> I guess the first thing I could do is to integrate some Rust code in
>>> MiniOS. Is there a part of the code you would recommend? Something
>>> well contained, without too many dependencies?
>>
>> I'd probably start with the page allocator:
>>
>> https://github.com/talex5/mini-os/blob/master/mm.c
>>
>> /*
>>  * Initialise allocator, placing addresses [@min,@max] in free pool.
>>  * @min and @max are PHYSICAL addresses.
>>  */
>> static void init_page_allocator(unsigned long min, unsigned long max)
>>
>> This gets called early during boot with all the free RAM as the
>> argument. It provides alloc_pages and free_pages to allocate from this
>> range.
>>
> I'll take a look
>
>>
>> Another possible starting place is the console driver:
>>
>> https://github.com/talex5/mini-os/blob/master/console/console.c
>>
>> That's a bit harder though because you're writing to memory shared
>> with dom0, so you need to be careful about memory barriers and atomic
>> operations. I assume Rust can handle this nicely? It would be fun to
>> see how to use Rust's ownership types to ensure that other bits of
>> code can't write to parts of a shared buffer that dom0 may be reading,
>> etc.
>>
>
> There are atomic types available, and a way to represent memory
> fences: https://doc.rust-lang.org/std/sync/atomic/

Great :-)


-- 
Dr Thomas Leonard        http://roscidus.com/blog/
GPG: DA98 25AE CAD0 8975 7CDA  BD8E 0713 3F96 CA74 D8BA

_______________________________________________
MirageOS-devel mailing list
MirageOS-devel@xxxxxxxxxxxxxxxxxxxx
http://lists.xenproject.org/cgi-bin/mailman/listinfo/mirageos-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.