about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAdam Joseph <adam@westernsemico.com>2022-02-20 20:32:52 -0800
committerAdam Joseph <adam@westernsemico.com>2022-03-10 20:30:16 -0800
commit12371a51e647a00b90fe250837f056642125c095 (patch)
tree7e46578a84ceb08b250e61be1516e3478c79b511
parentb77a575dc8f825eb82d6a916fe01fe953d93033e (diff)
downloadnixlib-12371a51e647a00b90fe250837f056642125c095.tar
nixlib-12371a51e647a00b90fe250837f056642125c095.tar.gz
nixlib-12371a51e647a00b90fe250837f056642125c095.tar.bz2
nixlib-12371a51e647a00b90fe250837f056642125c095.tar.lz
nixlib-12371a51e647a00b90fe250837f056642125c095.tar.xz
nixlib-12371a51e647a00b90fe250837f056642125c095.tar.zst
nixlib-12371a51e647a00b90fe250837f056642125c095.zip
lib/systems: add mips64el definitions
MIPS has a large space of {architecture,abi,endianness}; this commit
adds all of them to lib/systems/platforms.nix so we can be done with
it.

Currently lib/systems/inspect.nix has a single "isMips" predicate,
which is a bit ambiguous now that we will have both mips32 and mips64
support, with the latter having two ABIs.  Let's add four new
predicates (isMips32, isMips64, isMips64n32, and isMips64n64) and
treat the now-ambiguous isMips as deprecated in favor of the
more-specific predicates.  These predicates are used mainly for
enabling/disabling target-specific workarounds, and it is extremely
rare that a platform-specific workaround is needed, and both mips32
and mips64 need exactly the same workaround.

The separate predicates (isMips64n32 and isMips64n64) for ABI
distinctions are, unfortunately, useful.  Boost's user-scheduled
threading (used by nix) does does not currently supports mips64n32,
which is a very desirable ABI on routers since they rarely have
more than 2**32 bytes of DRAM.
-rw-r--r--lib/systems/default.nix3
-rw-r--r--lib/systems/doubles.nix8
-rw-r--r--lib/systems/examples.nix4
-rw-r--r--lib/systems/inspect.nix6
-rw-r--r--lib/systems/parse.nix7
-rw-r--r--lib/systems/platforms.nix49
-rw-r--r--lib/tests/systems.nix4
-rw-r--r--pkgs/stdenv/default.nix1
-rw-r--r--pkgs/stdenv/linux/make-bootstrap-tools-cross.nix2
-rw-r--r--pkgs/top-level/stage.nix44
10 files changed, 104 insertions, 24 deletions
diff --git a/lib/systems/default.nix b/lib/systems/default.nix
index 529eeb6514b9..7ddd5b8a5812 100644
--- a/lib/systems/default.nix
+++ b/lib/systems/default.nix
@@ -105,7 +105,8 @@ rec {
         else if final.isAarch64 then "arm64"
         else if final.isx86_32 then "i386"
         else if final.isx86_64 then "x86_64"
-        else if final.isMips then "mips"
+        else if final.isMips32 then "mips"
+        else if final.isMips64 then "mips"    # linux kernel does not distinguish mips32/mips64
         else if final.isPower then "powerpc"
         else if final.isRiscV then "riscv"
         else if final.isS390 then "s390"
diff --git a/lib/systems/doubles.nix b/lib/systems/doubles.nix
index 00e57339a310..27cdaf6a7233 100644
--- a/lib/systems/doubles.nix
+++ b/lib/systems/doubles.nix
@@ -26,7 +26,7 @@ let
 
     # Linux
     "aarch64-linux" "armv5tel-linux" "armv6l-linux" "armv7a-linux"
-    "armv7l-linux" "i686-linux" "m68k-linux" "mipsel-linux"
+    "armv7l-linux" "i686-linux" "m68k-linux" "mipsel-linux" "mips64el-linux"
     "powerpc64-linux" "powerpc64le-linux" "riscv32-linux"
     "riscv64-linux" "s390-linux" "s390x-linux" "x86_64-linux"
 
@@ -87,7 +87,11 @@ in {
   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; });
