* [bug#75027] [PATCH 0/3] 'guix system reconfigure' loads system for kexec reboot
@ 2024-12-22 15:56 Ludovic Courtès
2024-12-22 15:57 ` [bug#75027] [PATCH 1/3] syscalls: Add ‘kexec-load-file’ Ludovic Courtès
` (4 more replies)
0 siblings, 5 replies; 11+ messages in thread
From: Ludovic Courtès @ 2024-12-22 15:56 UTC (permalink / raw)
To: 75027
Cc: Jakob Kirsch, Ludovic Courtès, Christopher Baines,
Josselin Poiret, Ludovic Courtès, Mathieu Othacehe,
Simon Tournier, Tobias Geerinckx-Rice
Hello Guix,
Following work by Jakob Kirsch adding kexec support in the Shepherd
(the new ‘reboot -k’ option), here’s the Guix side of it: with these
patches, ‘guix system reconfigure’ loads the new system so that one
can run ‘reboot -k’ to quickly reboot into it.
Thoughts?
Ludo’.
PS: It took me a while to debug until I realized it was working
very well: it’s just that I was booting a kernel with “quiet”
on its command line, so I couldn’t see anything. 🤦
Ludovic Courtès (3):
syscalls: Add ‘kexec-load-file’.
system: Export ‘…-initrd-file’ and ‘…-root-file-system’.
reconfigure: Call ‘kexec-load-file’.
gnu/system.scm | 4 +-
gnu/tests/reconfigure.scm | 77 +++++++++++++++++++++++++++++
guix/build/syscalls.scm | 54 ++++++++++++++++++++
guix/scripts/system/reconfigure.scm | 25 ++++++++++
tests/syscalls.scm | 13 +++++
5 files changed, 172 insertions(+), 1 deletion(-)
base-commit: 9f53e10235cced7a85697481c859829742b9912c
--
2.46.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [bug#75027] [PATCH 1/3] syscalls: Add ‘kexec-load-file’.
2024-12-22 15:56 [bug#75027] [PATCH 0/3] 'guix system reconfigure' loads system for kexec reboot Ludovic Courtès
@ 2024-12-22 15:57 ` Ludovic Courtès
2024-12-22 15:57 ` [bug#75027] [PATCH 2/3] system: Export ‘…-initrd-file’ and ‘…-root-file-system’ Ludovic Courtès
` (3 subsequent siblings)
4 siblings, 0 replies; 11+ messages in thread
From: Ludovic Courtès @ 2024-12-22 15:57 UTC (permalink / raw)
To: 75027; +Cc: Ludovic Courtès
* guix/build/syscalls.scm (string->utf-8/nul-terminated)
(kexec-load-file): New procedures.
* tests/syscalls.scm ("kexec-load-file"): New test.
Change-Id: I3724226a14ecc07f346e77519fb5b0591096c7f6
---
guix/build/syscalls.scm | 54 +++++++++++++++++++++++++++++++++++++++++
tests/syscalls.scm | 13 ++++++++++
2 files changed, 67 insertions(+)
diff --git a/guix/build/syscalls.scm b/guix/build/syscalls.scm
index 2c20edf058..f8c9937f54 100644
--- a/guix/build/syscalls.scm
+++ b/guix/build/syscalls.scm
@@ -146,6 +146,12 @@ (define-module (guix build syscalls)
clone
setns
+ kexec-load-file
+ KEXEC_FILE_UNLOAD
+ KEXEC_FILE_ON_CRASH
+ KEXEC_FILE_NO_INITRAMFS
+ KEXEC_FILE_DEBUG
+
PF_PACKET
AF_PACKET
all-network-interface-names
@@ -765,6 +771,54 @@ (define-as-needed load-linux-module
(list (strerror err))
(list err)))))))
+(define (string->utf-8/nul-terminated str)
+ "Serialize STR to UTF-8; return the resulting bytevector, including
+terminating nul character."
+ (let* ((source (string->utf8 str))
+ (bv (make-bytevector (+ (bytevector-length source) 1) 0)))
+ (bytevector-copy! source 0 bv 0 (bytevector-length source))
+ bv))
+
+;; Constants from <linux/kexec.h>.
+(define KEXEC_FILE_UNLOAD #x00000001)
+(define KEXEC_FILE_ON_CRASH #x00000002)
+(define KEXEC_FILE_NO_INITRAMFS #x00000004)
+(define KEXEC_FILE_DEBUG #x00000008)
+
+(define kexec-load-file
+ (let* ((proc (syscall->procedure int "syscall"
+ (list long ;sysno
+ int ;kernel fd
+ int ;initrd fd
+ unsigned-long ;cmdline length
+ '* ;cmdline
+ unsigned-long))) ;flags
+ ;; TODO: Don't do this.
+ (syscall-id (match (utsname:machine (uname))
+ ("i686" 320)
+ ("x86_64" 320)
+ ("armv7l" 401)
+ ("aarch64" 401)
+ ;; XXX: There's apparently no support for ppc64le and
+ ;; riscv64.
+ (_ #f))))
+ (lambda* (kernel-fd initrd-fd command-line #:optional (flags 0))
+ "Load for eventual use of kexec(8) the Linux kernel from
+@var{kernel-fd}, its initial RAM disk from @var{initrd-fd}, with the given
+@var{command-line} (a string). Optionally, @var{flags} can be a bitwise or of
+the KEXEC_FILE_* constants."
+ (let*-values (((command-line)
+ (string->utf-8/nul-terminated command-line))
+ ((ret err)
+ (proc syscall-id kernel-fd initrd-fd
+ (bytevector-length command-line)
+ (bytevector->pointer command-line)
+ flags)))
+ (when (= ret -1)
+ (throw 'system-error "kexec-load-file" "~A"
+ (list (strerror err))
+ (list err)))))))
+
(define (linux-process-flags pid) ;copied from the Shepherd
"Return the process flags of @var{pid} (or'd @code{PF_} constants), assuming
the Linux /proc file system is mounted; raise a @code{system-error} exception
diff --git a/tests/syscalls.scm b/tests/syscalls.scm
index 13f4f11721..eef864d097 100644
--- a/tests/syscalls.scm
+++ b/tests/syscalls.scm
@@ -679,6 +679,19 @@ (define perform-container-tests?
(lambda args
(system-error-errno args))))))
+(when (or (zero? (getuid))
+ (not (string-contains %host-type "linux")))
+ (test-skip 1))
+(test-equal "kexec-load-file"
+ EPERM
+ (catch 'system-error
+ (lambda ()
+ (let ((fd1 (open-fdes "/dev/null" O_RDONLY))
+ (fd2 (open-fdes "/dev/null" O_RDONLY)))
+ (kexec-load-file fd1 fd2 "gnu.repl=yes")))
+ (lambda args
+ (system-error-errno args))))
+
(test-end)
(false-if-exception (delete-file temp-file))
--
2.46.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [bug#75027] [PATCH 2/3] system: Export ‘…-initrd-file’ and ‘…-root-file-system’.
2024-12-22 15:56 [bug#75027] [PATCH 0/3] 'guix system reconfigure' loads system for kexec reboot Ludovic Courtès
2024-12-22 15:57 ` [bug#75027] [PATCH 1/3] syscalls: Add ‘kexec-load-file’ Ludovic Courtès
@ 2024-12-22 15:57 ` Ludovic Courtès
2024-12-22 15:57 ` [bug#75027] [PATCH 3/3] reconfigure: Call ‘kexec-load-file’ Ludovic Courtès
` (2 subsequent siblings)
4 siblings, 0 replies; 11+ messages in thread
From: Ludovic Courtès @ 2024-12-22 15:57 UTC (permalink / raw)
To: 75027; +Cc: Ludovic Courtès
* gnu/system.scm (operating-system-initrd-file): Fix docstring and
export.
(operating-system-root-file-system): Export.
Change-Id: I5254d82ce547e8014027ed20675b8bfe5a5847c5
---
gnu/system.scm | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/gnu/system.scm b/gnu/system.scm
index dfcb8fb279..252a26cac3 100644
--- a/gnu/system.scm
+++ b/gnu/system.scm
@@ -110,6 +110,7 @@ (define-module (gnu system)
operating-system-default-label
operating-system-initrd-modules
operating-system-initrd
+ operating-system-initrd-file
operating-system-users
operating-system-groups
operating-system-issue
@@ -119,6 +120,7 @@ (define-module (gnu system)
operating-system-locale-libcs
operating-system-mapped-devices
operating-system-file-systems
+ operating-system-root-file-system
operating-system-store-file-system
operating-system-user-mapped-devices
operating-system-boot-mapped-devices
@@ -1355,7 +1357,7 @@ (define (operating-system-root-file-system os)
(location (operating-system-location os)))))))
(define (operating-system-initrd-file os)
- "Return a gexp denoting the initrd file of OS."
+ "Return a file-like object for the initrd file of OS."
(define boot-file-systems
(filter file-system-needed-for-boot?
(operating-system-file-systems os)))
--
2.46.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [bug#75027] [PATCH 3/3] reconfigure: Call ‘kexec-load-file’.
2024-12-22 15:56 [bug#75027] [PATCH 0/3] 'guix system reconfigure' loads system for kexec reboot Ludovic Courtès
2024-12-22 15:57 ` [bug#75027] [PATCH 1/3] syscalls: Add ‘kexec-load-file’ Ludovic Courtès
2024-12-22 15:57 ` [bug#75027] [PATCH 2/3] system: Export ‘…-initrd-file’ and ‘…-root-file-system’ Ludovic Courtès
@ 2024-12-22 15:57 ` Ludovic Courtès
2024-12-22 21:47 ` [bug#75027] [PATCH 0/3] 'guix system reconfigure' loads system for kexec reboot Jakob Kirsch via Guix-patches via
2024-12-26 17:21 ` [bug#75027] [PATCH v2 " Ludovic Courtès
4 siblings, 0 replies; 11+ messages in thread
From: Ludovic Courtès @ 2024-12-22 15:57 UTC (permalink / raw)
To: 75027
Cc: Ludovic Courtès, Christopher Baines, Josselin Poiret,
Ludovic Courtès, Mathieu Othacehe, Simon Tournier,
Tobias Geerinckx-Rice
This allows rebooting straight into the new system with ‘reboot -k’.
* guix/scripts/system/reconfigure.scm (kexec-loading-program): New
procedure.
(upgrade-shepherd-services): Use it.
* gnu/tests/reconfigure.scm (run-kexec-test): New procedure.
(%test-upgrade-kexec): New variable.
Change-Id: I86d11f1c348e4359bc9e73c86e5aebff60fe875c
---
gnu/tests/reconfigure.scm | 77 +++++++++++++++++++++++++++++
guix/scripts/system/reconfigure.scm | 25 ++++++++++
2 files changed, 102 insertions(+)
diff --git a/gnu/tests/reconfigure.scm b/gnu/tests/reconfigure.scm
index bcc7645fa3..8d33bdac9b 100644
--- a/gnu/tests/reconfigure.scm
+++ b/gnu/tests/reconfigure.scm
@@ -1,5 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2019 Jakob L. Kreuze <zerodaysfordays@sdf.org>
+;;; Copyright © 2024 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -18,9 +19,12 @@
(define-module (gnu tests reconfigure)
#:use-module (gnu bootloader)
+ #:use-module (gnu services)
+ #:use-module (gnu services base)
#:use-module (gnu services shepherd)
#:use-module (gnu system)
#:use-module (gnu system accounts)
+ #:use-module (gnu system file-systems)
#:use-module (gnu system shadow)
#:use-module (gnu system vm)
#:use-module (gnu tests)
@@ -31,6 +35,7 @@ (define-module (gnu tests reconfigure)
#:use-module (guix store)
#:export (%test-switch-to-system
%test-upgrade-services
+ %test-upgrade-kexec
%test-install-bootloader))
;;; Commentary:
@@ -178,6 +183,72 @@ (define* (run-upgrade-services-test)
(disable (upgrade-services-program '() '() '(dummy) '())))
(test enable disable))))
+(define* (run-kexec-test)
+ (define os
+ (marionette-operating-system
+ (operating-system
+ (inherit %simple-os)
+ (services (modify-services %base-services
+ (syslog-service-type
+ config => (syslog-configuration
+ (inherit config)
+ (config-file
+ (plain-file
+ "syslog.conf"
+ "*.* /dev/console\n")))))))
+ #:imported-modules '((gnu services herd)
+ (guix combinators))))
+
+ (define new-os
+ (marionette-operating-system
+ (virtualized-operating-system ;run as with "guix system vm"
+ (operating-system
+ (inherit %simple-os)
+ (host-name "the-new-os")
+ (kernel-arguments '("console=ttyS0"))) ;be verbose
+ #:volatile? #t) ;mount root read-only
+ #:imported-modules '((gnu services herd)
+ (guix combinators))))
+
+ (define vm (virtual-machine os))
+
+ (define test
+ (with-imported-modules '((gnu build marionette))
+ #~(begin
+ (use-modules (gnu build marionette)
+ (srfi srfi-64))
+
+ (define marionette
+ (make-marionette (list #$vm)))
+
+ (test-runner-current (system-test-runner #$output))
+ (test-begin "kexec")
+
+ (test-equal "host name"
+ #$(operating-system-host-name os)
+ (marionette-eval '(gethostname) marionette))
+
+ (test-assert "kexec-loading-program"
+ (marionette-eval
+ '(primitive-load #$(kexec-loading-program new-os))
+ marionette))
+
+ (test-assert "reboot/kexec"
+ (marionette-eval
+ '(begin
+ (use-modules (gnu services herd))
+ (with-shepherd-action 'root ('kexec) result
+ (pk 'reboot-kexec result)))
+ marionette))
+
+ (test-equal "host name of new OS"
+ #$(operating-system-host-name new-os)
+ (marionette-eval '(gethostname) marionette))
+
+ (test-end))))
+
+ (gexp->derivation "kexec-test" test))
+
(define* (run-install-bootloader-test)
"Run a test of an OS running INSTALL-BOOTLOADER-PROGRAM, which installs a
bootloader's configuration file."
@@ -268,6 +339,12 @@ (define %test-upgrade-services
loading new services.")
(value (run-upgrade-services-test))))
+(define %test-upgrade-kexec
+ (system-test
+ (name "upgrade-kexec")
+ (description "FIXME")
+ (value (run-kexec-test))))
+
(define %test-install-bootloader
(system-test
(name "install-bootloader")
diff --git a/guix/scripts/system/reconfigure.scm b/guix/scripts/system/reconfigure.scm
index ddb561d28c..9e08179613 100644
--- a/guix/scripts/system/reconfigure.scm
+++ b/guix/scripts/system/reconfigure.scm
@@ -31,6 +31,7 @@ (define-module (guix scripts system reconfigure)
#:use-module (gnu services herd)
#:use-module (gnu services shepherd)
#:use-module (gnu system)
+ #:autoload (gnu system file-systems) (file-system-device)
#:use-module (guix gexp)
#:use-module (guix modules)
#:use-module (guix monads)
@@ -51,6 +52,7 @@ (define-module (guix scripts system reconfigure)
upgrade-services-program
upgrade-shepherd-services
+ kexec-loading-program
install-bootloader-program
install-bootloader
@@ -176,6 +178,27 @@ (define (upgrade-services-program service-files to-start to-unload to-restart)
(for-each unload-service '#$to-unload)
(for-each start-service '#$to-start)))))
+(define (kexec-loading-program os)
+ "Return a program that calls 'kexec_file_load' to allow rebooting into OS
+via 'kexec'."
+ (let ((root-device (file-system-device
+ (operating-system-root-file-system os))))
+ (program-file
+ "kexec-load-system.scm"
+ (with-imported-modules '((guix build syscalls))
+ #~(begin
+ (use-modules (guix build syscalls))
+
+ (let ((kernel (open-fdes #$(operating-system-kernel-file os)
+ O_RDONLY))
+ (initrd (open-fdes #$(operating-system-initrd-file os)
+ O_RDONLY)))
+ (kexec-load-file kernel initrd
+ (string-join
+ (list #$@(operating-system-kernel-arguments
+ os root-device)))
+ KEXEC_FILE_DEBUG)))))))
+
(define* (upgrade-shepherd-services eval os)
"Using EVAL, a monadic procedure taking a single G-Expression as an argument,
upgrade the Shepherd (PID 1) by unloading obsolete services and loading new
@@ -200,6 +223,8 @@ (define* (upgrade-shepherd-services eval os)
running))
(service-files (map shepherd-service-file target-services)))
(eval #~(parameterize ((current-warning-port (%make-void-port "w")))
+ (when (string-contains %host-type "-linux")
+ (primitive-load #$(kexec-loading-program os)))
(primitive-load #$(upgrade-services-program service-files
to-start
to-unload
--
2.46.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [bug#75027] [PATCH 0/3] 'guix system reconfigure' loads system for kexec reboot
2024-12-22 15:56 [bug#75027] [PATCH 0/3] 'guix system reconfigure' loads system for kexec reboot Ludovic Courtès
` (2 preceding siblings ...)
2024-12-22 15:57 ` [bug#75027] [PATCH 3/3] reconfigure: Call ‘kexec-load-file’ Ludovic Courtès
@ 2024-12-22 21:47 ` Jakob Kirsch via Guix-patches via
[not found] ` <87y106ej9v.fsf@gnu.org>
2024-12-26 17:21 ` [bug#75027] [PATCH v2 " Ludovic Courtès
4 siblings, 1 reply; 11+ messages in thread
From: Jakob Kirsch via Guix-patches via @ 2024-12-22 21:47 UTC (permalink / raw)
To: Ludovic Courtès; +Cc: 75027
Would it be possible to expose the output of kexec-loading-program as a file in the output directory of the operating system (e.g. as /run/current-system/kexec)?
^ permalink raw reply [flat|nested] 11+ messages in thread
* [bug#75027] [PATCH 0/3] 'guix system reconfigure' loads system for kexec reboot
[not found] ` <87y106ej9v.fsf@gnu.org>
@ 2024-12-23 18:24 ` Jakob Kirsch via Guix-patches via
2024-12-26 17:25 ` Ludovic Courtès
0 siblings, 1 reply; 11+ messages in thread
From: Jakob Kirsch via Guix-patches via @ 2024-12-23 18:24 UTC (permalink / raw)
To: Ludovic Courtès; +Cc: 75027
On Mon, Dec 23, 2024 at 12:22:20PM +0100, Ludovic Courtès wrote:
> In addition to or instead of running it by default?
I would say in addition to but with a flag to not load it (like with "--no-bootloader" for the bootloader).
Btw I've also noticed that the framebuffer is only initialized after something graphical (gdm in my case) has been started. This usually isn't an issue for most users but my disks are encrypted so I can't see the password prompt but I can still type in my password.
^ permalink raw reply [flat|nested] 11+ messages in thread
* [bug#75027] [PATCH v2 0/3] 'guix system reconfigure' loads system for kexec reboot
2024-12-22 15:56 [bug#75027] [PATCH 0/3] 'guix system reconfigure' loads system for kexec reboot Ludovic Courtès
` (3 preceding siblings ...)
2024-12-22 21:47 ` [bug#75027] [PATCH 0/3] 'guix system reconfigure' loads system for kexec reboot Jakob Kirsch via Guix-patches via
@ 2024-12-26 17:21 ` Ludovic Courtès
2024-12-26 17:21 ` [bug#75027] [PATCH v2 1/3] syscalls: Add ‘kexec-load-file’ Ludovic Courtès
` (2 more replies)
4 siblings, 3 replies; 11+ messages in thread
From: Ludovic Courtès @ 2024-12-26 17:21 UTC (permalink / raw)
To: 75027
Cc: Jakob Kirsch, Ludovic Courtès, Christopher Baines,
Josselin Poiret, Ludovic Courtès, Mathieu Othacehe,
Maxim Cournoyer, Simon Tournier, Tobias Geerinckx-Rice
Hello,
Changes compared to v1:
• Move kexec code outside of ‘upgrade-shepherd-services’. Now both
(guix scripts system) and (gnu machine ssh) have to explicitly
call ‘load-system-for-kexec’.
• Add ‘--no-kexec’ command-line option for ‘guix system reconfigure’,
as Jakob suggested.
• Document kexec support under “Invoking guix system”.
The one thing I didn’t do is add a “kexec” symlink in the system; as it
turns out that’s not easily doable because of the circular dependency:
code returned by ‘kexec-loading-program’ needs to refer to the operating
system in which it would appear.
If we find a way to work around this, maybe we can add this later.
Thoughts?
Ludo’.
Ludovic Courtès (3):
syscalls: Add ‘kexec-load-file’.
system: Export ‘…-initrd-file’ and ‘…-root-file-system’.
reconfigure: Support loading the system for kexec reboot.
doc/guix.texi | 11 +++-
gnu/machine/ssh.scm | 9 +++-
gnu/system.scm | 4 +-
gnu/tests/reconfigure.scm | 78 +++++++++++++++++++++++++++++
guix/build/syscalls.scm | 54 ++++++++++++++++++++
guix/scripts/system.scm | 17 ++++++-
guix/scripts/system/reconfigure.scm | 31 ++++++++++++
tests/syscalls.scm | 13 +++++
8 files changed, 213 insertions(+), 4 deletions(-)
base-commit: f96c14e3ca6b22e56621cc04a1bf06a8cac6ca23
--
2.46.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [bug#75027] [PATCH v2 1/3] syscalls: Add ‘kexec-load-file’.
2024-12-26 17:21 ` [bug#75027] [PATCH v2 " Ludovic Courtès
@ 2024-12-26 17:21 ` Ludovic Courtès
2024-12-26 17:21 ` [bug#75027] [PATCH v2 2/3] system: Export ‘…-initrd-file’ and ‘…-root-file-system’ Ludovic Courtès
2024-12-26 17:21 ` [bug#75027] [PATCH v2 3/3] reconfigure: Support loading the system for kexec reboot Ludovic Courtès
2 siblings, 0 replies; 11+ messages in thread
From: Ludovic Courtès @ 2024-12-26 17:21 UTC (permalink / raw)
To: 75027; +Cc: Ludovic Courtès
* guix/build/syscalls.scm (string->utf-8/nul-terminated)
(kexec-load-file): New procedures.
* tests/syscalls.scm ("kexec-load-file"): New test.
Change-Id: I3724226a14ecc07f346e77519fb5b0591096c7f6
---
guix/build/syscalls.scm | 54 +++++++++++++++++++++++++++++++++++++++++
tests/syscalls.scm | 13 ++++++++++
2 files changed, 67 insertions(+)
diff --git a/guix/build/syscalls.scm b/guix/build/syscalls.scm
index 2c20edf058..f8c9937f54 100644
--- a/guix/build/syscalls.scm
+++ b/guix/build/syscalls.scm
@@ -146,6 +146,12 @@ (define-module (guix build syscalls)
clone
setns
+ kexec-load-file
+ KEXEC_FILE_UNLOAD
+ KEXEC_FILE_ON_CRASH
+ KEXEC_FILE_NO_INITRAMFS
+ KEXEC_FILE_DEBUG
+
PF_PACKET
AF_PACKET
all-network-interface-names
@@ -765,6 +771,54 @@ (define-as-needed load-linux-module
(list (strerror err))
(list err)))))))
+(define (string->utf-8/nul-terminated str)
+ "Serialize STR to UTF-8; return the resulting bytevector, including
+terminating nul character."
+ (let* ((source (string->utf8 str))
+ (bv (make-bytevector (+ (bytevector-length source) 1) 0)))
+ (bytevector-copy! source 0 bv 0 (bytevector-length source))
+ bv))
+
+;; Constants from <linux/kexec.h>.
+(define KEXEC_FILE_UNLOAD #x00000001)
+(define KEXEC_FILE_ON_CRASH #x00000002)
+(define KEXEC_FILE_NO_INITRAMFS #x00000004)
+(define KEXEC_FILE_DEBUG #x00000008)
+
+(define kexec-load-file
+ (let* ((proc (syscall->procedure int "syscall"
+ (list long ;sysno
+ int ;kernel fd
+ int ;initrd fd
+ unsigned-long ;cmdline length
+ '* ;cmdline
+ unsigned-long))) ;flags
+ ;; TODO: Don't do this.
+ (syscall-id (match (utsname:machine (uname))
+ ("i686" 320)
+ ("x86_64" 320)
+ ("armv7l" 401)
+ ("aarch64" 401)
+ ;; XXX: There's apparently no support for ppc64le and
+ ;; riscv64.
+ (_ #f))))
+ (lambda* (kernel-fd initrd-fd command-line #:optional (flags 0))
+ "Load for eventual use of kexec(8) the Linux kernel from
+@var{kernel-fd}, its initial RAM disk from @var{initrd-fd}, with the given
+@var{command-line} (a string). Optionally, @var{flags} can be a bitwise or of
+the KEXEC_FILE_* constants."
+ (let*-values (((command-line)
+ (string->utf-8/nul-terminated command-line))
+ ((ret err)
+ (proc syscall-id kernel-fd initrd-fd
+ (bytevector-length command-line)
+ (bytevector->pointer command-line)
+ flags)))
+ (when (= ret -1)
+ (throw 'system-error "kexec-load-file" "~A"
+ (list (strerror err))
+ (list err)))))))
+
(define (linux-process-flags pid) ;copied from the Shepherd
"Return the process flags of @var{pid} (or'd @code{PF_} constants), assuming
the Linux /proc file system is mounted; raise a @code{system-error} exception
diff --git a/tests/syscalls.scm b/tests/syscalls.scm
index 13f4f11721..eef864d097 100644
--- a/tests/syscalls.scm
+++ b/tests/syscalls.scm
@@ -679,6 +679,19 @@ (define perform-container-tests?
(lambda args
(system-error-errno args))))))
+(when (or (zero? (getuid))
+ (not (string-contains %host-type "linux")))
+ (test-skip 1))
+(test-equal "kexec-load-file"
+ EPERM
+ (catch 'system-error
+ (lambda ()
+ (let ((fd1 (open-fdes "/dev/null" O_RDONLY))
+ (fd2 (open-fdes "/dev/null" O_RDONLY)))
+ (kexec-load-file fd1 fd2 "gnu.repl=yes")))
+ (lambda args
+ (system-error-errno args))))
+
(test-end)
(false-if-exception (delete-file temp-file))
--
2.46.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [bug#75027] [PATCH v2 2/3] system: Export ‘…-initrd-file’ and ‘…-root-file-system’.
2024-12-26 17:21 ` [bug#75027] [PATCH v2 " Ludovic Courtès
2024-12-26 17:21 ` [bug#75027] [PATCH v2 1/3] syscalls: Add ‘kexec-load-file’ Ludovic Courtès
@ 2024-12-26 17:21 ` Ludovic Courtès
2024-12-26 17:21 ` [bug#75027] [PATCH v2 3/3] reconfigure: Support loading the system for kexec reboot Ludovic Courtès
2 siblings, 0 replies; 11+ messages in thread
From: Ludovic Courtès @ 2024-12-26 17:21 UTC (permalink / raw)
To: 75027; +Cc: Ludovic Courtès
* gnu/system.scm (operating-system-initrd-file): Fix docstring and
export.
(operating-system-root-file-system): Export.
Change-Id: I5254d82ce547e8014027ed20675b8bfe5a5847c5
---
gnu/system.scm | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/gnu/system.scm b/gnu/system.scm
index dfcb8fb279..252a26cac3 100644
--- a/gnu/system.scm
+++ b/gnu/system.scm
@@ -110,6 +110,7 @@ (define-module (gnu system)
operating-system-default-label
operating-system-initrd-modules
operating-system-initrd
+ operating-system-initrd-file
operating-system-users
operating-system-groups
operating-system-issue
@@ -119,6 +120,7 @@ (define-module (gnu system)
operating-system-locale-libcs
operating-system-mapped-devices
operating-system-file-systems
+ operating-system-root-file-system
operating-system-store-file-system
operating-system-user-mapped-devices
operating-system-boot-mapped-devices
@@ -1355,7 +1357,7 @@ (define (operating-system-root-file-system os)
(location (operating-system-location os)))))))
(define (operating-system-initrd-file os)
- "Return a gexp denoting the initrd file of OS."
+ "Return a file-like object for the initrd file of OS."
(define boot-file-systems
(filter file-system-needed-for-boot?
(operating-system-file-systems os)))
--
2.46.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [bug#75027] [PATCH v2 3/3] reconfigure: Support loading the system for kexec reboot.
2024-12-26 17:21 ` [bug#75027] [PATCH v2 " Ludovic Courtès
2024-12-26 17:21 ` [bug#75027] [PATCH v2 1/3] syscalls: Add ‘kexec-load-file’ Ludovic Courtès
2024-12-26 17:21 ` [bug#75027] [PATCH v2 2/3] system: Export ‘…-initrd-file’ and ‘…-root-file-system’ Ludovic Courtès
@ 2024-12-26 17:21 ` Ludovic Courtès
2 siblings, 0 replies; 11+ messages in thread
From: Ludovic Courtès @ 2024-12-26 17:21 UTC (permalink / raw)
To: 75027
Cc: Ludovic Courtès, Christopher Baines, Josselin Poiret,
Ludovic Courtès, Mathieu Othacehe, Maxim Cournoyer,
Simon Tournier, Tobias Geerinckx-Rice
This allows rebooting straight into the new system with ‘reboot -k’.
* guix/scripts/system/reconfigure.scm (kexec-loading-program)
(load-system-for-kexec): New procedures.
* gnu/tests/reconfigure.scm (run-kexec-test): New procedure.
(%test-upgrade-kexec): New variable.
* guix/scripts/system.scm (perform-action): Add #:load-for-kexec?.
Call ‘load-system-for-kexec’.
(show-help, %options): Add ‘--no-kexec’.
(%default-options): Add ‘load-for-kexec?’.
(process-action): Honor it and pass it to ‘perform-action’.
* gnu/machine/ssh.scm (deploy-managed-host): Add call to
‘load-system-for-kexec’.
* doc/guix.texi (Invoking guix system): Document it.
Change-Id: I86d11f1c348e4359bc9e73c86e5aebff60fe875c
---
doc/guix.texi | 11 +++-
gnu/machine/ssh.scm | 9 +++-
gnu/tests/reconfigure.scm | 78 +++++++++++++++++++++++++++++
guix/scripts/system.scm | 17 ++++++-
guix/scripts/system/reconfigure.scm | 31 ++++++++++++
5 files changed, 143 insertions(+), 3 deletions(-)
diff --git a/doc/guix.texi b/doc/guix.texi
index da4d2f5ebc..7bf14a49e9 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -43599,11 +43599,20 @@ Invoking guix system
overwritten. This behavior mirrors that of @command{guix package}
(@pxref{Invoking guix package}).
-It also adds a bootloader menu entry for the new OS configuration,
+It adds a bootloader menu entry for the new OS configuration,
---unless @option{--no-bootloader} is passed. For GRUB, it moves
entries for older configurations to a submenu, allowing you to choose
an older system generation at boot time should you need it.
+@cindex kexec, for fast reboots
+@cindex rebooting @i{via} Linux kexec
+On Linux, @command{guix system reconfigure} also loads the new system
+for fast reboot @i{via} kexec: running @command{reboot --kexec} will
+boot the new system by directly executing its kernel, thus bypassing the
+BIOS initialization phase and bootloader (@pxref{Invoking reboot,,,
+shepherd, The GNU Shepherd Manual}). You can avoid this behavior by
+passing the @option{--no-kexec} option.
+
@cindex provenance tracking, of the operating system
Upon completion, the new system is deployed under
@file{/run/current-system}. This directory contains @dfn{provenance
diff --git a/gnu/machine/ssh.scm b/gnu/machine/ssh.scm
index 3e10d984e7..f58fcdaf4a 100644
--- a/gnu/machine/ssh.scm
+++ b/gnu/machine/ssh.scm
@@ -1,6 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2019 Jakob L. Kreuze <zerodaysfordays@sdf.org>
-;;; Copyright © 2020-2023 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2020-2024 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2024 Ricardo <rekado@elephly.net>
;;;
;;; This file is part of GNU Guix.
@@ -552,6 +552,13 @@ (define (deploy-managed-host machine)
(inferior-exception-arguments
c)))
os)
+ (load-system-for-kexec (eval/error-handling c
+ (warning (G_ "\
+failed to load system of '~a' for kexec reboot:~%~{~s ~}~%")
+ host
+ (inferior-exception-arguments
+ c)))
+ os)
(install-bootloader (eval/error-handling c
(raise (formatted-message
(G_ "\
diff --git a/gnu/tests/reconfigure.scm b/gnu/tests/reconfigure.scm
index bcc7645fa3..a24a953e6e 100644
--- a/gnu/tests/reconfigure.scm
+++ b/gnu/tests/reconfigure.scm
@@ -1,5 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2019 Jakob L. Kreuze <zerodaysfordays@sdf.org>
+;;; Copyright © 2024 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -18,9 +19,12 @@
(define-module (gnu tests reconfigure)
#:use-module (gnu bootloader)
+ #:use-module (gnu services)
+ #:use-module (gnu services base)
#:use-module (gnu services shepherd)
#:use-module (gnu system)
#:use-module (gnu system accounts)
+ #:use-module (gnu system file-systems)
#:use-module (gnu system shadow)
#:use-module (gnu system vm)
#:use-module (gnu tests)
@@ -31,6 +35,7 @@ (define-module (gnu tests reconfigure)
#:use-module (guix store)
#:export (%test-switch-to-system
%test-upgrade-services
+ %test-upgrade-kexec
%test-install-bootloader))
;;; Commentary:
@@ -178,6 +183,73 @@ (define* (run-upgrade-services-test)
(disable (upgrade-services-program '() '() '(dummy) '())))
(test enable disable))))
+(define (run-kexec-test)
+ "Run a test aiming to reboot via Linux kexec into a new system."
+ (define os
+ (marionette-operating-system
+ (operating-system
+ (inherit %simple-os)
+ (services (modify-services %base-services
+ (syslog-service-type
+ config => (syslog-configuration
+ (inherit config)
+ (config-file
+ (plain-file
+ "syslog.conf"
+ "*.* /dev/console\n")))))))
+ #:imported-modules '((gnu services herd)
+ (guix combinators))))
+
+ (define new-os
+ (marionette-operating-system
+ (virtualized-operating-system ;run as with "guix system vm"
+ (operating-system
+ (inherit %simple-os)
+ (host-name "the-new-os")
+ (kernel-arguments '("console=ttyS0"))) ;be verbose
+ #:volatile? #t) ;mount root read-only
+ #:imported-modules '((gnu services herd)
+ (guix combinators))))
+
+ (define vm (virtual-machine os))
+
+ (define test
+ (with-imported-modules '((gnu build marionette))
+ #~(begin
+ (use-modules (gnu build marionette)
+ (srfi srfi-64))
+
+ (define marionette
+ (make-marionette (list #$vm)))
+
+ (test-runner-current (system-test-runner #$output))
+ (test-begin "kexec")
+
+ (test-equal "host name"
+ #$(operating-system-host-name os)
+ (marionette-eval '(gethostname) marionette))
+
+ (test-assert "kexec-loading-program"
+ (marionette-eval
+ '(primitive-load #$(kexec-loading-program new-os))
+ marionette))
+
+ (test-assert "reboot/kexec"
+ (marionette-eval
+ '(begin
+ (use-modules (gnu services herd))
+ (with-shepherd-action 'root ('kexec) result
+ (pk 'reboot-kexec result)))
+ marionette))
+
+ (test-equal "host name of new OS"
+ #$(operating-system-host-name new-os)
+ (marionette-eval '(gethostname) marionette))
+
+ (test-end))))
+
+ (gexp->derivation "kexec-test" test))
+
(define* (run-install-bootloader-test)
"Run a test of an OS running INSTALL-BOOTLOADER-PROGRAM, which installs a
bootloader's configuration file."
@@ -268,6 +340,12 @@ (define %test-upgrade-services
loading new services.")
(value (run-upgrade-services-test))))
+(define %test-upgrade-kexec
+ (system-test
+ (name "upgrade-kexec")
+ (description "Load a system and reboot into it via Linux kexec.")
+ (value (run-kexec-test))))
+
(define %test-install-bootloader
(system-test
(name "install-bootloader")
diff --git a/guix/scripts/system.scm b/guix/scripts/system.scm
index dd34f6cd15..f174c8ada1 100644
--- a/guix/scripts/system.scm
+++ b/guix/scripts/system.scm
@@ -798,6 +798,7 @@ (define* (perform-action action image
save-provenance?
skip-safety-checks?
install-bootloader?
+ load-for-kexec?
dry-run? derivations-only?
use-substitutes? target
full-boot?
@@ -900,7 +901,13 @@ (define* (perform-action action image
To complete the upgrade, run 'herd restart SERVICE' to stop,
upgrade, and restart each service that was not automatically restarted.\n")))
(return (format #t (G_ "\
-Run 'herd status' to view the list of services on your system.\n"))))))
+Run 'herd status' to view the list of services on your system.\n"))))
+ (mwhen load-for-kexec?
+ (mlet %store-monad ((kexec? (load-system-for-kexec local-eval
+ os)))
+ (mwhen kexec?
+ (return (info (G_ "system loaded for fast reboot \
+ with 'reboot --kexec'~%"))))))))
((init)
(newline)
(format #t (G_ "initializing operating system under '~a'...~%")
@@ -1025,6 +1032,8 @@ (define (show-help)
--image-size=SIZE for 'image', produce an image of SIZE"))
(display (G_ "
--no-bootloader for 'init', do not install a bootloader"))
+ (display (G_ "
+ --no-kexec for 'reconfigure', do not load system for kexec reboot"))
(display (G_ "
--volatile for 'image', make the root file system volatile"))
(display (G_ "
@@ -1127,6 +1136,9 @@ (define %options
(option '("no-bootloader" "no-grub") #f #f
(lambda (opt name arg result)
(alist-cons 'install-bootloader? #f result)))
+ (option '("no-kexec") #f #f
+ (lambda (opt name arg result)
+ (alist-cons 'load-for-kexec? #f result)))
(option '("volatile") #f #f
(lambda (opt name arg result)
(alist-cons 'volatile-image-root? #t result)))
@@ -1198,6 +1210,7 @@ (define %default-options
(image-type . mbr-hybrid-raw)
(image-size . guess)
(install-bootloader? . #t)
+ (load-for-kexec? . #t)
(label . #f)
(volatile-image-root? . #f)
(volatile-vm-root? . #t)
@@ -1275,6 +1288,7 @@ (define (process-action action args opts)
(leave (G_ "no configuration specified~%")))))))
(dry? (assoc-ref opts 'dry-run?))
(bootloader? (assoc-ref opts 'install-bootloader?))
+ (kexec? (assoc-ref opts 'load-for-kexec?))
(label (assoc-ref opts 'label))
(image-type (lookup-image-type-by-name
(assoc-ref opts 'image-type)))
@@ -1360,6 +1374,7 @@ (define (process-action action args opts)
(_ #f))
opts)
#:install-bootloader? bootloader?
+ #:load-for-kexec? kexec?
#:target target-file
#:gc-root (assoc-ref opts 'gc-root)))))
#:target target
diff --git a/guix/scripts/system/reconfigure.scm b/guix/scripts/system/reconfigure.scm
index ddb561d28c..e9e16e3422 100644
--- a/guix/scripts/system/reconfigure.scm
+++ b/guix/scripts/system/reconfigure.scm
@@ -31,6 +31,7 @@ (define-module (guix scripts system reconfigure)
#:use-module (gnu services herd)
#:use-module (gnu services shepherd)
#:use-module (gnu system)
+ #:autoload (gnu system file-systems) (file-system-device)
#:use-module (guix gexp)
#:use-module (guix modules)
#:use-module (guix monads)
@@ -52,6 +53,9 @@ (define-module (guix scripts system reconfigure)
upgrade-services-program
upgrade-shepherd-services
+ kexec-loading-program
+ load-system-for-kexec
+
install-bootloader-program
install-bootloader
@@ -176,6 +180,27 @@ (define (upgrade-services-program service-files to-start to-unload to-restart)
(for-each unload-service '#$to-unload)
(for-each start-service '#$to-start)))))
+(define (kexec-loading-program os)
+ "Return a program that calls 'kexec_file_load' to allow rebooting into OS
+via 'kexec'."
+ (let ((root-device (file-system-device
+ (operating-system-root-file-system os))))
+ (program-file
+ "kexec-load-system.scm"
+ (with-imported-modules '((guix build syscalls))
+ #~(begin
+ (use-modules (guix build syscalls))
+
+ (let ((kernel (open-fdes #$(operating-system-kernel-file os)
+ O_RDONLY))
+ (initrd (open-fdes #$(operating-system-initrd-file os)
+ O_RDONLY)))
+ (kexec-load-file kernel initrd
+ (string-join
+ (list #$@(operating-system-kernel-arguments
+ os root-device)))
+ KEXEC_FILE_DEBUG)))))))
+
(define* (upgrade-shepherd-services eval os)
"Using EVAL, a monadic procedure taking a single G-Expression as an argument,
upgrade the Shepherd (PID 1) by unloading obsolete services and loading new
@@ -205,6 +230,12 @@ (define* (upgrade-shepherd-services eval os)
to-unload
to-restart)))))))
+(define (load-system-for-kexec eval os)
+ "Load OS so that it can be rebooted into via kexec, if supported. Return
+true on success."
+ (eval #~(and (string-contains %host-type "-linux")
+ (primitive-load #$(kexec-loading-program os)))))
+
\f
;;;
;;; Bootloader configuration.
--
2.46.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [bug#75027] [PATCH 0/3] 'guix system reconfigure' loads system for kexec reboot
2024-12-23 18:24 ` Jakob Kirsch via Guix-patches via
@ 2024-12-26 17:25 ` Ludovic Courtès
0 siblings, 0 replies; 11+ messages in thread
From: Ludovic Courtès @ 2024-12-26 17:25 UTC (permalink / raw)
To: Jakob Kirsch; +Cc: 75027
Hi,
Jakob Kirsch <jakob.kirsch@web.de> skribis:
> On Mon, Dec 23, 2024 at 12:22:20PM +0100, Ludovic Courtès wrote:
>> In addition to or instead of running it by default?
>
> I would say in addition to but with a flag to not load it (like with "--no-bootloader" for the bootloader).
I sent v2, which includes some of your suggestions, but unfortunately
not the “kexec” system entry.
> Btw I've also noticed that the framebuffer is only initialized after something graphical (gdm in my case) has been started. This usually isn't an issue for most users but my disks are encrypted so I can't see the password prompt but I can still type in my password.
Weird; for me the Linux framebuffer is initialized early on.
Perhaps report a bug with details about your hardware and OS config?
Ludo’.
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2024-12-26 17:26 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-22 15:56 [bug#75027] [PATCH 0/3] 'guix system reconfigure' loads system for kexec reboot Ludovic Courtès
2024-12-22 15:57 ` [bug#75027] [PATCH 1/3] syscalls: Add ‘kexec-load-file’ Ludovic Courtès
2024-12-22 15:57 ` [bug#75027] [PATCH 2/3] system: Export ‘…-initrd-file’ and ‘…-root-file-system’ Ludovic Courtès
2024-12-22 15:57 ` [bug#75027] [PATCH 3/3] reconfigure: Call ‘kexec-load-file’ Ludovic Courtès
2024-12-22 21:47 ` [bug#75027] [PATCH 0/3] 'guix system reconfigure' loads system for kexec reboot Jakob Kirsch via Guix-patches via
[not found] ` <87y106ej9v.fsf@gnu.org>
2024-12-23 18:24 ` Jakob Kirsch via Guix-patches via
2024-12-26 17:25 ` Ludovic Courtès
2024-12-26 17:21 ` [bug#75027] [PATCH v2 " Ludovic Courtès
2024-12-26 17:21 ` [bug#75027] [PATCH v2 1/3] syscalls: Add ‘kexec-load-file’ Ludovic Courtès
2024-12-26 17:21 ` [bug#75027] [PATCH v2 2/3] system: Export ‘…-initrd-file’ and ‘…-root-file-system’ Ludovic Courtès
2024-12-26 17:21 ` [bug#75027] [PATCH v2 3/3] reconfigure: Support loading the system for kexec reboot Ludovic Courtès
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/guix.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).