summary refs log tree commit diff
path: root/lib/systems
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2021-08-04 10:43:07 +0000
committerAlyssa Ross <hi@alyssa.is>2021-08-04 10:43:07 +0000
commit62614cbef7da005c1eda8c9400160f6bcd6546b8 (patch)
treec2630f69080637987b68acb1ee8676d2681fe304 /lib/systems
parentd9c82ed3044c72cecf01c6ea042489d30914577c (diff)
parente24069138dfec3ef94f211f1da005bb5395adc11 (diff)
downloadnixpkgs-62614cbef7da005c1eda8c9400160f6bcd6546b8.tar
nixpkgs-62614cbef7da005c1eda8c9400160f6bcd6546b8.tar.gz
nixpkgs-62614cbef7da005c1eda8c9400160f6bcd6546b8.tar.bz2
nixpkgs-62614cbef7da005c1eda8c9400160f6bcd6546b8.tar.lz
nixpkgs-62614cbef7da005c1eda8c9400160f6bcd6546b8.tar.xz
nixpkgs-62614cbef7da005c1eda8c9400160f6bcd6546b8.tar.zst
nixpkgs-62614cbef7da005c1eda8c9400160f6bcd6546b8.zip
Merge branch 'nixpkgs-update' into master
Diffstat (limited to 'lib/systems')
-rw-r--r--lib/systems/architectures.nix107
-rw-r--r--lib/systems/default.nix55
-rw-r--r--lib/systems/doubles.nix118
-rw-r--r--lib/systems/examples.nix131
-rw-r--r--lib/systems/inspect.nix4
-rw-r--r--lib/systems/parse.nix78
-rw-r--r--lib/systems/platforms.nix714
7 files changed, 751 insertions, 456 deletions
diff --git a/lib/systems/architectures.nix b/lib/systems/architectures.nix
new file mode 100644
index 00000000000..ddc320d24e0
--- /dev/null
+++ b/lib/systems/architectures.nix
@@ -0,0 +1,107 @@
+{ lib }:
+
+rec {
+  # gcc.arch to its features (as in /proc/cpuinfo)
+  features = {
+    default        = [ ];
+    # x86_64 Intel
+    westmere       = [ "sse3" "ssse3" "sse4_1" "sse4_2"         "aes"                                    ];
+    sandybridge    = [ "sse3" "ssse3" "sse4_1" "sse4_2"         "aes" "avx"                              ];
+    ivybridge      = [ "sse3" "ssse3" "sse4_1" "sse4_2"         "aes" "avx"                              ];
+    haswell        = [ "sse3" "ssse3" "sse4_1" "sse4_2"         "aes" "avx" "avx2"          "fma"        ];
+    broadwell      = [ "sse3" "ssse3" "sse4_1" "sse4_2"         "aes" "avx" "avx2"          "fma"        ];
+    skylake        = [ "sse3" "ssse3" "sse4_1" "sse4_2"         "aes" "avx" "avx2"          "fma"        ];
+    skylake-avx512 = [ "sse3" "ssse3" "sse4_1" "sse4_2"         "aes" "avx" "avx2" "avx512" "fma"        ];
+    cannonlake     = [ "sse3" "ssse3" "sse4_1" "sse4_2"         "aes" "avx" "avx2" "avx512" "fma"        ];
+    icelake-client = [ "sse3" "ssse3" "sse4_1" "sse4_2"         "aes" "avx" "avx2" "avx512" "fma"        ];
+    icelake-server = [ "sse3" "ssse3" "sse4_1" "sse4_2"         "aes" "avx" "avx2" "avx512" "fma"        ];
+    cascadelake    = [ "sse3" "ssse3" "sse4_1" "sse4_2"         "aes" "avx" "avx2" "avx512" "fma"        ];
+    cooperlake     = [ "sse3" "ssse3" "sse4_1" "sse4_2"         "aes" "avx" "avx2" "avx512" "fma"        ];
+    tigerlake      = [ "sse3" "ssse3" "sse4_1" "sse4_2"         "aes" "avx" "avx2" "avx512" "fma"        ];
+    # x86_64 AMD
+    btver1         = [ "sse3" "ssse3" "sse4_1" "sse4_2"                                                  ];
+    btver2         = [ "sse3" "ssse3" "sse4_1" "sse4_2"         "aes" "avx"                              ];
+    bdver1         = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx"                 "fma" "fma4" ];
+    bdver2         = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx"                 "fma" "fma4" ];
+    bdver3         = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx"                 "fma" "fma4" ];
+    bdver4         = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx" "avx2"          "fma" "fma4" ];
+    znver1         = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx" "avx2"          "fma"        ];
+    znver2         = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx" "avx2"          "fma"        ];
+    znver3         = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx" "avx2"          "fma"        ];
+    # other
+    armv5te        = [ ];
+    armv6          = [ ];
+    armv7-a        = [ ];
+    armv8-a        = [ ];
+    mips32         = [ ];
+    loongson2f     = [ ];
+  };
+
+  # a superior CPU has all the features of an inferior and is able to build and test code for it
+  inferiors = {
+    # x86_64 Intel
+    default        = [ ];
+    westmere       = [ ];
+    sandybridge    = [ "westmere"    ] ++ inferiors.westmere;
+    ivybridge      = [ "sandybridge" ] ++ inferiors.sandybridge;
+    haswell        = [ "ivybridge"   ] ++ inferiors.ivybridge;
+    broadwell      = [ "haswell"     ] ++ inferiors.haswell;
+    skylake        = [ "broadwell"   ] ++ inferiors.broadwell;
+    skylake-avx512 = [ "skylake"     ] ++ inferiors.skylake;
+
+    # x86_64 AMD
+    # TODO: fill this (need testing)
+    btver1         = [ ];
+    btver2         = [ ];
+    bdver1         = [ ];
+    bdver2         = [ ];
+    bdver3         = [ ];
+    bdver4         = [ ];
+    # Regarding `skylake` as inferior of `znver1`, there are reports of
+    # successful usage by Gentoo users and Phoronix benchmarking of different
+    # `-march` targets.
+    #
+    # The GCC documentation on extensions used and wikichip documentation
+    # regarding supperted extensions on znver1 and skylake was used to create
+    # this partial order.
+    #
+    # Note:
+    #
+    # - The succesors of `skylake` (`cannonlake`, `icelake`, etc) use `avx512`
+    #   which no current AMD Zen michroarch support.
+    # - `znver1` uses `ABM`, `CLZERO`, `CX16`, `MWAITX`, and `SSE4A` which no
+    #   current Intel microarch support.
+    #
+    # https://www.phoronix.com/scan.php?page=article&item=amd-znver3-gcc11&num=1
+    # https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html
+    # https://en.wikichip.org/wiki/amd/microarchitectures/zen
+    # https://en.wikichip.org/wiki/intel/microarchitectures/skylake
+    znver1         = [ "skylake" ] ++ inferiors.skylake;
+    znver2         = [ "znver1"  ] ++ inferiors.znver1;
+    znver3         = [ "znver2"  ] ++ inferiors.znver2;
+
+    # other
+    armv5te        = [ ];
+    armv6          = [ ];
+    armv7-a        = [ ];
+    armv8-a        = [ ];
+    mips32         = [ ];
+    loongson2f     = [ ];
+  };
+
+  predicates = let
+    featureSupport = feature: x: builtins.elem feature features.${x} or [];
+  in {
+    sse3Support    = featureSupport "sse3";
+    ssse3Support   = featureSupport "ssse3";
+    sse4_1Support  = featureSupport "sse4_1";
+    sse4_2Support  = featureSupport "sse4_2";
+    sse4_aSupport  = featureSupport "sse4a";
+    avxSupport     = featureSupport "avx";
+    avx2Support    = featureSupport "avx2";
+    avx512Support  = featureSupport "avx512";
+    aesSupport     = featureSupport "aes";
+    fmaSupport     = featureSupport "fma";
+    fma4Support    = featureSupport "fma4";
+  };
+}
diff --git a/lib/systems/default.nix b/lib/systems/default.nix
index c929781dd8f..70ec98b03c1 100644
--- a/lib/systems/default.nix
+++ b/lib/systems/default.nix
@@ -7,6 +7,7 @@ rec {
   inspect = import ./inspect.nix { inherit lib; };
   platforms = import ./platforms.nix { inherit lib; };
   examples = import ./examples.nix { inherit lib; };
+  architectures = import ./architectures.nix { inherit lib; };
 
   # Elaborate a `localSystem` or `crossSystem` so that it contains everything
   # necessary.
@@ -23,8 +24,6 @@ rec {
       # Either of these can be losslessly-extracted from `parsed` iff parsing succeeds.
       system = parse.doubleFromSystem final.parsed;
       config = parse.tripleFromSystem final.parsed;
-      # Just a guess, based on `system`
-      platform = platforms.selectBySystem final.system;
       # Determine whether we are compatible with the provided CPU
       isCompatible = platform: parse.isCompatible final.parsed.cpu platform.parsed.cpu;
       # Derived meta-data
@@ -42,6 +41,19 @@ rec {
         else if final.isNetBSD              then "nblibc"
         # TODO(@Ericson2314) think more about other operating systems
         else                                     "native/impure";
+      # Choose what linker we wish to use by default. Someday we might also
+      # choose the C compiler, runtime library, C++ standard library, etc. in
+      # this way, nice and orthogonally, and deprecate `useLLVM`. But due to
+      # the monolithic GCC build we cannot actually make those choices
+      # independently, so we are just doing `linker` and keeping `useLLVM` for
+      # now.
+      linker =
+        /**/ if final.useLLVM or false      then "lld"
+        else if final.isDarwin              then "cctools"
+        # "bfd" and "gold" both come from GNU binutils. The existance of Gold
+        # is why we use the more obscure "bfd" and not "binutils" for this
+        # choice.
+        else                                     "bfd";
       extensions = {
         sharedLibrary =
           /**/ if final.isDarwin  then ".dylib"
@@ -76,13 +88,25 @@ rec {
          # uname -r
          release = null;
       };
+      isStatic = final.isWasm || final.isRedox;
+
+      # Just a guess, based on `system`
+      inherit
+        ({
+          linux-kernel = args.linux-kernel or {};
+          gcc = args.gcc or {};
+          rustc = args.rust or {};
+        } // platforms.select final)
+        linux-kernel gcc rustc;
 
-      kernelArch =
+      linuxArch =
         if final.isAarch32 then "arm"
         else if final.isAarch64 then "arm64"
-        else if final.isx86_32 then "x86"
-        else if final.isx86_64 then "ia64"
+        else if final.isx86_32 then "i386"
+        else if final.isx86_64 then "x86_64"
         else if final.isMips then "mips"
+        else if final.isPower then "powerpc"
+        else if final.isRiscV then "riscv"
         else final.parsed.cpu.name;
 
       qemuArch =
@@ -96,6 +120,24 @@ rec {
           powerpc64le = "ppc64le";
         }.${final.parsed.cpu.name} or final.parsed.cpu.name;
 
+      darwinArch = {
+        armv7a  = "armv7";
+        aarch64 = "arm64";
+      }.${final.parsed.cpu.name} or final.parsed.cpu.name;
+
+      darwinPlatform =
+        if final.isMacOS then "macos"
+        else if final.isiOS then "ios"
+        else null;
+      # The canonical name for this attribute is darwinSdkVersion, but some
+      # platforms define the old name "sdkVer".
+      darwinSdkVersion = final.sdkVer or (if final.isAarch64 then "11.0" else "10.12");
+      darwinMinVersion = final.darwinSdkVersion;
+      darwinMinVersionVariable =
+        if final.isMacOS then "MACOSX_DEPLOYMENT_TARGET"
+        else if final.isiOS then "IPHONEOS_DEPLOYMENT_TARGET"
+        else null;
+
       emulator = pkgs: let
         qemu-user = pkgs.qemu.override {
           smartcardSupport = false;
@@ -122,9 +164,12 @@ rec {
         then "${qemu-user}/bin/qemu-${final.qemuArch}"
         else if final.isWasi
         then "${pkgs.wasmtime}/bin/wasmtime"
+        else if final.isMmix
+        then "${pkgs.mmixware}/bin/mmix"
         else throw "Don't know how to run ${final.config} executables.";
 
     } // mapAttrs (n: v: v final.parsed) inspect.predicates
+      // mapAttrs (n: v: v final.gcc.arch or "default") architectures.predicates
       // args;
   in assert final.useAndroidPrebuilt -> final.isAndroid;
      assert lib.foldl
diff --git a/lib/systems/doubles.nix b/lib/systems/doubles.nix
index fb7d722e737..aa630b51ed8 100644
--- a/lib/systems/doubles.nix
+++ b/lib/systems/doubles.nix
@@ -6,39 +6,54 @@ let
   inherit (lib.attrsets) matchAttrs;
 
   all = [
-    "aarch64-linux"
-    "armv5tel-linux" "armv6l-linux" "armv7a-linux" "armv7l-linux"
+    # Cygwin
+    "i686-cygwin" "x86_64-cygwin"
 
-    "mipsel-linux"
+    # Darwin
+    "x86_64-darwin" "i686-darwin" "aarch64-darwin" "armv7a-darwin"
 
-    "i686-cygwin" "i686-freebsd" "i686-linux" "i686-netbsd" "i686-openbsd"
+    # FreeBSD
+    "i686-freebsd" "x86_64-freebsd"
 
-    "x86_64-cygwin" "x86_64-freebsd" "x86_64-linux"
-    "x86_64-netbsd" "x86_64-openbsd" "x86_64-solaris"
+    # Genode
+    "aarch64-genode" "i686-genode" "x86_64-genode"
 
-    "x86_64-darwin" "i686-darwin" "aarch64-darwin" "armv7a-darwin"
+    # illumos
+    "x86_64-solaris"
 
-    "x86_64-windows" "i686-windows"
+    # JS
+    "js-ghcjs"
 
-    "wasm64-wasi" "wasm32-wasi"
+    # Linux
+    "aarch64-linux" "armv5tel-linux" "armv6l-linux" "armv7a-linux"
+    "armv7l-linux" "i686-linux" "mipsel-linux" "powerpc64-linux"
+    "powerpc64le-linux" "riscv32-linux" "riscv64-linux" "x86_64-linux"
+    "m68k-linux" "s390-linux"
 
-    "x86_64-redox"
+    # MMIXware
+    "mmix-mmixware"
 
-    "powerpc64le-linux"
+    # NetBSD
+    "aarch64-netbsd" "armv6l-netbsd" "armv7a-netbsd" "armv7l-netbsd"
+    "i686-netbsd" "mipsel-netbsd" "powerpc-netbsd" "riscv32-netbsd"
+    "riscv64-netbsd" "x86_64-netbsd"
 
-    "riscv32-linux" "riscv64-linux"
+    # none
+    "aarch64-none" "arm-none" "armv6l-none" "avr-none" "i686-none" "msp430-none"
+    "or1k-none" "powerpc-none" "riscv32-none" "riscv64-none" "vc4-none" "m68k-none"
+    "s390-none" "x86_64-none"
 
-    "arm-none" "armv6l-none" "aarch64-none"
-    "avr-none"
-    "i686-none" "x86_64-none"
-    "powerpc-none"
-    "msp430-none"
-    "riscv64-none" "riscv32-none"
-    "vc4-none"
+    # OpenBSD
+    "i686-openbsd" "x86_64-openbsd"
 
-    "js-ghcjs"
+    # Redox
+    "x86_64-redox"
 
-    "aarch64-genode" "i686-genode" "x86_64-genode"
+    # WASI
+    "wasm64-wasi" "wasm32-wasi"
+
+    # Windows
+    "x86_64-windows" "i686-windows"
   ];
 
   allParsed = map parse.mkSystemFromString all;
@@ -50,32 +65,39 @@ in {
 
   none = [];
 
-  arm     = filterDoubles predicates.isAarch32;
-  aarch64 = filterDoubles predicates.isAarch64;
-  x86     = filterDoubles predicates.isx86;
-  i686    = filterDoubles predicates.isi686;
-  x86_64  = filterDoubles predicates.isx86_64;
-  mips    = filterDoubles predicates.isMips;
-  riscv   = filterDoubles predicates.isRiscV;
-  vc4     = filterDoubles predicates.isVc4;
-  js      = filterDoubles predicates.isJavaScript;
-
-  cygwin  = filterDoubles predicates.isCygwin;
-  darwin  = filterDoubles predicates.isDarwin;
-  freebsd = filterDoubles predicates.isFreeBSD;
+  arm           = filterDoubles predicates.isAarch32;
+  aarch64       = filterDoubles predicates.isAarch64;
+  x86           = filterDoubles predicates.isx86;
+  i686          = filterDoubles predicates.isi686;
+  x86_64        = filterDoubles predicates.isx86_64;
+  mips          = filterDoubles predicates.isMips;
+  mmix          = filterDoubles predicates.isMmix;
+  riscv         = filterDoubles predicates.isRiscV;
+  vc4           = filterDoubles predicates.isVc4;
+  or1k          = filterDoubles predicates.isOr1k;
+  m68k          = filterDoubles predicates.isM68k;
+  s390          = filterDoubles predicates.isS390;
+  js            = filterDoubles predicates.isJavaScript;
+
+  bigEndian     = filterDoubles predicates.isBigEndian;
+  littleEndian  = filterDoubles predicates.isLittleEndian;
+
+  cygwin        = filterDoubles predicates.isCygwin;
+  darwin        = filterDoubles predicates.isDarwin;
+  freebsd       = filterDoubles predicates.isFreeBSD;
   # Should be better, but MinGW is unclear.
-  gnu     = filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnu; }) ++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnueabi; }) ++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnueabihf; });
-  illumos = filterDoubles predicates.isSunOS;
-  linux   = filterDoubles predicates.isLinux;
-  netbsd  = filterDoubles predicates.isNetBSD;
-  openbsd = filterDoubles predicates.isOpenBSD;
-  unix    = filterDoubles predicates.isUnix;
-  wasi    = filterDoubles predicates.isWasi;
-  redox   = filterDoubles predicates.isRedox;
-  windows = filterDoubles predicates.isWindows;
-  genode  = filterDoubles predicates.isGenode;
-
-  embedded = filterDoubles predicates.isNone;
-
-  mesaPlatforms = ["i686-linux" "x86_64-linux" "x86_64-darwin" "armv5tel-linux" "armv6l-linux" "armv7l-linux" "armv7a-linux" "aarch64-linux" "powerpc64le-linux"];
+  gnu           = filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnu; }) ++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnueabi; }) ++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnueabihf; });
+  illumos       = filterDoubles predicates.isSunOS;
+  linux         = filterDoubles predicates.isLinux;
+  netbsd        = filterDoubles predicates.isNetBSD;
+  openbsd       = filterDoubles predicates.isOpenBSD;
+  unix          = filterDoubles predicates.isUnix;
+  wasi          = filterDoubles predicates.isWasi;
+  redox         = filterDoubles predicates.isRedox;
+  windows       = filterDoubles predicates.isWindows;
+  genode        = filterDoubles predicates.isGenode;
+
+  embedded      = filterDoubles predicates.isNone;
+
+  mesaPlatforms = ["i686-linux" "x86_64-linux" "x86_64-darwin" "armv5tel-linux" "armv6l-linux" "armv7l-linux" "armv7a-linux" "aarch64-linux" "powerpc64-linux" "powerpc64le-linux" "aarch64-darwin" "riscv64-linux"];
 }
