parent
6889fb09c2
commit
ebf3606705
@ -0,0 +1,27 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
localPackages = pkgs.buildPackages;
|
||||
utils = import ../lib {
|
||||
inherit (config.nixpkgs) system localSystem crossSystem;
|
||||
inherit pkgs;
|
||||
};
|
||||
in {
|
||||
genode.core = {
|
||||
prefix = "hw-pc-";
|
||||
supportedSystems = [ "x86_64-genode" ];
|
||||
basePackages = with pkgs.genodePackages; [ base-hw-pc rtc_drv ];
|
||||
};
|
||||
|
||||
genode.boot = {
|
||||
|
||||
initrd = "${config.genode.boot.image}/image.elf";
|
||||
|
||||
image = utils.hwImage "0xffffffc000000000" "0x00200000"
|
||||
pkgs.genodePackages.base-hw-pc config.system.name { }
|
||||
config.genode.boot.configFile;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
localPackages = pkgs.buildPackages;
|
||||
utils = import ../lib {
|
||||
inherit (config.nixpkgs) system localSystem crossSystem;
|
||||
inherit pkgs;
|
||||
};
|
||||
in {
|
||||
genode.core = {
|
||||
prefix = "hw-virt_qemu";
|
||||
supportedSystems = [ "aarch64-genode" ];
|
||||
basePackages = with pkgs.genodePackages; [ base-hw-virt_qemu rtc-dummy ];
|
||||
};
|
||||
|
||||
genode.boot = {
|
||||
|
||||
initrd = "${config.genode.boot.image}/image.elf";
|
||||
|
||||
image = utils.hwImage "0xffffffc000000000" "0x40000000"
|
||||
pkgs.genodePackages.base-hw-virt_qemu config.system.name { }
|
||||
config.genode.boot.configFile;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,157 @@
|
||||
{ config, pkgs, lib, modulesPath, ... }:
|
||||
|
||||
with lib;
|
||||
let localPackages = pkgs.buildPackages;
|
||||
in {
|
||||
options.genode = {
|
||||
core = {
|
||||
|
||||
prefix = mkOption {
|
||||
type = types.str;
|
||||
example = "hw-pc-";
|
||||
};
|
||||
|
||||
supportedSystems = mkOption {
|
||||
type = types.listOf types.str;
|
||||
example = [ "i686-genode" "x86_64-genode" ];
|
||||
};
|
||||
|
||||
basePackages = mkOption { type = types.listOf types.package; };
|
||||
|
||||
};
|
||||
|
||||
boot = {
|
||||
|
||||
kernel = mkOption {
|
||||
type = types.path;
|
||||
default = "${pkgs.genodePackages.bender}/bender";
|
||||
};
|
||||
|
||||
initrd = mkOption {
|
||||
type = types.str;
|
||||
default = "${pkgs.genodePackages.bender}/bender";
|
||||
description = "Path to an image or a command-line arguments";
|
||||
};
|
||||
|
||||
configFile = mkOption {
|
||||
type = types.path;
|
||||
description = ''
|
||||
Dhall boot configuration. See
|
||||
https://git.sr.ht/~ehmry/dhall-genode/tree/master/Boot/package.dhall
|
||||
'';
|
||||
};
|
||||
|
||||
image = mkOption {
|
||||
type = types.path;
|
||||
description =
|
||||
"Boot image containing the base component binaries and configuration.";
|
||||
};
|
||||
|
||||
romModules = mkOption {
|
||||
type = types.attrsOf types.path;
|
||||
description = "Attr set of initial ROM modules";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
config = let
|
||||
initInputs = unique config.genode.init.inputs;
|
||||
|
||||
addManifest = drv:
|
||||
drv // {
|
||||
manifest =
|
||||
localPackages.runCommand "${drv.name}.dhall" { inherit drv; } ''
|
||||
set -eu
|
||||
echo -n '[' >> $out
|
||||
find $drv/ -type f -printf ',{mapKey= "%f",mapValue="%p"}' >> $out
|
||||
${if builtins.elem "lib" drv.outputs then
|
||||
''
|
||||
find ${drv.lib}/ -type f -printf ',{mapKey= "%f",mapValue="%p"}' >> $out''
|
||||
else
|
||||
""}
|
||||
echo -n ']' >> $out
|
||||
'';
|
||||
};
|
||||
|
||||
mergeManifests = inputs:
|
||||
localPackages.writeTextFile {
|
||||
name = "manifest.dhall";
|
||||
text = with builtins;
|
||||
let
|
||||
f = head: input:
|
||||
if hasAttr "manifest" input then
|
||||
''
|
||||
${head}, { mapKey = "${
|
||||
lib.getName input
|
||||
}", mapValue = ${input.manifest} }''
|
||||
else
|
||||
abort "${input.pname} does not have a manifest";
|
||||
in (foldl' f "[" inputs) + "]";
|
||||
};
|
||||
|
||||
in {
|
||||
|
||||
assertions = [{
|
||||
assertion = builtins.any (s: s == config.nixpkgs.system)
|
||||
config.genode.core.supportedSystems;
|
||||
message = "invalid Genode core for this system";
|
||||
}];
|
||||
|
||||
genode.boot.configFile = let
|
||||
tarball =
|
||||
"${config.system.build.tarball}/tarball/${config.system.build.tarball.fileName}.tar";
|
||||
manifest = mergeManifests (map addManifest
|
||||
(config.genode.core.basePackages ++ [ config.system.build.tarball ]
|
||||
++ (with pkgs.genodePackages; [ init cached_fs_rom vfs ])));
|
||||
in localPackages.runCommand "boot.dhall" { } ''
|
||||
cat > $out << EOF
|
||||
${./store-wrapper.dhall}
|
||||
(${config.genode.init.configFile})
|
||||
"${config.system.build.tarball.fileName}.tar"
|
||||
$(stat --format '%s' ${tarball})
|
||||
${config.system.build.storeManifest} ${manifest}
|
||||
EOF
|
||||
'';
|
||||
|
||||
system.build.storeManifest = mergeManifests (map addManifest initInputs);
|
||||
|
||||
# Create the tarball of the store to live in core ROM
|
||||
system.build.tarball =
|
||||
pkgs.callPackage "${modulesPath}/../lib/make-system-tarball.nix" {
|
||||
contents = [ ];
|
||||
storeContents = [
|
||||
{
|
||||
# assume that the init config will depend
|
||||
# on every store path needed to boot
|
||||
object = config.genode.init.configFile;
|
||||
symlink = "/config.dhall";
|
||||
}
|
||||
{
|
||||
object = pkgs.buildPackages.symlinkJoin {
|
||||
name = config.system.name + ".rom";
|
||||
paths = config.genode.init.inputs;
|
||||
};
|
||||
symlink = "/rom";
|
||||
}
|
||||
];
|
||||
compressCommand = "cat";
|
||||
compressionExtension = "";
|
||||
};
|
||||
|
||||
system.build.initXml = pkgs.buildPackages.runCommand "init.xml" {
|
||||
nativeBuildInputs = with pkgs.buildPackages; [ dhall xorg.lndir ];
|
||||
DHALL_GENODE = "${pkgs.genodePackages.dhallGenode}/binary.dhall";
|
||||
BOOT_CONFIG = config.genode.boot.configFile;
|
||||
} ''
|
||||
export XDG_CACHE_HOME=$NIX_BUILD_TOP
|
||||
lndir -silent \
|
||||
${pkgs.genodePackages.dhallGenode}/.cache \
|
||||
$XDG_CACHE_HOME
|
||||
dhall text <<< "(env:DHALL_GENODE).Init.render (env:BOOT_CONFIG).config" > $out
|
||||
'';
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
inputs = mkOption {
|
||||
description = "List of packages to build a ROM store with.";
|
||||
type = types.listOf types.package;
|
||||
};
|
||||
in {
|
||||
|
||||
options.genode.init = {
|
||||
inherit inputs;
|
||||
|
||||
configFile = mkOption {
|
||||
description = ''
|
||||
Dhall configuration of this init instance after children have been merged.
|
||||
'';
|
||||
type = types.path;
|
||||
};
|
||||
|
||||
baseConfig = mkOption {
|
||||
description =
|
||||
"Dhall configuration of this init instance before merging children.";
|
||||
type = types.str;
|
||||
default = ''
|
||||
let Genode = env:DHALL_GENODE
|
||||
|
||||
in Genode.Init::{
|
||||
, routes =
|
||||
[ Genode.Init.ServiceRoute.parent "File_system"
|
||||
, Genode.Init.ServiceRoute.parent "Rtc"
|
||||
, Genode.Init.ServiceRoute.parent "Timer"
|
||||
, Genode.Init.ServiceRoute.parent "IRQ"
|
||||
, Genode.Init.ServiceRoute.parent "IO_MEM"
|
||||
, Genode.Init.ServiceRoute.parent "IO_PORT"
|
||||
]
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
children = mkOption {
|
||||
default = { };
|
||||
type = with types;
|
||||
attrsOf (submodule {
|
||||
options = {
|
||||
inherit inputs;
|
||||
configFile = mkOption {
|
||||
type = types.path;
|
||||
description = ''
|
||||
Dhall configuration of child.
|
||||
See https://git.sr.ht/~ehmry/dhall-genode/tree/master/Init/Child/Type
|
||||
'';
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
subinits = mkOption {
|
||||
default = { };
|
||||
type = with types;
|
||||
attrsOf (submodule {
|
||||
options = {
|
||||
inherit inputs;
|
||||
configFile = mkOption {
|
||||
type = types.path;
|
||||
description = ''
|
||||
Dhall configuration of child init.
|
||||
See https://git.sr.ht/~ehmry/dhall-genode/tree/master/Init/Type
|
||||
'';
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
config = {
|
||||
|
||||
genode.init.inputs = with builtins;
|
||||
[ pkgs.genodePackages.report_rom ] ++ concatLists (catAttrs "inputs"
|
||||
((attrValues config.genode.init.children)
|
||||
++ (attrValues config.genode.init.subinits)));
|
||||
|
||||
# TODO: convert the subinits to children
|
||||
|
||||
genode.init.configFile = pkgs.writeText "init.dhall" ''
|
||||
let Genode = env:DHALL_GENODE
|
||||
let baseConfig = ${config.genode.init.baseConfig}
|
||||
|
||||
in baseConfig with children = baseConfig.children # toMap {${
|
||||
concatMapStrings (name:
|
||||
", `${name}` = (${
|
||||
config.genode.init.children.${name}.configFile
|
||||
} : Genode.Init.Child.Type)")
|
||||
(builtins.attrNames config.genode.init.children)
|
||||
} ${
|
||||
concatMapStrings (name: ''
|
||||
, `${name}` =
|
||||
Genode.Init.toChild
|
||||
(${
|
||||
config.genode.init.subinits.${name}.configFile
|
||||
} : Genode.Init.Type)
|
||||
Genode.Init.Attributes.default
|
||||
'') (builtins.attrNames config.genode.init.subinits)
|
||||
} }
|
||||
'';
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,195 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
options.networking.interfaces = lib.mkOption {
|
||||
type = with types;
|
||||
attrsOf (submodule ({ ... }: {
|
||||
options.genode = {
|
||||
|
||||
driver = mkOption {
|
||||
type = types.enum [ "ipxe" "virtio" ];
|
||||
default = "ipxe";
|
||||
};
|
||||
|
||||
stack = mkOption {
|
||||
type = types.enum [ "lwip" "lxip" ];
|
||||
default = "lwip";
|
||||
};
|
||||
|
||||
};
|
||||
}));
|
||||
};
|
||||
|
||||
config.genode.init.children = let
|
||||
inherit (builtins) toFile;
|
||||
|
||||
nics = mapAttrs' (name: interface:
|
||||
let name' = "nic." + name;
|
||||
in {
|
||||
name = name';
|
||||
value = {
|
||||
inputs = with pkgs.genodePackages;
|
||||
{
|
||||
ipxe = [ ipxe_nic_drv ];
|
||||
virtio = [ virtio_nic_drv ];
|
||||
}.${interface.genode.driver};
|
||||
configFile = toFile "${name'}.dhall" ''
|
||||
let Genode = env:DHALL_GENODE
|
||||
|
||||
let Init = Genode.Init
|
||||
|
||||
in Init.Child.flat
|
||||
Init.Child.Attributes::{
|
||||
, binary = "virtio_pci_nic"
|
||||
, provides = [ "Nic" ]
|
||||
, resources = Init.Resources::{
|
||||
, caps = 128
|
||||
, ram = Genode.units.MiB 4
|
||||
}
|
||||
, routes = [ Init.ServiceRoute.parent "IO_MEM" ]
|
||||
, config = Init.Config::{
|
||||
, policies =
|
||||
[ Init.Config.Policy::{
|
||||
, service = "Nic"
|
||||
, label =
|
||||
Init.LabelSelector.prefix "sockets.${name}"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
'';
|
||||
};
|
||||
}) config.networking.interfaces;
|
||||
|
||||
sockets = mapAttrs' (name: interface:
|
||||
let name' = "sockets." + name;
|
||||
in {
|
||||
name = name';
|
||||
value = {
|
||||
inputs = with pkgs.genodePackages;
|
||||
{
|
||||
lwip = [ vfs_lwip ];
|
||||
lxip = [ vfs_lixp ];
|
||||
}.${interface.genode.stack};
|
||||
configFile = let ipv4 = builtins.head interface.ipv4.addresses;
|
||||
in toFile "${name'}.dhall" ''
|
||||
let Genode = env:DHALL_GENODE
|
||||
|
||||
let Init = Genode.Init
|
||||
|
||||
in Init.Child.flat
|
||||
Init.Child.Attributes::{
|
||||
, binary = "vfs"
|
||||
, provides = [ "File_system" ]
|
||||
, resources = Init.Resources::{ caps = 128, ram = Genode.units.MiB 16 }
|
||||
, config = Init.Config::{
|
||||
, policies =
|
||||
[ Init.Config.Policy::{
|
||||
, service = "File_system"
|
||||
, label = Init.LabelSelector.suffix "sockets"
|
||||
, attributes = toMap { root = "/" }
|
||||
}
|
||||
]
|
||||
, content =
|
||||
let XML = Genode.Prelude.XML
|
||||
|
||||
in [ XML.element
|
||||
{ name = "vfs"
|
||||
, attributes = XML.emptyAttributes
|
||||
, content =
|
||||
[ XML.leaf
|
||||
{ name = "lwip"
|
||||
, attributes = toMap
|
||||
{ ip_addr = "${ipv4.address}", netmask = "${
|
||||
if ipv4.prefixLength == 24 then
|
||||
"255.255.255.0"
|
||||
else
|
||||
throw
|
||||
"missing prefix to netmask conversion"
|
||||
}" }
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
'';
|
||||
};
|
||||
}) config.networking.interfaces;
|
||||
|
||||
in nics // sockets // {
|
||||
|
||||
platform_drv = {
|
||||
inputs = [ pkgs.genodePackages.platform_drv ];
|
||||
configFile = let
|
||||
policies = concatMapStrings (name: ''
|
||||
Init.Config.Policy::{
|
||||
, service = "Platform"
|
||||
, label = Init.LabelSelector.prefix "nic.${name}"
|
||||
, content =
|
||||
[ Genode.Prelude.XML.leaf
|
||||
{ name = "pci", attributes = toMap { class = "ETHERNET" } }
|
||||
]
|
||||
}
|
||||
'') (builtins.attrNames config.networking.interfaces);
|
||||
in toFile "platform_drv.dhall" ''
|
||||
let Genode = env:DHALL_GENODE
|
||||
|
||||
let Init = Genode.Init
|
||||
|
||||
let label = \(_ : Text) -> { local = _, route = _ }
|
||||
|
||||
in Init.Child.flat
|
||||
Init.Child.Attributes::{
|
||||
, binary = "platform_drv"
|
||||
, resources = Init.Resources::{
|
||||
, caps = 800
|
||||
, ram = Genode.units.MiB 4
|
||||
, constrainPhys = True
|
||||
}
|
||||
, reportRoms = [ label "acpi" ]
|
||||
, provides = [ "Platform" ]
|
||||
, routes =
|
||||
[ Init.ServiceRoute.parent "IRQ"
|
||||
, Init.ServiceRoute.parent "IO_MEM"
|
||||
, Init.ServiceRoute.parent "IO_PORT"
|
||||
]
|
||||
, config = Init.Config::{
|
||||
, policies = [ ${policies} ]
|
||||
}
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
acpi_drv = {
|
||||
inputs = [ pkgs.genodePackages.acpi_drv ];
|
||||
configFile = toFile "acpi_drv.dhall" ''
|
||||
let Genode = env:DHALL_GENODE
|
||||
|
||||
let Init = Genode.Init
|
||||
|
||||
let label = \(_ : Text) -> { local = _, route = _ }
|
||||
|
||||
in Init.Child.flat
|
||||
Init.Child.Attributes::{
|
||||
, binary = "acpi_drv"
|
||||
, resources = Init.Resources::{
|
||||
, caps = 400
|
||||
, ram = Genode.units.MiB 4
|
||||
, constrainPhys = True
|
||||
}
|
||||
, romReports = [ label "acpi" ]
|
||||
, routes =
|
||||
[ Init.ServiceRoute.parent "IRQ"
|
||||
, Init.ServiceRoute.parent "IO_MEM"
|
||||
, Init.ServiceRoute.parent "IO_PORT"
|
||||
]
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
localPackages = pkgs.buildPackages;
|
||||
utils = import ../lib {
|
||||
inherit (config.nixpkgs) system localSystem crossSystem;
|
||||
inherit pkgs;
|
||||
};
|
||||
in {
|
||||
genode.core = {
|
||||
prefix = "nova-";
|
||||
supportedSystems = [ "x86_64-genode" ];
|
||||
basePackages = with pkgs.genodePackages; [ base-nova rtc_drv ];
|
||||
};
|
||||
|
||||
genode.boot = {
|
||||
|
||||
initrd =
|
||||
"'${pkgs.genodePackages.NOVA}/hypervisor-x86_64 arg=iommu novpid serial,${config.genode.boot.image}/image.elf'";
|
||||
|
||||
image =
|
||||
utils.novaImage config.system.name { } config.genode.boot.configFile;
|
||||
|
||||
};
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,166 @@
|
||||
let Genode =
|
||||
env:DHALL_GENODE sha256:e90438be23b5100003cf018b783986df67bc6d0e3d35e800677d0d9109ff6aa9
|
||||
|
||||
let Prelude = Genode.Prelude
|
||||
|
||||
let XML = Prelude.XML
|
||||
|
||||
let Init = Genode.Init
|
||||
|
||||
let Child = Init.Child
|
||||
|
||||
let TextMapType = Prelude.Map.Type Text
|
||||
|
||||
let Manifest/Type = TextMapType (TextMapType Text)
|
||||
|
||||
let Manifest/toRoutes =
|
||||
λ(manifest : Manifest/Type) →
|
||||
Prelude.List.map
|
||||
(Prelude.Map.Entry Text Text)
|
||||
Init.ServiceRoute.Type
|
||||
( λ(entry : Prelude.Map.Entry Text Text) →
|
||||
{ service =
|
||||
{ name = "ROM"
|
||||
, label = Init.LabelSelector.Type.Last entry.mapKey
|
||||
}
|
||||
, route =
|
||||
Init.Route.Type.Child
|
||||
{ name = "store_rom"
|
||||
, label = Some entry.mapValue
|
||||
, diag = Some True
|
||||
}
|
||||
}
|
||||
)
|
||||
( Prelude.List.concat
|
||||
(Prelude.Map.Entry Text Text)
|
||||
(Prelude.Map.values Text (Prelude.Map.Type Text Text) manifest)
|
||||
)
|
||||
|
||||
let parentROMs =
|
||||
Prelude.List.map
|
||||
Text
|
||||
Init.ServiceRoute.Type
|
||||
( λ(label : Text) →
|
||||
{ service = { name = "ROM", label = Init.LabelSelector.last label }
|
||||
, route =
|
||||
Init.Route.Type.Parent { label = Some label, diag = None Bool }
|
||||
}
|
||||
)
|
||||
|
||||
let wrapStore
|
||||
: Init.Type → Manifest/Type → Child.Type
|
||||
= λ(init : Init.Type) →
|
||||
λ(manifest : Manifest/Type) →
|
||||
Init.toChild
|
||||
init
|
||||
Init.Attributes::{
|
||||
, exitPropagate = True
|
||||
, resources = Init.Resources::{ ram = Genode.units.MiB 4 }
|
||||
, routes =
|
||||
[ Init.ServiceRoute.parent "IO_MEM"
|
||||
, Init.ServiceRoute.parent "IO_PORT"
|
||||
, Init.ServiceRoute.parent "IRQ"
|
||||
, Init.ServiceRoute.parent "VM"
|
||||
, Init.ServiceRoute.child "Timer" "timer"
|
||||
, Init.ServiceRoute.child "Rtc" "rtc"
|
||||
]
|
||||
# parentROMs
|
||||
[ "ld.lib.so"
|
||||
, "init"
|
||||
, "platform_info"
|
||||
, "core_log"
|
||||
, "kernel_log"
|
||||
, "vfs"
|
||||
, "vfs.lib.so"
|
||||
, "cached_fs_rom"
|
||||
]
|
||||
# Manifest/toRoutes manifest
|
||||
# [ Init.ServiceRoute.child "ROM" "store_rom" ]
|
||||
}
|
||||
|
||||
in λ(subinit : Init.Type) →
|
||||
λ(storeName : Text) →
|
||||
λ(storeSize : Natural) →
|
||||
λ(storeManifest : Manifest/Type) →
|
||||
λ(bootManifest : Manifest/Type) →
|
||||
Genode.Boot::{
|
||||
, config = Init::{
|
||||
, children =
|
||||
let child = Prelude.Map.keyValue Child.Type
|
||||
|
||||
in [ child
|
||||
"timer"
|
||||
( Child.flat
|
||||
Child.Attributes::{
|
||||
, binary = "timer_drv"
|
||||
, provides = [ "Timer" ]
|
||||
}
|
||||
)
|
||||
, child
|
||||
"rtc"
|
||||
( Child.flat
|
||||
Child.Attributes::{
|
||||
, binary = "rtc_drv"
|
||||
, provides = [ "Rtc" ]
|
||||
, routes = [ Init.ServiceRoute.parent "IO_PORT" ]
|
||||
}
|
||||
)
|
||||
, child
|
||||
"store_fs"
|
||||
( Child.flat
|
||||
Child.Attributes::{
|
||||
, binary = "vfs"
|
||||
, config = Init.Config::{
|
||||
, content =
|
||||
[ XML.element
|
||||
{ name = "vfs"
|
||||
, attributes = XML.emptyAttributes
|
||||
, content =
|
||||
[ XML.leaf
|
||||
{ name = "tar"
|
||||
, attributes = toMap { name = storeName }
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
, policies =
|
||||
[ Init.Config.Policy::{
|
||||
, service = "File_system"
|
||||
, label = Init.LabelSelector.suffix "nix-store"
|
||||
, attributes = toMap { root = "/nix/store" }
|
||||
}
|
||||
, Init.Config.Policy::{
|
||||
, service = "File_system"
|
||||
, label = Init.LabelSelector.prefix "store_rom"
|
||||
, attributes = toMap { root = "/" }
|
||||
}
|
||||
]
|
||||
}
|
||||
, provides = [ "File_system" ]
|
||||
}
|
||||
)
|
||||
, child
|
||||
"store_rom"
|
||||
( Child.flat
|
||||
Child.Attributes::{
|
||||
, binary = "cached_fs_rom"
|
||||
, provides = [ "ROM" ]
|
||||
, resources = Init.Resources::{
|
||||
, ram = storeSize + Genode.units.MiB 1
|
||||
}
|
||||
}
|
||||
)
|
||||
, child "init" (wrapStore subinit storeManifest)
|
||||
]
|
||||
}
|
||||
, rom =
|
||||
Genode.BootModules.toRomPaths
|
||||
( Prelude.List.concat
|
||||
(Prelude.Map.Entry Text Text)
|
||||
( Prelude.Map.values
|
||||
Text
|
||||
(Prelude.Map.Type Text Text)
|
||||
bootManifest
|
||||
)
|
||||
)
|
||||
}
|
@ -0,0 +1,159 @@
|
||||
let Genode = env:DHALL_GENODE
|
||||
|
||||
let Prelude = Genode.Prelude
|
||||
|
||||
let XML = Prelude.XML
|
||||
|
||||
let Init = Genode.Init
|
||||
|
||||
let Child = Init.Child
|
||||
|
||||
let parentRoutes =
|
||||
Prelude.List.map Text Init.ServiceRoute.Type Init.ServiceRoute.parent
|
||||
|
||||
in λ(params : { coreutils : Text, execStart : Text }) →
|
||||
Init::{
|
||||
, verbose = True
|
||||
, routes = parentRoutes [ "Timer", "Rtc", "File_system" ]
|
||||
, children = toMap
|
||||
{ vfs =
|
||||
Child.flat
|
||||
Child.Attributes::{
|
||||
, binary = "vfs"
|
||||
, exitPropagate = True
|
||||
, provides = [ "File_system" ]
|
||||
, resources = Genode.Init.Resources::{
|
||||
, caps = 256
|
||||
, ram = Genode.units.MiB 8
|
||||
}
|
||||
, config = Init.Config::{
|
||||
, content =
|
||||
[ XML.element
|
||||
{ name = "vfs"
|
||||
, attributes = XML.emptyAttributes
|
||||
, content =
|
||||
let dir =
|
||||
λ(name : Text) →
|
||||
λ(content : List XML.Type) →
|
||||
XML.element
|
||||
{ name = "dir"
|
||||
, content
|
||||
, attributes = toMap { name }
|
||||
}
|
||||
|
||||
let leaf =
|
||||
λ(name : Text) →
|
||||
XML.leaf
|
||||
{ name, attributes = XML.emptyAttributes }
|
||||
|
||||
in [ dir
|
||||
"dev"
|
||||
[ dir "pipes" [ leaf "pipe" ]
|
||||
, dir
|
||||
"sockets"
|
||||
[ XML.leaf
|
||||
{ name = "fs"
|
||||
, attributes = toMap
|
||||
{ label = "sockets" }
|
||||
}
|
||||
]
|
||||
, leaf "log"
|
||||
, leaf "null"
|
||||
, leaf "rtc"
|
||||
, leaf "zero"
|
||||
]
|
||||
, dir
|
||||
"etc"
|
||||
[ XML.element
|
||||
{ name = "inline"
|
||||
, attributes = toMap
|
||||
{ name = "ExecStart" }
|
||||
, content =
|
||||
[ XML.text params.execStart ]
|
||||
}
|
||||
]
|
||||
, dir
|
||||
"usr"
|
||||
[ dir
|
||||
"bin"
|
||||
[ XML.leaf
|
||||
{ name = "symlink"
|
||||
, attributes = toMap
|
||||
{ name = "env"
|
||||
, target =
|
||||
"${params.coreutils}/bin/env"
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
, dir "tmp" [ leaf "ram" ]
|
||||
, dir
|
||||
"nix"
|
||||
[ dir
|
||||
"store"
|
||||
[ XML.leaf
|
||||
{ name = "fs"
|
||||
, attributes = toMap
|
||||
{ label = "nix-store" }
|
||||
}
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
, policies =
|
||||
[ Init.Config.Policy::{
|
||||
, service = "File_system"
|
||||
, label = Init.LabelSelector.prefix "shell"
|
||||
, attributes = toMap { root = "/", writeable = "yes" }
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
, shell =
|
||||
Child.flat
|
||||
Child.Attributes::{
|
||||
, binary = "bash"
|
||||
, exitPropagate = True
|
||||
, resources = Genode.Init.Resources::{
|
||||
, caps = 256
|
||||
, ram = Genode.units.MiB 8
|
||||
}
|
||||
, config = Genode.Init.Config::{
|
||||
, content =
|
||||
[ XML.leaf
|
||||
{ name = "libc"
|
||||
, attributes = toMap
|
||||
{ stdin = "/dev/null"
|
||||
, stdout = "/dev/log"
|
||||
, stderr = "/dev/log"
|
||||
, pipe = "/dev/pipes"
|
||||
, rtc = "/dev/rtc"
|
||||
, socket = "/dev/sockets"
|
||||
}
|
||||
}
|
||||
, XML.element
|
||||
{ name = "vfs"
|
||||
, attributes = XML.emptyAttributes
|
||||
, content =
|
||||
[ XML.leaf
|
||||
{ name = "fs"
|
||||
, attributes = XML.emptyAttributes
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
# Prelude.List.map
|
||||
Text
|
||||
XML.Type
|
||||
( λ(x : Text) →
|
||||
XML.leaf
|
||||
{ name = "arg"
|
||||
, attributes = toMap { value = x }
|
||||
}
|
||||
)
|
||||
[ "bash", "/etc/ExecStart" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
with lib; {
|
||||
|
||||
options.systemd.services = lib.mkOption {
|
||||
type = types.attrsOf (types.submodule ({ name, config, ... }: {
|
||||
options.genode.enable = lib.mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Translate this systemd unit to a Genode subsystem.";
|
||||
};
|
||||
}));
|
||||
};
|
||||
|
||||
config.services.klogd.enable = false;
|
||||
# The default is determined by checking the Linux version
|
||||
# which cannot be evaluated here.
|
||||
|
||||
config.genode.init.subinits = mapAttrs' (name: service:
|
||||
let name' = "services." + name;
|
||||
in {
|
||||
name = name';
|
||||
value = {
|
||||
inputs = with pkgs; with genodePackages; [ bash libc posix vfs_pipe ];
|
||||
configFile = pkgs.writeText "${name'}.dhall" ''
|
||||
${./systemd-runner.dhall} {
|
||||
, coreutils = "${pkgs.coreutils}"
|
||||
, execStart = "${toString service.serviceConfig.ExecStart}"
|
||||
}
|
||||
'';
|
||||
};
|
||||
}) (filterAttrs (name: service: service.genode.enable)
|
||||
config.systemd.services);
|
||||
}
|
@ -1,324 +1,63 @@
|
||||
{ self, apps, localPackages, genodepkgs, lib, nixpkgs, legacyPackages }:
|
||||
{ flake, system, localSystem, crossSystem, pkgs }:
|
||||
|
||||
let
|
||||
|
||||
callTest = path:
|
||||
import path {
|
||||
pkgs = testPkgs;
|
||||
inherit nixpkgs localPackages legacyPackages;
|
||||
};
|
||||
|
||||
testFiles =
|
||||
map callTest [ ./log.nix ./posix.nix ./vmm_arm.nix ./vmm_x86.nix ./x86.nix ]
|
||||
++ (callTest ./solo5);
|
||||
|
||||
testPkgs = genodepkgs;
|
||||
|
||||
qemu' = localPackages.qemu;
|
||||
|
||||
qemuBinary = qemuPkg:
|
||||
{
|
||||
aarch64-genode = "${qemuPkg}/bin/qemu-system-aarch64";
|
||||
x86_64-genode = "${qemuPkg}/bin/qemu-system-x86_64";
|
||||
}.${genodepkgs.stdenv.hostPlatform.system};
|
||||
lib = flake.lib.${system};
|
||||
nixpkgs = flake.legacyPackages.${system};
|
||||
legacyPackages = flake.legacyPackages.${system};
|
||||
|
||||
testingPython = import ./lib/testing-python.nix;
|
||||
|
||||
testSpecs = map (p: import p) [
|
||||
./hello.nix
|
||||
./log.nix
|
||||
./solo5/multi.nix
|
||||
./vmm_x86.nix
|
||||
./x86.nix
|
||||
];
|
||||
|
||||
cores = [
|
||||
{
|
||||
prefix = "hw-pc-";
|
||||
testingPython = testingPython {
|
||||
inherit flake system localSystem crossSystem pkgs;
|
||||
extraConfigurations = [ ../nixos-modules/base-hw-pc.nix ];
|
||||
};
|
||||
specs = [ "x86" "hw" ];
|
||||
platforms = [ "x86_64-genode" ];
|
||||
basePackages = [ testPkgs.base-hw-pc ]
|
||||
++ map testPkgs.genodeSources.depot [ "rtc_drv" ];
|
||||
makeImage =
|
||||
lib.hwImage "0xffffffc000000000" "0x00200000" testPkgs.base-hw-pc;
|
||||
startVM = vmName: image: ''
|
||||
#! ${localPackages.runtimeShell}
|
||||
exec ${qemuBinary qemu'} \
|
||||
-name ${vmName} \
|
||||
-machine q35 \
|
||||
-m 384 \
|
||||
-netdev user,id=net0 \
|
||||
-device virtio-net-pci,netdev=net0 \
|
||||
-kernel "${testPkgs.bender}/bender" \
|
||||
-initrd "${image}/image.elf" \
|
||||
$QEMU_OPTS \
|
||||
"$@"
|
||||
'';
|
||||
}
|
||||
{
|
||||
prefix = "hw-virt_qemu-";
|
||||
specs = [ "aarch64" "hw" ];
|
||||
platforms = [ "aarch64-genode" ];
|
||||
basePackages = with testPkgs; [ base-hw-virt_qemu rtc-dummy ];
|
||||
makeImage = lib.hwImage "0xffffffc000000000" "0x40000000"
|
||||
testPkgs.base-hw-virt_qemu;
|
||||
startVM = vmName: image: ''
|
||||
#! ${localPackages.runtimeShell}
|
||||
exec ${qemuBinary qemu'} \
|
||||
-name ${vmName} \
|
||||
-M virt,virtualization=true,gic_version=3 \
|
||||
-cpu cortex-a53 \
|
||||
-smp 4 \
|
||||
-m 384 \
|
||||
-kernel "${image}/image.elf" \
|
||||
$QEMU_OPTS \
|
||||
"$@"
|
||||
'';
|
||||
}
|
||||
/* {
|
||||
prefix = "hw-virt_qemu-";
|
||||
testingPython = testingPython {
|
||||
inherit flake system localSystem crossSystem pkgs;
|
||||
extraConfigurations = [ ../nixos-modules/base-hw-virt_qemu.nix ];
|
||||
};
|
||||
specs = [ "aarch64" "hw" ];
|
||||
platforms = [ "aarch64-genode" ];
|
||||
}
|
||||
*/
|
||||
{
|
||||
prefix = "nova-";
|
||||
testingPython = testingPython {
|
||||
inherit flake system localSystem crossSystem pkgs;
|
||||
extraConfigurations = [ ../nixos-modules/nova.nix ];
|
||||
};
|
||||
specs = [ "x86" "nova" ];
|
||||
platforms = [ "x86_64-genode" ];
|
||||
basePackages = [ testPkgs.base-nova ]
|
||||
++ map testPkgs.genodeSources.depot [ "rtc_drv" ];
|
||||
makeImage = lib.novaImage;
|
||||
startVM = vmName: image: ''
|
||||
#! ${localPackages.runtimeShell}
|
||||
exec ${qemuBinary qemu'} \
|
||||
-name ${vmName} \
|
||||
-machine q35 \
|
||||
-m 384 \
|
||||
-kernel "${testPkgs.bender}/bender" \
|
||||
-initrd "${testPkgs.NOVA}/hypervisor-x86_64 arg=iommu novpid serial,${image}/image.elf" \
|
||||
$QEMU_OPTS \
|
||||
"$@"
|
||||
'';
|
||||
}
|
||||
];
|
||||
|
||||
cores' = builtins.filter (core:
|
||||
builtins.any (x: x == genodepkgs.stdenv.hostPlatform.system) core.platforms)
|
||||
builtins.any (x: x == pkgs.stdenv.hostPlatform.system) core.platforms)
|
||||
cores;
|
||||
|
||||
testDriver = with localPackages;
|
||||
let testDriverScript = ./test-driver/test-driver.py;
|
||||
in stdenv.mkDerivation {
|
||||
name = "nixos-test-driver";
|
||||
|
||||
nativeBuildInputs = [ makeWrapper ];
|
||||
buildInputs = [ (python3.withPackages (p: [ p.ptpython ])) ];
|
||||
checkInputs = with python3Packages; [ pylint mypy ];
|
||||
|
||||
dontUnpack = true;
|
||||
|
||||
preferLocalBuild = true;
|
||||
|
||||
doCheck = true;
|
||||
checkPhase = ''
|
||||
mypy --disallow-untyped-defs \
|
||||
--no-implicit-optional \
|
||||
--ignore-missing-imports ${testDriverScript}
|
||||
pylint --errors-only ${testDriverScript}
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
cp ${testDriverScript} $out/bin/nixos-test-driver
|
||||
chmod u+x $out/bin/nixos-test-driver
|
||||
# TODO: copy user script part into this file (append)
|
||||
|
||||
wrapProgram $out/bin/nixos-test-driver \
|
||||
--prefix PATH : "${lib.makeBinPath [ qemu' coreutils ]}" \
|
||||
'';
|
||||
};
|
||||
|
||||
defaultTestScript = ''
|
||||
start_all()
|
||||
machine.wait_until_serial_output('child "init" exited with exit value 0')
|
||||
'';
|
||||
|
||||
makeTest = with localPackages;
|
||||
{ prefix, specs, platforms, basePackages, makeImage, startVM }:
|
||||
{ name ? "unnamed", testScript ? defaultTestScript,
|
||||
# Skip linting (mainly intended for faster dev cycles)
|
||||
skipLint ? false, ... }@t:
|
||||
|
||||
let
|
||||
testDriverName = "genode-test-driver-${name}";
|
||||
|
||||
buildVM = vmName:
|
||||
{ config, inputs, env ? { }, extraPaths ? [ ] }:
|
||||
let
|
||||
storeTarball = localPackages.runCommand "store" { } ''
|
||||
mkdir -p $out
|
||||
tar cf "$out/store.tar" --absolute-names ${toString inputs} ${
|
||||
toString extraPaths
|
||||
}
|
||||
'';
|
||||
addManifest = drv:
|
||||
drv // {
|
||||
manifest =
|
||||
nixpkgs.runCommand "${drv.name}.dhall" { inherit drv; } ''
|
||||
set -eu
|
||||
echo -n '[' >> $out
|
||||
find $drv/ -type f -printf ',{mapKey= "%f",mapValue="%p"}' >> $out
|
||||
${if builtins.elem "lib" drv.outputs then
|
||||
''
|
||||
find ${drv.lib}/ -type f -printf ',{mapKey= "%f",mapValue="%p"}' >> $out''
|
||||
else
|
||||
""}
|
||||
echo -n ']' >> $out
|
||||
'';
|
||||
};
|
||||
|
||||
storeManifest = lib.mergeManifests (map addManifest inputs);
|
||||
manifest = lib.mergeManifests (map addManifest (basePackages
|
||||
++ [ testPkgs.sotest-producer storeTarball ]
|
||||
++ map testPkgs.genodeSources.depot [
|
||||
"init"
|
||||
"vfs"
|
||||
"cached_fs_rom"
|
||||
]));
|
||||
config' = "${
|
||||
./test-wrapper.dhall
|
||||
} (${config}) $(stat --format '%s' ${storeTarball}/store.tar) ${storeManifest} ${manifest}";
|
||||
env' = {
|
||||
DHALL_GENODE = "${testPkgs.dhallGenode}/source.dhall";
|
||||
DHALL_GENODE_TEST = "${./test.dhall}";
|
||||
} // env;
|
||||
|
||||
image = makeImage vmName env' config';
|
||||
startVM' = startVM vmName image;
|
||||
in {
|
||||
script = localPackages.writeScriptBin "run-${vmName}-vm" startVM';
|
||||
|
||||
config = lib.runDhallCommand (name + ".dhall") env' ''
|
||||
${apps.dhall.program} <<< "${config'}" > $out
|
||||
'';
|
||||
|
||||
store = storeTarball;
|
||||
|
||||
xml = lib.runDhallCommand (name + ".config") env'
|
||||
''${apps.render-init.program} <<< "(${config'}).config" > $out'';
|
||||
};
|
||||
|
||||
nodes = lib.mapAttrs buildVM
|
||||
(t.nodes or (if t ? machine then { machine = t.machine; } else { }));
|
||||
|
||||
testScript' =
|
||||
# Call the test script with the computed nodes.
|
||||
if lib.isFunction testScript then
|
||||
testScript { inherit nodes; }
|
||||
else
|
||||
testScript;
|
||||
|
||||
vms = map (node: node.script) (lib.attrValues nodes);
|
||||
|
||||
# Generate onvenience wrappers for running the test driver
|
||||
# interactively with the specified network, and for starting the
|
||||
# VMs from the command line.
|
||||
driver =
|
||||
let warn = if skipLint then lib.warn "Linting is disabled!" else lib.id;
|
||||
in warn (runCommand testDriverName {
|
||||
buildInputs = [ makeWrapper ];
|
||||
testScript = testScript';
|
||||
preferLocalBuild = true;
|
||||
testName = name;
|
||||
} ''
|
||||
mkdir -p $out/bin
|
||||
|
||||
echo -n "$testScript" > $out/test-script
|
||||
${lib.optionalString (!skipLint) ''
|
||||
${python3Packages.black}/bin/black --check --quiet --diff $out/test-script
|
||||
''}
|
||||
|
||||
ln -s ${testDriver}/bin/nixos-test-driver $out/bin/
|
||||
vms=($(for i in ${toString vms}; do echo $i/bin/run-*-vm; done))
|
||||
wrapProgram $out/bin/nixos-test-driver \
|
||||
--add-flags "''${vms[*]}" \
|
||||
--run "export testScript=\"\$(${coreutils}/bin/cat $out/test-script)\""
|
||||
ln -s ${testDriver}/bin/nixos-test-driver $out/bin/nixos-run-vms
|
||||
wrapProgram $out/bin/nixos-run-vms \
|
||||
--add-flags "''${vms[*]}" \
|
||||
--set tests 'start_all(); join_all();'
|
||||
''); # "
|
||||
|
||||
passMeta = drv:
|
||||
drv
|
||||
// lib.optionalAttrs (t ? meta) { meta = (drv.meta or { }) // t.meta; };
|
||||
|
||||
# Run an automated test suite in the given virtual network.
|
||||
# `driver' is the script that runs the network.
|
||||
runTests = driver:
|
||||
stdenv.mkDerivation {
|
||||
name = "test-run-${driver.testName}";
|
||||
|
||||
buildCommand = ''
|
||||
mkdir -p $out
|
||||
|
||||
LOGFILE=/dev/null tests='exec(os.environ["testScript"])' ${driver}/bin/nixos-test-driver
|
||||
'';
|
||||
};
|
||||
|
||||
test = passMeta (runTests driver);
|
||||
|
||||
nodeNames = builtins.attrNames nodes;
|
||||
invalidNodeNames =
|
||||
lib.filter (node: builtins.match "^[A-z_]([A-z0-9_]+)?$" node == null)
|
||||
nodeNames;
|
||||
|
||||
in if lib.length invalidNodeNames > 0 then
|
||||
throw ''
|
||||
Cannot create machines out of (${
|
||||
lib.concatStringsSep ", " invalidNodeNames
|
||||
})!
|
||||
All machines are referenced as python variables in the testing framework which will break the
|
||||
script when special characters are used.
|
||||
|
||||
Please stick to alphanumeric chars and underscores as separation.
|
||||
''
|
||||
else
|
||||
test // { inherit nodes driver test; };
|
||||
|
||||
testList = let
|
||||
f = core:
|
||||
let makeTest' = makeTest core;
|
||||
in test:
|
||||
f = core: test:
|
||||
if |