+  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; })
+                  ++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnuabin32; })
+                  ++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnuabi64; });
   illumos       = filterDoubles predicates.isSunOS;
   linux         = filterDoubles predicates.isLinux;
   netbsd        = filterDoubles predicates.isNetBSD;
diff --git a/lib/systems/examples.nix b/lib/systems/examples.nix
index 9c0c91617e8a..9cac909093d6 100644
--- a/lib/systems/examples.nix
+++ b/lib/systems/examples.nix
@@ -93,6 +93,10 @@ rec {
     config = "mipsel-unknown-linux-gnu";
   } // platforms.fuloong2f_n32;
 
+  mips64el-linux-gnuabin32      = platforms.mips64el-linux-gnuabin32;
+  mips64el-linux-gnuabi64       = platforms.mips64el-linux-gnuabi64  // { rustc.config = "mips64el-unknown-linux-gnuabi64"; };
+  mips64el-qemu-linux-gnuabi64  = platforms.mips64el-qemu-linux-gnuabi64;
+
   muslpi = raspberryPi // {
     config = "armv6l-unknown-linux-musleabihf";
   };
diff --git a/lib/systems/inspect.nix b/lib/systems/inspect.nix
index 718954e0839a..89cac575c67d 100644
--- a/lib/systems/inspect.nix
+++ b/lib/systems/inspect.nix
@@ -17,6 +17,10 @@ rec {
     isAarch32      = { cpu = { family = "arm"; bits = 32; }; };
     isAarch64      = { cpu = { family = "arm"; bits = 64; }; };
     isMips         = { cpu = { family = "mips"; }; };
+    isMips32       = { cpu = { family = "mips"; bits = 32; }; };
+    isMips64       = { cpu = { family = "mips"; bits = 64; }; };
+    isMips64n32    = { cpu = { family = "mips"; bits = 64; }; abi = { abi = "n32"; }; };
+    isMips64n64    = { cpu = { family = "mips"; bits = 64; }; abi = { abi = "64";  }; };
     isMmix         = { cpu = { family = "mmix"; }; };
     isRiscV        = { cpu = { family = "riscv"; }; };
     isSparc        = { cpu = { family = "sparc"; }; };
@@ -57,7 +61,7 @@ rec {
 
     isAndroid      = [ { abi = abis.android; } { abi = abis.androideabi; } ];
     isGnu          = with abis; map (a: { abi = a; }) [ gnuabi64 gnu gnueabi gnueabihf ];
-    isMusl         = with abis; map (a: { abi = a; }) [ musl musleabi musleabihf ];
+    isMusl         = with abis; map (a: { abi = a; }) [ musl musleabi musleabihf muslabin32 muslabi64 ];
     isUClibc       = with abis; map (a: { abi = a; }) [ uclibc uclibceabi uclibceabihf ];
 
     isEfi          = map (family: { cpu.family = family; })
diff --git a/lib/systems/parse.nix b/lib/systems/parse.nix
index f0e87c30e473..3ceddbb599b9 100644
--- a/lib/systems/parse.nix
+++ b/lib/systems/parse.nix
@@ -359,6 +359,13 @@ rec {
       ];
     };
     gnuabi64     = { abi = "64"; };
+    muslabi64    = { abi = "64"; };
+
+    # NOTE: abi=n32 requires a 64-bit MIPS chip!  That is not a typo.
+    # It is basically the 64-bit abi with 32-bit pointers.  Details:
+    # https://www.linux-mips.org/pub/linux/mips/doc/ABI/MIPS-N32-ABI-Handbook.pdf
+    gnuabin32    = { abi = "n32"; };
+    muslabin32   = { abi = "n32"; };
 
     musleabi     = { float = "soft"; };
     musleabihf   = { float = "hard"; };
diff --git a/lib/systems/platforms.nix b/lib/systems/platforms.nix
index b2a8dbedef4f..9bfbb87c08ce 100644
--- a/lib/systems/platforms.nix
+++ b/lib/systems/platforms.nix
@@ -482,6 +482,55 @@ rec {
     };
   };
 