diff --git a/lib/systems/examples.nix b/lib/systems/examples.nix
index ca562d2e456..32b236d6960 100644
--- a/lib/systems/examples.nix
+++ b/lib/systems/examples.nix
@@ -7,7 +7,6 @@ let
 
   riscv = bits: {
     config = "riscv${bits}-unknown-linux-gnu";
-    platform = platforms.riscv-multiplatform bits;
   };
 in
 
@@ -17,74 +16,88 @@ rec {
   #
   powernv = {
     config = "powerpc64le-unknown-linux-gnu";
-    platform = platforms.powernv;
   };
   musl-power = {
     config = "powerpc64le-unknown-linux-musl";
-    platform = platforms.powernv;
+  };
+
+  ppc64 = {
+    config = "powerpc64-unknown-linux-gnu";
+    gcc = { abi = "elfv2"; }; # for gcc configuration
+  };
+  ppc64-musl = {
+    config = "powerpc64-unknown-linux-musl";
+    gcc = { abi = "elfv2"; }; # for gcc configuration
   };
 
   sheevaplug = {
     config = "armv5tel-unknown-linux-gnueabi";
-    platform = platforms.sheevaplug;
-  };
+  } // platforms.sheevaplug;
 
   raspberryPi = {
     config = "armv6l-unknown-linux-gnueabihf";
-    platform = platforms.raspberrypi;
-  };
+  } // platforms.raspberrypi;
+
+  remarkable1 = {
+    config = "armv7l-unknown-linux-gnueabihf";
+  } // platforms.zero-gravitas;
+
+  remarkable2 = {
+    config = "armv7l-unknown-linux-gnueabihf";
+  } // platforms.zero-sugar;
 
   armv7l-hf-multiplatform = {
     config = "armv7l-unknown-linux-gnueabihf";
-    platform = platforms.armv7l-hf-multiplatform;
   };
 
   aarch64-multiplatform = {
     config = "aarch64-unknown-linux-gnu";
-    platform = platforms.aarch64-multiplatform;
   };
 
   armv7a-android-prebuilt = {
     config = "armv7a-unknown-linux-androideabi";
-    sdkVer = "24";
-    ndkVer = "18b";
-    platform = platforms.armv7a-android;
+    rustc.config = "armv7-linux-androideabi";
+    sdkVer = "29";
+    ndkVer = "21";
     useAndroidPrebuilt = true;
-  };
+  } // platforms.armv7a-android;
 
   aarch64-android-prebuilt = {
     config = "aarch64-unknown-linux-android";
-    sdkVer = "24";
-    ndkVer = "18b";
-    platform = platforms.aarch64-multiplatform;
+    rustc.config = "aarch64-linux-android";
+    sdkVer = "29";
+    ndkVer = "21";
     useAndroidPrebuilt = true;
   };
 
