GNU Guix: Guix/Hurd on a Thinkpad X60
A lot has happened with respect to the Hurd since our Childhurds and GNU/Hurd Substitutes post. As long as two years ago some of you have been asking for a progress update and although there have been rumours on a new blog post for over a year, we were kind of waiting for the rumoured x86_64 support.
With all the exciting progress on the Hurd coming available after the recent (last?) merger of core-updates
we thought it better not to wait any longer. So here is a short overview of our Hurd work over the past years:
Update Hurd to 3ff7053, gnumach 1.8+git20220827, and fix build failures,
Initial rumpdisk support, more on this below, which needed to wait for:
A libc specific to Hurd, updating gnumach to 1.8+git20221224 and hurd to 0.9.git20230216,
Some 40 native package build fixes for the Hurd so that all development dependencies of the guix package are now available,
A hack to use Git source in commencement to update and fix cross build and native build for the Hurd,
Support for buiding
guix
natively on the Hurd by splitting the build into more steps for 32-bit hostsEven nicer offloading support for Childhurds by introducing Smart Hurdloading so that now both the Bordeaux and Berlin build farms build packages for i586-gnu,
Locale fixes for wrong
glibc-utf8-locales
package used on GNU/Hurd,More locale fixes to use
glibc-utf8-locales/hurd
in %standard-patch-inputs,And even more locale fixes for using the right locales on GNU/Hurd,
A new glibc 2.38 allowing us to do
(define-public glibc/hurd glibc)
—i.e., once again use the same glibc for Linux and Hurd alike, and: Better Hurd support!,Creation of
hurd-team
branch with build fixes, updating gnumach to 1.8+git20230410 and hurd to 0.9.git20231217,A constructive meeting with sixteen people during the Guix Days just before FOSDEM '24 with notes that contain some nice ideas,
Another new glibc 2.39; even better Hurd support, opening the door to
x86_64
support,Yet another restoring of i586-gnu (32-bit GNU/Hurd) support,
The installer just learnt about the Hurd! More on this below, and finally,
Another set of updates: gnumach (1.8+git20240714), mig (1.8+git20231217), hurd (0.9.git20240714), netdde (c0ef248d), rumpkernel (f1ffd640), and initial support for x86_64-gnu, aka the 64bit Hurd.
NetDDE and Rumpdisk support
Back in 2020, Ricardo Wurmus added the NetDDE package that provides Linux 2.6 network drivers. At the time we didn't get to integrate and use it though and meanwhile it bitrotted.
After we resurrected the NetDDE build, and with kind help of the Hurd developers we finally managed to support NetDDE for the Hurd.. This allows the usage of the Intel 82573L Gigabit Ethernet Controller of the Thinkpad X60 (and many other network cards, possibly even WIFI). Instead of using the builtin kernel driver in GNU Mach, it would be running as a userland driver.
What sparked this development was upstream's NetBSD rumpdisk support that would allow using modern hard disks such as SSDs, again running as a userland driver. Hard disk support builtin in GNU Mach was once considered to be a nice hack but it only supported disks up to 128 GiB…
First, we needed to fix the cross build on Guix.
After the initial attempt at rumpdisk support for the Hurd it took (v2) some (v3) work (v4) to finally arrive at rumpdisk support for the Hurd, really, *
really*
(v5)
Sadly when actually using them, booting hangs:
start: pci.arbiter:
What did not really help is that upstream's rumpkernel archive was ridiculously large. We managed to work with upstream to remove unused bits from the archive. Upstream created a new archive that instead of 1.8 GiB (!) now “only” weighs 670 MiB.
Anyway, after a lot of building, rebuilding, and debugging and some more with kind help from upstream we finally got Rumpdisk and NetDDE to run in a Childhurd.
Initial Guix/Hurd on the Thinkpad X60
Now that the last (!) core-updates
merge has finally happened (thanks everyone!), the recipe of installing Guix/Hurd has been much simpfilied. It goes something along these lines.
Install Guix/Linux on your X60,
Reserve a partition and format it for the Hurd:
mke2fs -o hurd -L hurd /dev/sdaX
In your
config.scm
, add some code to add GRUB menuentries for booting the Hurd, and mount the Hurd partition under/hurd
:(use-modules (srfi srfi-26) (ice-9 match) (ice-9 rdelim) (ice-9 regex) (gnu build file-systems))
(define %hurd-menuentry-regex
"menuentry \"(GNU with the Hurd[^{\"])\".*multiboot ([^ \n]) +([^\n])")
(define (text->hurd-menuentry text)
(let ((m (string-match %hurd-menuentry-regex text))
(label (match:substring m 1))
(kernel (match:substring m 2))
(arguments (match:substring m 3))
(arguments (string-split arguments #\space))
(root (find (cute string-prefix? "root=" <>) arguments))
(device-spec (match (string-split root #=)
(("root" device) device)))
(device (hurd-device-name->device-name device-spec))
(modules (list-matches "module ([^\n]*)" text))
(modules (map (cute match:substring <> 1) modules))
(modules (map (cute string-split <> #\space) modules)))
(menu-entry
(label label)
(device device)
(multiboot-kernel kernel)
(multiboot-arguments arguments)
(multiboot-modules modules))))(define %hurd-menuentries-regex
"menuentry \"(GNU with the Hurd[^{\"])\" \{([^}]|[^\n]\})\n\}")
(define (grub.cfg->hurd-menuentries grub.cfg)
(let* ((entries (list-matches %hurd-menuentries-regex grub.cfg))
(entries (map (cute match:substring <> 0) entries)))
(map text->hurd-menuentry entries)))(define (hurd-menuentries)
(let ((grub.cfg (with-input-from-file "/hurd/boot/grub/grub.cfg"
read-string)))
(grub.cfg->hurd-menuentries grub.cfg)))...
(operating-system
...
(bootloader (bootloader-configuration
(bootloader grub-bootloader)
(targets '("/dev/sda"))
(menu-entries (hurd-menuentries))))
(file-systems (cons* (file-system
(device (file-system-label "guix"))
(mount-point "/")
(type "ext4"))
(file-system
(device (file-system-label "hurd"))
(mount-point "/hurd")
(type "ext2"))
%base-file-systems))
...)Create a
config.scm
for your Hurd system. You can get inspiration from bare-hurd.tmpl and inherit from%hurd-default-operating-system
. Usegrub-minimal-bootloader
and add astatic-networking-service-type
. Something like:(use-modules (srfi srfi-1) (ice-9 match))
(use-modules (gnu) (gnu system hurd))
(operating-system
(inherit %hurd-default-operating-system)
(bootloader (bootloader-configuration
(bootloader grub-minimal-bootloader)
(targets '("/dev/sda"))))
(kernel-arguments '("noide"))
...
(services
(cons*
(service static-networking-service-type
(list %loopback-static-networking
(static-networking
(addresses
(list
(network-address
(device "eth0")
(value "192.168.178.37/24"))))
(routes
(list (network-route
(destination "default")
(gateway "192.168.178.1"))))
(requirement '())
(provision '(networking))
(name-servers '("192.168.178.1")))))
...)))Install the Hurd. Assuming you have an
ext2
filesystem mounted on/hurd
, do something like:guix system build --target=i586-pc-gnu vuurvlieg.hurd --verbosity=1
sudo -E guix system init --target=i586-pc-gnu --skip-checks \
vuurvlieg.hurd /hurd
sudo -E guix system reconfigure vuurvlieg.scmReboot and...
Hurray!
We now have Guix/Hurd running on Thinkpad.
Guix/Hurd on Real Iron
While the initial manual install on the X60 was an inspiring milestone, we can do better. As mentioned above, just recently the installer learnt about the Hurd, right after some smaller problems were addressed, like guix system init
creating essential devices for the Hurd, not attempting to run a cross-built grub-install
to install Grub, soft-coding the hard-coded part:1:device:wd0
root file-system, adding support for booting Guix/Hurd more than once.
To install Guix/Hurd, first, build a 32bit installation image and copy it to a USB stick:
guix system image --image-type=iso9660 --system=i686-linux gnu/system/install.scm
dd if=/gnu/store/cabba9e-image.iso of=/dev/sdX status=progress
sync
then boot it on a not-too-new machine that has wired internet (although installation over WIFI is possible, there is currently no WIFI support for the installed Hurd to use it). On the new Kernel
page:
choose Hurd
. Do not choose a desktop environment, that's not available yet. On the Network management
page:
choose the new Static networking service
. In the final Configuration file
step, don't forget to edit:
and fill-in your IP
and GATEWAY
:
You may want to add some additional packages such as git-minimal
from (gnu packages version-control)
and sqlite
from (gnu packages sqlite)
.
If you also intend to do Guix development on the Hurd—e.g., debugging and fixing native package builds—then you might want to include all dependencies to build the guix package, see the devel-hurd.tmpl
for inspiration on how to do that. Note that any package you add must already have support for cross-building.
Good luck, and let us know if it works for you and on what kind of machine, or why it didn't!
What's next?
In an earlier post we tried to answer the question “Why bother with the Hurd anyway?” An obvious question because it is all too easy to get discouraged, to downplay or underestimate the potential social impact of GNU and the Hurd.
The most pressing problem currently is that the guix-daemon fails when invoking guix authenticate
on the Hurd, which means that we cannot easily keep our substitutes up to date. guix pull
is known to work but only by pulling from a local branch doing something like:
mkdir -p ~/src/guix
cd src/guix
git clone https://git.savannah.gnu.org/git/guix.git master
guix pull --url=~/src/guix/master
kinda like we did it in the old days. Sometimes it seems that guix does not grok the sqlite store database. This is needs to be resolved but as sqlite
does read it this can be easily worked around by doing something like:
mv /var/guix/db/db.sqlite /var/guix/db/db.sqlite.orig
sqlite3 /var/guix/db/db.sqlite.orig .dump > /var/guix/db/db.sqlite.dump
sqlite3 -init /var/guix/db/db.sqlite.dump /var/guix/db/db.sqlite .quit
Also, the boot process still fails to handle an unclean root file system. Whenever the Hurd has suffered an unclean shutdown, cleaning it must currently be done manually, e.g., by booting from the installer USB stick.
Upstream now has decent support for 64bit (x86_64) albeit with more bugs and fewer packages. As mentioned in the overview we are now working to have that in Guix and have made some progress:
more on that in another post. Other interesting task for Guix include:
- Have
guix system reconfigure
work on the Hurd, - Figure out WiFi support with NetDDE (and add it to installer!),
- An isolated build environment (or better wait for, err, contribute to the Guile guix-daemon?),
- An installer running the Hurd, and,
- Packages, packages, packages!
We tried to make Hurd development as easy and as pleasant as we could. As you have seen, things start to work pretty nicely and there is still plenty of work to do in Guix. In a way this is “merely packaging” the amazing work of others. Some of the real work that needs to be done and which is being discussed and is in progress right now includes:
- Audio support (this is sponsored by NLnet, thanks!),
- Rumpnet,
- SMP,
- AArch64.
All these tasks look daunting, and indeed that’s a lot of work ahead. But the development environment is certainly an advantage. Take an example: surely anyone who’s hacked on device drivers or file systems before would have loved to be able to GDB into the code, restart it, add breakpoints and so on—that’s exactly the experience that the Hurd offers. As for Guix, it will make it easy to test changes to the micro-kernel and to the Hurd servers, and that too has the potential to speed up development and make it a very nice experience.
Join #guix
and #hurd
on libera.chat
or the mailing lists and get involved!
There are no comments yet.