M nixos-modules/nixos-host.nix => nixos-modules/nixos-host.nix +43 -14
@@ 6,22 6,29 @@
{
options.genodeGuests = with lib;
+ with lib.types;
let
genodeOpts = { ... }: {
options = {
name = mkOption {
example = "webserver";
- type = types.str;
+ type = str;
description = "Name of the Genode subsystem.";
};
config = mkOption {
- type = types.str;
- default = "<config/>";
+ type = oneOf [ str path ];
+ example = ''
+ let Genode = env:DHALL_GENODE
+
+ in Genode.Init::{=}
+ '';
description = ''
- Configuration of the Genode subsystem.
- Must be rendered in the Genode XML format.
+ Configuration of the Genode subsystem in Dhall.
+ The type of the expression must be <literal>Genode.Init.Type<literal>,
+ where the <literal>Genode<literal> is library available at
+ <literal>env:DHALL_GENODE<literal>.
'';
};
@@ 39,15 46,24 @@
'';
};
+ nics = mkOption {
+ type = with types; listOf str;
+ default = [ ];
+ example = [ "tap0" "tap1" ];
+ description = ''
+ TAP interfaces to pass from NixOS into the Genode guest.
+ '';
+ };
+
};
};
in mkOption {
- type = with lib.types; loaOf (submodule genodeOpts);
+ type = loaOf (submodule genodeOpts);
default = { };
example = {
foobar = {
- config = "<empty/>";
+ config = "…";
rom = pkgs: { };
};
};
@@ 64,25 80,38 @@
inherit (crossPkgs.genodePackages) base-linux;
toService = name: cfg: {
description = "Genode subsystem";
+ after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
preStart = let
+ config' =
+ self.lib.${crossSystem}.runDhallCommand "${name}.config" { } ''
+ set -e
+ exec ${self.apps.${crossSystem}.render-init.program} > $out << EOF
+ ${./root-config.dhall}
+ { guest = ${cfg.config}
+ , nics = [ "${builtins.concatStringsSep ''", "'' cfg.nics}" ]
+ }
+ EOF
+ '';
rom' = with crossPkgs.genodePackages;
{
- core = "${base-linux}/bin/core-linux";
- init = "${init}/bin/init";
- "ld.lib.so" = "${base-linux}/bin/ld.lib.so";
- timer = "${base-linux}/bin/linux_timer_drv";
- config = builtins.toFile "${name}.config.xml" cfg.config;
+ init = "${init}/init";
+ "ld.lib.so" = "${base-linux}/lib/ld.lib.so";
+ timer_drv = "${base-linux}/timer_drv";
+ config = config';
+ linux_nic_drv = "${
+ crossPkgs.genodeSources.depot "linux_nic_drv"
+ }/linux_nic_drv";
} // (cfg.rom crossPkgs);
in builtins.concatStringsSep "\n"
- (lib.mapAttrsToList (name: value: "ln -s ${value} ${name}") rom');
+ (lib.mapAttrsToList (name: value: "ln -sv ${value} ${name}") rom');
serviceConfig = {
DynamicUser = true;
RuntimeDirectory = "genode/" + name;
WorkingDirectory = "/run/genode/" + name;
- ExecStart = "${base-linux}/bin/core-linux";
+ ExecStart = "${base-linux}/core-linux";
};
};
in lib.mapAttrs toService config.genodeGuests;
A nixos-modules/root-config.dhall => nixos-modules/root-config.dhall +70 -0
@@ 0,0 1,70 @@
+let Genode = env:DHALL_GENODE
+
+let Prelude = Genode.Prelude
+
+let Init = Genode.Init
+
+let Child = Init.Child
+
+let nicChild
+ : Text → Init.Children.Entry
+ = λ(tapDevice : Text)
+ → { mapKey = tapDevice
+ , mapValue =
+ Child.flat
+ Child.Attributes::{
+ , binary = "linux_nic_drv"
+ , config = Init.Config::{ attributes = toMap { tap = tapDevice } }
+ , ld = False
+ , resources = Init.Resources::{
+ , caps = 256
+ , ram = Genode.units.MiB 4
+ }
+ , provides = [ "Nic" ]
+ }
+ }
+
+let nicChildren = Prelude.List.map Text Init.Children.Entry nicChild
+
+let init =
+ λ(params : { guest : Init.Type, nics : List Text })
+ → Init::{
+ , routes = [ Init.ServiceRoute.child "Timer" "timer_drv" ]
+ , children =
+ nicChildren params.nics
+ # toMap
+ { timer_drv =
+ Child.flat
+ Child.Attributes::{
+ , binary = "timer_drv"
+ , provides = [ "Timer" ]
+ }
+ , init =
+ Init.toChild
+ params.guest
+ Init.Attributes::{
+ , exitPropagate = True
+ , routes =
+ Prelude.List.map
+ Text
+ Init.ServiceRoute.Type
+ ( λ(tapDevice : Text)
+ → { service =
+ { name = "Nic"
+ , label = Init.LabelSelector.last tapDevice
+ }
+ , route =
+ Init.Route.Type.Child
+ { name = tapDevice
+ , label = None Text
+ , diag = None Bool
+ }
+ }
+ )
+ params.nics
+ }
+ }
+ , verbose = True
+ }
+
+in init
M tests/nixos-host.nix => tests/nixos-host.nix +62 -27
@@ 6,45 6,80 @@ import "${self.inputs.nixpkgs}/nixos/tests/make-test-python.nix"
# meta.maintainers = [ pkgs.lib.maintainers.ehmry ];
machine = {
+
imports = [
self.nixosModules.genodeGuests
"${self.inputs.nixpkgs}/nixos/modules/profiles/minimal.nix"
];
- genodeGuests.signal-test = {
+
+ networking.bridges.br0.interfaces = [ "eth0" "tap0" ];
+
+ networking.interfaces.eth0.useDHCP = false;
+
+ networking.interfaces.tap0 = {
+ useDHCP = false;
+ virtual = true;
+ virtualType = "tap";
+ };
+
+ genodeGuests.tap-test = {
config = ''
- <config>
- <parent-provides>
- <service name="ROM"/>
- <service name="CPU"/>
- <service name="RM"/>
- <service name="PD"/>
- <service name="LOG"/>
- </parent-provides>
- <default-route>
- <any-service> <parent/> <any-child/> </any-service>
- </default-route>
- <default caps="100"/>
- <start name="timer" caps="96">
- <resource name="RAM" quantum="1M"/>
- <provides><service name="Timer"/></provides>
- </start>
- <start name="test-signal" caps="500">
- <resource name="RAM" quantum="10M"/>
- </start>
- </config>
+ let Genode = env:DHALL_GENODE
+
+ let Prelude = Genode.Prelude
+
+ let XML = Prelude.XML
+
+ let Init = Genode.Init
+
+ in Init::{
+ , children = toMap
+ { lwip_fs =
+ Init.Child.flat
+ Init.Child.Attributes::{
+ , binary = "vfs"
+ , config = Init.Config::{
+ , content =
+ [ XML.element
+ { name = "vfs"
+ , attributes = XML.emptyAttributes
+ , content =
+ [ XML.leaf
+ { name = "lwip"
+ , attributes = toMap { dhcp = "yes" }
+ }
+ ]
+ }
+ ]
+ }
+ , provides = [ "File_system" ]
+ , resources = Init.Resources::{
+ , caps = 256
+ , ram = Genode.units.MiB 8
+ }
+ , routes =
+ [ Init.ServiceRoute.parentLabel "Nic" (None Text) (Some "tap0")
+ , Init.ServiceRoute.parent "Timer"
+ ]
+ }
+ }
+ , verbose = True
+ }
'';
+ nics = [ "tap0" ];
rom = pkgs: {
- "test-signal" =
- "${pkgs.genodeSources.depot "test-signal"}/bin/test-signal";
+ "vfs" = "${pkgs.genodeSources.depot "vfs"}/vfs";
+ "libvfs.so" = "${(pkgs.genodeSources.depot "vfs").lib}/lib/libvfs.so";
+ "libvfs_lwip.so" =
+ "${pkgs.genodeSources.depot "vfs_lwip"}/lib/libvfs_lwip.so";
};
};
+
};
testScript = ''
start_all()
- machine.wait_for_unit("genode")
+ machine.wait_for_unit("tap-test")
machine.wait_for_open_port("1965")
'';
-}) {
- system = localSystem;
-}
+}) { system = localSystem; }