Porting Alpine Linux to RISC-V
drewdevault.com
drewdevault.com
Or is it about the helper programs / scripts around the core compilation process that are too often hard coded to read out the configuration from the host system? So basically there is no technical hurdle, just the social norm that target arch == host arch, and thus make procedures aren't sufficiently tested for cross compilation from the get go?
It tends to be the dependencies (of the compiler and the libraries) that assume target==host.
Clang isn't broken like that, and for clang you are right that the issue is normally dependencies. Again GNU's libc is kind of broken.
Cross compiling with Clang and Musl is not too bad.
If my chip vendor decides to replace the ARM core on a SoC with a RISC-V core but leave all peripherals and memory mappings the same, I want to simply change the target and rebuild.
I mean, I don't know what distro you're working on (and whether they package these toolchains conveniently), but on Arch you just change your configured target in your conf/build system, and make sure you have the other one installed. If you're using autotools or cmake, you may not even need to change the configure scripts.
If you're doing embedded with memory mapped peripherals, surely you're building all your deps statically anyway.
If you don't have hardcoded addresses and are fully abstracted by a modern HAL and VM like on Linux then it's mostly a problem of the Linux distro or the OS vendor.
So if you want to have a cross toolchain for, say, RISC-V on x86, it's not enough to have the compiler and assembler, you need a RISC-V linker script (for your particular RISC-V target), a RISC-V build of the C library (again target-specific), the libgcc helper library, headers for all the relevant platform code (they seem simple, but in my experience headers are routinely the biggest mess).
And unlike the host toolchain where there is an unambiguous "correct" answer for all that stuff, a cross environment might be asked to support all kinds of crazy alternatives. Your ARM gcc might be used to produce a binary to run on Fedora, or for a busybox/uclibc build on an ancient kernel, or to target Zephyr (my world)...
It gets messy very fast. But it's not "hard". Putting it together for one system isn't any harder than it is for any other.
Different toolchains support it differently. So for example, if you want to cross-compile with gcc and ld, you need to first compile gcc and ld for the target architecture. This is because you pick the host and target at compile time. So you get aarch64-elf-gcc instead of just plain gcc. This means that you either hope that someone else has already done this for you, or you have to build it yourself. It's not impossible but it is a pain. Contrast this with llvm; clang and lldb support multiple hosts and targets in one binary. You pass --target (or whatever) and you're good to go. This removes that setup step.
The outside world. If you want to target an OS that's not your OS... you need the API for that OS. On Linuxes, that's the actual syscall interface, but on many other OSes, for example, Windows, the syscall interface is not stable. You must use the library the OS provides. This means that, if you're on Linux and you want to cross-compile to Windows, you need to get a copy of all the stuff that's in C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.10.24728\lib or whatever, because your program is going to need it.
Is your project all in one language? If not, you'll need to do the above in multiple ways, maybe. For example, a pure Ruby program is easy to "cross compile", you just cross-compile the interpreter. (I don't know how hard that actually is these days, but it's an analogy, work with me here.) But if you use C extensions, you also need to have them cross-compiled. Use both Rust and C? You'll need the toolchains for both, and to coordinate them. (We've tried to generally make this very easy for Rust but there's still details where it's not.)
Then, you need to make sure that the software understands that host != target. So for example, in Rust, we now have compile time function evaluation. The way that this works is, we include a full interpreter into the compiler, and it runs CTFE stuff with the interpreter set to the properties of the target, not the host. Not all languages do this kind of thing. There's tons of other ways this can possibly go wrong too, as it's not the case that many people expect. For example, maybe the software uses linux-specific stuff. You can't just automatically cross-compile it then. But it's not like anything tells you you're using os-specific stuff, and so if you never attempt to cross-compile, then you may not even realize.
I wonder, could the GNU toolchain devs be convinced to add support for multiple hosts/targets in one binary? Do they have a philosophical objection to it? Or is it simply that it is a lot of work and nobody has done it? It would make cross-compiling with the GNU toolchain a lot easier.
That said, this is getting easier and easier to do. I think this is because debian packages have to be architecture specific just for Intel architectures now, to handle both x86 (32 bit) and x86_64 ISAs. Once you have the environment, creating and using a different compiler executable is the easy part.
Could cranelift or similar allow rust to support multiple targets easier than llvm?
Building the cross-compiling toolchain is relatively easy, compared to dealing with the problems in software
I ran into a bug in bash [0], for example, that you would really only hit if you were cross-compiling it (there are other ways, because it wasn't related to being cross-compiled just features that were disabled automatically when cross-compiling). It took a while to convince people that this bug existed because it wasn't obvious that it was caused by being cross-compiled.
The real problems come from "modern" package managers as well as scripting languages in general.
Scripting languages and their extension mechanism are, in general, absolutely ignorant of cross-compiling and the idea that you might be building an extension to the language for a different platform than the running interpreter is completely foreign to most. Ruby fails especially hard here -- it looks ONLY at the running interpreter to determine how to build the extension. Python is a bit better because, but still rigid in versions. Perl's cross-compilation story requires having access to a system to SSH into (though there are alternative autoconf-based build systems that make this sane -- I don't know if they work for extensions, I just abandoned the idea of including Perl based on how poor their build system was). Tcl was the best, since it's extension system (TEA) is autoconf-based.
LuaJIT can't be cross-compiled from a 32-bit system for a 64-bit system [1] since it, at build-time, tries to do some stuff and fails at it.
[0] https://lists.gnu.org/archive/html/bug-bash/2015-06/msg00042... [1] http://luajit.org/install.html#cross
Ex: GOOS=windows go build .
GOOS=linux GOARCH=arm go build .
And you can run that from any os / arch, I can build a single Windows binary from my Raspberry Pi with the above example.
EDIT: Try to build NetBSD for some esoteric platform from the comfort of your desktop machine. Remember to pick up your jaw from the floow when you're done. ;-) My point is, it does not have to be hard.
Rust projects make much more use of C libraries than Go projects do, though, so for things other than the Rust compiler, this is still a good point.
[0] http://www.ieee-hpec.org/2018/2018program/index_htm_files/15...
The STREAM benchmark [6] was also compiled and executed, confirming that DRAM performance is limited to less than 1.6 GB/s on this platform. It’s unclear if this is a problem with the cache hierarchy, memory controller, or the configuration of the DDR Controller Control Registers
Wow, that's unspeakably terrible. That's about 10-20% of the b/w one should get from 2400 mem (depending on how many channels the mem controller uses).
I hope this is some simple misconfiguration that can be fixed in firmware or in the kernel.
The generated RTL is open but that is of course limited.
- In which fab is the CPU manufactured?
- How much slower does it compile stuff than a mainstream CPU? (Author only says "somewhat slower", but could have been more precise)
- Is the RISC-V architecture free from Spectre-like bugs?
- What does the memory hierarchy look like?
It's an in-order 64 bit 4 core processor (actually 5 cores, because there's a small 32 bit core which does nothing normally). Think Cortex A53. It's very usable for development (I have two of them), and we even have people using them for desktop running GNOME. But it's not a Xeon. The main issue is the cost and lack of SATA on the development board (there's a daughter board providing that, at extra cost). Everything is open source.
This chip is free of speculation bugs because it doesn't do speculation. However the architecture itself is not in any way better or worse than others, and a RISC-V core with a different microarchitecture might well be vulnerable, although since these attacks are now well-known steps should be taken by designers to avoid them.
Memory architecture is very simple, it has small L1 and L2 caches and main memory. There's also a chiplink connection which takes the memory bus off-chip. You can read more here: https://www.sifive.com/chip-designer#fu540
https://www.crowdsupply.com/microsemi/hifive-unleashed-expan...
It takes the Chiplink connection and routes it to a PCIe bridge. There's also a large FPGA on there, but I'm not quite clear how it's all connected up.
I don't know much about what people are using this for. Also the whole setup costs like $4000 so I guess it's not quite ready for casual home users just yet. If you want to go the FPGA route, then it might be better looking at a Virtex-7 and putting the RISC-V rocketchip core on there, along with whatever local customizations you want to try out.
This talk (https://www.youtube.com/watch?v=NjEslX_-t0Q) is about the OoO core on RISC-V and what they did to remove the chance of speculation attacks.
>"I’m working on making this hardware available to builds.sr.ht users in the next few months, where I intend to use it to automate the remainder of the Alpine Linux port and make it available to any other operating systems (including non-Linux) and userspace software which are interested in working on a RISC-V port."
Is this author also the designer of the board? Or do they made they're working on making the software available?
This looks really exciting, looking forward to following the progress.
[1] Or we were up to yesterday when we had a hardware failure (on an Intel machine) so our build system is currently down. Four days before Christmas, so the worst possible time ...
According to the Handbook. They currently support
Alpha, AMD64, ARM, ARM64 HPPA/PA-RISC, IA64, MIPS, PPC, PPC64, SPARC and x86 (i486 and i686)
What exactly is cool about this board?
This isn't Rust. GCC-6.4 will compile literally any C or C++ project you find (that works with any recent version of GCC), including stuff requiring C++-14 and _most_ of C++-17. Hell, GCC-4.9 (from 2014) is sufficient to compile the latest linux kernel, the latest sqlite3, the latest nginx, the latest of any real significant package.
I still encounter version 5 in production.
That being said, CentOS 5 hasn't received security updates for year or so (or 2?), so maybe there's a security risk in continuing to rely on it? I guess CentOS 6 would be the oldest still supported distro.
You don’t. It’s a baked in reminder that logging into a container is a sin worthy of punishment.
Though, they do have issues with alpine-aports patches (alpine-aports is their package repository scripts). They don't have a large enough team so a patch generally needs a few months to get in.