-  scaleway-c1 = armv7l-hf-multiplatform // rec {
-    platform = platforms.scaleway-c1;
-    inherit (platform.gcc) fpu;
+  aarch64-android = {
+    config = "aarch64-unknown-linux-android";
+    sdkVer = "30";
+    ndkVer = "21";
+    libc = "bionic";
+    useAndroidPrebuilt = false;
+    useLLVM = true;
   };
 
+  scaleway-c1 = armv7l-hf-multiplatform // platforms.scaleway-c1;
+
   pogoplug4 = {
     config = "armv5tel-unknown-linux-gnueabi";
-    platform = platforms.pogoplug4;
-  };
+  } // platforms.pogoplug4;
 
   ben-nanonote = {
     config = "mipsel-unknown-linux-uclibc";
-    platform = platforms.ben_nanonote;
-  };
+  } // platforms.ben_nanonote;
 
   fuloongminipc = {
     config = "mipsel-unknown-linux-gnu";
-    platform = platforms.fuloong2f_n32;
-  };
+  } // platforms.fuloong2f_n32;
 
   muslpi = raspberryPi // {
     config = "armv6l-unknown-linux-musleabihf";
   };
 
-  aarch64-multiplatform-musl = aarch64-multiplatform // {
+  aarch64-multiplatform-musl = {
     config = "aarch64-unknown-linux-musl";
   };
 