+  # MIPS ABI table transcribed from here: https://wiki.debian.org/Multiarch/Tuples
+
+  # can execute on 32bit chip
+  mips-linux-gnu                = { config = "mips-linux-gnu";                gcc = { arch = "mips32r2"; abi = "o32"; float = "hard"; }; };
+  mipsel-linux-gnu              = { config = "mipsel-linux-gnu";              gcc = { arch = "mips32r2"; abi = "o32"; float = "hard"; }; };
+  mipsisa32r6-linux-gnu         = { config = "mipsisa32r6-linux-gnu";         gcc = { arch = "mips32r6"; abi = "o32"; float = "hard"; }; };
+  mipsisa32r6el-linux-gnu       = { config = "mipsisa32r6el-linux-gnu";       gcc = { arch = "mips32r6"; abi = "o32"; float = "hard"; }; };
+
+  # require 64bit chip (for more registers, 64-bit floating point, 64-bit "long long") but use 32bit pointers
+  mips64-linux-gnuabin32        = { config = "mips64-linux-gnuabin32";        gcc = { arch = "mips64r2"; abi = "n32"; float = "hard"; }; };
+  mips64el-linux-gnuabin32      = { config = "mips64el-linux-gnuabin32";      gcc = { arch = "mips64r2"; abi = "n32"; float = "hard"; }; };
+  mipsisa64r6-linux-gnuabin32   = { config = "mipsisa64r6-linux-gnuabin32";   gcc = { arch = "mips64r6"; abi = "n32"; float = "hard"; }; };
+  mipsisa64r6el-linux-gnuabin32 = { config = "mipsisa64r6el-linux-gnuabin32"; gcc = { arch = "mips64r6"; abi = "n32"; float = "hard"; }; };
+
+  # 64bit pointers
+  mips64-linux-gnuabi64         = { config = "mips64-linux-gnuabi64";         gcc = { arch = "mips64r2"; abi =  "64"; float = "hard"; }; };
+  mips64el-linux-gnuabi64       = { config = "mips64el-linux-gnuabi64";       gcc = { arch = "mips64r2"; abi =  "64"; float = "hard"; }; };
+  mipsisa64r6-linux-gnuabi64    = { config = "mipsisa64r6-linux-gnuabi64";    gcc = { arch = "mips64r6"; abi =  "64"; float = "hard"; }; };
+  mipsisa64r6el-linux-gnuabi64  = { config = "mipsisa64r6el-linux-gnuabi64";  gcc = { arch = "mips64r6"; abi =  "64"; float = "hard"; }; };
+
+  # based on:
+  #   https://www.mail-archive.com/qemu-discuss@nongnu.org/msg05179.html
+  #   https://gmplib.org/~tege/qemu.html#mips64-debian
+  mips64el-qemu-linux-gnuabi64 = mips64el-linux-gnuabi64 // {
+    linux-kernel = {
+      name = "mips64el";
+      baseConfig = "64r2el_defconfig";
+      target = "vmlinuz";
+      autoModules = false;
+      DTB = true;
+      # for qemu 9p passthrough filesystem
+      extraConfig = ''
+        MIPS_MALTA y
+        PAGE_SIZE_4KB y
+        CPU_LITTLE_ENDIAN y
+        CPU_MIPS64_R2 y
+        64BIT y
+        CPU_MIPS64_R2 y
+
+        NET_9P y
+        NET_9P_VIRTIO y
+        9P_FS y
+        9P_FS_POSIX_ACL y
+        PCI y
+        VIRTIO_PCI y
+      '';
+    };
+  };
+
   ##
   ## Other
   ##
