From 36b227de10ed951ac1d253cebde133ea7189671f Mon Sep 17 00:00:00 2001 From: Adam Joseph Date: Sun, 20 Feb 2022 20:32:52 -0800 Subject: [PATCH 1/5] mips64el support: first steps MIPS has an uncharacteristically-large space of permutations for {architecture,abi,endianness}; this patch 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. --- lib/systems/default.nix | 3 ++- lib/systems/doubles.nix | 4 ++-- lib/systems/examples.nix | 3 +++ lib/systems/inspect.nix | 4 ++++ lib/systems/parse.nix | 5 +++++ lib/systems/platforms.nix | 20 +++++++++++++++++++ lib/tests/systems.nix | 4 ++-- pkgs/stdenv/default.nix | 1 + .../linux/make-bootstrap-tools-cross.nix | 2 ++ 9 files changed, 41 insertions(+), 5 deletions(-) diff --git a/lib/systems/default.nix b/lib/systems/default.nix index 529eeb6514b9e..7ddd5b8a58129 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 00e57339a3102..a4e3096a2ecf0 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,7 @@ 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 9c0c91617e8a1..61735c7fa9621 100644 --- a/lib/systems/examples.nix +++ b/lib/systems/examples.nix @@ -93,6 +93,9 @@ rec { config = "mipsel-unknown-linux-gnu"; } // platforms.fuloong2f_n32; + mips64el-linux-gnuabin32 = platforms.mips64el-linux-gnuabin32; + mips64el-linux-gnuabi64 = platforms.mips64el-linux-gnuabi64; + muslpi = raspberryPi // { config = "armv6l-unknown-linux-musleabihf"; }; diff --git a/lib/systems/inspect.nix b/lib/systems/inspect.nix index 718954e0839a1..98caf9e789340 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"; }; abi = abis.gnuabin32; }; + isMips64n64 = { cpu = { family = "mips"; }; abi = abis.gnuabi64; }; isMmix = { cpu = { family = "mmix"; }; }; isRiscV = { cpu = { family = "riscv"; }; }; isSparc = { cpu = { family = "sparc"; }; }; diff --git a/lib/systems/parse.nix b/lib/systems/parse.nix index 8a88d8cfbe87a..53024d1558bd7 100644 --- a/lib/systems/parse.nix +++ b/lib/systems/parse.nix @@ -360,6 +360,11 @@ rec { }; gnuabi64 = { 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"; }; + musleabi = { float = "soft"; }; musleabihf = { float = "hard"; }; musl = {}; diff --git a/lib/systems/platforms.nix b/lib/systems/platforms.nix index b2a8dbedef4fc..8b7f6fa729a59 100644 --- a/lib/systems/platforms.nix +++ b/lib/systems/platforms.nix @@ -482,6 +482,26 @@ rec { }; }; + # MIPS ABI table transcribed from here: https://wiki.debian.org/Multiarch/Tuples + + # can execute on 32bit chip + mips-linux-gnuabin32 = { config = "mips-linux-gnuabin32"; gcc = { arch = "mips32r2"; abi = "o32"; float = "hard"; }; }; + mipsel-linux-gnuabin32 = { config = "mipsel-linux-gnuabin32"; 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"; }; }; + ## ## Other ## diff --git a/lib/tests/systems.nix b/lib/tests/systems.nix index 2646e792682ba..c88adbf4651aa 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 0d328d98ba110..25a593c67437c 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 d8ab96952b7f2..a21f677f117c0 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; From f6714f14d705533863f7c75dd1aeb79ed7e21ce2 Mon Sep 17 00:00:00 2001 From: Adam Joseph Date: Wed, 23 Feb 2022 00:57:50 -0800 Subject: [PATCH 2/5] lib/systems/platforms.nix: fix transcription typo in MIPS ABI table This corrects a mistake made when transcribing the ABI coordinate of the first two tuples from https://wiki.debian.org/Multiarch/Tuples --- lib/systems/platforms.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/systems/platforms.nix b/lib/systems/platforms.nix index 8b7f6fa729a59..f138f0cd27600 100644 --- a/lib/systems/platforms.nix +++ b/lib/systems/platforms.nix @@ -485,8 +485,8 @@ rec { # MIPS ABI table transcribed from here: https://wiki.debian.org/Multiarch/Tuples # can execute on 32bit chip - mips-linux-gnuabin32 = { config = "mips-linux-gnuabin32"; gcc = { arch = "mips32r2"; abi = "o32"; float = "hard"; }; }; - mipsel-linux-gnuabin32 = { config = "mipsel-linux-gnuabin32"; gcc = { arch = "mips32r2"; abi = "o32"; float = "hard"; }; }; + 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"; }; }; From a2c24b0341aa07c0849de0fc4f56d134e92b9dcb Mon Sep 17 00:00:00 2001 From: Adam Joseph Date: Wed, 23 Feb 2022 00:39:06 -0800 Subject: [PATCH 3/5] lib/systems/inspect.nix: libc-neutral wording of isMips64{n32,n64} The predicate for isMips64n32 matches not only mips64el-*-gnuabin32, but also mips64el-*-muslabin32. This is the desired/expected behavior. However the definition of isMips64n32 mentions abis.gnuabin32, which might mislead a reader into believing that the predicate matches only glibc targets. This commit inlines the definition of abis.gnuabin32, leaving the predicate's behavior unchanged while avoiding potential confusion. Likewise for isMips64n64. --- lib/systems/inspect.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/systems/inspect.nix b/lib/systems/inspect.nix index 98caf9e789340..2014337c246ac 100644 --- a/lib/systems/inspect.nix +++ b/lib/systems/inspect.nix @@ -19,8 +19,8 @@ rec { isMips = { cpu = { family = "mips"; }; }; isMips32 = { cpu = { family = "mips"; bits = 32; }; }; isMips64 = { cpu = { family = "mips"; bits = 64; }; }; - isMips64n32 = { cpu = { family = "mips"; }; abi = abis.gnuabin32; }; - isMips64n64 = { cpu = { family = "mips"; }; abi = abis.gnuabi64; }; + isMips64n32 = { cpu = { family = "mips"; }; abi = { abi = "n32"; }; }; + isMips64n64 = { cpu = { family = "mips"; }; abi = { abi = "64"; }; }; isMmix = { cpu = { family = "mmix"; }; }; isRiscV = { cpu = { family = "riscv"; }; }; isSparc = { cpu = { family = "sparc"; }; }; From b8c418e5f1e6cccd70bda82101b813f01cc54012 Mon Sep 17 00:00:00 2001 From: Adam Joseph Date: Wed, 23 Feb 2022 04:23:34 -0800 Subject: [PATCH 4/5] mips64el: add support for mips64el-linux-musl This is used in the bootstrap process, which involves cross-compiling a statically-linked nix binary. --- lib/systems/inspect.nix | 3 ++- lib/systems/parse.nix | 2 ++ pkgs/top-level/stage.nix | 5 ++++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/systems/inspect.nix b/lib/systems/inspect.nix index 2014337c246ac..6b4bf16737313 100644 --- a/lib/systems/inspect.nix +++ b/lib/systems/inspect.nix @@ -20,7 +20,8 @@ rec { isMips32 = { cpu = { family = "mips"; bits = 32; }; }; isMips64 = { cpu = { family = "mips"; bits = 64; }; }; isMips64n32 = { cpu = { family = "mips"; }; abi = { abi = "n32"; }; }; - isMips64n64 = { cpu = { family = "mips"; }; abi = { abi = "64"; }; }; + isMips64n64 =[{ cpu = { family = "mips"; }; abi = { abi = "64"; }; } + { cpu = { family = "mips"; bits = 64; }; abi = { name = "musl"; }; } ]; isMmix = { cpu = { family = "mmix"; }; }; isRiscV = { cpu = { family = "riscv"; }; }; isSparc = { cpu = { family = "sparc"; }; }; diff --git a/lib/systems/parse.nix b/lib/systems/parse.nix index 53024d1558bd7..9e44a021f05e0 100644 --- a/lib/systems/parse.nix +++ b/lib/systems/parse.nix @@ -359,11 +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/pkgs/top-level/stage.nix b/pkgs/top-level/stage.nix index 9d34ddb3685fb..88e3dd4402735 100644 --- a/pkgs/top-level/stage.nix +++ b/pkgs/top-level/stage.nix @@ -247,7 +247,10 @@ let musleabi = lib.systems.parse.abis.musleabi; musleabihf = lib.systems.parse.abis.musleabihf; }.${stdenv.hostPlatform.parsed.abi.name} - or lib.systems.parse.abis.musl; + or (if stdenv.hostPlatform.isMips64n32 then lib.systems.parse.abis.muslabin32 + # commented out because glibc does not yet understand *-muslabi64 + #else if stdenv.hostPlatform.isMips64n64 then lib.systems.parse.abis.muslabi64 + else lib.systems.parse.abis.musl); }; } // lib.optionalAttrs (stdenv.hostPlatform.system == "powerpc64-linux") { gcc.abi = "elfv2"; From 45909d028dd2908227439c23191df180fff3bc6b Mon Sep 17 00:00:00 2001 From: Adam Joseph Date: Fri, 25 Feb 2022 23:01:55 -0800 Subject: [PATCH 5/5] mips64el: bootstrap-files --- pkgs/stdenv/linux/bootstrap-files/mips64el.nix | 12 ++++++++++++ pkgs/stdenv/linux/default.nix | 2 ++ 2 files changed, 14 insertions(+) create mode 100644 pkgs/stdenv/linux/bootstrap-files/mips64el.nix diff --git a/pkgs/stdenv/linux/bootstrap-files/mips64el.nix b/pkgs/stdenv/linux/bootstrap-files/mips64el.nix new file mode 100644 index 0000000000000..004feb5a9e285 --- /dev/null +++ b/pkgs/stdenv/linux/bootstrap-files/mips64el.nix @@ -0,0 +1,12 @@ +{ + busybox = import { + url = "file:///nix/store/5xy00yds18lycmcm3qzwaxpybqkhbyx9-stdenv-bootstrap-tools-mips64el-linux-gnuabi64/on-server/busybox"; + sha256 = "sha256-0K3Cz+uoG3J8Lfjz8i7NTFujnyKklp9d+NBnLPFAH0I="; + executable = true; + }; + + bootstrapTools = import { + url = "file:///nix/store/5xy00yds18lycmcm3qzwaxpybqkhbyx9-stdenv-bootstrap-tools-mips64el-linux-gnuabi64/on-server/bootstrap-tools.tar.xz"; + sha256 = "sha256-So+8RJ+omB9V2I46Z/sbHiFsOVTW4wIscYr3SXxVz8o="; + }; +} diff --git a/pkgs/stdenv/linux/default.nix b/pkgs/stdenv/linux/default.nix index d2c28b97ff939..44628f360a547 100644 --- a/pkgs/stdenv/linux/default.nix +++ b/pkgs/stdenv/linux/default.nix @@ -15,6 +15,7 @@ armv6l-linux = import ./bootstrap-files/armv6l.nix; armv7l-linux = import ./bootstrap-files/armv7l.nix; aarch64-linux = import ./bootstrap-files/aarch64.nix; + mips64el-linux = import ./bootstrap-files/mips64el.nix; mipsel-linux = import ./bootstrap-files/loongson2f.nix; riscv64-linux = import ./bootstrap-files/riscv64.nix; }; @@ -22,6 +23,7 @@ aarch64-linux = import ./bootstrap-files/aarch64-musl.nix; armv6l-linux = import ./bootstrap-files/armv6l-musl.nix; x86_64-linux = import ./bootstrap-files/x86_64-musl.nix; + mips64el-linux = import ./bootstrap-files/mips64el.nix; }; };