From mboxrd@z Thu Jan 1 00:00:00 1970 From: Efraim Flashner Subject: Re: [BLOG] custom kernel config Date: Fri, 17 May 2019 10:50:45 +0300 Message-ID: <20190517075045.GC9163@macbook41> References: <20190401180434.GF21029@macbook41> <20190515180945.GA7636@macbook41> <87h89uo4kb.fsf@devup.no> <87d0kiaqc0.fsf@netris.org> Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="DrWhICOqskFTAXiy" Return-path: Received: from eggs.gnu.org ([209.51.188.92]:51877) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hRXdp-0007Im-H0 for guix-devel@gnu.org; Fri, 17 May 2019 03:50:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hRXdn-0005c6-Jq for guix-devel@gnu.org; Fri, 17 May 2019 03:50:57 -0400 Received: from flashner.co.il ([178.62.234.194]:41408) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hRXdn-0005a0-9J for guix-devel@gnu.org; Fri, 17 May 2019 03:50:55 -0400 Content-Disposition: inline In-Reply-To: <87d0kiaqc0.fsf@netris.org> List-Id: "Development of GNU Guix and the GNU System distribution." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-devel-bounces+gcggd-guix-devel=m.gmane.org@gnu.org Sender: "Guix-devel" To: Mark H Weaver Cc: guix-devel@gnu.org --DrWhICOqskFTAXiy Content-Type: multipart/mixed; boundary="jousvV0MzM2p6OtC" Content-Disposition: inline --jousvV0MzM2p6OtC Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Thu, May 16, 2019 at 08:15:16PM -0400, Mark H Weaver wrote: > Hi Marius, >=20 > Marius Bakke writes: >=20 > > I just want to point out an (IMO) easier way to provide a custom kernel > > configuration, that does not involve the "make-linux-libre" procedure: > > > > (define-public linux-libre/custom > > (package > > (inherit linux-libre) > > (native-inputs > > `(("kconfig" ,(local-file "kernel.config")) > > ,@(alist-delete "kconfig" > > (package-native-inputs linux-libre)))))) > > > > At the end of the day, Linux-Libre is just a regular package that can be > > inherited and overridden like any other :-) >=20 > I think this is the approach we should promote for now. I would prefer > to leave 'make-linux-libre' as an internal implementation detail, and > hopefully one with a limited life span. >=20 > Thanks, > Mark I've removed my custom E2140 kernel config example and replaced it with the above example. I've changed "/custom" to "/E2140". I've also taken the "Linux-Libre is just a ..." sentence and prepended it to the example. --=20 Efraim Flashner =D7=90=D7=A4=D7=A8=D7=99=D7=9D = =D7=A4=D7=9C=D7=A9=D7=A0=D7=A8 GPG key =3D A28B F40C 3E55 1372 662D 14F7 41AA E7DC CA3D 8351 Confidentiality cannot be guaranteed on emails sent or received unencrypted --jousvV0MzM2p6OtC Content-Type: text/plain; charset=utf-8 Content-Disposition: attachment; filename="custom-kernel.md" Content-Transfer-Encoding: quoted-printable title: Creating and using a custom Linux kernel on Guix System date: 2019-05-20 00:00 author: Efraim Flashner tags: kernel, customization --- Guix is, at its core, a source based distribution with substitutes, and as such building packages from their source code is an expected part of regular package installations and upgrades. Given this starting point, it makes sense that efforts are made to reduce the amount of time spent compiling packages, and recent changes and upgrades to the building and distribution of substitutes continues to be a topic of discussion within Guix. One of the packages which I prefer to not build myself is the Linux-Libre kernel. The kernel, while not requiring an overabundance of RAM to build, does take a very long time on my build machine (which my children argue is actually their Kodi computer), and I will often delay reconfiguring my laptop while I want for a substitute to be prepared by the official build farm. The official kernel configuration, as is the case with many GNU/Linux distributions, errs on the side of inclusiveness, and this is really what causes the build to take such a long time when I build the package for myself. The Linux kernel, however, can also just be described as a package installed on my machine, and as such can be customized just like any other package. The procedure is a little bit different, although this is primarily due to the nature of how the package definition is written. The linux-libre kernel package definition is actually a procedure which creates a package. ```scheme (define* (make-linux-libre version hash supported-systems #:key ;; A function that takes an arch and a variant. ;; See kernel-config for an example. (extra-version #f) (configuration-file #f) (defconfig "defconfig") (extra-options %default-extra-linux-options) (patches (list %boot-logo-patch))) ...) ``` The current linux-libre package is for the 5.1.x series, and is declared like this: ```scheme (define-public linux-libre (make-linux-libre %linux-libre-version %linux-libre-hash '("x86_64-linux" "i686-linux" "armhf-linux" "aarch64-li= nux") #:patches %linux-libre-5.1-patches #:configuration-file kernel-config)) ``` Any keys which are not assigned values inherit their default value from the make-linux-libre definition. When comparing the two snippets above, you may notice that the code comment in the first doesn't actually refer to the extra-version keyword; it is actually for configuration-file. Because of this, it is not actually easy to include a custom kernel configuration from the definition, but don't worry, there are other ways to work with what we do have. There are two ways to create a kernel with a custom kernel configuration. The first is to provide a standard '.config' file during the build process by including an actual '.config' file as a native-input to our custom kernel. The following is a snippet from the custom 'configure phase of the make-linux-libre package definition: ```scheme (let ((build (assoc-ref %standard-phases 'build)) (config (assoc-ref (or native-inputs inputs) "kconfig"))) ;; Use a custom kernel configuration file or a default ;; configuration file. (if config (begin (copy-file config ".config") (chmod ".config" #o666)) (invoke "make" ,defconfig)) ``` Below is a sample kernel package for one of my computers. Linux-Libre is just like other regular packages and can be inherited and overridden like any other: ```scheme (define-public linux-libre/E2140 (package (inherit linux-libre) (native-inputs `(("kconfig" ,(local-file "E2140.config")) ,@(alist-delete "kconfig" (package-native-inputs linux-libre)))))) ``` In the same directory as the file defining linux-libre-E2140 is a file named E2140.config, which is an actual kernel configuration file. I left the defconfig keyword of make-linux-libre blank, so the only kernel configuration in the package is the one which I included as a native-input. The second way to create a custom kernel is to pass a new value to the extra-options keyword of the make-linux-libre procedure. The extra-options keyword works with another function defined right below it: ```scheme (define %default-extra-linux-options `(;; https://lists.gnu.org/archive/html/guix-devel/2014-04/msg00039.html ("CONFIG_DEVPTS_MULTIPLE_INSTANCES" . #t) ;; Modules required for initrd: ("CONFIG_NET_9P" . m) ("CONFIG_NET_9P_VIRTIO" . m) ("CONFIG_VIRTIO_BLK" . m) ("CONFIG_VIRTIO_NET" . m) ("CONFIG_VIRTIO_PCI" . m) ("CONFIG_VIRTIO_BALLOON" . m) ("CONFIG_VIRTIO_MMIO" . m) ("CONFIG_FUSE_FS" . m) ("CONFIG_CIFS" . m) ("CONFIG_9P_FS" . m))) (define (config->string options) (string-join (map (match-lambda ((option . 'm) (string-append option "=3Dm")) ((option . #t) (string-append option "=3Dy")) ((option . #f) (string-append option "=3Dn"))) options) "\n")) ``` And in the custom configure script from the make-linux-libre package: ```scheme ;; Appending works even when the option wasn't in the ;; file. The last one prevails if duplicated. (let ((port (open-file ".config" "a")) (extra-configuration ,(config->string extra-options))) (display extra-configuration port) (close-port port)) (invoke "make" "oldconfig")))) ``` So by not providing a configuration-file the '.config' starts blank, and then we write into it the collection of flags that we want. Here's another custom kernel which I have: ```scheme (define %macbook41-full-config (append %macbook41-config-options %filesystems %efi-support %emulation (@@ (gnu packages linux) %default-extra-linux-options))) (define-public linux-libre-macbook41 ;; XXX: Access the internal 'make-linux-libre' procedure, which is ;; private and unexported, and is liable to change in the future. ((@@ (gnu packages linux) make-linux-libre) (@@ (gnu packages linux) %lin= ux-libre-version) (@@ (gnu packages linux) %linux-libre-hash) '("x86_64-linux") #:extra-version "macbook41" #:patches (@@ (gnu packages linux) %linux-libre-5.1-p= atches) #:extra-options %macbook41-config-options)) ``` =46rom the above example %filesystems is a collection of flags enabling different filesystem support, %efi-support enables EFI support and %emulation enables my x86_64-linux machine to act in 32-bit mode also. %default-extra-linux-options are the ones quoted above, which had to be added in since I replaced them in the extra-options keyword. This all sounds like it should be doable, but how does one even know which modules are required for their system? The two places I found most helpful to try to answer this question were the [Gentoo Handbook](https://wiki.gentoo.org/wiki/Handbook:AMD64/Installation/Kernel), and the [documentation](https://www.kernel.org/doc/html/latest/admin-guide/README.h= tml?highlight=3Dlocalmodconfig) =66rom the kernel itself. From the kernel documentation, it seems that "make localmodconfig" is the command we want. In order to actually run `make localmodconfig` we first need to get and unpack the kernel source code: ```shell tar xf $(guix build linux-libre --source) ``` Once inside the directory containing the source code run `touch .config` to create an initial, empty '.config' to start with. `make localmodconfig` works by seeing what you already have in '.config' and letting you know what you're missing. If the file is blank then you're missing everything. The next step is to run ```shell guix environment linux-libre -- make localmodconfig ``` and note the output. Do note that the '.config' file is still empty. The output generally contains two types of warnings. The first start with "WARNING" and can actually be ignored in our case. The second read: ```shell module pcspkr did not have configs CONFIG_INPUT_PCSPKR ``` For each of these lines, copy the CONFIG_XXXX_XXXX portion into the '.config' in the directory, and append "=3Dm", so in the end it looks like this: ```shell CONFIG_INPUT_PCSPKR=3Dm CONFIG_VIRTIO=3Dm ``` After copying all the configuration options, run `make localmodconfig` again to make sure that you don't have any output starting with "module". After all of these machine specific modules there are a couple more left that are also needed. CONFIG_MODULES is necessary so that you can build and load modules separately and not have everything built into the kernel. CONFIG_BLK_DEV_SD is required for reading from hard drives. It is possible that there are other modules which you will need. This post does not aim to be a guide to configuring your own kernel however, so if you do decide to build a custom kernel you'll have to seek out other guides to create a kernel which is just right for your needs. The second way to setup the kernel configuration makes more use of Guix's features and allows you to share configuration segments between different kernels. For example, all machines using EFI to boot have a number of EFI configuration flags that they need. It is likely that all the kernels will share a list of filesystems to support. By using variables it is easier to see at a glance what features are enabled and to make sure you don't have features in one kernel but missing in another. Left undiscussed however, is Guix's initrd and its customization. It is likely that you'll need to modify the initrd on a machine using a custom kernel, since certain modules which are expected to be built may not be available for inclusion into the initrd. Suggestions and contributions toward working toward a satisfactory custom initrd and kernel are welcome! #### About GNU Guix [GNU=C2=A0Guix](https://www.gnu.org/software/guix) is a transactional packa= ge manager and an advanced distribution of the GNU system that [respects user freedom](https://www.gnu.org/distros/free-system-distribution-guidelines.ht= ml). Guix can be used on top of any system running the kernel Linux, or it can be used as a standalone operating system distribution for i686, x86_64, ARMv7, and AArch64 machines. In addition to standard package management features, Guix supports transactional upgrades and roll-backs, unprivileged package management, per-user profiles, and garbage collection. When used as a standalone GNU/Linux distribution, Guix offers a declarative, stateless approach to operating system configuration management. Guix is highly customizable and hackable through [Guile](https://www.gnu.org/software/guile) programming interfaces and extensions to the [Scheme](http://schemers.org) language. --jousvV0MzM2p6OtC-- --DrWhICOqskFTAXiy Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEoov0DD5VE3JmLRT3Qarn3Mo9g1EFAlzeZ80ACgkQQarn3Mo9 g1GLfg//d4A8JPmvHTsbD/fqG9r9ggu99phiKfE03YYlXkGSsLEV8R6w43F6q0uJ Kt+2fZEzKavvHHsRWnEdNecW85n4jKxnHh58TBr4miMnEQx+FGXIEGyi7l/aTpXd SM5E/JvvaIDRmwS1SDsnHr8EW6QHdU6WBHwWjqrRCbdBapiGBUPjRgbi8g3QjF1d M+H4VMP03EzcVtJeM0kzaVfn3tsVXY5QuixzFMgh0vKwouTltAdlodePauiuwiBJ Nd1dW83GaUBA4uayYA3gwb07FAxRbdm1YXaDCl4S0x7R9j2yDId6aEo4wuE1Ynxf QQ+jfpx9BcnbFE9qzrXnXLwRo0UuI/aEd2ZxqJGp8sbolkvkl979LZqTG/TsO9xF fpLDwU6pi+SoWZxar2hFXBvMzNryDJqZcWMM9S2GA1JFbu2H2JIhP8NGYmRoDJT5 7+Nh97KxamxL1dkEVopx9bWaMWbLLtzExc/xDCWlL0NER9oKV0Rr53EEkqYegFpV SdCxlQhdzeui+mCOWE9XQz2d1W5gptFfG5L5z19SEkt6pRMLhdsWhEAFMDNVsCxe dUuFyNBUUAxlxmr+841MYH8pgW6cgO0ILwEtBYJRUDisOXUBnD6hEX8kuT+zilUM dtpIUkmipAKLYtzIpGkV0RvRt6AquR7buw1+3XSdckRh3R1yuyk= =sfty -----END PGP SIGNATURE----- --DrWhICOqskFTAXiy--