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