@@ -100,13 +113,16 @@ rec {
   riscv64-embedded = {
     config = "riscv64-none-elf";
     libc = "newlib";
-    platform = platforms.riscv-multiplatform "64";
   };
 
   riscv32-embedded = {
     config = "riscv32-none-elf";
     libc = "newlib";
-    platform = platforms.riscv-multiplatform "32";
+  };
+
+  mmix = {
+    config = "mmix-unknown-mmixware";
+    libc = "newlib";
   };
 
   msp430 = {
@@ -121,7 +137,19 @@ rec {
   vc4 = {
     config = "vc4-elf";
     libc = "newlib";
-    platform = {};
+  };
+
+  or1k = {
+    config = "or1k-elf";
+    libc = "newlib";
+  };
+
+  m68k = {
+    config = "m68k-unknown-linux-gnu";
+  };
+
+  s390 = {
+    config = "s390-unknown-linux-gnu";
   };
 
   arm-embedded = {
@@ -131,6 +159,12 @@ rec {
   armhf-embedded = {
     config = "arm-none-eabihf";
     libc = "newlib";
+    # GCC8+ does not build without this
+    # (https://www.mail-archive.com/gcc-bugs@gcc.gnu.org/msg552339.html):
+    gcc = {
+      arch = "armv5t";
+      fpu = "vfp";
+    };
   };
 
   aarch64-embedded = {
@@ -179,40 +213,44 @@ rec {
   iphone64 = {
     config = "aarch64-apple-ios";
     # config = "aarch64-apple-darwin14";
-    sdkVer = "12.4";
-    xcodeVer = "10.3";
+    sdkVer = "14.3";
+    xcodeVer = "12.3";
     xcodePlatform = "iPhoneOS";
     useiOSPrebuilt = true;
-    platform = {};
   };
 
   iphone32 = {
     config = "armv7a-apple-ios";
     # config = "arm-apple-darwin10";
-    sdkVer = "12.4";
-    xcodeVer = "10.3";
+    sdkVer = "14.3";
+    xcodeVer = "12.3";
     xcodePlatform = "iPhoneOS";
     useiOSPrebuilt = true;
-    platform = {};
   };
 
   iphone64-simulator = {
     config = "x86_64-apple-ios";
     # config = "x86_64-apple-darwin14";
-    sdkVer = "12.4";
-    xcodeVer = "10.3";
+    sdkVer = "14.3";
+    xcodeVer = "12.3";
     xcodePlatform = "iPhoneSimulator";
+    darwinPlatform = "ios-simulator";
     useiOSPrebuilt = true;
-    platform = {};
   };
 
   iphone32-simulator = {
     config = "i686-apple-ios";
     # config = "i386-apple-darwin11";
-    sdkVer = "12.4";
-    xcodeVer = "10.3";
+    sdkVer = "14.3";
+    xcodeVer = "12.3";
     xcodePlatform = "iPhoneSimulator";
+    darwinPlatform = "ios-simulator";
     useiOSPrebuilt = true;
+  };
+
+  aarch64-darwin = {
+    config = "aarch64-apple-darwin";
+    xcodePlatform = "MacOSX";
     platform = {};
   };
 
@@ -224,7 +262,6 @@ rec {
   mingw32 = {
     config = "i686-w64-mingw32";
     libc = "msvcrt"; # This distinguishes the mingw (non posix) toolchain
-    platform = {};
   };
 
   # 64 bit mingw-w64
@@ -232,14 +269,21 @@ rec {
     # That's the triplet they use in the mingw-w64 docs.
     config = "x86_64-w64-mingw32";
     libc = "msvcrt"; # This distinguishes the mingw (non posix) toolchain
-    platform = {};
   };
 
   # BSDs
 
-  amd64-netbsd = {
+  amd64-netbsd = lib.warn "The amd64-netbsd system example is deprecated. Use x86_64-netbsd instead." x86_64-netbsd;
+
+  x86_64-netbsd = {
+    config = "x86_64-unknown-netbsd";
+    libc = "nblibc";
+  };
+
+  x86_64-netbsd-llvm = {
     config = "x86_64-unknown-netbsd";
     libc = "nblibc";
+    useLLVM = true;
   };
 
   #
@@ -254,6 +298,5 @@ rec {
   # Ghcjs
   ghcjs = {
     config = "js-unknown-ghcjs";
-    platform = {};
   };
 }
diff --git a/lib/systems/inspect.nix b/lib/systems/inspect.nix
index 8fa63057250..2fba95aa1a6 100644
--- a/lib/systems/inspect.nix
+++ b/lib/systems/inspect.nix
@@ -17,6 +17,7 @@ rec {
     isAarch32      = { cpu = { family = "arm"; bits = 32; }; };
     isAarch64      = { cpu = { family = "arm"; bits = 64; }; };
     isMips         = { cpu = { family = "mips"; }; };
+    isMmix         = { cpu = { family = "mmix"; }; };
     isRiscV        = { cpu = { family = "riscv"; }; };
     isSparc        = { cpu = { family = "sparc"; }; };
     isWasm         = { cpu = { family = "wasm"; }; };
@@ -24,6 +25,9 @@ rec {
     isVc4          = { cpu = { family = "vc4"; }; };
     isAvr          = { cpu = { family = "avr"; }; };
     isAlpha        = { cpu = { family = "alpha"; }; };
+    isOr1k         = { cpu = { family = "or1k"; }; };
+    isM68k         = { cpu = { family = "m68k"; }; };
+    isS390         = { cpu = { family = "s390"; }; };
     isJavaScript   = { cpu = cpuTypes.js; };
 
     is32bit        = { cpu = { bits = 32; }; };
diff --git a/lib/systems/parse.nix b/lib/systems/parse.nix
index 6bd44a00746..386f252f2ba 100644
--- a/lib/systems/parse.nix
+++ b/lib/systems/parse.nix
@@ -93,6 +93,10 @@ rec {
     mips64   = { bits = 64; significantByte = bigEndian;    family = "mips"; };
     mips64el = { bits = 64; significantByte = littleEndian; family = "mips"; };
 
+    mmix     = { bits = 64; significantByte = bigEndian;    family = "mmix"; };
+
+    m68k     = { bits = 32; significantByte = bigEndian; family = "m68k"; };
+
     powerpc  = { bits = 32; significantByte = bigEndian;    family = "power"; };
     powerpc64 = { bits = 64; significantByte = bigEndian; family = "power"; };
     powerpc64le = { bits = 64; significantByte = littleEndian; family = "power"; };
@@ -101,6 +105,8 @@ rec {
     riscv32  = { bits = 32; significantByte = littleEndian; family = "riscv"; };
     riscv64  = { bits = 64; significantByte = littleEndian; family = "riscv"; };
 
+    s390     = { bits = 32; significantByte = bigEndian; family = "s390"; };
+
     sparc    = { bits = 32; significantByte = bigEndian;    family = "sparc"; };
     sparc64  = { bits = 64; significantByte = bigEndian;    family = "sparc"; };
 
@@ -114,18 +120,33 @@ rec {
 
     vc4      = { bits = 32; significantByte = littleEndian; family = "vc4"; };
 
+    or1k     = { bits = 32; significantByte = bigEndian; family = "or1k"; };
+
     js       = { bits = 32; significantByte = littleEndian; family = "js"; };
   };
 
-  # Determine where two CPUs are compatible with each other. That is,
-  # can we run code built for system b on system a? For that to
-  # happen, then the set of all possible possible programs that system
-  # b accepts must be a subset of the set of all programs that system
-  # a accepts. This compatibility relation forms a category where each
-  # CPU is an object and each arrow from a to b represents
-  # compatibility. CPUs with multiple modes of Endianness are
-  # isomorphic while all CPUs are endomorphic because any program
-  # built for a CPU can run on that CPU.
+  # GNU build systems assume that older NetBSD architectures are using a.out.
+  gnuNetBSDDefaultExecFormat = cpu:
+    if (cpu.family == "x86" && cpu.bits == 32) ||
+       (cpu.family == "arm" && cpu.bits == 32) ||
+       (cpu.family == "sparc" && cpu.bits == 32)
+    then execFormats.aout
+    else execFormats.elf;
+
+  # Determine when two CPUs are compatible with each other. That is,
+  # can code built for system B run on system A? For that to happen,
+  # the programs that system B accepts must be a subset of the
+  # programs that system A accepts.
+  #
+  # We have the following properties of the compatibility relation,
+  # which must be preserved when adding compatibility information for
+  # additional CPUs.
+  # - (reflexivity)
+  #   Every CPU is compatible with itself.
+  # - (transitivity)
+  #   If A is compatible with B and B is compatible with C then A is compatible with C.
+  # - (compatible under multiple endianness)
+  #   CPUs with multiple modes of endianness are pairwise compatible.
   isCompatible = a: b: with cpuTypes; lib.any lib.id [
     # x86
     (b == i386 && isCompatible a i486)
@@ -267,20 +288,21 @@ rec {
 
   kernels = with execFormats; with kernelFamilies; setTypes types.openKernel {
     # TODO(@Ericson2314): Don't want to mass-rebuild yet to keeping 'darwin' as
-    # the nnormalized name for macOS.
-    macos   = { execFormat = macho;   families = { inherit darwin; }; name = "darwin"; };
-    ios     = { execFormat = macho;   families = { inherit darwin; }; };
-    freebsd = { execFormat = elf;     families = { inherit bsd; }; };
-    linux   = { execFormat = elf;     families = { }; };
-    netbsd  = { execFormat = elf;     families = { inherit bsd; }; };
-    none    = { execFormat = unknown; families = { }; };
-    openbsd = { execFormat = elf;     families = { inherit bsd; }; };
-    solaris = { execFormat = elf;     families = { }; };
-    wasi    = { execFormat = wasm;    families = { }; };
-    redox   = { execFormat = elf;     families = { }; };
-    windows = { execFormat = pe;      families = { }; };
-    ghcjs   = { execFormat = unknown; families = { }; };
-    genode  = { execFormat = elf;     families = { }; };
+    # the normalized name for macOS.
+    macos    = { execFormat = macho;   families = { inherit darwin; }; name = "darwin"; };
+    ios      = { execFormat = macho;   families = { inherit darwin; }; };
+    freebsd  = { execFormat = elf;     families = { inherit bsd; }; };
+    linux    = { execFormat = elf;     families = { }; };
+    netbsd   = { execFormat = elf;     families = { inherit bsd; }; };
+    none     = { execFormat = unknown; families = { }; };
+    openbsd  = { execFormat = elf;     families = { inherit bsd; }; };
+    solaris  = { execFormat = elf;     families = { }; };
+    wasi     = { execFormat = wasm;    families = { }; };
+    redox    = { execFormat = elf;     families = { }; };
+    windows  = { execFormat = pe;      families = { }; };
+    ghcjs    = { execFormat = unknown; families = { }; };
+    genode   = { execFormat = elf;     families = { }; };
+    mmixware = { execFormat = unknown; families = { }; };
   } // { # aliases
     # 'darwin' is the kernel for all of them. We choose macOS by default.
     darwin = kernels.macos;
@@ -382,7 +404,7 @@ rec {
       else if (elemAt l 1) == "elf"
         then { cpu = elemAt l 0; vendor = "unknown";  kernel = "none";     abi = elemAt l 1; }
       else   { cpu = elemAt l 0;                      kernel = elemAt l 1;                   };
-    "3" = # Awkwards hacks, beware!
+    "3" = # Awkward hacks, beware!
       if elemAt l 1 == "apple"
         then { cpu = elemAt l 0; vendor = "apple";    kernel = elemAt l 2;                   }
       else if (elemAt l 1 == "linux") || (elemAt l 2 == "gnu")
@@ -393,6 +415,8 @@ rec {
         then { cpu = elemAt l 0; vendor = elemAt l 1; kernel = "wasi";                       }
       else if (elemAt l 2 == "redox")
         then { cpu = elemAt l 0; vendor = elemAt l 1; kernel = "redox";                      }
+      else if (elemAt l 2 == "mmixware")
+        then { cpu = elemAt l 0; vendor = elemAt l 1; kernel = "mmixware";                   }
       else if hasPrefix "netbsd" (elemAt l 2)
         then { cpu = elemAt l 0; vendor = elemAt l 1;    kernel = elemAt l 2;                }
       else if (elem (elemAt l 2) ["eabi" "eabihf" "elf"])
@@ -451,8 +475,12 @@ rec {
     else "${cpu.name}-${kernel.name}";
 
   tripleFromSystem = { cpu, vendor, kernel, abi, ... } @ sys: assert isSystem sys; let
+    optExecFormat =
+      lib.optionalString (kernel.name == "netbsd" &&
+                          gnuNetBSDDefaultExecFormat cpu != kernel.execFormat)
+        kernel.execFormat.name;
     optAbi = lib.optionalString (abi != abis.unknown) "-${abi.name}";
-  in "${cpu.name}-${vendor.name}-${kernel.name}${optAbi}";
+  in "${cpu.name}-${vendor.name}-${kernel.name}${optExecFormat}${optAbi}";
 
   ################################################################################
 
diff --git a/lib/systems/platforms.nix b/lib/systems/platforms.nix
index ab3cf1d5430..92285346f75 100644
--- a/lib/systems/platforms.nix
+++ b/lib/systems/platforms.nix
@@ -1,39 +1,36 @@
 { lib }:
 rec {
-  pcBase = {
-    name = "pc";
-    kernelBaseConfig = "defconfig";
-    # Build whatever possible as a module, if not stated in the extra config.
-    kernelAutoModules = true;
-    kernelTarget = "bzImage";
-  };
-
-  pc64 = pcBase // { kernelArch = "x86_64"; };
-
-  pc32 = pcBase // { kernelArch = "i386"; };
-
-  pc32_simplekernel = pc32 // {
-    kernelAutoModules = false;
+  pc = {
+    linux-kernel = {
+      name = "pc";
+
+      baseConfig = "defconfig";
+      # Build whatever possible as a module, if not stated in the extra config.
+      autoModules = true;
+      target = "bzImage";
+    };
   };
 
-  pc64_simplekernel = pc64 // {
-    kernelAutoModules = false;
+  pc_simplekernel = lib.recursiveUpdate pc {
+    linux-kernel.autoModules = false;
   };
 
   powernv = {
-    name = "PowerNV";
-    kernelArch = "powerpc";
-    kernelBaseConfig = "powernv_defconfig";
-    kernelTarget = "zImage";
-    kernelInstallTarget = "install";
-    kernelFile = "vmlinux";
-    kernelAutoModules = true;
-    # avoid driver/FS trouble arising from unusual page size
-    kernelExtraConfig = ''
-      PPC_64K_PAGES n
-      PPC_4K_PAGES y
-      IPV6 y
-    '';
+    linux-kernel = {
+      name = "PowerNV";
+
+      baseConfig = "powernv_defconfig";
+      target = "zImage";
+      installTarget = "install";
+      file = "vmlinux";
+      autoModules = true;
+      # avoid driver/FS trouble arising from unusual page size
+      extraConfig = ''
+        PPC_64K_PAGES n
+        PPC_4K_PAGES y
+        IPV6 y
+      '';
+    };
   };
 
   ##
@@ -41,18 +38,121 @@ rec {
   ##
 
   pogoplug4 = {
-    name = "pogoplug4";
+    linux-kernel = {
+      name = "pogoplug4";
 
+      baseConfig = "multi_v5_defconfig";
+      autoModules = false;
+      extraConfig = ''
+        # Ubi for the mtd
+        MTD_UBI y
+        UBIFS_FS y
+        UBIFS_FS_XATTR y
+        UBIFS_FS_ADVANCED_COMPR y
+        UBIFS_FS_LZO y
+        UBIFS_FS_ZLIB y
+        UBIFS_FS_DEBUG n
+      '';
+      makeFlags = [ "LOADADDR=0x8000" ];
+      target = "uImage";
+      # TODO reenable once manual-config's config actually builds a .dtb and this is checked to be working
+      #DTB = true;
+    };
     gcc = {
       arch = "armv5te";
     };
+  };
+
+  sheevaplug = {
+    linux-kernel = {
+      name = "sheevaplug";
+
+      baseConfig = "multi_v5_defconfig";
+      autoModules = false;
+      extraConfig = ''
+        BLK_DEV_RAM y
+        BLK_DEV_INITRD y
+        BLK_DEV_CRYPTOLOOP m
+        BLK_DEV_DM m
+        DM_CRYPT m
+        MD y
+        REISERFS_FS m
+        BTRFS_FS m
+        XFS_FS m
+        JFS_FS m
+        EXT4_FS m
+        USB_STORAGE_CYPRESS_ATACB m
+
+        # mv cesa requires this sw fallback, for mv-sha1
+        CRYPTO_SHA1 y
+        # Fast crypto
+        CRYPTO_TWOFISH y
+        CRYPTO_TWOFISH_COMMON y
+        CRYPTO_BLOWFISH y
+        CRYPTO_BLOWFISH_COMMON y
+
+        IP_PNP y
+        IP_PNP_DHCP y
+        NFS_FS y
+        ROOT_NFS y
+        TUN m
+        NFS_V4 y
+        NFS_V4_1 y
+        NFS_FSCACHE y
+        NFSD m
+        NFSD_V2_ACL y
+        NFSD_V3 y
+        NFSD_V3_ACL y
+        NFSD_V4 y
+        NETFILTER y
+        IP_NF_IPTABLES y
+        IP_NF_FILTER y
+        IP_NF_MATCH_ADDRTYPE y
+        IP_NF_TARGET_LOG y
+        IP_NF_MANGLE y
+        IPV6 m
+        VLAN_8021Q m
+
+        CIFS y
+        CIFS_XATTR y
+        CIFS_POSIX y
+        CIFS_FSCACHE y
+        CIFS_ACL y
+
+        WATCHDOG y
+        WATCHDOG_CORE y
+        ORION_WATCHDOG m
+
+        ZRAM m
+        NETCONSOLE m
+
+        # Disable OABI to have seccomp_filter (required for systemd)
+        # https://github.com/raspberrypi/firmware/issues/651
+        OABI_COMPAT n
+
+        # Fail to build
+        DRM n
+        SCSI_ADVANSYS n
+        USB_ISP1362_HCD n
+        SND_SOC n
+        SND_ALI5451 n
+        FB_SAVAGE n
+        SCSI_NSP32 n
+        ATA_SFF n
+        SUNGEM n
+        IRDA n
+        ATM_HE n
+        SCSI_ACARD n
+        BLK_DEV_CMD640_ENHANCED n
+
+        FUSE_FS m
+
+        # systemd uses cgroups
+        CGROUPS y
+
+        # Latencytop
+        LATENCYTOP y
 
-    kernelMajor = "2.6";
-    kernelBaseConfig = "multi_v5_defconfig";
-    kernelArch = "arm";
-    kernelAutoModules = false;
-    kernelExtraConfig =
-      ''
         # Ubi for the mtd
         MTD_UBI y
         UBIFS_FS y
@@ -61,139 +161,36 @@ rec {
         UBIFS_FS_LZO y
         UBIFS_FS_ZLIB y
         UBIFS_FS_DEBUG n
-      '';
-    kernelMakeFlags = [ "LOADADDR=0x8000" ];
-    kernelTarget = "uImage";
-    # TODO reenable once manual-config's config actually builds a .dtb and this is checked to be working
-    #kernelDTB = true;
-  };
 
-  sheevaplug = {
-    name = "sheevaplug";
-    kernelMajor = "2.6";
-    kernelBaseConfig = "multi_v5_defconfig";
-    kernelArch = "arm";
-    kernelAutoModules = false;
-    kernelExtraConfig = ''
-      BLK_DEV_RAM y
-      BLK_DEV_INITRD y
-      BLK_DEV_CRYPTOLOOP m
-      BLK_DEV_DM m
-      DM_CRYPT m
-      MD y
-      REISERFS_FS m
-      BTRFS_FS m
-      XFS_FS m
-      JFS_FS m
-      EXT4_FS m
-      USB_STORAGE_CYPRESS_ATACB m
-
-      # mv cesa requires this sw fallback, for mv-sha1
-      CRYPTO_SHA1 y
-      # Fast crypto
-      CRYPTO_TWOFISH y
-      CRYPTO_TWOFISH_COMMON y
-      CRYPTO_BLOWFISH y
-      CRYPTO_BLOWFISH_COMMON y
-
-      IP_PNP y
-      IP_PNP_DHCP y
-      NFS_FS y
-      ROOT_NFS y
-      TUN m
-      NFS_V4 y
-      NFS_V4_1 y
-      NFS_FSCACHE y
-      NFSD m
-      NFSD_V2_ACL y
-      NFSD_V3 y
-      NFSD_V3_ACL y
-      NFSD_V4 y
-      NETFILTER y
-      IP_NF_IPTABLES y
-      IP_NF_FILTER y
-      IP_NF_MATCH_ADDRTYPE y
-      IP_NF_TARGET_LOG y
-      IP_NF_MANGLE y
-      IPV6 m
-      VLAN_8021Q m
-
-      CIFS y
-      CIFS_XATTR y
-      CIFS_POSIX y
-      CIFS_FSCACHE y
-      CIFS_ACL y
-
-      WATCHDOG y
-      WATCHDOG_CORE y
-      ORION_WATCHDOG m
-
-      ZRAM m
-      NETCONSOLE m
-
-      # Disable OABI to have seccomp_filter (required for systemd)
-      # https://github.com/raspberrypi/firmware/issues/651
-      OABI_COMPAT n
-
-      # Fail to build
-      DRM n
-      SCSI_ADVANSYS n
-      USB_ISP1362_HCD n
-      SND_SOC n
-      SND_ALI5451 n
-      FB_SAVAGE n
-      SCSI_NSP32 n
-      ATA_SFF n
-      SUNGEM n
-      IRDA n
-      ATM_HE n
-      SCSI_ACARD n
-      BLK_DEV_CMD640_ENHANCED n
-
-      FUSE_FS m
-
-      # systemd uses cgroups
-      CGROUPS y
-
-      # Latencytop
-      LATENCYTOP y
-
-      # Ubi for the mtd
-      MTD_UBI y
-      UBIFS_FS y
-      UBIFS_FS_XATTR y
-      UBIFS_FS_ADVANCED_COMPR y
-      UBIFS_FS_LZO y
-      UBIFS_FS_ZLIB y
-      UBIFS_FS_DEBUG n
-
-      # Kdb, for kernel troubles
-      KGDB y
-      KGDB_SERIAL_CONSOLE y
-      KGDB_KDB y
-    '';
-    kernelMakeFlags = [ "LOADADDR=0x0200000" ];
-    kernelTarget = "uImage";
-    kernelDTB = true; # Beyond 3.10
+        # Kdb, for kernel troubles
+        KGDB y
+        KGDB_SERIAL_CONSOLE y
+        KGDB_KDB y
+      '';
+      makeFlags = [ "LOADADDR=0x0200000" ];
+      target = "uImage";
+      DTB = true; # Beyond 3.10
+    };
     gcc = {
       arch = "armv5te";
     };
   };
 
   raspberrypi = {
-    name = "raspberrypi";
-    kernelMajor = "2.6";
-    kernelBaseConfig = "bcm2835_defconfig";
-    kernelDTB = true;
-    kernelArch = "arm";
-    kernelAutoModules = true;
-    kernelPreferBuiltin = true;
-    kernelExtraConfig = ''
-      # Disable OABI to have seccomp_filter (required for systemd)
-      # https://github.com/raspberrypi/firmware/issues/651
-      OABI_COMPAT n
-    '';
-    kernelTarget = "zImage";
+    linux-kernel = {
+      name = "raspberrypi";
+
+      baseConfig = "bcm2835_defconfig";
+      DTB = true;
+      autoModules = true;
+      preferBuiltin = true;
+      extraConfig = ''
+        # Disable OABI to have seccomp_filter (required for systemd)
+        # https://github.com/raspberrypi/firmware/issues/651
+        OABI_COMPAT n
+      '';
+      target = "zImage";
+    };
     gcc = {
       arch = "armv6";
       fpu = "vfp";
@@ -203,7 +200,40 @@ rec {
   # Legacy attribute, for compatibility with existing configs only.
   raspberrypi2 = armv7l-hf-multiplatform;
 
-  scaleway-c1 = armv7l-hf-multiplatform // {
+  zero-gravitas = {
+    linux-kernel = {
+      name = "zero-gravitas";
+
+      baseConfig = "zero-gravitas_defconfig";
+      # Target verified by checking /boot on reMarkable 1 device
+      target = "zImage";
+      autoModules = false;
+      DTB = true;
+    };
+    gcc = {
+      fpu = "neon";
+      cpu = "cortex-a9";
+    };
+  };
+
+  zero-sugar = {
+    linux-kernel = {
+      name = "zero-sugar";
+
+      baseConfig = "zero-sugar_defconfig";
+      DTB = true;
+      autoModules = false;
+      preferBuiltin = true;
+      target = "zImage";
+    };
+    gcc = {
+      cpu = "cortex-a7";
+      fpu = "neon-vfpv4";
+      float-abi = "hard";
+    };
+  };
+
+  scaleway-c1 = lib.recursiveUpdate armv7l-hf-multiplatform {
     gcc = {
       cpu = "cortex-a9";
       fpu = "vfpv3";
@@ -211,13 +241,11 @@ rec {
   };
 
   utilite = {
-    name = "utilite";
-    kernelMajor = "2.6";
-    kernelBaseConfig = "multi_v7_defconfig";
-    kernelArch = "arm";
-    kernelAutoModules = false;
-    kernelExtraConfig =
-      ''
+    linux-kernel = {
+      name = "utilite";
+      maseConfig = "multi_v7_defconfig";
+      autoModules = false;
+      extraConfig = ''
         # Ubi for the mtd
         MTD_UBI y
         UBIFS_FS y
@@ -227,35 +255,37 @@ rec {
         UBIFS_FS_ZLIB y
         UBIFS_FS_DEBUG n
       '';
-    kernelMakeFlags = [ "LOADADDR=0x10800000" ];
-    kernelTarget = "uImage";
-    kernelDTB = true;
+      makeFlags = [ "LOADADDR=0x10800000" ];
+      target = "uImage";
+      DTB = true;
+    };
     gcc = {
       cpu = "cortex-a9";
       fpu = "neon";
     };
   };
 
-  guruplug = sheevaplug // {
+  guruplug = lib.recursiveUpdate sheevaplug {
     # Define `CONFIG_MACH_GURUPLUG' (see
     # <http://kerneltrap.org/mailarchive/git-commits-head/2010/5/19/33618>)
     # and other GuruPlug-specific things.  Requires the `guruplug-defconfig'
     # patch.
-
-    kernelBaseConfig = "guruplug_defconfig";
+    linux-kernel.baseConfig = "guruplug_defconfig";
   };
 
-  beaglebone = armv7l-hf-multiplatform // {
-    name = "beaglebone";
-    kernelBaseConfig = "bb.org_defconfig";
-    kernelAutoModules = false;
-    kernelExtraConfig = ""; # TBD kernel config
-    kernelTarget = "zImage";
+  beaglebone = lib.recursiveUpdate armv7l-hf-multiplatform {
+    linux-kernel = {
+      name = "beaglebone";
+      baseConfig = "bb.org_defconfig";
+      autoModules = false;
+      extraConfig = ""; # TBD kernel config
+      target = "zImage";
+    };
   };
 
   # https://developer.android.com/ndk/guides/abis#v7a
-  armv7a-android =  {
-    name = "armeabi-v7a";
+  armv7a-android = {
+    linux-kernel.name = "armeabi-v7a";
     gcc = {
       arch = "armv7-a";
       float-abi = "softfp";
@@ -264,30 +294,29 @@ rec {
   };
 
   armv7l-hf-multiplatform = {
-    name = "armv7l-hf-multiplatform";
-    kernelMajor = "2.6"; # Using "2.6" enables 2.6 kernel syscalls in glibc.
-    kernelBaseConfig = "multi_v7_defconfig";
-    kernelArch = "arm";
-    kernelDTB = true;
-    kernelAutoModules = true;
-    kernelPreferBuiltin = true;
-    kernelTarget = "zImage";
-    kernelExtraConfig = ''
-      # Serial port for Raspberry Pi 3. Upstream forgot to add it to the ARMv7 defconfig.
-      SERIAL_8250_BCM2835AUX y
-      SERIAL_8250_EXTENDED y
-      SERIAL_8250_SHARE_IRQ y
-
-      # Fix broken sunxi-sid nvmem driver.
-      TI_CPTS y
-
-      # Hangs ODROID-XU4
-      ARM_BIG_LITTLE_CPUIDLE n
-
-      # Disable OABI to have seccomp_filter (required for systemd)
-      # https://github.com/raspberrypi/firmware/issues/651
-      OABI_COMPAT n
-    '';
+    linux-kernel = {
+      name = "armv7l-hf-multiplatform";
+      Major = "2.6"; # Using "2.6" enables 2.6 kernel syscalls in glibc.
+      baseConfig = "multi_v7_defconfig";
+      DTB = true;
+      autoModules = true;
+      preferBuiltin = true;
+      target = "zImage";
+      extraConfig = ''
+        # Serial port for Raspberry Pi 3. Wasn't included in ARMv7 defconfig
+        # until 4.17.
+        SERIAL_8250_BCM2835AUX y
+        SERIAL_8250_EXTENDED y
+        SERIAL_8250_SHARE_IRQ y
+
+        # Hangs ODROID-XU4
+        ARM_BIG_LITTLE_CPUIDLE n
+
+        # Disable OABI to have seccomp_filter (required for systemd)
+        # https://github.com/raspberrypi/firmware/issues/651
+        OABI_COMPAT n
+      '';
+    };
     gcc = {
       # Some table about fpu flags:
       # http://community.arm.com/servlet/JiveServlet/showImage/38-1981-3827/blogentry-103749-004812900+1365712953_thumb.png
@@ -312,48 +341,55 @@ rec {
   };
 
   aarch64-multiplatform = {
-    name = "aarch64-multiplatform";
-    kernelMajor = "2.6"; # Using "2.6" enables 2.6 kernel syscalls in glibc.
-    kernelBaseConfig = "defconfig";
-    kernelArch = "arm64";
-    kernelDTB = true;
-    kernelAutoModules = true;
-    kernelPreferBuiltin = true;
-    kernelExtraConfig = ''
-      # Raspberry Pi 3 stuff. Not needed for kernels >= 4.10.
-      ARCH_BCM2835 y
-      BCM2835_MBOX y
-      BCM2835_WDT y
-      RASPBERRYPI_FIRMWARE y
-      RASPBERRYPI_POWER y
-      SERIAL_8250_BCM2835AUX y
-      SERIAL_8250_EXTENDED y
-      SERIAL_8250_SHARE_IRQ y
-
-      # Cavium ThunderX stuff.
-      PCI_HOST_THUNDER_ECAM y
-
-      # Nvidia Tegra stuff.
-      PCI_TEGRA y
-
-      # The default (=y) forces us to have the XHCI firmware available in initrd,
-      # which our initrd builder can't currently do easily.
-      USB_XHCI_TEGRA m
-    '';
-    kernelTarget = "Image";
+    linux-kernel = {
+      name = "aarch64-multiplatform";
+      baseConfig = "defconfig";
+      DTB = true;
+      autoModules = true;
+      preferBuiltin = true;
+      extraConfig = ''
+        # Raspberry Pi 3 stuff. Not needed for   s >= 4.10.
+        ARCH_BCM2835 y
+        BCM2835_MBOX y
+        BCM2835_WDT y
+        RASPBERRYPI_FIRMWARE y
+        RASPBERRYPI_POWER y
+        SERIAL_8250_BCM2835AUX y
+        SERIAL_8250_EXTENDED y
+        SERIAL_8250_SHARE_IRQ y
+
+        # Cavium ThunderX stuff.
+        PCI_HOST_THUNDER_ECAM y
+
+        # Nvidia Tegra stuff.
+        PCI_TEGRA y
+
+        # The default (=y) forces us to have the XHCI firmware available in initrd,
+        # which our initrd builder can't currently do easily.
+        USB_XHCI_TEGRA m
+      '';
+      target = "Image";
+    };
     gcc = {
       arch = "armv8-a";
     };
   };
 
+  apple-m1 = {
+    gcc = {
+      arch = "armv8.3-a+crypto+sha2+aes+crc+fp16+lse+simd+ras+rdm+rcpc";
+      cpu = "apple-a13";
+    };
+  };
+
   ##
   ## MIPS
   ##
 
   ben_nanonote = {
-    name = "ben_nanonote";
-    kernelMajor = "2.6";
-    kernelArch = "mips";
+    linux-kernel = {
+      name = "ben_nanonote";
+    };
     gcc = {
       arch = "mips32";
       float = "soft";
@@ -361,76 +397,76 @@ rec {
   };
 
   fuloong2f_n32 = {
-    name = "fuloong2f_n32";
-    kernelMajor = "2.6";
-    kernelBaseConfig = "lemote2f_defconfig";
-    kernelArch = "mips";
-    kernelAutoModules = false;
-    kernelExtraConfig = ''
-      MIGRATION n
-      COMPACTION n
-
-      # nixos mounts some cgroup
-      CGROUPS y
-
-      BLK_DEV_RAM y
-      BLK_DEV_INITRD y
-      BLK_DEV_CRYPTOLOOP m
-      BLK_DEV_DM m
-      DM_CRYPT m
-      MD y
-      REISERFS_FS m
-      EXT4_FS m
-      USB_STORAGE_CYPRESS_ATACB m
-
-      IP_PNP y
-      IP_PNP_DHCP y
-      IP_PNP_BOOTP y
-      NFS_FS y
-      ROOT_NFS y
-      TUN m
-      NFS_V4 y
-      NFS_V4_1 y
-      NFS_FSCACHE y
-      NFSD m
-      NFSD_V2_ACL y
-      NFSD_V3 y
-      NFSD_V3_ACL y
-      NFSD_V4 y
-
-      # Fail to build
-      DRM n
-      SCSI_ADVANSYS n
-      USB_ISP1362_HCD n
-      SND_SOC n
-      SND_ALI5451 n
-      FB_SAVAGE n
-      SCSI_NSP32 n
-      ATA_SFF n
-      SUNGEM n
-      IRDA n
-      ATM_HE n
-      SCSI_ACARD n
-      BLK_DEV_CMD640_ENHANCED n
-
-      FUSE_FS m
-
-      # Needed for udev >= 150
-      SYSFS_DEPRECATED_V2 n
-
-      VGA_CONSOLE n
-      VT_HW_CONSOLE_BINDING y
-      SERIAL_8250_CONSOLE y
-      FRAMEBUFFER_CONSOLE y
-      EXT2_FS y
-      EXT3_FS y
-      REISERFS_FS y
-      MAGIC_SYSRQ y
-
-      # The kernel doesn't boot at all, with FTRACE
-      FTRACE n
-    '';
-    kernelTarget = "vmlinux";
+    linux-kernel = {
+      name = "fuloong2f_n32";
+      baseConfig = "lemote2f_defconfig";
+      autoModules = false;
+      extraConfig = ''
+        MIGRATION n
+        COMPACTION n
+
+        # nixos mounts some cgroup
+        CGROUPS y
+
+        BLK_DEV_RAM y
+        BLK_DEV_INITRD y
+        BLK_DEV_CRYPTOLOOP m
+        BLK_DEV_DM m
+        DM_CRYPT m
+        MD y
+        REISERFS_FS m
+        EXT4_FS m
+        USB_STORAGE_CYPRESS_ATACB m
+
+        IP_PNP y
+        IP_PNP_DHCP y
+        IP_PNP_BOOTP y
+        NFS_FS y
+        ROOT_NFS y
+        TUN m
+        NFS_V4 y
+        NFS_V4_1 y
+        NFS_FSCACHE y
+        NFSD m
+        NFSD_V2_ACL y
+        NFSD_V3 y
+        NFSD_V3_ACL y
+        NFSD_V4 y
+
+        # Fail to build
+        DRM n
+        SCSI_ADVANSYS n
+        USB_ISP1362_HCD n
+        SND_SOC n
+        SND_ALI5451 n
+        FB_SAVAGE n
+        SCSI_NSP32 n
+        ATA_SFF n
+        SUNGEM n
+        IRDA n
+        ATM_HE n
+        SCSI_ACARD n
+        BLK_DEV_CMD640_ENHANCED n
+
+        FUSE_FS m
+
+        # Needed for udev >= 150
+        SYSFS_DEPRECATED_V2 n
+
+        VGA_CONSOLE n
+        VT_HW_CONSOLE_BINDING y
+        SERIAL_8250_CONSOLE y
+        FRAMEBUFFER_CONSOLE y
+        EXT2_FS y
+        EXT3_FS y
+        REISERFS_FS y
+        MAGIC_SYSRQ y
+
+        # The kernel doesn't boot at all, with FTRACE
+        FTRACE n
+      '';
+      target = "vmlinux";
+    };
     gcc = {
       arch = "loongson2f";
       float = "hard";
@@ -442,30 +478,40 @@ rec {
   ## Other
   ##
 
-  riscv-multiplatform = bits: {
-    name = "riscv-multiplatform";
-    kernelArch = "riscv";
-    bfdEmulation = "elf${bits}lriscv";
-    kernelTarget = "vmlinux";
-    kernelAutoModules = true;
-    kernelBaseConfig = "defconfig";
-    kernelExtraConfig = ''
-      FTRACE n
-      SERIAL_OF_PLATFORM y
-    '';
+  riscv-multiplatform = {
+    linux-kernel = {
+      name = "riscv-multiplatform";
+      target = "Image";
+      autoModules = true;
+      baseConfig = "defconfig";
+      DTB = true;
+      extraConfig = ''
+        SERIAL_OF_PLATFORM y
+      '';
+    };
   };
 
-  selectBySystem = system: {
-      i486-linux = pc32;
-      i586-linux = pc32;
-      i686-linux = pc32;
-      x86_64-linux = pc64;
-      armv5tel-linux = sheevaplug;
-      armv6l-linux = raspberrypi;
-      armv7a-linux = armv7l-hf-multiplatform;
-      armv7l-linux = armv7l-hf-multiplatform;
-      aarch64-linux = aarch64-multiplatform;
-      mipsel-linux = fuloong2f_n32;
-      powerpc64le-linux = powernv;
-    }.${system} or pcBase;
+  select = platform:
+    # x86
+    /**/ if platform.isx86 then pc
+
+    # ARM
+    else if platform.isAarch32 then let
+      version = platform.parsed.cpu.version or null;
+      in     if version == null then pc
+        else if lib.versionOlder version "6" then sheevaplug
+        else if lib.versionOlder version "7" then raspberrypi
+        else armv7l-hf-multiplatform
+
+    else if platform.isAarch64 then
+      if platform.isDarwin then apple-m1
+      else aarch64-multiplatform
+
+    else if platform.isRiscV then riscv-multiplatform
+
+    else if platform.parsed.cpu == lib.systems.parse.cpuTypes.mipsel then fuloong2f_n32
+
+    else if platform.parsed.cpu == lib.systems.parse.cpuTypes.powerpc64le then powernv
+
+    else pc;
 }