Skip to content

Commit

Permalink
lib/systems: add mips64el definitions
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Adam Joseph committed Mar 11, 2022
1 parent b77a575 commit 12371a5
Show file tree
Hide file tree
Showing 10 changed files with 104 additions and 24 deletions.
3 changes: 2 additions & 1 deletion lib/systems/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
8 changes: 6 additions & 2 deletions lib/systems/doubles.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions lib/systems/examples.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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";
};
Expand Down
6 changes: 5 additions & 1 deletion lib/systems/inspect.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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"; }; };
Expand Down Expand Up @@ -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; })
Expand Down
7 changes: 7 additions & 0 deletions lib/systems/parse.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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"; };
Expand Down
49 changes: 49 additions & 0 deletions lib/systems/platforms.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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
##
Expand Down
4 changes: 2 additions & 2 deletions lib/tests/systems.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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" ];

Expand All @@ -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" ];
Expand Down
1 change: 1 addition & 0 deletions pkgs/stdenv/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions pkgs/stdenv/linux/make-bootstrap-tools-cross.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
44 changes: 26 additions & 18 deletions pkgs/top-level/stage.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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.";

Expand Down Expand Up @@ -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";
};
Expand Down

1 comment on commit 12371a5

@nixos-discourse
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/how-to-add-a-new-cross-compilation-target/24342/2

Please sign in to comment.