This is because config apparently tries to be smart and understand both system doubles and autotools triples and a “kernel” part is always expected. Because elf is not a kernel part in nixpkgs, it expects the kernel part in the unknown place. nixpkgs does understand none as kernel, so maybe the following works for you (if I guessed correctly what you want):
let
crossPkgs =
import <nixpkgs> {
# uses GCC and newlib
crossSystem = { system = "riscv64-none-elf"; };
};
in
# use crossPkgs' mkShell to use the correct stdenv!
crossPkgs.mkShell {}