diff --git a/lib/tests/systems.nix b/lib/tests/systems.nix
index 2646e792682b..c88adbf4651a 100644
--- a/lib/tests/systems.nix
+++ b/lib/tests/systems.nix
@@ -17,7 +17,7 @@ with lib.systems.doubles; lib.runTests {
 
   testarm = mseteq arm [ "armv5tel-linux" "armv6l-linux" "armv6l-netbsd" "armv6l-none" "armv7a-linux" "armv7a-netbsd" "armv7l-linux" "armv7l-netbsd" "arm-none" "armv7a-darwin" ];
   testi686 = mseteq i686 [ "i686-linux" "i686-freebsd" "i686-genode" "i686-netbsd" "i686-openbsd" "i686-cygwin" "i686-windows" "i686-none" "i686-darwin" ];
-  testmips = mseteq mips [ "mipsel-linux" "mipsel-netbsd" ];
+  testmips = mseteq mips [ "mips64el-linux" "mipsel-linux" "mipsel-netbsd" ];
   testmmix = mseteq mmix [ "mmix-mmixware" ];
   testx86_64 = mseteq x86_64 [ "x86_64-linux" "x86_64-darwin" "x86_64-freebsd" "x86_64-genode" "x86_64-redox" "x86_64-openbsd" "x86_64-netbsd" "x86_64-cygwin" "x86_64-solaris" "x86_64-windows" "x86_64-none" ];
 
@@ -28,7 +28,7 @@ with lib.systems.doubles; lib.runTests {
   testredox = mseteq redox [ "x86_64-redox" ];
   testgnu = mseteq gnu (linux /* ++ kfreebsd ++ ... */);
   testillumos = mseteq illumos [ "x86_64-solaris" ];
-  testlinux = mseteq linux [ "aarch64-linux" "armv5tel-linux" "armv6l-linux" "armv7a-linux" "armv7l-linux" "i686-linux" "mipsel-linux" "riscv32-linux" "riscv64-linux" "x86_64-linux" "powerpc64-linux" "powerpc64le-linux" "m68k-linux" "s390-linux" "s390x-linux" ];
+  testlinux = mseteq linux [ "aarch64-linux" "armv5tel-linux" "armv6l-linux" "armv7a-linux" "armv7l-linux" "i686-linux" "mips64el-linux" "mipsel-linux" "riscv32-linux" "riscv64-linux" "x86_64-linux" "powerpc64-linux" "powerpc64le-linux" "m68k-linux" "s390-linux" "s390x-linux" ];
   testnetbsd = mseteq netbsd [ "aarch64-netbsd" "armv6l-netbsd" "armv7a-netbsd" "armv7l-netbsd" "i686-netbsd" "m68k-netbsd" "mipsel-netbsd" "powerpc-netbsd" "riscv32-netbsd" "riscv64-netbsd" "x86_64-netbsd" ];
   testopenbsd = mseteq openbsd [ "i686-openbsd" "x86_64-openbsd" ];
   testwindows = mseteq windows [ "i686-cygwin" "x86_64-cygwin" "i686-windows" "x86_64-windows" ];
diff --git a/pkgs/stdenv/default.nix b/pkgs/stdenv/default.nix
index 0d328d98ba11..25a593c67437 100644
--- a/pkgs/stdenv/default.nix
+++ b/pkgs/stdenv/default.nix
@@ -53,6 +53,7 @@ in
     armv8m-linux = stagesLinux;
     aarch64-linux = stagesLinux;
     mipsel-linux = stagesLinux;
+    mips64el-linux = stagesLinux;
     powerpc-linux = /* stagesLinux */ stagesNative;
     powerpc64-linux = stagesLinux;
     powerpc64le-linux = stagesLinux;
diff --git a/pkgs/stdenv/linux/make-bootstrap-tools-cross.nix b/pkgs/stdenv/linux/make-bootstrap-tools-cross.nix
index d8ab96952b7f..a21f677f117c 100644
--- a/pkgs/stdenv/linux/make-bootstrap-tools-cross.nix
+++ b/pkgs/stdenv/linux/make-bootstrap-tools-cross.nix
@@ -17,6 +17,8 @@ in lib.mapAttrs (n: make) (with lib.systems.examples; {
   armv6l-musl  = muslpi;
   aarch64-musl = aarch64-multiplatform-musl;
   riscv64 = riscv64;
+  mips64el-linux-gnuabin32 = lib.systems.platforms.mips64el-linux-gnuabin32;
+  mips64el-linux-gnuabi64  = lib.systems.platforms.mips64el-linux-gnuabi64;
   powerpc64 = ppc64;
   powerpc64-musl = ppc64-musl;
   powerpc64le = powernv;
diff --git a/pkgs/top-level/stage.nix b/pkgs/top-level/stage.nix
index 9d34ddb3685f..8ca69315b542 100644
--- a/pkgs/top-level/stage.nix
+++ b/pkgs/top-level/stage.nix
@@ -64,6 +64,30 @@
 } @args:
 
 let
+  # This is a function from parsed platforms (like
+  # stdenv.hostPlatform.parsed) to parsed platforms.
+  makeStaticParsedPlatform = parsed:
+    # The following line guarantees that the output of this function
+    # is a well-formed platform with no missing fields.  It will be
+    # uncommented in a separate PR, in case it breaks the build.
+    #(x: lib.trivial.pipe x [ (x: builtins.removeAttrs x [ "_type" ]) lib.systems.parse.mkSystem ])
+      (parsed // {
+        abi = {
+          gnu = lib.systems.parse.abis.musl;
+          gnueabi = lib.systems.parse.abis.musleabi;
+          gnueabihf = lib.systems.parse.abis.musleabihf;
+          musleabi = lib.systems.parse.abis.musleabi;
+          musleabihf = lib.systems.parse.abis.musleabihf;
+          gnuabin32 = lib.systems.parse.abis.muslabin32;
+          gnuabi64 = lib.systems.parse.abis.muslabi64;
+          # The following two entries ensure that this function is idempotent.
+          muslabin32 = lib.systems.parse.abis.muslabin32;
+          muslabi64 = lib.systems.parse.abis.muslabi64;
+        }.${parsed.abi.name}
+          or lib.systems.parse.abis.musl;
+      });
+
+
   stdenvAdapters = self: super:
     let
       res = import ../stdenv/adapters.nix {
@@ -188,14 +212,7 @@ let
       })] ++ overlays;
       ${if stdenv.hostPlatform == stdenv.buildPlatform
         then "localSystem" else "crossSystem"} = {
-        parsed = stdenv.hostPlatform.parsed // {
-          abi = {
-            gnu = lib.systems.parse.abis.musl;
-            gnueabi = lib.systems.parse.abis.musleabi;
-            gnueabihf = lib.systems.parse.abis.musleabihf;
-          }.${stdenv.hostPlatform.parsed.abi.name}
-            or lib.systems.parse.abis.musl;
-        };
+        parsed = makeStaticParsedPlatform stdenv.hostPlatform.parsed;
       };
     } else throw "Musl libc only supports Linux systems.";
 
@@ -239,16 +256,7 @@ let
     } // lib.optionalAttrs stdenv.hostPlatform.isLinux {
       crossSystem = {
         isStatic = true;
-        parsed = stdenv.hostPlatform.parsed // {
-          abi = {
-            gnu = lib.systems.parse.abis.musl;
-            gnueabi = lib.systems.parse.abis.musleabi;
-            gnueabihf = lib.systems.parse.abis.musleabihf;
-            musleabi = lib.systems.parse.abis.musleabi;
-            musleabihf = lib.systems.parse.abis.musleabihf;
-          }.${stdenv.hostPlatform.parsed.abi.name}
-            or lib.systems.parse.abis.musl;
-        };
+        parsed = makeStaticParsedPlatform stdenv.hostPlatform.parsed;
       } // lib.optionalAttrs (stdenv.hostPlatform.system == "powerpc64-linux") {
         gcc.abi = "elfv2";
       };