gnu: diffoscope: Update to 136.
[jackhill/guix/guix.git] / gnu / services / virtualization.scm
CommitLineData
e6051057
RM
1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2017 Ryan Moe <ryan.moe@gmail.com>
6738c29f 3;;; Copyright © 2018 Ludovic Courtès <ludo@gnu.org>
e6051057
RM
4;;;
5;;; This file is part of GNU Guix.
6;;;
7;;; GNU Guix is free software; you can redistribute it and/or modify it
8;;; under the terms of the GNU General Public License as published by
9;;; the Free Software Foundation; either version 3 of the License, or (at
10;;; your option) any later version.
11;;;
12;;; GNU Guix is distributed in the hope that it will be useful, but
13;;; WITHOUT ANY WARRANTY; without even the implied warranty of
14;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;;; GNU General Public License for more details.
16;;;
17;;; You should have received a copy of the GNU General Public License
18;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
19
20(define-module (gnu services virtualization)
21 #:use-module (gnu services)
22 #:use-module (gnu services configuration)
23 #:use-module (gnu services base)
24 #:use-module (gnu services dbus)
25 #:use-module (gnu services shepherd)
26 #:use-module (gnu system shadow)
6738c29f 27 #:use-module (gnu system file-systems)
e6051057
RM
28 #:use-module (gnu packages admin)
29 #:use-module (gnu packages virtualization)
30 #:use-module (guix records)
31 #:use-module (guix gexp)
32 #:use-module (guix packages)
6738c29f
LC
33 #:use-module (srfi srfi-9)
34 #:use-module (srfi srfi-26)
35 #:use-module (rnrs bytevectors)
e6051057
RM
36 #:use-module (ice-9 match)
37
38 #:export (libvirt-configuration
39 libvirt-service-type
daf823ad 40 virtlog-configuration
6738c29f
LC
41 virtlog-service-type
42
43 %qemu-platforms
44 lookup-qemu-platforms
45 qemu-platform?
46 qemu-platform-name
47
48 qemu-binfmt-configuration
49 qemu-binfmt-configuration?
50 qemu-binfmt-service-type))
e6051057
RM
51
52(define (uglify-field-name field-name)
53 (let ((str (symbol->string field-name)))
54 (string-join
55 (string-split (string-delete #\? str) #\-)
56 "_")))
57
58(define (quote-val val)
59 (string-append "\"" val "\""))
60
61(define (serialize-field field-name val)
62 (format #t "~a = ~a\n" (uglify-field-name field-name) val))
63
64(define (serialize-string field-name val)
65 (serialize-field field-name (quote-val val)))
66
67(define (serialize-boolean field-name val)
68 (serialize-field field-name (if val 1 0)))
69
70(define (serialize-integer field-name val)
71 (serialize-field field-name val))
72
73(define (build-opt-list val)
74 (string-append
75 "["
76 (string-join (map quote-val val) ",")
77 "]"))
78
79(define optional-list? list?)
80(define optional-string? string?)
81
82(define (serialize-list field-name val)
83 (serialize-field field-name (build-opt-list val)))
84
85(define (serialize-optional-list field-name val)
86 (if (null? val)
87 (format #t "# ~a = []\n" (uglify-field-name field-name))
88 (serialize-list field-name val)))
89
90(define (serialize-optional-string field-name val)
91 (if (string-null? val)
92 (format #t "# ~a = \"\"\n" (uglify-field-name field-name))
93 (serialize-string field-name val)))
94
95(define-configuration libvirt-configuration
96 (libvirt
97 (package libvirt)
98 "Libvirt package.")
99 (listen-tls?
100 (boolean #t)
101 "Flag listening for secure TLS connections on the public TCP/IP port.
102must set @code{listen} for this to have any effect.
103
104It is necessary to setup a CA and issue server certificates before
105using this capability.")
106 (listen-tcp?
107 (boolean #f)
108 "Listen for unencrypted TCP connections on the public TCP/IP port.
109must set @code{listen} for this to have any effect.
110
111Using the TCP socket requires SASL authentication by default. Only
112SASL mechanisms which support data encryption are allowed. This is
113DIGEST_MD5 and GSSAPI (Kerberos5)")
114 (tls-port
115 (string "16514")
116 "Port for accepting secure TLS connections This can be a port number,
117or service name")
118 (tcp-port
119 (string "16509")
120 "Port for accepting insecure TCP connections This can be a port number,
121or service name")
122 (listen-addr
123 (string "0.0.0.0")
124 "IP address or hostname used for client connections.")
125 (mdns-adv?
126 (boolean #f)
127 "Flag toggling mDNS advertisement of the libvirt service.
128
129Alternatively can disable for all services on a host by
130stopping the Avahi daemon.")
131 (mdns-name
132 (string (string-append "Virtualization Host " (gethostname)))
133 "Default mDNS advertisement name. This must be unique on the
134immediate broadcast network.")
135 (unix-sock-group
136 (string "root")
137 "UNIX domain socket group ownership. This can be used to
138allow a 'trusted' set of users access to management capabilities
139without becoming root.")
140 (unix-sock-ro-perms
141 (string "0777")
142 "UNIX socket permissions for the R/O socket. This is used
143for monitoring VM status only.")
144 (unix-sock-rw-perms
145 (string "0770")
146 "UNIX socket permissions for the R/W socket. Default allows
147only root. If PolicyKit is enabled on the socket, the default
148will change to allow everyone (eg, 0777)")
149 (unix-sock-admin-perms
150 (string "0777")
151 "UNIX socket permissions for the admin socket. Default allows
152only owner (root), do not change it unless you are sure to whom
153you are exposing the access to.")
154 (unix-sock-dir
155 (string "/var/run/libvirt")
156 "The directory in which sockets will be found/created.")
157 (auth-unix-ro
158 (string "polkit")
159 "Authentication scheme for UNIX read-only sockets. By default
160socket permissions allow anyone to connect")
161 (auth-unix-rw
162 (string "polkit")
163 "Authentication scheme for UNIX read-write sockets. By default
164socket permissions only allow root. If PolicyKit support was compiled
165into libvirt, the default will be to use 'polkit' auth.")
166 (auth-tcp
167 (string "sasl")
168 "Authentication scheme for TCP sockets. If you don't enable SASL,
169then all TCP traffic is cleartext. Don't do this outside of a dev/test
170scenario.")
171 (auth-tls
172 (string "none")
173 "Authentication scheme for TLS sockets. TLS sockets already have
174encryption provided by the TLS layer, and limited authentication is
175done by certificates.
176
177It is possible to make use of any SASL authentication mechanism as
178well, by using 'sasl' for this option")
179 (access-drivers
180 (optional-list '())
181 "API access control scheme.
182
183By default an authenticated user is allowed access to all APIs. Access
184drivers can place restrictions on this.")
185 (key-file
186 (string "")
187 "Server key file path. If set to an empty string, then no private key
188is loaded.")
189 (cert-file
190 (string "")
191 "Server key file path. If set to an empty string, then no certificate
192is loaded.")
193 (ca-file
194 (string "")
195 "Server key file path. If set to an empty string, then no CA certificate
196is loaded.")
197 (crl-file
198 (string "")
199 "Certificate revocation list path. If set to an empty string, then no
200CRL is loaded.")
201 (tls-no-sanity-cert
202 (boolean #f)
203 "Disable verification of our own server certificates.
204
205When libvirtd starts it performs some sanity checks against its own
206certificates.")
207 (tls-no-verify-cert
208 (boolean #f)
209 "Disable verification of client certificates.
210
211Client certificate verification is the primary authentication mechanism.
212Any client which does not present a certificate signed by the CA
213will be rejected.")
214 (tls-allowed-dn-list
215 (optional-list '())
216 "Whitelist of allowed x509 Distinguished Name.")
217 (sasl-allowed-usernames
218 (optional-list '())
219 "Whitelist of allowed SASL usernames. The format for username
220depends on the SASL authentication mechanism.")
221 (tls-priority
222 (string "NORMAL")
223 "Override the compile time default TLS priority string. The
224default is usually \"NORMAL\" unless overridden at build time.
225Only set this is it is desired for libvirt to deviate from
226the global default settings.")
227 (max-clients
228 (integer 5000)
229 "Maximum number of concurrent client connections to allow
230over all sockets combined.")
231 (max-queued-clients
232 (integer 1000)
233 "Maximum length of queue of connections waiting to be
234accepted by the daemon. Note, that some protocols supporting
235retransmission may obey this so that a later reattempt at
236connection succeeds.")
237 (max-anonymous-clients
238 (integer 20)
239 "Maximum length of queue of accepted but not yet authenticated
240clients. Set this to zero to turn this feature off")
241 (min-workers
242 (integer 5)
243 "Number of workers to start up initially.")
244 (max-workers
245 (integer 20)
246 "Maximum number of worker threads.
247
248If the number of active clients exceeds @code{min-workers},
249then more threads are spawned, up to max_workers limit.
250Typically you'd want max_workers to equal maximum number
251of clients allowed.")
252 (prio-workers
253 (integer 5)
254 "Number of priority workers. If all workers from above
255pool are stuck, some calls marked as high priority
256(notably domainDestroy) can be executed in this pool.")
257 (max-requests
258 (integer 20)
259 "Total global limit on concurrent RPC calls.")
260 (max-client-requests
261 (integer 5)
262 "Limit on concurrent requests from a single client
263connection. To avoid one client monopolizing the server
264this should be a small fraction of the global max_requests
265and max_workers parameter.")
266 (admin-min-workers
267 (integer 1)
268 "Same as @code{min-workers} but for the admin interface.")
269 (admin-max-workers
270 (integer 5)
271 "Same as @code{max-workers} but for the admin interface.")
272 (admin-max-clients
273 (integer 5)
274 "Same as @code{max-clients} but for the admin interface.")
275 (admin-max-queued-clients
276 (integer 5)
277 "Same as @code{max-queued-clients} but for the admin interface.")
278 (admin-max-client-requests
279 (integer 5)
280 "Same as @code{max-client-requests} but for the admin interface.")
281 (log-level
282 (integer 3)
283 "Logging level. 4 errors, 3 warnings, 2 information, 1 debug.")
284 (log-filters
285 (string "3:remote 4:event")
286 "Logging filters.
287
288A filter allows to select a different logging level for a given category
289of logs
290The format for a filter is one of:
291@itemize
292@item x:name
293
294@item x:+name
295@end itemize
296
297where @code{name} is a string which is matched against the category
298given in the @code{VIR_LOG_INIT()} at the top of each libvirt source
299file, e.g., \"remote\", \"qemu\", or \"util.json\" (the name in the
300filter can be a substring of the full category name, in order
301to match multiple similar categories), the optional \"+\" prefix
302tells libvirt to log stack trace for each message matching
303name, and @code{x} is the minimal level where matching messages should
304be logged:
305
306@itemize
307@item 1: DEBUG
308@item 2: INFO
309@item 3: WARNING
310@item 4: ERROR
311@end itemize
312
313Multiple filters can be defined in a single filters statement, they just
314need to be separated by spaces.")
315 (log-outputs
b64fa7f0 316 (string "3:syslog:libvirtd")
e6051057
RM
317 "Logging outputs.
318
319An output is one of the places to save logging information
320The format for an output can be:
321
322@table @code
323@item x:stderr
324output goes to stderr
325
326@item x:syslog:name
327use syslog for the output and use the given name as the ident
328
329@item x:file:file_path
330output to a file, with the given filepath
331
332@item x:journald
333output to journald logging system
334@end table
335
336In all case the x prefix is the minimal level, acting as a filter
337
338@itemize
339@item 1: DEBUG
340@item 2: INFO
341@item 3: WARNING
342@item 4: ERROR
343@end itemize
344
345Multiple outputs can be defined, they just need to be separated by spaces.")
346 (audit-level
347 (integer 1)
348 "Allows usage of the auditing subsystem to be altered
349
350@itemize
351@item 0: disable all auditing
352@item 1: enable auditing, only if enabled on host
353@item 2: enable auditing, and exit if disabled on host.
354@end itemize
355")
356 (audit-logging
357 (boolean #f)
358 "Send audit messages via libvirt logging infrastructure.")
359 (host-uuid
360 (optional-string "")
361 "Host UUID. UUID must not have all digits be the same.")
362 (host-uuid-source
363 (string "smbios")
364 "Source to read host UUID.
365
366@itemize
367
368@item @code{smbios}: fetch the UUID from @code{dmidecode -s system-uuid}
369
370@item @code{machine-id}: fetch the UUID from @code{/etc/machine-id}
371
372@end itemize
373
374If @code{dmidecode} does not provide a valid UUID a temporary UUID
375will be generated.")
376 (keepalive-interval
377 (integer 5)
378 "A keepalive message is sent to a client after
379@code{keepalive_interval} seconds of inactivity to check if
380the client is still responding. If set to -1, libvirtd will
381never send keepalive requests; however clients can still send
382them and the daemon will send responses.")
383 (keepalive-count
384 (integer 5)
385 "Maximum number of keepalive messages that are allowed to be sent
386to the client without getting any response before the connection is
387considered broken.
388
389In other words, the connection is automatically
390closed approximately after
391@code{keepalive_interval * (keepalive_count + 1)} seconds since the last
392message received from the client. When @code{keepalive-count} is
393set to 0, connections will be automatically closed after
394@code{keepalive-interval} seconds of inactivity without sending any
395keepalive messages.")
396 (admin-keepalive-interval
397 (integer 5)
398 "Same as above but for admin interface.")
399 (admin-keepalive-count
400 (integer 5)
401 "Same as above but for admin interface.")
402 (ovs-timeout
403 (integer 5)
404 "Timeout for Open vSwitch calls.
405
406The @code{ovs-vsctl} utility is used for the configuration and
407its timeout option is set by default to 5 seconds to avoid
408potential infinite waits blocking libvirt."))
409
410(define* (libvirt-conf-file config)
411 "Return a libvirtd config file."
412 (plain-file "libvirtd.conf"
413 (with-output-to-string
414 (lambda ()
415 (serialize-configuration config libvirt-configuration-fields)))))
416
417(define %libvirt-accounts
418 (list (user-group (name "libvirt") (system? #t))))
419
420(define (%libvirt-activation config)
421 (let ((sock-dir (libvirt-configuration-unix-sock-dir config)))
422 #~(begin
423 (use-modules (guix build utils))
424 (mkdir-p #$sock-dir))))
425
426
427(define (libvirt-shepherd-service config)
428 (let* ((config-file (libvirt-conf-file config))
429 (libvirt (libvirt-configuration-libvirt config)))
430 (list (shepherd-service
431 (documentation "Run the libvirt daemon.")
432 (provision '(libvirtd))
433 (start #~(make-forkexec-constructor
434 (list (string-append #$libvirt "/sbin/libvirtd")
5df412bf 435 "-f" #$config-file)
2dfb9ba4 436 ;; For finding qemu and ip binaries.
5df412bf 437 #:environment-variables
2dfb9ba4
MÁAV
438 (list (string-append
439 "PATH=/run/current-system/profile/bin:"
440 "/run/current-system/profile/sbin"))))
e6051057
RM
441 (stop #~(make-kill-destructor))))))
442
443(define libvirt-service-type
444 (service-type (name 'libvirt)
445 (extensions
446 (list
447 (service-extension polkit-service-type
448 (compose list libvirt-configuration-libvirt))
449 (service-extension profile-service-type
ef640db2
SB
450 (lambda (config)
451 (list
452 (libvirt-configuration-libvirt config)
453 qemu)))
e6051057
RM
454 (service-extension activation-service-type
455 %libvirt-activation)
456 (service-extension shepherd-root-service-type
457 libvirt-shepherd-service)
458 (service-extension account-service-type
459 (const %libvirt-accounts))))
460 (default-value (libvirt-configuration))))
461
462
463(define-record-type* <virtlog-configuration>
464 virtlog-configuration make-virtlog-configuration
465 virtlog-configuration?
466 (libvirt virtlog-configuration-libvirt
467 (default libvirt))
468 (log-level virtlog-configuration-log-level
469 (default 3))
470 (log-filters virtlog-configuration-log-filters
471 (default "3:remote 4:event"))
472 (log-outputs virtlog-configuration-log-outputs
473 (default "3:syslog:virtlogd"))
474 (max-clients virtlog-configuration-max-clients
475 (default 1024))
476 (max-size virtlog-configuration-max-size
477 (default 2097152)) ;; 2MB
478 (max-backups virtlog-configuration-max-backups
479 (default 3)))
480
481(define* (virtlogd-conf-file config)
482 "Return a virtlogd config file."
483 (plain-file "virtlogd.conf"
484 (string-append
485 "log_level = " (number->string (virtlog-configuration-log-level config)) "\n"
486 "log_filters = \"" (virtlog-configuration-log-filters config) "\"\n"
487 "log_outputs = \"" (virtlog-configuration-log-outputs config) "\"\n"
488 "max_clients = " (number->string (virtlog-configuration-max-clients config)) "\n"
489 "max_size = " (number->string (virtlog-configuration-max-size config)) "\n"
490 "max_backups = " (number->string (virtlog-configuration-max-backups config)) "\n")))
491
492(define (virtlogd-shepherd-service config)
493 (let* ((config-file (virtlogd-conf-file config))
494 (libvirt (virtlog-configuration-libvirt config)))
495 (list (shepherd-service
496 (documentation "Run the virtlog daemon.")
497 (provision '(virtlogd))
498 (start #~(make-forkexec-constructor
499 (list (string-append #$libvirt "/sbin/virtlogd")
500 "-f" #$config-file)))
501 (stop #~(make-kill-destructor))))))
502
503(define virtlog-service-type
504 (service-type (name 'virtlogd)
505 (extensions
506 (list
507 (service-extension shepherd-root-service-type
508 virtlogd-shepherd-service)))
509 (default-value (virtlog-configuration))))
510
511(define (generate-libvirt-documentation)
512 (generate-documentation
513 `((libvirt-configuration ,libvirt-configuration-fields))
514 'libvirt-configuration))
6738c29f
LC
515
516\f
517;;;
518;;; Transparent QEMU emulation via binfmt_misc.
519;;;
520
521;; Platforms that QEMU can emulate.
522(define-record-type <qemu-platform>
523 (qemu-platform name family magic mask)
524 qemu-platform?
525 (name qemu-platform-name) ;string
526 (family qemu-platform-family) ;string
527 (magic qemu-platform-magic) ;bytevector
528 (mask qemu-platform-mask)) ;bytevector
529
530(define-syntax bv
531 (lambda (s)
532 "Expand the given string into a bytevector."
533 (syntax-case s ()
534 ((_ str)
535 (string? (syntax->datum #'str))
536 (let ((bv (u8-list->bytevector
537 (map char->integer
538 (string->list (syntax->datum #'str))))))
539 bv)))))
540
541;;; The platform descriptions below are taken from
542;;; 'scripts/qemu-binfmt-conf.sh' in QEMU.
543
544(define %i386
545 (qemu-platform "i386" "i386"
546 (bv "\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00")
547 (bv "\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff")))
548
549(define %i486
550 (qemu-platform "i486" "i386"
551 (bv "\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x06\x00")
552 (bv "\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff")))
553
554(define %alpha
555 (qemu-platform "alpha" "alpha"
556 (bv "\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x26\x90")
557 (bv "\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff")))
558
559(define %arm
560 (qemu-platform "arm" "arm"
561 (bv "\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00")
562 (bv "\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff")))
563
564(define %armeb
565 (qemu-platform "armeb" "arm"
566 (bv "\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28")
567 (bv "\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff")))
568
569(define %sparc
570 (qemu-platform "sparc" "sparc"
571 (bv "\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x02")
572 (bv "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff")))
573
574(define %sparc32plus
575 (qemu-platform "sparc32plus" "sparc"
576 (bv "\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x12")
577 (bv "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff")))
578
579(define %ppc
580 (qemu-platform "ppc" "ppc"
581 (bv "\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x14")
582 (bv "\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff")))
583
584(define %ppc64
585 (qemu-platform "ppc64" "ppc"
586 (bv "\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x15")
587 (bv "\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff")))
588
589(define %ppc64le
590 (qemu-platform "ppc64le" "ppcle"
591 (bv "\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x15\x00")
592 (bv "\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\x00")))
593
594(define %m68k
595 (qemu-platform "m68k" "m68k"
596 (bv "\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x04")
597 (bv "\xff\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff")))
598
599;; XXX: We could use the other endianness on a MIPS host.
600(define %mips
601 (qemu-platform "mips" "mips"
602 (bv "\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08")
603 (bv "\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff")))
604
605(define %mipsel
606 (qemu-platform "mipsel" "mips"
607 (bv "\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00")
608 (bv "\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff")))
609
610(define %mipsn32
611 (qemu-platform "mipsn32" "mips"
612 (bv "\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08")
613 (bv "\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff")))
614
615(define %mipsn32el
616 (qemu-platform "mipsn32el" "mips"
617 (bv "\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00")
618 (bv "\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff")))
619
620(define %mips64
621 (qemu-platform "mips64" "mips"
622 (bv "\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08")
623 (bv "\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff")))
624
625(define %mips64el
626 (qemu-platform "mips64el" "mips"
627 (bv "\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00")
628 (bv "\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff")))
629
630(define %sh4
631 (qemu-platform "sh4" "sh4"
632 (bv "\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a\x00")
633 (bv "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff")))
634
635(define %sh4eb
636 (qemu-platform "sh4eb" "sh4"
637 (bv "\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a")
638 (bv "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff")))
639
640(define %s390x
641 (qemu-platform "s390x" "s390x"
642 (bv "\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x16")
643 (bv "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff")))
644
645(define %aarch64
646 (qemu-platform "aarch64" "arm"
647 (bv "\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7\x00")
648 (bv "\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff")))
649
650(define %hppa
651 (qemu-platform "hppa" "hppa"
652 (bv "\x7f\x45\x4c\x46\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x0f")
653 (bv "\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff")))
654
655(define %qemu-platforms
656 (list %i386 %i486 %alpha %arm %sparc32plus %ppc %ppc64 %ppc64le %m68k
657 %mips %mipsel %mipsn32 %mipsn32el %mips64 %mips64el
658 %sh4 %sh4eb %s390x %aarch64 %hppa))
659
660(define (lookup-qemu-platforms . names)
661 "Return the list of QEMU platforms that match NAMES--a list of names such as
662\"arm\", \"hppa\", etc."
663 (filter (lambda (platform)
664 (member (qemu-platform-name platform) names))
665 %qemu-platforms))
666
667(define-record-type* <qemu-binfmt-configuration>
668 qemu-binfmt-configuration make-qemu-binfmt-configuration
669 qemu-binfmt-configuration?
670 (qemu qemu-binfmt-configuration-qemu
671 (default qemu))
672 (platforms qemu-binfmt-configuration-platforms
71b98b9d
LC
673 (default '())) ;safest default
674 (guix-support? qemu-binfmt-configuration-guix-support?
675 (default #f)))
6738c29f
LC
676
677(define (qemu-platform->binfmt qemu platform)
678 "Return a gexp that evaluates to a binfmt string for PLATFORM, using the
679given QEMU package."
680 (define (bytevector->binfmt-string bv)
681 ;; Return a binfmt-friendly string representing BV. Hex-encode every
682 ;; character, in particular because the doc notes "that you must escape
683 ;; any NUL bytes; parsing halts at the first one".
684 (string-concatenate
685 (map (lambda (n)
686 (string-append "\\x"
687 (string-pad (number->string n 16) 2 #\0)))
688 (bytevector->u8-list bv))))
689
690 (match platform
691 (($ <qemu-platform> name family magic mask)
692 ;; See 'Documentation/binfmt_misc.txt' in the kernel.
693 #~(string-append ":qemu-" #$name ":M::"
694 #$(bytevector->binfmt-string magic)
695 ":" #$(bytevector->binfmt-string mask)
696 ":" #$(file-append qemu "/bin/qemu-" name)
697 ":" ;FLAGS go here
698 ))))
699
700(define %binfmt-mount-point
701 (file-system-mount-point %binary-format-file-system))
702
703(define %binfmt-register-file
704 (string-append %binfmt-mount-point "/register"))
705
706(define qemu-binfmt-shepherd-services
707 (match-lambda
708 (($ <qemu-binfmt-configuration> qemu platforms)
709 (list (shepherd-service
710 (provision '(qemu-binfmt))
711 (documentation "Install binfmt_misc handlers for QEMU.")
712 (requirement '(file-system-/proc/sys/fs/binfmt_misc))
713 (start #~(lambda ()
714 ;; Register the handlers for all of PLATFORMS.
715 (for-each (lambda (str)
716 (call-with-output-file
717 #$%binfmt-register-file
718 (lambda (port)
719 (display str port))))
720 (list
721 #$@(map (cut qemu-platform->binfmt qemu
722 <>)
723 platforms)))
724 #t))
725 (stop #~(lambda (_)
726 ;; Unregister the handlers.
727 (for-each (lambda (name)
728 (let ((file (string-append
729 #$%binfmt-mount-point
730 "/qemu-" name)))
731 (call-with-output-file file
732 (lambda (port)
733 (display "-1" port)))))
734 '#$(map qemu-platform-name platforms))
735 #f)))))))
736
71b98b9d
LC
737(define qemu-binfmt-guix-chroot
738 (match-lambda
739 ;; Add QEMU and its dependencies to the guix-daemon chroot so that our
740 ;; binfmt_misc handlers work in the chroot (otherwise 'execve' would fail
741 ;; with ENOENT.)
742 ;;
743 ;; The 'F' flag of binfmt_misc is meant to address this problem by loading
744 ;; the interpreter upfront rather than lazily, but apparently that is
745 ;; insufficient (perhaps it loads the 'qemu-ARCH' binary upfront but looks
746 ;; up its dependencies lazily?).
747 (($ <qemu-binfmt-configuration> qemu platforms guix?)
748 (if guix? (list qemu) '()))))
749
6738c29f
LC
750(define qemu-binfmt-service-type
751 ;; TODO: Make a separate binfmt_misc service out of this?
752 (service-type (name 'qemu-binfmt)
753 (extensions
754 (list (service-extension file-system-service-type
755 (const
756 (list %binary-format-file-system)))
757 (service-extension shepherd-root-service-type
71b98b9d
LC
758 qemu-binfmt-shepherd-services)
759 (service-extension guix-service-type
760 qemu-binfmt-guix-chroot)))
6738c29f
LC
761 (default-value (qemu-binfmt-configuration))
762 (description
763 "This service supports transparent emulation of binaries
764compiled for other architectures using QEMU and the @code{binfmt_misc}
765functionality of the kernel Linux.")))