<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <channel>
    <link href="https://flusp.ime.usp.br/feed-en.xml" rel="self" type="application/atom+xml"/>
    <link href="https://flusp.ime.usp.br/" rel="alternate" type="text/html"/>
    <updated>2026-04-14T23:03:01-03:00</updated>
    <id>https://flusp.ime.usp.br</id>
    <title type="html">FLUSP - FLOSS at USP</title>
    <subtitle>Free Libre Open Software group at USP</subtitle>
    
    
    <entry>
        <title type="html">Linux kernel patch submission guidelines (FSD 2026)</title>
        <link href="https://flusp.ime.usp.br/courses/linux-kernel-patch-submission-guidelines/"/>
        <published>2026-04-08T00:00:00-03:00</published>
        <id isPermaLink="true">https://flusp.ime.usp.br/courses/linux-kernel-patch-submission-guidelines/</id>
        <category>courses</category>
        <content type="html">&lt;!--end-abstract--&gt;

&lt;h1 id=&quot;1-clone-the-right-kernel-tree-and-branch&quot;&gt;1. Clone the right kernel tree and branch&lt;/h1&gt;

&lt;p&gt;For each Linux subsystem/subproject you want to contribute to, you must use a dedicated &lt;strong&gt;git repository&lt;/strong&gt; (called kernel tree, in this context). The information about where this tree is located so you can do a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git clone&lt;/code&gt; is at the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MAINTAINERS&lt;/code&gt; file present at the root of any kernel tree. Here is a Web version of it: &lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/MAINTAINERS&quot;&gt;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/MAINTAINERS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Search for the subsystem/subproject you are working on and, if it has a dedicated git tree, it will be indicated in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T: &amp;lt;remote-url&amp;gt;&lt;/code&gt; attribute. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;remote-url&amp;gt;&lt;/code&gt; points to the tree, so you can do the below to clone the respective kernel tree:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone &amp;lt;remote-url&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In the case of the Industrial I/O (IIO) and AMD DRM subsystems, which we have curated issues, the git clone commands are:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# IIO&lt;/span&gt;
git clone git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio &lt;span class=&quot;nt&quot;&gt;--branch&lt;/span&gt; togreg

&lt;span class=&quot;c&quot;&gt;# AMD DRM&lt;/span&gt;
git clone https://gitlab.freedesktop.org/agd5f/linux.git &lt;span class=&quot;nt&quot;&gt;--branch&lt;/span&gt; amd-staging-drm-next
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p class=&quot;info&quot;&gt;&lt;strong&gt;Note:&lt;/strong&gt; 
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--branch&lt;/code&gt; option that sets the development branch used as a base. This is because, apart from the right kernel tree, we need to ensure we are at the latest development branch before making patches to avoid working on something that has already been solved or that doesn’t make sense anymore.&lt;/p&gt;

&lt;p&gt;Unfortunately, I don’t know a clear-cut way of knowing the right development branch of a project. Still, it should be documented somewhere in the subsystem/subproject.&lt;/p&gt;

&lt;p&gt;Also, don’t forget to keep the development branch updated with&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git pull
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p class=&quot;info&quot;&gt;&lt;strong&gt;Note:&lt;/strong&gt; 
If you are working on a branch like testing for IIO, it is also recommended to do a rebase (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git pull --rebase&lt;/code&gt;) because the maintainers frequently make changes to the tree. This ensures your local branch stays up-to-date and avoids unnecessary merge commits.&lt;/p&gt;

&lt;h1 id=&quot;2-create-a-dedicated-local-branch-to-isolate-your-work&quot;&gt;2. Create a dedicated local branch to isolate your work&lt;/h1&gt;

&lt;p&gt;As mentioned, you will be using a specific branch as base for each subsystem/subproject and objective. So, after checking out to the correct base branch (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;testing&lt;/code&gt; for IIO and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;amd-staging-drm-next&lt;/code&gt;), create a new branch to isolate your work. The name doesn’t matter to anyone but you, but having a meaningful name to keep things organized is a good idea:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git switch &amp;lt;base-branch&amp;gt;
git checkout &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt; &amp;lt;name-of-your-patch-branch&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;3-ensure-that-your-change-is-being-compiled&quot;&gt;3. Ensure that your change is being compiled&lt;/h1&gt;

&lt;p&gt;When tinkering with the Linux codebase, you need to be sure that the code you are modifying (at least) doesn’t break compilation. For this, you need to have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.config&lt;/code&gt; file configured to compile the portion of the code you’ve changed in the correct context. Ok, this is really ambiguous and circular, so here is one way you can be sure that the file you are modifying is being considered for compilation.&lt;/p&gt;

&lt;p&gt;I can’t confirm that this is the most efficient and reliable way, but this helps on getting an idea of the configurations you need to enable in order to produce the correct compilation. We are going to show an example on how to proceed when you don’t know much about the file you are editing.&lt;/p&gt;

&lt;p&gt;Say you are modifying the file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drivers/iio/dummy/iio_simple_dummy.c&lt;/code&gt; and you don’t know how to include it in the compilation. You should look in the same directory of the file for a Kconfig. This file has many configuration definitions in the form of&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;config &amp;lt;config_name&amp;gt;

    ...

    help

    &amp;lt;description_of_the_config&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You would look for a config name and description that relates to where you are working, like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IIO_SIMPLE_DUMMY&lt;/code&gt;. Then, you would open the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.config&lt;/code&gt; file for editing with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make nconfig&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw build --menu&lt;/code&gt;. Hit the &lt;strong&gt;F8 Key (SymSearch)&lt;/strong&gt; and type in the config name you’ve noted. This should open a menu with entries starting with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Symbol:&lt;/code&gt;. You would look for the config name you’ve typed at the top. You should see a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Depends on:&lt;/code&gt; attribute with the dependencies needed to be enabled before &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IIO_SIMPLE_DUMMY&lt;/code&gt;. There is also a  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Location:&lt;/code&gt; with a series of indentations that show the menus sequence to activate the config you’ve entered; you should see a number by the side of the closest menu entry you can reach.&lt;/p&gt;

&lt;p&gt;For example, you might see something like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Symbol: IIO_SIMPLE_DUMMY [=n]                                                       
Type  : tristate                                                                    
Defined at drivers/iio/dummy/Kconfig:12                                             
  Prompt: An example driver with no hardware requirements                           
  Depends on: IIO [=y] &amp;amp;&amp;amp; IIO_SW_DEVICE [=n]                                        
  Location:                                                                         
    -&amp;gt; Device Drivers                                                               
      -&amp;gt; Industrial I/O support (IIO [=y])                                          
(1)     -&amp;gt; IIO dummy driver                                                         
          -&amp;gt; An example driver with no hardware requirements (IIO_SIMPLE_DUMMY [=n])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In this case you would need to hit &lt;strong&gt;ESC&lt;/strong&gt;, hit &lt;strong&gt;F8&lt;/strong&gt;, and search for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IIO_SW_DEVICE&lt;/code&gt; (which is not enabled). You could see an output like&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Symbol: IIO_SW_DEVICE [=n]                                        
Type  : tristate                                                  
Defined at drivers/iio/Kconfig:53                                 
  Prompt: Enable software IIO device support                      
  Depends on: IIO [=y]                                            
  Location:                                                       
    -&amp;gt; Device Drivers                                             
      -&amp;gt; Industrial I/O support (IIO [=y])                        
(1)     -&amp;gt; Enable software IIO device support (IIO_SW_DEVICE [=n])
Selects: IIO_CONFIGFS [=n]                                        
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Hitting &lt;strong&gt;1&lt;/strong&gt; should jump you to the menu that enables &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IIO_SW_DEVICE&lt;/code&gt;. Then you would repeat it to enable the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IIO_SIMPLE_DUMMY&lt;/code&gt; config. Finally, you would save and quit the editing of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.config&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Note that this is a “blind” direction on how to enable a specific config in the Kbuild/Kconfig system, which doesn’t guarantee that the compilation will be “correct” for your patchset context (maybe the config name you’ve noted doesn’t even enable the target file).&lt;/p&gt;

&lt;p&gt;Nevertheless, to test if file is being compiled, use the old technique add-a-clear-compilation-error to the file. If the compilation fails, then you can be sure that your file is being compiled (at least, part of it).&lt;/p&gt;

&lt;h1 id=&quot;4-backup-your-config-files&quot;&gt;4. Backup your .config files&lt;/h1&gt;

&lt;p&gt;When developing for Linux, having to stop everything to produce a new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.config&lt;/code&gt; file is tedious and time consuming. So whenever you have a working .config file that is of your interest backup it by copying it to a “safe” location or by using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw kernel-config-manager&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The same goes for the virtual machine images you use to test custom built kernel. You can make backups of these images with simple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cp&lt;/code&gt; commands.&lt;/p&gt;

&lt;h1 id=&quot;5-make-atomic-commits-and-work-on-your-commit-message&quot;&gt;5. Make atomic commits and work on your commit message&lt;/h1&gt;

&lt;p&gt;General good commit practices are almost obligatory in the kernel, to the point that a perfect change, from the technical perspective, can be rejected if the commit does multiple things at once, so focus on atomic changes.&lt;/p&gt;

&lt;p&gt;Descriptive commit messages that follow the subsystem/subproject pattern are also important. For example, doing&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git log drivers/iio/adc/ad4030.c
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;will output all the commits that modified the file, and can give us with a good base for writing our commit subject. Pay attention to the prefix of the message. For this example, the command will (probably, if you are on the IIO testing branch) output as the latest commit (first entry in the list)&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;iio: adc: ad4030: Add support for ADAQ4216 and ADAQ4224
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;What is of interesting to us is the iio: adc: ad4030: part, which we can use as reference for our commit message title. However, the maintainer/community have the final word, so if they ask you to change the format of the title follow the request (even though, you can mention you’ve used a past commit as an example, pointing to it).&lt;/p&gt;

&lt;p class=&quot;warning&quot;&gt;&lt;strong&gt;Important:&lt;/strong&gt; 
The commit message body is obligatory, even if your change is so small and simple that it will be redundant with the title.&lt;/p&gt;

&lt;p class=&quot;info&quot;&gt;For more guidance on writing good commit messages, see &lt;a name=&quot;cite-gitCommit-back&quot; href=&quot;#cite-gitCommit&quot;&gt;[1]&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;6-add-your-signed-off-by-and-co-developed-by&quot;&gt;6. Add your Signed-off-by and Co-developed-by&lt;/h1&gt;

&lt;p&gt;There is another hard-rule that is homogenous for every subsystem/subproject which is the addition of a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Signed-off-by: Your Name &amp;lt;your@email.com&amp;gt;&lt;/code&gt; line with the author’s name and email. To configure git to automatically add this for you, run&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config &lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt; user.name &amp;lt;Your Name&amp;gt;
git config &lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt; user.email &amp;lt;your@email.com&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;then just do commit as follow&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git commit &lt;span class=&quot;nt&quot;&gt;--signoff&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# or&lt;/span&gt;
git commit &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;All integrants of the group must add their own signature. By rule, only the committer should add a Signed-off-by and the remaining developers should add Co-developed-by followed by a Signed-off-by. Apart from the committer that has the signature added automatically (with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--signoff&lt;/code&gt; flag) the others should add their signatures manually or when doing the commit by modifying the command to&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git commit &lt;span class=&quot;nt&quot;&gt;--signoff&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--trailer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;Co-developed-by: Integrant 2 &amp;lt;email@2.com&amp;gt;&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--trailer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;Signed-off-by: Integrant 2 &amp;lt;email@2.com&amp;gt;&apos;&lt;/span&gt; ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As an example, imagine that Paulo Meirelles and David Tadokoro are developing the patchset. Considering that Paulo is the committer (the one that runs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git commit --signoff&lt;/code&gt;), the signatures at the end of the commit message should be&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Signed-off-by: Paulo Meirelles &amp;lt;paulormm@ime.usp.br&amp;gt;
Co-developed-by: David Tadokoro &amp;lt;davidbtadokoro@ime.usp.br&amp;gt;
Signed-off-by: David Tadokoro &amp;lt;davidbtadokoro@ime.usp.br&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;7-check-that-your-patchset-doesnt-introduce-coding-style-problems&quot;&gt;7. Check that your patchset doesn’t introduce coding style problems&lt;/h1&gt;

&lt;p&gt;To make your patchset more robust, it is advisable to check for possible coding style problems that your patchset may be introducing. To do this, run&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git format-patch &lt;span class=&quot;nt&quot;&gt;-1&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--stdout&lt;/span&gt; | ./scripts/checkpatch.pl &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will make &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;checkpatch.pl&lt;/code&gt; check for problems on the current commit (the one pointed by the HEAD; the commit you are at the moment) and will output the ones it finds.&lt;/p&gt;

&lt;p class=&quot;warning&quot;&gt;&lt;strong&gt;Important:&lt;/strong&gt;
The problems found by the tool are not always correct, so be critic about them and apply them only if they are reasonable.&lt;/p&gt;

&lt;h1 id=&quot;8-official-linux-kernel-guidelines-in-submitting-patches&quot;&gt;8. Official Linux kernel guidelines in submitting patches&lt;/h1&gt;

&lt;p&gt;There is also an official guide on submitting patches done by the Linux kernel community&lt;a name=&quot;cite-kernelPatchGuide-back&quot; href=&quot;#cite-kernelPatchGuide&quot;&gt;[2]&lt;/a&gt;. It is very extensive (even more than the one I did above), but you can check it if you are in doubt about anything more specific.&lt;/p&gt;

&lt;h1 id=&quot;9-configure-git-send-email&quot;&gt;9. Configure &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt;&lt;/h1&gt;

&lt;p&gt;Before sending patches, you need to do some configuration. We assume you are using you @usp.br email, which is gmail under the hood. The configuration is described in this tutorial: &lt;a href=&quot;/git/sending-patches-with-git-and-a-usp-email/&quot;&gt;Sending patches with git and a USP email&lt;/a&gt;&lt;/p&gt;

&lt;h1 id=&quot;10-send-your-contribution-to-our-ci-before-sending-it-to-the-world&quot;&gt;10. Send your contribution to our CI before sending it “to the world”&lt;/h1&gt;

&lt;p&gt;After your patch(set) is ready, before sending your contributions to the respective mailing list(s) and maintainer(s), send your contribution only to the address &lt;strong&gt;kernel@lists.ime.usp.br&lt;/strong&gt;. Below is the safe command to send the last &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;n&amp;gt;&lt;/code&gt; commits.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kw send-patch &lt;span class=&quot;nt&quot;&gt;--send&lt;/span&gt; -&amp;lt;n&amp;gt; &lt;span class=&quot;nt&quot;&gt;--simulate&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--private&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--to&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;kernel@lists.ime.usp.br
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The above command is safe because the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--simulate&lt;/code&gt; option makes kw do everything except sending the message(s). Before removing this option to actually send the message(s), make sure that the recipients (the RCPT TO: fields) are correct. You can optionally append a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--cc=&amp;lt;your@email.com&amp;gt;&lt;/code&gt; at the end the command to copy yourself and be more comfortable about the email being delivered.&lt;/p&gt;

&lt;p&gt;All the patches sent to the mailing list will be available on our lore instance: &lt;a href=&quot;https://lore.kernel.ime.usp.br/kernel.ime/&quot;&gt;https://lore.kernel.ime.usp.br/kernel.ime/&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;It may take some time for the patch to appear in the mailing list archive.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sending the patchset to this address will trigger our local CI where the patch will be applied to the corresponding kernel tree, compiled, and booted into a VM where a basic boot cycle test will be executed. The main job stages are build and test. The former is responsible for applying and compiling the kernel image. The latter loads it and runs the boot cycle.&lt;/p&gt;

&lt;p&gt;We have 4 CI repositories. When submitting a patch, you can track its progress on the respective repository, by finding the CI pipeline that was triggered the moment you’ve sent the patch.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://gitlab.freedesktop.org/marcelomspessoto/dsl-linux/-/pipelines&quot;&gt;DSL-LINUX is the main CI repository&lt;/a&gt;. It detects the tree that matches your patch and triggers the build and test jobs to one of the repository below. You can track the entire CI flow for every tree from here.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://gitlab.freedesktop.org/marcelomspessoto/iio-ci/-/pipelines&quot;&gt;IIO-CI is the repository for the IIO tree&lt;/a&gt;. CI jobs for IIO patches will be here;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://gitlab.freedesktop.org/marcelomspessoto/amd-display-ci/-/pipelines&quot;&gt;AMD-DISPLAY-CI is the repository for the AMD DISPLAY tree&lt;/a&gt;. CI jobs for AMD DISPLAY jobs will be here;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://gitlab.freedesktop.org/marcelomspessoto/linux-next-ci/-/pipelines&quot;&gt;LINUX-NEXT-CI is the repository for the LINUX-NEXT tree&lt;/a&gt;. This tree contains bleeding edge from all development trees and is used as a fallback if your patch doesn’t match the IIO or AMD trees.&lt;/li&gt;
&lt;/ol&gt;

&lt;p class=&quot;warning&quot;&gt;&lt;strong&gt;Important:&lt;/strong&gt;
Despite being functional, our UI/UX for CI feedback is still lacking a centralized and organized interface. You may ask one of the teacher assistants if you struggle to track the CI status of your patch. Keep in mind that the UI aspect of our CI is WIP and may face significant improvements during the next days (and this documentation will be updated accordingly)&lt;/p&gt;

&lt;p&gt;The CI pipeline may present some bugs, such as wrong job failures. If your patch gets buggy pipelines, we’ll address the bug and manually run your patch through the CI until it is properly evaluated by our CI system.&lt;/p&gt;

&lt;h1 id=&quot;11-send-your-patchset-to-the-world-after-approval-from-our-ci&quot;&gt;11. Send your patchset “to the world” after approval from our CI&lt;/h1&gt;

&lt;p&gt;After your patchset has been approved in the previous step, you can send it to the correct maintainers and mailing list by running the previous command without the additional &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--private&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--to&lt;/code&gt; options:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kw send-patch &lt;span class=&quot;nt&quot;&gt;--send&lt;/span&gt; -&amp;lt;n&amp;gt; &lt;span class=&quot;nt&quot;&gt;--simulate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p class=&quot;info&quot;&gt;Remember to drop the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--simulate&lt;/code&gt; flag after you feel confident that the messages to be sent are correct and destined to the correct recipients.&lt;/p&gt;

&lt;h2 id=&quot;history&quot;&gt;History&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;V1: First version release (thanks to Guilherme Ivo).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;p&gt;&lt;a name=&quot;cite-gitCommit&quot;&gt;[1]&lt;/a&gt; cbeams. “How to Write a Git Commit Message”. (2014) URL: &lt;a href=&quot;https://cbea.ms/git-commit/&quot;&gt;https://cbea.ms/git-commit/&lt;/a&gt;. &lt;big&gt;&lt;big&gt;&lt;big&gt;&lt;a href=&quot;#cite-gitCommit-back&quot;&gt;⤴&lt;/a&gt;&lt;/big&gt;&lt;/big&gt;&lt;/big&gt;&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;cite-kernelPatchGuide&quot;&gt;[2]&lt;/a&gt; Linux Kernel Community. “Submitting Patches - The Linux Kernel”. (2026) URL: &lt;a href=&quot;https://www.kernel.org/doc/html/v6.14/process/submitting-patches.html&quot;&gt;https://www.kernel.org/doc/html/v6.14/process/submitting-patches.html&lt;/a&gt;. &lt;big&gt;&lt;big&gt;&lt;big&gt;&lt;a href=&quot;#cite-kernelPatchGuide-back&quot;&gt;⤴&lt;/a&gt;&lt;/big&gt;&lt;/big&gt;&lt;/big&gt;&lt;/p&gt;

</content>
    </entry>
    
    <entry>
        <title type="html">Linux kernel patch suggestions (FSD 2026)</title>
        <link href="https://flusp.ime.usp.br/courses/linux-kernel-patch-suggestions/"/>
        <published>2026-04-07T00:00:00-03:00</published>
        <id isPermaLink="true">https://flusp.ime.usp.br/courses/linux-kernel-patch-suggestions/</id>
        <category>courses</category>
        <content type="html">&lt;p&gt;To finalise the first phase of the Free Software Development 2026 course, each group will send one or more contributions to the Linux project. There are no restrictions on which subsystems the groups can send patches to, and this post includes a few directions to help you devise your contributions. The mentors of FSD 2026 have curated these suggestions, but always rely on the Linux community and maintainers, as well as on your own critical sense when developing for the kernel.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; Before proceeding to the patch suggestions, make sure you are comfortable with the submission part of the process by consulting the &lt;a href=&quot;/courses/linux-kernel-patch-submission-guidelines/&quot;&gt;patch submission guidelines post&lt;/a&gt;.&lt;/p&gt;

&lt;p class=&quot;warning&quot;&gt;This is an WIP version that may be altered in the future.&lt;/p&gt;

&lt;!--end-abstract--&gt;

&lt;h3 id=&quot;suggestions-summary&quot;&gt;Suggestions summary&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#suggestion-11-replace-mutex_locklock-and-mutex_unlocklock-calls-with-guardmutexlock&quot;&gt;&lt;strong&gt;Suggestion 1.1)&lt;/strong&gt; Replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mutex_lock(&amp;amp;lock)&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mutex_unlock(&amp;amp;lock)&lt;/code&gt; calls with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;guard(mutex)(&amp;amp;lock)&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#suggestion-21-replace-manual-bitfield-manipulations-with-field_get-field_prep-and-field_modify&quot;&gt;&lt;strong&gt;Suggestion 2.1)&lt;/strong&gt; Replace manual bitfield manipulations with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FIELD_GET()&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FIELD_PREP()&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FIELD_MODIFY()&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#suggestion-22-update-iio-drivers-to-be-include-what-you-use-iwyu-compliant&quot;&gt;&lt;strong&gt;Suggestion 2.2)&lt;/strong&gt; Update IIO drivers to be Include-What-You-Use (IWYU) compliant&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#suggestion-23-improvements-in-the-iio-area-of-staging&quot;&gt;&lt;strong&gt;Suggestion 2.3)&lt;/strong&gt; Improvements in the IIO area of staging&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#suggestion-31-convert-logging-to-drm_-functions-with-drm_device-parameter&quot;&gt;&lt;strong&gt;Suggestion 3.1)&lt;/strong&gt; Convert logging to drm_* functions with drm_device parameter&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#suggestion-32-read-and-expand-the-subsystem-documentation&quot;&gt;&lt;strong&gt;Suggestion 3.2)&lt;/strong&gt; Read and expand the subsystem documentation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#suggestion-41-duplications-with-100-similarity&quot;&gt;&lt;strong&gt;Suggestion 4.1)&lt;/strong&gt; Duplications with 100% similarity&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#suggestion-42-duplications-with-90-similarity&quot;&gt;&lt;strong&gt;Suggestion 4.2)&lt;/strong&gt; Duplications with 90% similarity&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;1-any-subsystemsubproject&quot;&gt;1. Any subsystem/subproject&lt;/h1&gt;

&lt;h2 id=&quot;suggestion-11-replace-mutex_locklock-and-mutex_unlocklock-calls-with-guardmutexlock&quot;&gt;Suggestion 1.1) Replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mutex_lock(&amp;amp;lock)&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mutex_unlock(&amp;amp;lock)&lt;/code&gt; calls with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;guard(mutex)(&amp;amp;lock)&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;Synchronisation is fundamental in the Linux kernel, as you need to be mindful of concurrency issues such as data inconsistency, race conditions, and deadlocks. A common synchronisation primitive is a mutex, which is implemented in Linux. An example of initialising a mutex, acquiring it, and unlocking it would be&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mutex&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;// declaring a mutex&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;mutex_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;// dynamically initialising the mutex&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;mutex_lock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;// acquiring the mutex&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;                  &lt;span class=&quot;c1&quot;&gt;// critical section&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;mutex_unlock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// unlocking the mutex&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;However, there are two problems with this approach that compromise cleanup after calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mutex_lock()&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The developer needs to remember to call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mutex_unlock()&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Depending on the conditional paths of the critical section, many &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mutex_unlock()&lt;/code&gt; calls need to be placed&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To circumvent these problems, developers may use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;goto error&lt;/code&gt; pattern, where the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mutex_unlock()&lt;/code&gt; is centralised at the end of the critical section. For instance, this template of a function is pretty common:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;function_with_mutex_and_goto_error_pattern&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;mutex_lock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// lock is a struct mutex that has been initialised&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FOO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;do_foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// suppose this function never fails&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BAR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;do_first_bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// suppose this function can fail&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// i.e., if do_first_bar() failed&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            
        &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;do_second_bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// suppose this function can fail&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// i.e., if do_second_bar() failed&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            
        &lt;span class=&quot;n&quot;&gt;do_third_bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// suppose this function never fails&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;default:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;EINVAL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    
&lt;span class=&quot;nl&quot;&gt;out:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;mutex_unlock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The kernel provides what it calls &lt;a href=&quot;https://docs.kernel.org/core-api/cleanup.html&quot;&gt;Scope-based Cleanup Helpers&lt;/a&gt; (defined in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;include/linux/cleanup.h&lt;/code&gt;), which, in a very broad sense, allow transparent cleanup when resources go out of scope. For mutexes, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;guard(mutex)(&amp;amp;lock)&lt;/code&gt; macro basically solves the two mentioned problems associated with cleaning up acquired mutexes. In the above example, if we were to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;guard(mutex)(&amp;amp;lock)&lt;/code&gt;, the code could be rewritten without any functional change as&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;function_with_guard_mutex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;guard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mutex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// lock is a struct mutex that has been initialised&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FOO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;do_foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// suppose this function never fails&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BAR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;do_first_bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// suppose this function can fail&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// i.e., if do_first_bar() failed&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            
        &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;do_second_bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// suppose this function can fail&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// i.e., if do_second_bar() failed&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        
        &lt;span class=&quot;n&quot;&gt;do_third_bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// suppose this function never fails&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;default:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;EINVAL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note that in this example, as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;guard(mutex)(&amp;amp;lock)&lt;/code&gt; is called “at the root scope” of the function, the mutex is unlocked if and only if it goes out of the function scope (in the example, in any of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;return&lt;/code&gt; statements). There is a similar macro, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scoped_guard(mutex, &amp;amp;lock)&lt;/code&gt;, that creates an explicit block scope where the mutex is unlocked when it goes out of this block. For example, if we have a sequence in which we only want a small part of it to represent our critical section, we can use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scoped_guard(mutex, &amp;amp;lock)&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;function_with_scoped_guard_mutex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// do some stuff with no mutex active&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;scoped_guard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mutex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// lock is a struct mutex that has been initialised&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// inside these curly braces, the mutex is active&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// from here on, the mutex is unlocked&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// do some other stuff with no mutex active&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;important-observations&quot;&gt;Important observations&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Obs.1&lt;/strong&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;guard(mutex)(&amp;amp;lock)&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scoped_guard(mutex, &amp;amp;lock)&lt;/code&gt; are only a specific type of guard cleanups, and guard cleanups are only part of these Scope-based Cleanup Helpers. You can check the documentation https://docs.kernel.org/core-api/cleanup.html to understand this better, if you are interested.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Obs.2&lt;/strong&gt;: The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;goto error&lt;/code&gt; pattern isn’t solely used for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mutex_unlock(&amp;amp;lock)&lt;/code&gt;, as other unwind operations can happen in the same goto (deallocate memory, unregister char device, and so on). In these cases, you can’t simply throw away the gotos and enforce the guard mutex cleanups.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Obs.3&lt;/strong&gt;: We exemplified the use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mutex_lock(&amp;amp;lock)&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mutex_unlock(&amp;amp;lock)&lt;/code&gt; with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;goto error&lt;/code&gt; pattern, but even in cases where multiple explicit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mutex_unlock(&amp;amp;lock)&lt;/code&gt; calls are made to avoid gotos, refactoring with guard mutex cleanups can make the code more robust.
{ .warning}&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;patch-examples&quot;&gt;Patch examples&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://lore.kernel.org/linux-iio/20250618031638.26477-4-andrew.lopes@alumni.usp.br/&quot;&gt;https://lore.kernel.org/linux-iio/20250618031638.26477-4-andrew.lopes@alumni.usp.br/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://lore.kernel.org/amd-gfx/20251002174245.1691343-7-mario.limonciello@amd.com/&quot;&gt;https://lore.kernel.org/amd-gfx/20251002174245.1691343-7-mario.limonciello@amd.com/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://lore.kernel.org/netdev/20250516230734.2564775-7-seanjc@google.com/&quot;&gt;https://lore.kernel.org/netdev/20250516230734.2564775-7-seanjc@google.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;2-industrial-io-iio&quot;&gt;2. Industrial I/O (IIO)&lt;/h1&gt;

&lt;p&gt;The suggestions below were pointed by Marcelo Schmitt and refined by us.&lt;/p&gt;

&lt;h2 id=&quot;suggestion-21-replace-manual-bitfield-manipulations-with-field_get-field_prep-and-field_modify&quot;&gt;Suggestion 2.1) Replace manual bitfield manipulations with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FIELD_GET()&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FIELD_PREP()&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FIELD_MODIFY()&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;Although we normally think of numbers in the decimal system, we can represent them in different bases. Take the number 26, for example. In binary, it is:&lt;/p&gt;

\[\begin{aligned}
(11010)_2 &amp;amp;= (2^4*1 + 2^3*1 + 2^2*0 + 2^1*1 + 2^0*0)_{10} \\
          &amp;amp;= (16*1 + 8*1 + 4*0 + 2*1 + 1*0)_{10} \\
          &amp;amp;= (16 + 8 + 0 + 2 + 0)_{10} \\
          &amp;amp;= (26)_{10}
\end{aligned}\]

&lt;p&gt;We can also represent 26 in the hexadecimal system:&lt;/p&gt;

\[\begin{aligned}
(1\textrm{A})_{16} &amp;amp;= (16^1*1 + 16^0*10)_{10} \\
          &amp;amp;= (16*1 + 1*10)_{10} \\
          &amp;amp;= (16 + 10)_{10} \\
          &amp;amp;= (26)_{10}
\end{aligned}\]

&lt;p&gt;In kernel development, it is common to treat numbers as bitfields, where each bit or bit sequence encodes a different attribute. As an analogy, imagine a 4-bit bitfield &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dish&lt;/code&gt; that encodes an order at a restaurant serving 4 dishes, with each dish having two sizes (small and large) and two spice levels (regular and spicy). We can define how the bits in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dish&lt;/code&gt; represent every possible dish as such (“bigger bits” to the left):&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Bits 0-1 -&amp;gt; Dish ID: \((00)_2\) is dish 0, \((01)_2\) is dish 1, \((10)_2\) is dish 2,
and \((11)_2\) is dish 3.&lt;/li&gt;
  &lt;li&gt;Bit 2 -&amp;gt; Dish size: \((0)_2\) is the small size and \((1)_2\) is the large size.&lt;/li&gt;
  &lt;li&gt;Bit 3 -&amp;gt; Dish spiciness: \((0)_2\) is regular and \((1)_2\) is spicy.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this analogy, the bitfield &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dish&lt;/code&gt; that represents the spicy small dish 1 is \((1001)_2\) (or \((9)_{10}\), in decimal). Now, imagine I want to query the bitfield &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dish&lt;/code&gt; for the dish size, i.e., isolate bit 2 from this 4-bit bitfield. The way to compute this value is to perform a mask (target specific bits) and a shift (move the bits left/right) operation. More specifically, these are the operations in pseudocode:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;size = dish AND (0100)_2  // MASK: &quot;selects&quot; only bit 2
size = size &amp;gt;&amp;gt; 2          // SHIFT: &quot;moves&quot; bit 2 to bit 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Alternatively, if you were handed a bit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;spiceness&lt;/code&gt; and you had to modify &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dish&lt;/code&gt; to have this spiceness. In this case, there would be a shift, a mask, then an OR operation:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;val = spiceness &amp;lt;&amp;lt; 3    // SHIFT: &quot;moves&quot; spiceness to bit 3
val = val AND (1000)_2  // MASK: &quot;selects&quot; only bit 3
dish = val OR dish      // MODIFY: &quot;updates&quot; dish with spiceness
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This simple analogy illustrates the core common bitfield manipulations in the kernel, and the pseudocodes aren’t too far from the real implementations. These manipulations are so frequent that the kernel provides macros that simplify them, while making them more secure. These macros are the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FIELD_GET(mask, bitfield)&lt;/code&gt; (e.g., get dish size), &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FIELD_PREP(mask, field_val)&lt;/code&gt; (e.g., prepare dish spiceness), and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FIELD_MODIFY(mask, bitfield, field_val)&lt;/code&gt; (e.g., prepare dish spiceness and modify dish). These macros are defined in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;include/linux/bitfield.h&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the context of IIO, you can check for manual bitfield (also referred to as registers) manipulations and see if they can be replaced by one of the above macros.&lt;/p&gt;

&lt;h3 id=&quot;patch-examples-1&quot;&gt;Patch examples&lt;/h3&gt;

&lt;p&gt;…&lt;/p&gt;

&lt;h2 id=&quot;suggestion-22-update-iio-drivers-to-be-include-what-you-use-iwyu-compliant&quot;&gt;Suggestion 2.2) Update IIO drivers to be Include-What-You-Use (IWYU) compliant&lt;/h2&gt;

&lt;p&gt;IWYU is a Clang-based tool developed by Google to optimize &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#include&lt;/code&gt; directives in C/C++ code (&lt;a href=&quot;https://include-what-you-use.org/&quot;&gt;https://include-what-you-use.org/&lt;/a&gt;). Check the patch examples for guidelines on how to pursue this suggestion.&lt;/p&gt;

&lt;h3 id=&quot;patch-examples-2&quot;&gt;Patch examples&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://lore.kernel.org/linux-iio/20260119212110.726941-1-jic23@kernel.org/&quot;&gt;https://lore.kernel.org/linux-iio/20260119212110.726941-1-jic23@kernel.org/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://lore.kernel.org/linux-iio/20250629194336.34a03946@jic23-huawei/&quot;&gt;https://lore.kernel.org/linux-iio/20250629194336.34a03946@jic23-huawei/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://lore.kernel.org/linux-iio/20260123081640.590335bd@jic23-huawei/T/#m39327915c3ccea954ecdd81a3cd6ef2068a410d3&quot;&gt;https://lore.kernel.org/linux-iio/20260123081640.590335bd@jic23-huawei/T/#m39327915c3ccea954ecdd81a3cd6ef2068a410d3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;suggestion-23-improvements-in-the-iio-area-of-staging&quot;&gt;Suggestion 2.3) Improvements in the IIO area of staging&lt;/h2&gt;

&lt;p&gt;Linux has its own “quarantine zone” for drivers, where code that is either entering or leaving the kernel lives, due to it not being quite refined or being problematic, respectively. This area is located in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drivers/staging&lt;/code&gt; directory, and the IIO-related drivers of staging are in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drivers/staging/iio&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Usually, staging drivers are really rough, in terms of following the kernel conventions, coding style, and other requirements, so some patch opportunities can be considered newcomer friendly. (Un)fortunately, the IIO staging drivers are already well developed, making these easier tasks more rare.&lt;/p&gt;

&lt;p&gt;Nevertheless, see this message from Marcelo Schmitt on the mailing list regarding possible tasks for IIO staging drivers: &lt;a href=&quot;https://lore.kernel.org/linux-iio/Z8U0lsntJpTuBzyT@debian-BULLSEYE-live-builder-AMD64/&quot;&gt;https://lore.kernel.org/linux-iio/Z8U0lsntJpTuBzyT@debian-BULLSEYE-live-builder-AMD64/&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;patch-examples-3&quot;&gt;Patch examples&lt;/h3&gt;

&lt;p&gt;…&lt;/p&gt;

&lt;h1 id=&quot;3-drm-amdgpu-drivers&quot;&gt;3. DRM AMDGPU DRIVERS&lt;/h1&gt;

&lt;p&gt;The suggestions below were taken from &lt;a href=&quot;https://dri.freedesktop.org/docs/drm/gpu/todo.html&quot;&gt;https://dri.freedesktop.org/docs/drm/gpu/todo.html&lt;/a&gt; and from &lt;a href=&quot;https://dri.freedesktop.org/docs/drm/gpu/amdgpu/display/display-contributing.html&quot;&gt;https://dri.freedesktop.org/docs/drm/gpu/amdgpu/display/display-contributing.html&lt;/a&gt;. If you want to dig for other TODOs feel free to investigate these lists.&lt;/p&gt;

&lt;h2 id=&quot;suggestion-31-convert-logging-to-drm_-functions-with-drm_device-parameter&quot;&gt;Suggestion 3.1) Convert logging to drm_* functions with drm_device parameter&lt;/h2&gt;

&lt;p&gt;For drivers which could have multiple instances, it is necessary to differentiate between which is which in the logs. Since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DRM_INFO/WARN/ERROR&lt;/code&gt; don’t do this, drivers used &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dev_info/warn/err&lt;/code&gt; to make this differentiation. We now have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drm_*&lt;/code&gt; variants of the DRM print functions, so we can start to convert those drivers back to using DRM-formatted specific log messages. This should only work in files inside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drivers/gpu/drm/amd/display/amdgpu_dm/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Before you start this conversion please contact the relevant maintainers to make sure your work will be merged - not everyone agrees that the DRM dmesg macros are better. The documentation mentions contacting Sean Paul and the maintainer of the driver you plan to convert.&lt;/p&gt;

&lt;h3 id=&quot;patch-examples-4&quot;&gt;Patch examples&lt;/h3&gt;

&lt;p&gt;…&lt;/p&gt;

&lt;h2 id=&quot;suggestion-32-read-and-expand-the-subsystem-documentation&quot;&gt;Suggestion 3.2) Read and expand the subsystem documentation&lt;/h2&gt;

&lt;p&gt;Graphics is already a complicated field, but when it comes to 3D-accelerated graphics in the kernel, things can be get really complex really fast. So reading through the GPU Driver Developer’s Guide (&lt;a href=&quot;https://docs.kernel.org/gpu/index.html&quot;&gt;https://docs.kernel.org/gpu/index.html&lt;/a&gt;), the DRM AMDGPU drivers doc (&lt;a href=&quot;https://docs.kernel.org/gpu/amdgpu/index.html&quot;&gt;https://docs.kernel.org/gpu/amdgpu/index.html&lt;/a&gt;), and the display part of DRM AMDGPU drivers doc (&lt;a href=&quot;https://docs.kernel.org/gpu/amdgpu/display/index.html&quot;&gt;https://docs.kernel.org/gpu/amdgpu/display/index.html&lt;/a&gt;), can be a great way to grasp some knowledge, whilst contributing to it.&lt;/p&gt;

&lt;p&gt;An important observation is that we don’t encourage you to simply correct typos, but to dive deep into the documentation, reading the code, and updating/expanding parts that seem incorrect/unclear.&lt;/p&gt;

&lt;h3 id=&quot;patch-examples-5&quot;&gt;Patch examples&lt;/h3&gt;

&lt;p&gt;…&lt;/p&gt;

&lt;h1 id=&quot;4-code-duplications&quot;&gt;4. Code duplications&lt;/h1&gt;

&lt;h2 id=&quot;suggestion-41-duplications-with-100-similarity&quot;&gt;Suggestion 4.1) Duplications with 100% similarity&lt;/h2&gt;

&lt;p&gt;1) 3 sets of correlated duplications. Feel free to try to solve one or all of them. The specified files are in the directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drivers/gpu/drm/amd/amdgpu/&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;jpeg_v5_0_1.c::jpeg_v5_0_1_process_interrupt AND jpeg_v5_0_2.c::jpeg_v5_0_2_process_interrupt , TOTAL NUMBER LINES IN FUNCTIONS: 59

jpeg_v5_0_0.c::jpeg_v5_0_0_process_interrupt AND jpeg_v5_3_0.c::jpeg_v5_3_0_process_interrupt , TOTAL NUMBER LINES IN FUNCTIONS: 18

jpeg_v2_0.c::jpeg_v2_0_process_interrupt AND jpeg_v3_0.c::jpeg_v3_0_process_interrupt , TOTAL NUMBER LINES IN FUNCTIONS: 18
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;2) The specified files are in the directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drivers/gpu/drm/amd/amdgpu/&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gfx_v11_0.c::gfx_v11_0_eop_irq AND gfx_v12_0.c::gfx_v12_0_eop_irq , TOTAL NUMBER LINES IN FUNCTIONS: 52
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;3) The specified files are in the directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drivers/gpu/drm/amd/amdgpu/&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gfx_v11_0.c::gfx_v11_0_ring_preempt_ib AND gfx_v12_0.c::gfx_v12_0_ring_preempt_ib , TOTAL NUMBER LINES IN FUNCTIONS: 49
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;4) The specified files are in the directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drivers/gpu/drm/amd/amdgpu/&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gmc_v10_0.c::gmc_v10_0_get_vm_pte AND gmc_v11_0.c::gmc_v11_0_get_vm_pte , TOTAL NUMBER LINES IN FUNCTIONS: 46
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;5) The specified files are in the directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drivers/gpu/drm/amd/amdgpu/&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gfx_v11_0.c::gfx_v11_0_set_userq_eop_interrupts AND gfx_v12_0.c::gfx_v12_0_set_userq_eop_interrupts , TOTAL NUMBER LINES IN FUNCTIONS: 42
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;6) The specified files are in the directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drivers/gpu/drm/amd/amdgpu/&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gfx_v11_0.c::gfx11_kiq_map_queues AND gfx_v12_0.c::gfx_v12_0_kiq_map_queues , TOTAL NUMBER LINES IN FUNCTIONS: 42
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;7) 2 sets of correlated duplications. Feel free to try to solve one or all of them. The specified files are in the directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drivers/gpu/drm/amd/amdgpu/&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Functions find: cik_sdma.c::cik_sdma_process_trap_irq AND sdma_v2_4.c::sdma_v2_4_process_trap_irq , TOTAL NUMBER LINES IN FUNCTIONS: 40

Functions find: cik_sdma.c::cik_sdma_process_trap_irq AND sdma_v3_0.c::sdma_v3_0_process_trap_irq , TOTAL NUMBER LINES IN FUNCTIONS: 40
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;8) The specified files are in the directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drivers/gpu/drm/amd/amdgpu/&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gmc_v10_0.c::gmc_v10_0_vm_fault_interrupt_state AND gmc_v12_0.c::gmc_v12_0_vm_fault_interrupt_state , TOTAL NUMBER LINES IN FUNCTIONS: 36
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;9) The specified files are in the directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drivers/gpu/drm/amd/amdgpu/&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gfx_v11_0.c::gfx_v11_0_handle_priv_fault AND gfx_v12_0.c::gfx_v12_0_handle_priv_fault , TOTAL NUMBER LINES IN FUNCTIONS: 36
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;10) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drivers/iio/&lt;/code&gt;: the cluster only identifies these 6 files. However, it is possible to find other functions that exhibit minor variations in their signature, for example, receiving only a pointer to a channel (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chan&lt;/code&gt;) or using an explicit index (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;channel&lt;/code&gt;) within the channels array.&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Cluster #3 (Files: 6, Pairs: 15, Lines: 270)
---------------------
Function find: accel/hid-sensor-accel-3d.c::accel_3d_adjust_channel_bit_mask, TOTAL NUMBER LINES IN FUNCTION: 9
Function find: pressure/hid-sensor-press.c::press_adjust_channel_bit_mask, TOTAL NUMBER LINES IN FUNCTION: 9
Function find: magnetometer/hid-sensor-magn-3d.c::magn_3d_adjust_channel_bit_mask, TOTAL NUMBER LINES IN FUNCTION: 9
Function find: light/hid-sensor-prox.c::prox_adjust_channel_bit_mask, TOTAL NUMBER LINES IN FUNCTION: 9
Function find: light/hid-sensor-als.c::als_adjust_channel_bit_mask, TOTAL NUMBER LINES IN FUNCTION: 9
Function find: gyro/hid-sensor-gyro-3d.c::gyro_3d_adjust_channel_bit_mask, TOTAL NUMBER LINES IN FUNCTION: 9
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;11) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drivers/iio/&lt;/code&gt;: bidirectional mappings of the same table.&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Cluster #5 (Files: 2, Pairs: 1, Lines: 74)
---------------------
Function find: light/tsl2591.c::tsl2591_persist_cycle_to_lit, TOTAL NUMBER LINES IN FUNCTION: 37
Function find: light/tsl2591.c::tsl2591_persist_lit_to_cycle, TOTAL NUMBER LINES IN FUNCTION: 37
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;suggestion-42-duplications-with-90-similarity&quot;&gt;Suggestion 4.2) Duplications with 90% similarity&lt;/h2&gt;

&lt;p&gt;1) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drivers/iio/&lt;/code&gt;: There is a common configuration sanitization step for both functions (retained from 2025)&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;imu/inv_icm42600/inv_icm42600_core.c::inv_icm42600_set_accel_conf AND imu/inv_icm42600/inv_icm42600_core.c::inv_icm42600_set_gyro_conf , TOTAL NUMBER LINES IN FUNCTIONS: 60
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;2) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drivers/iio/&lt;/code&gt;: Possibly a refactoring opportunity (retained from 2025)&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;light/veml6030.c::veml6030_hw_init AND light/veml6030.c::veml6035_hw_init , TOTAL NUMBER LINES IN FUNCTIONS: 49
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Difference in the configuration of register &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x00&lt;/code&gt;: &lt;a href=&quot;https://www.vishay.com/docs/84366/veml6030.pdf&quot;&gt;https://www.vishay.com/docs/84366/veml6030.pdf&lt;/a&gt; and &lt;a href=&quot;https://www.vishay.com/docs/84889/veml6035.pdf&quot;&gt;https://www.vishay.com/docs/84889/veml6035.pdf&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;deduplications-from-last-year-2025&quot;&gt;Deduplications from last year (2025)&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/arkanjo-tool/arkanjo/blob/main/docs/PATCHES_MAC0470_5856_2025.md&quot;&gt;https://github.com/arkanjo-tool/arkanjo/blob/main/docs/PATCHES_MAC0470_5856_2025.md&lt;/a&gt;&lt;/p&gt;

&lt;h1 id=&quot;history&quot;&gt;History&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;V0.1: First work-in-progress version for the FSD 2026 workshop of 07/04/2026.&lt;/li&gt;
  &lt;li&gt;V0.2: Add link to patch submission guidelines (thanks to Guilherme Ivo).&lt;/li&gt;
&lt;/ul&gt;
</content>
    </entry>
    
    <entry>
        <title type="html">Sending patches with git and a USP email</title>
        <link href="https://flusp.ime.usp.br/git/sending-patches-with-git-and-a-usp-email/"/>
        <published>2026-03-24T00:00:00-03:00</published>
        <id isPermaLink="true">https://flusp.ime.usp.br/git/sending-patches-with-git-and-a-usp-email/</id>
        <category>git</category>
        <content type="html">&lt;p&gt;This tutorial explains how to send patches via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt; using a USP
email account, which involves some extra steps. We will be using
&lt;a href=&quot;https://kworkflow.org&quot;&gt;kworkflow&lt;/a&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw&lt;/code&gt;) to simplify setup and automatically
resolve maintainers when dealing with kernel contributions. An important
prerequisite of this tutorial is reading the “&lt;a href=&quot;/git/sending-patches-by-email-with-git/&quot;&gt;Sending patches by email with
git&lt;/a&gt;”
post.&lt;/p&gt;

&lt;!--end-abstract--&gt;

&lt;h1 id=&quot;introduction&quot;&gt;Introduction&lt;/h1&gt;

&lt;p&gt;When contributing to projects that do not use workflows like GitHub’s
Pull-Requests or GitLab’s Merge-Requests (some call those &lt;em&gt;Web-based
workflows&lt;/em&gt;), but rather workflows where you need to send contributions via
email, using a tool like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt; is very convenient, as it greatly
simplifies the process of converting and sending your commits. For example, you
do not need to worry about your email messages (that contain your code) being
misformatted or even leaving your local repository to accomplish the task.&lt;/p&gt;

&lt;p&gt;Nevertheless, no matter the tool you use, you need to deal with authentication
issues that may vary widely depending on your email account and provider. In
this case, we are focusing on USP email accounts, which are Gmail accounts with
some particularities when used to send patches.&lt;/p&gt;

&lt;h3 id=&quot;what-is-the-problem-with-usp-emails&quot;&gt;What is the problem with USP emails?&lt;/h3&gt;

&lt;p&gt;Usually, when using Gmail accounts, you need to set up an &lt;a href=&quot;https://support.google.com/mail/answer/185833&quot;&gt;App
Password&lt;/a&gt; to signal Google that
you are allowing an external service that uses this password to (in our case)
send email messages with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt;. To set up an &lt;em&gt;App Password&lt;/em&gt;, you
must first enable &lt;a href=&quot;https://support.google.com/accounts/answer/185839?hl=en&amp;amp;co=GENIE.Platform%3DDesktop&quot;&gt;2-Step
Verification&lt;/a&gt;,
which is not possible for USP emails.&lt;/p&gt;

&lt;p&gt;To cover cases where setting up an &lt;em&gt;App Password&lt;/em&gt; is not an option, Google
still provides &lt;em&gt;Less Secure Apps&lt;/em&gt; to allow authentication with the usual Gmail
account password, even though this method is said to be unsupported since
January 2025. You can check your USP Google account settings for the &lt;em&gt;Less
Secure Apps&lt;/em&gt; configuration, enable it, and try to use it, but I can tell you
that this won’t work (at least, I would be very surprised if it did). The
motive behind it is a long and obscure one, but the TL;DR is that the USP
systems suffered security attacks in the first semester of 2025, which resulted
in the admins locking down some vulnerable features like &lt;em&gt;Less Secure Apps&lt;/em&gt;
(you can imagine why).&lt;/p&gt;

&lt;h3 id=&quot;the-alternative-oauth-20&quot;&gt;The alternative: OAuth 2.0&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://oauth.net/2/&quot;&gt;OAuth 2.0&lt;/a&gt; is a widely used protocol for authentication.
It “delegates” authentication of the third-party app (again, in our case, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git
send-email&lt;/code&gt;) to an authorisation server (Google itself) without ever needing to
store or share sensitive passwords.&lt;/p&gt;

&lt;p class=&quot;info&quot;&gt;This post is not about OAuth, so feel free to consult the linked page for
further information.&lt;/p&gt;

&lt;p&gt;Through OAuth, we can finally overcome the problems with USP emails, though it
requires some (hopefully) not-so-complicated setup. More specifically, we will
present two options to handle the OAuth protocol part, which &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt;
doesn’t do:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Option A)&lt;/strong&gt; Using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git credential&lt;/code&gt; command with a helper.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Option B)&lt;/strong&gt; Using an email proxy capable of authenticating through OAuth.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each option is suited for a different scenario. We suggest trying &lt;strong&gt;Option A&lt;/strong&gt;
first, then, only if things go wrong, moving to &lt;strong&gt;Option B&lt;/strong&gt;.&lt;/p&gt;

&lt;h3 id=&quot;summary-of-this-tutorial&quot;&gt;Summary of this tutorial&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Option A&lt;/strong&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git credential&lt;/code&gt; helper
    &lt;ul&gt;
      &lt;li&gt;Installing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git credential&lt;/code&gt; helper and generating the access token&lt;/li&gt;
      &lt;li&gt;Configuring &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;credential&lt;/code&gt; manually&lt;/li&gt;
      &lt;li&gt;Testing the setup with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw send-patch&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Option B&lt;/strong&gt;: Email Proxy
    &lt;ul&gt;
      &lt;li&gt;Running the email proxy&lt;/li&gt;
      &lt;li&gt;Configuring &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw send-patch&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Testing the setup with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw send-patch&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Miscellaneous Notes&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p class=&quot;warning&quot;&gt;For students of the Free Software Development course, pay attention to these
warning boxes, as they will contain specific instructions for this audience.&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;option-a-git-credential-helper&quot;&gt;Option A: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git credential&lt;/code&gt; helper&lt;/h1&gt;

&lt;p&gt;Beyond helping you with commits, branches, remotes, sending emails, etc., &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt;
also has a command for storing/retrieving credentials and prompting the user
for usernames and passwords called &lt;a href=&quot;https://git-scm.com/docs/git-credential&quot;&gt;git
credential&lt;/a&gt;. This is a versatile
command that is extensible using arbitrary helpers that need “only” to provide
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fill&lt;/code&gt; (fill username and password), &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;approve&lt;/code&gt; (store credentials), and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reject&lt;/code&gt; (remove credentials) actions.&lt;/p&gt;

&lt;p&gt;An example of a built-in helper in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt; is
&lt;a href=&quot;https://git-scm.com/docs/git-credential-cache&quot;&gt;credential-cache&lt;/a&gt;, which can
temporarily store credentials for a given context.&lt;/p&gt;

&lt;h2 id=&quot;installing-the-git-credential-helper-and-generating-the-access-token&quot;&gt;Installing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git credential&lt;/code&gt; helper and generating the access token&lt;/h2&gt;

&lt;p&gt;As mentioned, you can create your own helper that implements the necessary
actions for a USP (Gmail) email. Nevertheless, for simplicity, we will use an
existing project called
&lt;a href=&quot;https://github.com/AdityaGarg8/git-credential-email&quot;&gt;git-credential-email&lt;/a&gt;,
which provides a helper for Gmail accounts. To install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git-credential-gmail&lt;/code&gt;
(the Gmail helper), refer to the &lt;a href=&quot;https://github.com/AdityaGarg8/git-credential-email?tab=readme-ov-file#installation&quot;&gt;installation
section&lt;/a&gt;
for system-specific instructions. Note that you only need to install the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git-credential-gmail&lt;/code&gt; helper, not the helpers for other email providers.&lt;/p&gt;

&lt;p&gt;After installing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git-credential-gmail&lt;/code&gt;, you need to obtain an OAuth client ID
and secret. These two client tokens need to be generated on your own, although
you can &lt;a href=&quot;https://github.com/simonrob/email-oauth2-proxy/?tab=readme-ov-file#oauth-20-client-credentials&quot;&gt;reuse other “open”
tokens&lt;/a&gt;.
By default, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git-credential-email&lt;/code&gt; helpers use the Thunderbird token pair, but
you can set specific ones by running this command and selecting the 6th option
it gives:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git credential-gmail &lt;span class=&quot;nt&quot;&gt;--set-client&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note that this will also prompt for a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Redirect URI&lt;/code&gt;, which you should fill
with:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-out&quot;&gt;Enter the Redirect URI: http://localhost
&lt;/code&gt;&lt;/pre&gt;

&lt;p class=&quot;warning&quot;&gt;For students of the Free Software Development course, &lt;strong&gt;consult the pad for the
tokens&lt;/strong&gt;, &lt;strong&gt;set them&lt;/strong&gt;, and &lt;strong&gt;don’t forget to add your USP email address
there&lt;/strong&gt; as instructed by the mentors.&lt;/p&gt;

&lt;p&gt;After setting the OAuth client, we need to generate the access token (the OAuth
“password”) by authenticating:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git credential-gmail --authenticate --external-auth
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Follow the instructions that appear, which boil down to pasting the provided
URL in a browser, authenticating your USP email, and then pasting the resulting
URL back in the terminal. If everything went right, you should be able to see
the access token with:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git credential-gmail
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p class=&quot;info&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git-credential-email&lt;/code&gt; stores the access token (and the refresh token) in your
system’s keyring with the help of the &lt;a href=&quot;https://pypi.org/project/keyring/&quot;&gt;keyring Python
module&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;configuring-git-send-email-and-credential-manually&quot;&gt;Configuring &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;credential&lt;/code&gt; manually&lt;/h2&gt;

&lt;p&gt;For this tutorial, we will not develop or submit a real contribution, so create
an empty repository just for us to test the setup:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git init /tmp/git-credential-test
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then, move to this repo:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /tmp/git-credential-test
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Inside the created repo&lt;/strong&gt;, let’s edit the &lt;strong&gt;local&lt;/strong&gt; configurations that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git
send-email&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;credential&lt;/code&gt; will use:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config --local --edit
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will open an editor, with the local &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt; config file (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.git/config&lt;/code&gt;),
where you need to append it with (adapt the necessary fields):&lt;/p&gt;

&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;[credential &quot;smtp://smtp.gmail.com:465&quot;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;helper&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; 
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;helper = gmail&lt;/span&gt;
&lt;span class=&quot;nn&quot;&gt;[sendemail]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;smtpEncryption&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ssl&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;smtpServer&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;smtp.gmail.com&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;smtpUser&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;lt;ADAPT-TO-YOUR-USP-EMAIL-ADDRESS&amp;gt;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;smtpServerPort&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;465&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;smtpAuth&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;OAUTHBEARER&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;lt;ADAPT-TO-YOUR-NAME-AND-SURNAME&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The configurations above tell &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt; to use OAuth to authenticate to
Google’s SMTP servers, and to use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;credential&lt;/code&gt; helper &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gmail&lt;/code&gt; (i.e., the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git-credential-gmail&lt;/code&gt; helper we installed) for credentials. These commands
will modify your local Git configurations inside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.git/config&lt;/code&gt;. In case of any
trouble, check this file to see if the information is correct.&lt;/p&gt;

&lt;h2 id=&quot;testing-the-setup-with-kw-send-patch&quot;&gt;Testing the setup with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw send-patch&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;After configuring your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;credential&lt;/code&gt; helper for Gmail, we
are ready to test our setup! For this, we will be using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw send-patch&lt;/code&gt;.&lt;/p&gt;

&lt;p class=&quot;info&quot;&gt;We won’t cover installing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw&lt;/code&gt;, so refer to the kworkflow
&lt;a href=&quot;https://kworkflow.org&quot;&gt;site&lt;/a&gt; or the &lt;a href=&quot;https://github.com/kworkflow/kworkflow&quot;&gt;GitHub
repo&lt;/a&gt; if you need help.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Inside the empty repo&lt;/strong&gt;, we initialised and configured &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt; and
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;credential&lt;/code&gt; helper. Create any commit you wish and choose the email
address(es) that will receive this test message.&lt;/p&gt;

&lt;p class=&quot;warning&quot;&gt;For students of the Free Software Development course, create a commit titled
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;YOUR-FIRST-NAME&amp;gt; &amp;lt;YOUR-SURNAME&amp;gt;&lt;/code&gt; that adds a file named
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;YOUR-FIRST-NAME&amp;gt;.&amp;lt;YOUR-SURNAME&amp;gt;.txt&lt;/code&gt; that contains the string &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;I am &amp;lt;YOUR-FIRST-NAME&amp;gt; &amp;lt;YOUR-SURNAME&amp;gt;&lt;/code&gt;.
For the message recipients, use your own email address and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dsl26oauthproxy@gmail.com&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After preparing our &lt;em&gt;test commit&lt;/em&gt;, first let us check if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw send-patch&lt;/code&gt; would
send the correct message to the correct people before actually sending the
message (this is a good idea every time we are dealing with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw send-patch&lt;/code&gt; or
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt;) &lt;strong&gt;adapting the necessary fields&lt;/strong&gt;:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kw send-patch &lt;span class=&quot;nt&quot;&gt;--send&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-1&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--private&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--simulate&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--to&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;EMAIL-ADDRESS-1&amp;gt;&apos;&lt;/span&gt;,&lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;EMAIL-ADDRESS-2&amp;gt;&apos;&lt;/span&gt; ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This command will open an editor with the contents of the message to be sent,
including the code. With the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--simulate&lt;/code&gt; flag, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw send-patch&lt;/code&gt; will do
everything it would do if it were to send the message, except actually sending
it. In this sense, you can check the output of the command to see if the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;To:&lt;/code&gt;
and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cc:&lt;/code&gt; fields are correct, along with the message subject, contents, etc.
After being sure that the correct message and recipients are generated, drop
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--simulate&lt;/code&gt; flag and rerun the command:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kw send-patch &lt;span class=&quot;nt&quot;&gt;--send&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-1&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--private&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--to&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;EMAIL-ADDRESS-1&amp;gt;&apos;&lt;/span&gt;,&lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;EMAIL-ADDRESS-2&amp;gt;&apos;&lt;/span&gt; ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After exiting the editor, it should indicate that the message was successfully
sent, and you can check the recipient(s) of your test email to see if the
message(s) have arrived.&lt;/p&gt;

&lt;p class=&quot;warning&quot;&gt;For students of the Free Software Development course, you don’t need to notify
the mentors to check if the messages arrived in the previously provided email
address, as just checking your own email inboxes will be sufficient.&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;option-b-email-proxy&quot;&gt;Option B: Email Proxy&lt;/h1&gt;

&lt;p&gt;Our email proxy will be based on the
&lt;a href=&quot;https://github.com/simonrob/email-oauth2-proxy/&quot;&gt;email-oauth2-proxy&lt;/a&gt; project,
a Python script configurable via an
&lt;a href=&quot;https://en.wikipedia.org/wiki/INI_file&quot;&gt;INI&lt;/a&gt;-like file. To avoid
distro-specific nuances, we will use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-compose&lt;/code&gt; to
streamline the process, so &lt;strong&gt;make sure they are installed and configured on
your system&lt;/strong&gt;!&lt;/p&gt;

&lt;h2 id=&quot;running-the-email-proxy&quot;&gt;Running the email proxy&lt;/h2&gt;

&lt;p&gt;Once you have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-compose&lt;/code&gt; installed and configured, clone
this repository:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone https://github.com/davidbtadokoro/emailproxy-container.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In this repo, you will find 3 files:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dockerfile&lt;/code&gt;: the recipe for our cotainer image.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-compose.yaml&lt;/code&gt;: the orchestration script to simplify running our container.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;emailproxy.config&lt;/code&gt;: the configuration file for the email proxy.&lt;/li&gt;
&lt;/ol&gt;

&lt;p class=&quot;info&quot;&gt;For this tutorial, you will only need to modify &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;emailproxy.config&lt;/code&gt;; however, you can check and tinker with the other 2 files if you are curious, as they are really simple.&lt;/p&gt;

&lt;p&gt;Opening &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;emailproxy.config&lt;/code&gt;, you will notice some &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;FILL-HERE-...&amp;gt;&lt;/code&gt; fields:&lt;/p&gt;

&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;[Account setup]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;[&amp;lt;FILL-HERE-USP-EMAIL-ADDRESS&amp;gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;permission_url&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;https://accounts.google.com/o/oauth2/auth&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;token_url&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;https://oauth2.googleapis.com/token&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;oauth2_scope&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;https://mail.google.com/&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;redirect_uri&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;http://localhost&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;client_id&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;lt;FILL-HERE-CLIENT-ID&amp;gt;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;client_secret&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;lt;FILL-HERE-CLIENT-SECRET&amp;gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You need to replace these fields with the USP email address you will use and
the OAuth client ID and secret. These two client tokens need to be generated on
your own, although you can &lt;a href=&quot;https://github.com/simonrob/email-oauth2-proxy/?tab=readme-ov-file#oauth-20-client-credentials&quot;&gt;reuse other “open”
tokens&lt;/a&gt;.&lt;/p&gt;

&lt;p class=&quot;warning&quot;&gt;For students of the Free Software Development course, &lt;strong&gt;consult the pad for the
tokens&lt;/strong&gt; and &lt;strong&gt;don’t forget to add your USP email address there&lt;/strong&gt; as instructed
by the mentors.&lt;/p&gt;

&lt;p&gt;After filling the necessary fields, build and start the container with
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-compose&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker compose up &lt;span class=&quot;nt&quot;&gt;--build&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you investigated the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dockerfile&lt;/code&gt;, you may have noticed that this container
does nothing (it only sleeps to infinity), so, on another terminal, enter the
container:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker &lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; emailproxy-container-server-1 /bin/bash
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The container name should match the one above. If you run into any trouble,
first check that you are using the correct name with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker ps&lt;/code&gt;. &lt;strong&gt;Inside the
container&lt;/strong&gt;, start the email proxy:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;emailproxy &lt;span class=&quot;nt&quot;&gt;--no-gui&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--external-auth&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--config-file&lt;/span&gt; /app/emailproxy.config
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If everything worked correctly, you should see this at the end:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-out&quot;&gt;...
Initialised Email OAuth 2.0 Proxy - listening for authentication requests. Connect your email client to begin
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Of course, don’t kill this process or the container, as the email proxy needs to be running for the next steps.&lt;/p&gt;

&lt;h2 id=&quot;configuring-git-send-email-with-kw-send-patch&quot;&gt;Configuring &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw send-patch&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;For this tutorial, we will not develop or submit a real contribution, so we
will use the previously cloned repo for the email proxy in our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt;
configuration and testing. To accomplish this, we will leverage the convenience
of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw send-patch&lt;/code&gt;.&lt;/p&gt;

&lt;p class=&quot;info&quot;&gt;We won’t cover installing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw&lt;/code&gt;, so refer to the kworkflow
&lt;a href=&quot;https://kworkflow.org&quot;&gt;site&lt;/a&gt; or the &lt;a href=&quot;https://github.com/kworkflow/kworkflow&quot;&gt;GitHub
repo&lt;/a&gt; if you need help.&lt;/p&gt;

&lt;p&gt;On another terminal (again, &lt;strong&gt;keep the container and process running in the
other terminals&lt;/strong&gt;), go to the email proxy repo and run the following commands
&lt;strong&gt;adapting the necessary fields&lt;/strong&gt;:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kw send-patch &lt;span class=&quot;nt&quot;&gt;--setup&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;ADAPT-TO-YOUR-NAME-AND-SURNAME&amp;gt;&apos;&lt;/span&gt;
kw send-patch &lt;span class=&quot;nt&quot;&gt;--setup&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--email&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;ADAPT-TO-YOUR-USP-EMAIL-ADDRESS&amp;gt;&apos;&lt;/span&gt;
kw send-patch &lt;span class=&quot;nt&quot;&gt;--setup&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--smtpuser&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;ADAPT-TO-YOUR-USP-EMAIL-ADDRESS&amp;gt;&apos;&lt;/span&gt;
kw send-patch &lt;span class=&quot;nt&quot;&gt;--setup&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--smtpserver&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;127.0.0.1&apos;&lt;/span&gt;
kw send-patch &lt;span class=&quot;nt&quot;&gt;--setup&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--smtpserverport&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;2587&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;These commands will modify your local Git configurations inside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.git/config&lt;/code&gt;.
In case of any trouble, check this file to see if the information is correct.&lt;/p&gt;

&lt;h2 id=&quot;testing-the-setup-with-kw-send-patch-1&quot;&gt;Testing the setup with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw send-patch&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;After starting the email proxy and configuring your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw
send-patch&lt;/code&gt;, we are ready to test our setup! Inside the email proxy repo,
create any commit you wish and choose an email address(es) that will receive
this test message.&lt;/p&gt;

&lt;p class=&quot;warning&quot;&gt;For students of the Free Software Development course, create a commit titled
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;YOUR-FIRST-NAME&amp;gt; &amp;lt;YOUR-SURNAME&amp;gt;&lt;/code&gt; that adds a file named
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;YOUR-FIRST-NAME&amp;gt;.&amp;lt;YOUR-SURNAME&amp;gt;.txt&lt;/code&gt; that contains the string &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;I am &amp;lt;YOUR-FIRST-NAME&amp;gt; &amp;lt;YOUR-SURNAME&amp;gt;&lt;/code&gt;.
For the message recipients, use your own
email address and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dsl26oauthproxy@gmail.com&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After preparing our &lt;em&gt;test commit&lt;/em&gt;, first let us check if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw send-patch&lt;/code&gt; would
send the correct message to the correct people before actually sending the
message (this is a good idea every time we are dealing with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw send-patch&lt;/code&gt; or
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt;) &lt;strong&gt;adapting the necessary fields&lt;/strong&gt;:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kw send-patch &lt;span class=&quot;nt&quot;&gt;--send&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-1&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--private&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--simulate&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--to&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;EMAIL-ADDRESS-1&amp;gt;&apos;&lt;/span&gt;,&lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;EMAIL-ADDRESS-2&amp;gt;&apos;&lt;/span&gt; ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This command will open an editor with the contents of the message to be sent,
including the code. With the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--simulate&lt;/code&gt; flag, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw send-patch&lt;/code&gt; will do
everything it would do if it were to send the message, except actually sending
it. In this sense, you can check the output of the command to see if the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;To:&lt;/code&gt;
and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cc:&lt;/code&gt; fields are correct, along with the message subject, contents, etc.
After being sure that the correct message and recipients are generated, drop
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--simulate&lt;/code&gt; flag and rerun the command:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kw send-patch &lt;span class=&quot;nt&quot;&gt;--send&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-1&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--private&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--to&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;EMAIL-ADDRESS-1&amp;gt;&apos;&lt;/span&gt;,&lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;EMAIL-ADDRESS-2&amp;gt;&apos;&lt;/span&gt; ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After exiting the editor, you will be prompted to enter a password. For example:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-out&quot;&gt;...
Password for &apos;smtp://davidbtadokoro%40ime.usp.br@127.0.0.1:2587&apos;:
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This password &lt;strong&gt;is not the same as the one you use for your account&lt;/strong&gt;;
actually, you can type in any password you wish, as this will be a &lt;em&gt;local
password&lt;/em&gt; for the email proxy. Just note that you need to use this same &lt;em&gt;local
password&lt;/em&gt; in future uses of the email proxy. After providing your password, go
back to the terminal running the container (the one you ran &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker exec&lt;/code&gt;), and
note that you have an output similar to:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-out&quot;&gt;Please visit the following URL to authenticate account davidbtadokoro@ime.usp.br: https://accounts.google.com/o/oauth2/auth?client_id=17174063743-ts28k6ie7lmospgcfs775m8qvek6n4ma.apps.googleusercontent.com&amp;amp;redirect_uri=http%3A%2F%2Flocalhost&amp;amp;scope=https%3A%2F%2Fmail.google.com%2F&amp;amp;response_type=code&amp;amp;access_type=offline&amp;amp;login_hint=davidbtadokoro%40ime.usp.br

Copy+paste or press [↵ Return] to visit the following URL and authenticate account davidbtadokoro@ime.usp.br: https://accounts.google.com/o/oauth2/auth?client_id=17174063743-ts28k6ie7lmospgcfs775m8qvek6n4ma.apps.googleusercontent.com&amp;amp;redirect_uri=http%3A%2F%2Flocalhost&amp;amp;scope=https%3A%2F%2Fmail.google.com%2F&amp;amp;response_type=code&amp;amp;access_type=offline&amp;amp;login_hint=davidbtadokoro%40ime.usp.br then paste here the full post-authentication URL from the browser&apos;s address bar (it should start with http://localhost):
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I suggest not using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[↵ Return]&lt;/code&gt; option and instead copying and pasting the
URL into your browser. Doing so will open a Google authentication page that
first asks whether you trust the client app associated with the tokens you
provided, then prompts you to log in if necessary. After doing those, you will
land on an &lt;em&gt;Unable to connect&lt;/em&gt; or &lt;em&gt;Problem loading&lt;/em&gt; page, which is
&lt;strong&gt;expected&lt;/strong&gt;! The only use of this page is its URL, starting with
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://localhost/...&lt;/code&gt; that you need to copy and then paste back in the
terminal running the container and &lt;strong&gt;press enter&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-out&quot;&gt;Copy+paste or press [↵ Return] to visit the following URL and authenticate account davidbtadokoro@ime.usp.br: https://accounts.google.com/o/oauth2/auth?client_id=17174063743-ts28k6ie7lmospgcfs775m8qvek6n4ma.apps.googleusercontent.com&amp;amp;redirect_uri=http%3A%2F%2Flocalhost&amp;amp;scope=https%3A%2F%2Fmail.google.com%2F&amp;amp;response_type=code&amp;amp;access_type=offline&amp;amp;login_hint=davidbtadokoro%40ime.usp.br then paste here the full post-authentication URL from the browser&apos;s address bar (it should start with http://localhost): http://localhost/?iss=https://accounts.google.com&amp;amp;code=4/0Aci98E-fygcbbASm0JYllktwUvUo6gKexj4khWtKBMlLWWutANBX3tUtKHJAwaWq3uEcgg&amp;amp;scope=https://mail.google.com/
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After that, you should see a log like:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-out&quot;&gt;SMTP (0.0.0.0:2587; davidbtadokoro@ime.usp.br) [ Successfully authenticated SMTP connection - releasing session ]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With that, you can go back to the terminal where you ran &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw send-patch&lt;/code&gt;, and
it should indicate success. Check the recipient(s) of your test email to see if
the message(s) have arrived.&lt;/p&gt;

&lt;p class=&quot;warning&quot;&gt;For students of the Free Software Development course, you don’t need to notify
the mentors to check if the messages arrived in the previously provided email
address, as just checking your own email inboxes will be sufficient.&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;miscellaneous-notes&quot;&gt;Miscellaneous Notes&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;The email proxy approach used in this tutorial focused on portability and on
the specific task of sending patches with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt;. You can optimise the
approach to run natively on your own system and for other purposes. For
example, I use the email proxy project mentioned as a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt; service that
initialises with my system and that I use for my email client.&lt;/li&gt;
  &lt;li&gt;We didn’t delve deep into the protocol part of sending emails, but this is
related to SMTP. That is why you see that the server setup in
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;emailproxy.config&lt;/code&gt; has only an SMTP section with very specific values.&lt;/li&gt;
  &lt;li&gt;As OAuth is a protocol, you could implement your own system to do this
proxying. The question is that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt; (and sometimes other
email-related apps too) doesn’t implement the client-side of the protocol, so
we need to fill this in some way or another.&lt;/li&gt;
  &lt;li&gt;We used &lt;strong&gt;local&lt;/strong&gt; Git configurations, which will be enforced in a per-repo
logic. For &lt;strong&gt;global&lt;/strong&gt; configurations, simply remove the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--local&lt;/code&gt; flags in the
configuration commands.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;history&quot;&gt;History&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;V1: Release with just the email proxy option.&lt;/li&gt;
  &lt;li&gt;V2: Include the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;credential&lt;/code&gt; helper option and do small adjustments to the rest of the post. Thanks Guilherme Ivo for the helper idea and for the review of this post.&lt;/li&gt;
&lt;/ul&gt;
</content>
    </entry>
    
    <entry>
        <title type="html">Building and booting a custom Linux kernel for ARM using kw</title>
        <link href="https://flusp.ime.usp.br/kernel/build-linux-for-arm-kw/"/>
        <published>2025-03-09T00:00:00-03:00</published>
        <id isPermaLink="true">https://flusp.ime.usp.br/kernel/build-linux-for-arm-kw/</id>
        <category>kernel</category>
        <content type="html">&lt;p&gt;This tutorial describes how to build - in other words, compile - the Linux
kernel for the &lt;a href=&quot;https://www.arm.com/architecture/cpu&quot;&gt;ARM architecture&lt;/a&gt; and boot
test it in a Virtual Machine (VM) using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw&lt;/code&gt; to streamline and automate some
processes we will be doing. Basic kernel build configuration is covered too.&lt;/p&gt;

&lt;p&gt;This tutorial was originally thought to be part of a set of tutorials tailored
to aid newcomers in developing the Linux kernel Industrial I/O subsystem (IIO).
It is the second in the series and a continuation of the “&lt;a href=&quot;/kernel/qemu-libvirt-setup/&quot;&gt;Setting up a test
environment for Linux Kernel Dev using QEMU and libvirt&lt;/a&gt;” tutorial. This post is an adaptation of “&lt;a href=&quot;/kernel/build-linux-for-arm/&quot;&gt;Building and booting a custom
Linux kernel for ARM&lt;/a&gt;” to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw&lt;/code&gt; wherever is convenient.&lt;/p&gt;

&lt;!--end-abstract--&gt;

&lt;!--begin-references--&gt;

&lt;!--url=&quot;https://docs.kernel.org/kbuild/makefiles.html#descending-down-in-directories&quot; %}
--&gt;

&lt;!--
[1]: https://docs.kernel.org/kbuild/modules.html
[2]: https://www.linuxjournal.com/content/kbuild-linux-kernel-build-system
[3]: https://docs.kernel.org/kbuild/kconfig-language.html
[4]: https://docs.kernel.org/kbuild/makefiles.html#descending-down-in-directories
--&gt;

&lt;!--end-references--&gt;

&lt;h3 id=&quot;command-summary&quot;&gt;Command Summary&lt;/h3&gt;

&lt;p class=&quot;warning&quot;&gt;Skip this section if you have not completed this tutorial yet. This is a
reference for those who have gone through this tutorial and want to remember
specific commands.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;### INSTALL `kw`&lt;/span&gt;
git clone https://github.com/kworkflow/kworkflow.git &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$KW_DIR&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$KW_DIR&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
git switch unstable &lt;span class=&quot;c&quot;&gt;# changes to the branch `unstable`&lt;/span&gt;
./setup.sh &lt;span class=&quot;nt&quot;&gt;--full-installation&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# install `kw` w/ all dependencies for building Linux kernel&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;### SHALLOWLY CLONING THE IIO TREE W/ ACTIVE DEVELOPMENT BRANCH&lt;/span&gt;
git clone git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IIO_TREE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--branch&lt;/span&gt; testing &lt;span class=&quot;nt&quot;&gt;--single-branch&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--depth&lt;/span&gt; 10

&lt;span class=&quot;c&quot;&gt;### CONFIGURING `kw`&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# go to the IIO tree directory&lt;/span&gt;
kw init &lt;span class=&quot;c&quot;&gt;# initialize local configurations for the IIO tree&lt;/span&gt;
kw remote &lt;span class=&quot;nt&quot;&gt;--add&lt;/span&gt; arm64 root@&amp;lt;VM-IP-address&amp;gt; &lt;span class=&quot;nt&quot;&gt;--set-default&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# adds a remote named `arm64` to local context and set it to default&lt;/span&gt;
kw config build.arch &lt;span class=&quot;s1&quot;&gt;&apos;arm64&apos;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# defines the target architecture to ARM64&lt;/span&gt;
kw config build.cross_compile &lt;span class=&quot;s1&quot;&gt;&apos;aarch64-linux-gnu-&apos;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# defines the cross-compiler&lt;/span&gt;
kw config build.kernel_img_name &lt;span class=&quot;s1&quot;&gt;&apos;Image.gz&apos;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# defines the kernel image format&lt;/span&gt;
kw config &lt;span class=&quot;nt&quot;&gt;--show&lt;/span&gt; build &lt;span class=&quot;c&quot;&gt;# check `kw build` configurations&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;### CREATING A LEAN `.config` file&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# go to the IIO tree directory&lt;/span&gt;
make &lt;span class=&quot;nv&quot;&gt;ARCH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;arm64 defconfig &lt;span class=&quot;c&quot;&gt;# create predefined defconfig&lt;/span&gt;
make &lt;span class=&quot;nv&quot;&gt;ARCH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;arm64 olddefconfig &lt;span class=&quot;c&quot;&gt;# update defconfig with new default values&lt;/span&gt;
kw ssh &lt;span class=&quot;nt&quot;&gt;--get&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;~/vm_mod_list&apos;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# copy VM modules list to IIO tree&lt;/span&gt;
make &lt;span class=&quot;nv&quot;&gt;ARCH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;arm64 &lt;span class=&quot;nv&quot;&gt;LSMOD&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;vm_mod_list localmodconfig
kw kernel-config-manager &lt;span class=&quot;nt&quot;&gt;--save&lt;/span&gt; arm64-optimized &lt;span class=&quot;c&quot;&gt;# saves `.config` w/ name `arm64-optimized`&lt;/span&gt;
kw kernel-config-manager &lt;span class=&quot;nt&quot;&gt;--list&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# lists all managed `.config`s&lt;/span&gt;
kw kernel-config-manager &lt;span class=&quot;nt&quot;&gt;--get&lt;/span&gt; arm64-optimized &lt;span class=&quot;c&quot;&gt;# gets managed `.config` w/ name `arm64-optimized`&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;### BUILDING A LINUX KERNEL FROM SOURCE CODE&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# go to the IIO tree directory&lt;/span&gt;
kw build &lt;span class=&quot;nt&quot;&gt;--menu&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# safely modify `.config` w/ a TUI&lt;/span&gt;
kw build &lt;span class=&quot;c&quot;&gt;# compile Linux kernel from source considering local configurations&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;### INSTALLING LINUX KERNEL MODULES&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# go to the IIO tree directory&lt;/span&gt;
kw deploy &lt;span class=&quot;nt&quot;&gt;--modules&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# only install modules into the VM&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;introduction&quot;&gt;Introduction&lt;/h1&gt;

&lt;p&gt;After setting up a test environment with VMs using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QEMU&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libvirt&lt;/code&gt;, we
begin compiling (also called &lt;em&gt;building&lt;/em&gt;) a custom Linux kernel from source and
booting it. This involves taking the source code developed by the Linux
community, compiling it into a monolithic executable that can be loaded into
memory and run on hardware (virtualized or not), and using it to start a system.
Additionally, we will compile and install kernel modules, smaller units that can
be dynamically loaded and unloaded while the system is running.
Cross-compilation will also be a factor, as we assume that the machine used to
compile the source code to these artifacts has an AMD64 architecture, while the
target architecture is ARM64.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://kworkflow.org/&quot;&gt;kworkflow&lt;/a&gt;, or just &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw&lt;/code&gt;, is a &lt;em&gt;Free/Libre and Open
Source Software&lt;/em&gt; (FLOSS) &lt;em&gt;Developer Automation Workflow System&lt;/em&gt; (DAWS),
which has the mission of &lt;em&gt;reducing the environment and setup overhead of
developing for Linux&lt;/em&gt;. Similar to how &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libvirt&lt;/code&gt; facilitated our management
of VMs - albeit after some overhead setting its permissions to work - the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw&lt;/code&gt; project helps kernel developers in their day-to-day tasks, like
streamlining and automating building and deploying custom Linux kernels from
source. In this tutorial, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw&lt;/code&gt; will help us fetch an optimized &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.config&lt;/code&gt; for
our VM, build the custom kernel image and modules, and install the modules
inside the VM. It will also ease our life in terms of installing necessary
dependencies to compile a Linux kernel.&lt;/p&gt;

&lt;h1 id=&quot;configuring-building-and-booting-a-custom-linux-kernel&quot;&gt;Configuring, building, and booting a custom Linux kernel&lt;/h1&gt;

&lt;p&gt;In this section we will go through the steps on how to configure, compile, and
boot customized Linux images in ARM64 VMs using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Summary of this tutorial:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Installing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Cloning a Linux kernel tree&lt;/li&gt;
  &lt;li&gt;Configure &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw&lt;/code&gt; in a local context for IIO development&lt;/li&gt;
  &lt;li&gt;Configuring the Linux kernel compilation&lt;/li&gt;
  &lt;li&gt;Building a custom Linux kernel&lt;/li&gt;
  &lt;li&gt;Installing modules and booting the custom-built Linux kernel&lt;/li&gt;
&lt;/ol&gt;

&lt;p class=&quot;warning&quot;&gt;Before proceding remember to have the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activate.sh&lt;/code&gt; script we’ve created
available to be modified and active for all the commands run in the host system.
Also assure that you have your testing environment set up from the last
tutorial.&lt;/p&gt;

&lt;h3 id=&quot;1-installing-kw&quot;&gt;1) Installing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;The easiest way to install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw&lt;/code&gt; is to clone it using git and run the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setup.sh&lt;/code&gt;
script. First, let’s add an env var for the path of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw&lt;/code&gt; repository in the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activate.sh&lt;/code&gt; script.&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;--- a/activate.sh
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+++ b/activate.sh
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@@ -4,6 +4,7 @@&lt;/span&gt;
 export LK_DEV_DIR=&apos;/home/lk_dev&apos; # path to testing environment directory
 export VM_DIR=&quot;${LK_DEV_DIR}/vm&quot; # path to VM directory
 export BOOT_DIR=&quot;${VM_DIR}/arm64_boot&quot; # path to boot artifacts
&lt;span class=&quot;gi&quot;&gt;+export KW_DIR=&quot;${LK_DEV_DIR}/kw&quot; # path to `kw` repository
&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt; # utility functions
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Rerun the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activate.sh&lt;/code&gt; after that and clone the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw&lt;/code&gt; repository&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone https://github.com/kworkflow/kworkflow.git &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$KW_DIR&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then, go to the repository’s root and change it to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unstable&lt;/code&gt; branch. The
default &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; is OK for this tutorial, but the latest &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw&lt;/code&gt; development is
pretty stable, although the name of the branch suggests otherwise.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$KW_DIR&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
git switch unstable &lt;span class=&quot;c&quot;&gt;# changes to the branch `unstable`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Finally, do the full installation of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw&lt;/code&gt; to include dependencies for building
the kernel. If you are using a Arch, Debian, or Fedora-based distro, it should
detect it and prompt you to enter the superuser credentials to start installing
all the packages necessary.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;./setup.sh &lt;span class=&quot;nt&quot;&gt;--full-installation&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# install `kw` w/ all dependencies for building Linux kernel&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p class=&quot;info&quot;&gt;From now on, you can update &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw&lt;/code&gt; with itself! Running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw self-update&lt;/code&gt; updates
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw&lt;/code&gt; with the latest development on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; branch, while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw self-update
--unstable&lt;/code&gt; does the same for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unstable&lt;/code&gt; branch.&lt;/p&gt;

&lt;p&gt;You may need to exit and rerun the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activate.sh&lt;/code&gt; script for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw&lt;/code&gt; to show on your
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PATH&lt;/code&gt;. To ensure your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw&lt;/code&gt; installation was successful, run the following to
see information about the release.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kw &lt;span class=&quot;nt&quot;&gt;--version&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# print information about the `kw` release installed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;2-cloning-a-linux-kernel-tree&quot;&gt;2) Cloning a Linux kernel tree&lt;/h3&gt;

&lt;p&gt;There are several repositories that contain the source code for the Linux
kernel. These repositories are known as &lt;em&gt;Linux kernel trees&lt;/em&gt;, in short, kernel
trees or just trees, because, as every software project, its source code is
arranged in a tree-like file hierarchy. Some trees are widely known such as
Linus Torvalds’ tree (known as &lt;em&gt;mainline&lt;/em&gt;) that represent the most updated
official version of Linux and the Linux stable tree that represents the stable
releases (the 6.10, 6.11, 6.12, etc.). In general, a Linux tree is a repository
where some development for the kernel happens and each tree follows its own
development ruled by its own community. Many of those repos are at
&lt;a href=&quot;https://git.kernel.org/&quot;&gt;kernel.org&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Some examples of Linux kernel trees are:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/&quot;&gt;Linus Torvalds’ tree (mainline)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git&quot;&gt;Linux-stable tree&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git&quot;&gt;Linux-next tree&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git/&quot;&gt;IIO subsystem tree&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/raspberrypi/linux&quot;&gt;Raspberry Pi tree&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/analogdevicesinc/linux&quot;&gt;Analog Devices tree&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this workshop, we’ll be using the &lt;em&gt;Industrial I/O&lt;/em&gt; (IIO) subsystem tree so
download (clone) it with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt;. First, modify your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activate.sh&lt;/code&gt; script&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;--- a/activate.sh
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+++ b/activate.sh
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@@ -4,6 +4,7 @@&lt;/span&gt;
 export LK_DEV_DIR=&apos;/home/lk_dev&apos; # path to testing environment directory
 export VM_DIR=&quot;${LK_DEV_DIR}/vm&quot; # path to VM directory
 export BOOT_DIR=&quot;${VM_DIR}/arm64_boot&quot; # path to boot artifacts
 export KW_DIR=&quot;${LK_DEV_DIR}/kw&quot; # path to `kw` repository
&lt;span class=&quot;gi&quot;&gt;+export IIO_TREE=&quot;${LK_DEV_DIR}/iio&quot; # path to IIO subsystem Linux kernel tree
&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt; # utility functions
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;then rerun the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activate.sh&lt;/code&gt; script and clone the tree.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IIO_TREE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--branch&lt;/span&gt; testing &lt;span class=&quot;nt&quot;&gt;--single-branch&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--depth&lt;/span&gt; 10
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In terms of source code, Linux kernel trees are already huge (a couple of GB in
disk space), but the git history is even bigger at this point (around 5GB). To
(hopefully) not use too much disk space and avoid longer download times, we use
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--branch&lt;/code&gt; option, which tells git we want the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;testing&lt;/code&gt; branch of the
remote pointed by the URL, and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--depth=10&lt;/code&gt; option, which limits the git
history to the latest 10 commits in the branch to be fetched. We’ve chosen the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;testing&lt;/code&gt; branch instead of the default &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; because the former is where the
actual development happens. Hence, as in this series, we aim to (possibly)
develop and propose changes to IIO, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;testing&lt;/code&gt; branch is the one we are
interested in.&lt;/p&gt;

&lt;p&gt;If you have plenty of disk space (and probably some spare time), I suggest you
clone the tree without the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--branch&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--depth&lt;/code&gt; flags because commit logs
are often a good source of information when trying to understand kernel code. By
the time this post was written, the IIO tree (with its entire git history) was
sizing roughly 5GB.&lt;/p&gt;

&lt;h3 id=&quot;3-configure-kw-in-a-local-context-for-iio-development&quot;&gt;3) Configure &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw&lt;/code&gt; in a local context for IIO development&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw&lt;/code&gt; can create specific isolated configurations for each Linux kernel tree in
the user’s filesystem. It can actually create multiple environments for a single
tree, but this is too advanced for this tutorial. For now, let’s move into the
IIO tree and initialize local configurations for that tree.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# go to the IIO tree directory&lt;/span&gt;
kw init &lt;span class=&quot;c&quot;&gt;# initialize local configurations for the IIO tree&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For all &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw&lt;/code&gt; commands run inside this tree, local configurations will override
global ones whilst keeping them encapsulated in this context. This is similar to
how &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git config&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git config --global&lt;/code&gt; work.&lt;/p&gt;

&lt;p&gt;Before moving forward, let’s start the VM running ARM64, which we set up in the
last tutorial. Note that if either &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libvirtd&lt;/code&gt;, the default network, or the VM
are already started, some commands will raise errors, indicating that these are
already active.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@host
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl start libvirtd &lt;span class=&quot;c&quot;&gt;# starts the libvirt daemon&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;virsh net-start default &lt;span class=&quot;c&quot;&gt;# starts `virsh` default network&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;virsh start &lt;span class=&quot;nt&quot;&gt;--console&lt;/span&gt; arm64 &lt;span class=&quot;c&quot;&gt;# start a registered instance attaching console&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;virsh net-dhcp-leases default &lt;span class=&quot;c&quot;&gt;# list `default` network to get VM IP&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Inside the IIO tree, add the VM remote configurations for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw&lt;/code&gt; to manage it
seamlessly.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@host
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;### ADAPT THE COMMAND BELOW ###&lt;/span&gt;
kw remote &lt;span class=&quot;nt&quot;&gt;--add&lt;/span&gt; arm64 root@&amp;lt;VM-IP-address&amp;gt; &lt;span class=&quot;nt&quot;&gt;--set-default&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# adds a remote named `arm64` to local context and set it to default&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To test if the remote addition was correctly done, run the following to initiate
an SSH connection inside the IIO tree.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@host
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
kw ssh &lt;span class=&quot;c&quot;&gt;# initiate an SSH connection to the default remote&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can check the remotes available in the current local context with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw remote
--list&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;4-configuring-the-linux-kernel-compilation&quot;&gt;4) Configuring the Linux kernel compilation&lt;/h3&gt;

&lt;p&gt;The &lt;em&gt;Kernel Build System&lt;/em&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kbuild&lt;/code&gt;) is based on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make&lt;/code&gt; and other GNU tools and
allows a highly modular and customizable build process for the Linux kernel. By
default, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kbuild&lt;/code&gt; uses the configuration options stored in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.config&lt;/code&gt; file
under the root directory of the Linux kernel tree, which shouldn’t be present in
a freshly cloned tree. Those options hold values for configuration symbols
associated with kernel resources such as drivers, tools, and features in
general. Nearly all directories inside a kernel tree have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Kconfig&lt;/code&gt; file,
which defines the symbols for the resources at the same level. Top &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Kconfig&lt;/code&gt;
files include (&lt;em&gt;source&lt;/em&gt;) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Kconfig&lt;/code&gt; files from subdirectories thus creating a
tree of configuration symbols. When needed, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kbuild&lt;/code&gt; generates configuration
options from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Kconfig&lt;/code&gt; symbols and stores their values in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.config&lt;/code&gt; file.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kbuild&lt;/code&gt; Makefiles then use these configuration values to compile code
conditionally and to decide which objects to include in the monolithic kernel
image and which objects to become modules
&lt;a name=&quot;cite-linuxj:kbuild-back&quot; href=&quot;#cite-linuxj:kbuild&quot;&gt;[1]&lt;/a&gt;
&lt;a name=&quot;cite-kdoc:kbuild-back&quot; href=&quot;#cite-kdoc:kbuild&quot;&gt;[2]&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are predefined &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.config&lt;/code&gt;s for building kernels for different architectures
and purposes. These are called &lt;em&gt;defconfig&lt;/em&gt; (default configuration) files.
defconfig files store only specific non-default values for configuration
symbols. For instance, one can find defconfig files for ARM architecture
machines under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;arch/arm/configs&lt;/code&gt;. We will create a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.config&lt;/code&gt; file from the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;arm64&lt;/code&gt; defconfig.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@host
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
make &lt;span class=&quot;nv&quot;&gt;ARCH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;arm64 defconfig &lt;span class=&quot;c&quot;&gt;# create predefined defconfig&lt;/span&gt;
make &lt;span class=&quot;nv&quot;&gt;ARCH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;arm64 olddefconfig &lt;span class=&quot;c&quot;&gt;# update defconfig with new default values&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Fetch the saved list of modules you’ve generated in the first tutorial of the
series and generate an optimized &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.config&lt;/code&gt; based on it. Refer to section 4 of
the first tutorial, in case you don’t have this file.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@host
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
kw ssh &lt;span class=&quot;nt&quot;&gt;--get&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;~/vm_mod_list&apos;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# copy VM modules list to IIO tree&lt;/span&gt;
make &lt;span class=&quot;nv&quot;&gt;ARCH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;arm64 &lt;span class=&quot;nv&quot;&gt;LSMOD&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;vm_mod_list localmodconfig
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw kernel-config-manager&lt;/code&gt; helps us manage multiple configs without having to
manually move and rename files. Below are some commands to help you more
robustly manage these &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.config&lt;/code&gt;s. Note that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.config&lt;/code&gt;s are considered in a
“global” context, so files managed by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw&lt;/code&gt; are accessible no matter the kernel
tree you are.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@host
kw kernel-config-manager &lt;span class=&quot;nt&quot;&gt;--save&lt;/span&gt; arm64-optimized &lt;span class=&quot;c&quot;&gt;# saves `.config` w/ name `arm64-optimized`&lt;/span&gt;
kw kernel-config-manager &lt;span class=&quot;nt&quot;&gt;--list&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# lists all managed `.config`s&lt;/span&gt;
kw kernel-config-manager &lt;span class=&quot;nt&quot;&gt;--get&lt;/span&gt; arm64-optimized &lt;span class=&quot;c&quot;&gt;# gets managed `.config` w/ name `arm64-optimized`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It is possible to open the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.config&lt;/code&gt; file and directly edit it, but this isn’t
recommended. A safer and more palatable way is to use &lt;strong&gt;one of&lt;/strong&gt; the &lt;em&gt;Terminal
User Interfaces&lt;/em&gt; (TUI) provided by the Linux project&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@host
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
kw build &lt;span class=&quot;nt&quot;&gt;--menu&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# open a TUI to safely edit the `.config`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Use the arrow keys to navigate and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ENTER&lt;/code&gt; to change/toggle a configuration. You
can take some time to familiarize with these menus and see the available
configurations.&lt;/p&gt;

&lt;p&gt;For this tutorial, we want to make a tiny customization: change the kernel image
name. In the menu, select &lt;em&gt;General setup&lt;/em&gt;, then in &lt;em&gt;Local version - append to
kernel release&lt;/em&gt;, put whatever you want to be appended after the kernel version,
and disable &lt;em&gt;Automatically append version information to the version string&lt;/em&gt;.
Be aware that the string you input will be part of the name of your first custom
kernel, so treat it well :)&lt;/p&gt;

&lt;p&gt;To exit, hit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;F9&lt;/code&gt;, which will prompt you to save the changes. The figure below
illustrates the steps.&lt;/p&gt;

&lt;figure&gt;

  &lt;a href=&quot;/img/posts/tutorials/kernel/build_linux_for_arm_kw/2025-03-09-build-linux-for-arm-kw/change_name.png&quot;&gt;

&lt;img class=&quot;img-center&quot; src=&quot;/img/posts/tutorials/kernel/build_linux_for_arm_kw/2025-03-09-build-linux-for-arm-kw/change_name.png&quot; alt=&quot;Changing the kernel name with `nconfig`&quot; /&gt;

&lt;/a&gt;


  
  &lt;figcaption class=&quot;fig-center&quot;&gt;
    &lt;b&gt;Figure 1.&lt;/b&gt;
    Changing the kernel name with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nconfig&lt;/code&gt;

  &lt;/figcaption&gt;
  

&lt;/figure&gt;

&lt;p&gt;You can check how many modules will be compiled along with other informations
using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@host
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
kw build &lt;span class=&quot;nt&quot;&gt;--info&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;5-building-a-custom-linux-kernel&quot;&gt;5) Building a custom Linux kernel&lt;/h3&gt;

&lt;p&gt;Different processor architectures have distinct instruction sets and register
names. Due to that, the binaries produced by a compiler for architecture &lt;em&gt;A&lt;/em&gt;
will not work on a machine of architecture &lt;em&gt;B&lt;/em&gt;. So, we need to use a compiler
that produces binaries compatible with the instruction set of the machine we
want to run our kernel. Essentially, this concept is called
&lt;a href=&quot;https://www.gnu.org/software/automake/manual/html_node/Cross_002dCompilation.html&quot;&gt;&lt;em&gt;Cross-Compilation&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In our case, we assume we have a development system of the AMD64 (x86_64)
architecture, and the target machine is a VM of the ARM64 architecture.&lt;/p&gt;

&lt;p&gt;Most distros should have a GCC package with a compiler for AMD64 host machines
that produces binaries for ARM64 targets. On Debian and Fedora, the package name
is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc-aarch64-linux-gnu&lt;/code&gt;, while in Arch the package name is
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aarch64-linux-gnu-gcc&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Arch-based distros&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-Syy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; aarch64-linux-gnu-gcc
&lt;span class=&quot;c&quot;&gt;# Debian-based distros&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt update &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;gcc-aarch64-linux-gnu
&lt;span class=&quot;c&quot;&gt;# Fedora-based distros&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dnf update &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dnf &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;gcc-aarch64-linux-gnu
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;See the &lt;em&gt;Complementary Commands&lt;/em&gt; section for advice if you are having problems
in finding an equivalent package to your distro.&lt;/p&gt;

&lt;p&gt;We just need to configure &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw&lt;/code&gt; a little bit more to be good to go. As said, the
IIO tree has local configurations, and we need to set some related to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw
build&lt;/code&gt;, the feature that deals with everything related to compiling kernels. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw
config --show build&lt;/code&gt; shows the status of configurations available.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@host
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
kw config build.arch &lt;span class=&quot;s1&quot;&gt;&apos;arm64&apos;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# defines the target architecture to ARM64&lt;/span&gt;
kw config build.cross_compile &lt;span class=&quot;s1&quot;&gt;&apos;aarch64-linux-gnu-&apos;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# defines the cross-compiler&lt;/span&gt;
kw config build.kernel_img_name &lt;span class=&quot;s1&quot;&gt;&apos;Image.gz&apos;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# defines the kernel image format&lt;/span&gt;
kw config &lt;span class=&quot;nt&quot;&gt;--show&lt;/span&gt; build &lt;span class=&quot;c&quot;&gt;# check `kw build` configurations&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Finally, let’s build our custom Linux kernel from source code. Mind that,
although we made a really lean &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.config&lt;/code&gt;, compiling the kernel still is a heavy
task, and even more so when cross-compiling.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@host
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
kw build &lt;span class=&quot;c&quot;&gt;# compile Linux kernel from source considering local configurations&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If everything goes right, you should see an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;arch/arm64/boot/Image&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;modules.order&lt;/code&gt; and alike files under the Linux source root directory.&lt;/p&gt;

&lt;h3 id=&quot;6-installing-modules-and-booting-the-custom-built-linux-kernel&quot;&gt;6) Installing modules and booting the custom-built Linux kernel&lt;/h3&gt;

&lt;p&gt;Before booting the custom-built kernel, we need to install the modules into the
VM, i.e., we need to move the module objects compiled to the right place inside
the VM’s filesystem. To do this, ensure the VM is running, and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw&lt;/code&gt; remote
configuration is correct. Then run&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@host
kw deploy &lt;span class=&quot;nt&quot;&gt;--modules&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# only install modules into the VM&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p class=&quot;warning&quot;&gt;There may be some errors thrown about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;strip&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make&lt;/code&gt; not being able to do
some things, but they may not indicate a real error.&lt;/p&gt;

&lt;p&gt;Finally, update your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activate.sh&lt;/code&gt; script to boot the VM (both through pure
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QEMU&lt;/code&gt; and with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libvirt&lt;/code&gt;) with the custom-built kernel. Don’t forget to adapt
the modification to have the correct &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt; and the correct &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vda&lt;/code&gt; partition
depending on your VM particularities!&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;--- a/activate.sh
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+++ b/activate.sh
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@@ -23,7 +23,7 @@&lt;/span&gt; function launch_vm_qemu() {
         -smp 2 \
         -netdev user,id=net0 -device virtio-net-device,netdev=net0 \
         -initrd &quot;${BOOT_DIR}/&amp;lt;initrd&amp;gt;&quot; \
&lt;span class=&quot;gd&quot;&gt;-        -kernel &quot;${BOOT_DIR}/&amp;lt;kernel&amp;gt;&quot; \
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+        -kernel &quot;${IIO_TREE}/arch/arm64/boot/Image&quot; \
&lt;/span&gt;         -append &quot;loglevel=8 root=/dev/&amp;lt;vdaX&amp;gt; rootwait&quot; \
         -device virtio-blk-pci,drive=hd \
         -drive if=none,file=&quot;${VM_DIR}/arm64_img.qcow2&quot;,format=qcow2,id=hd \
&lt;span class=&quot;p&quot;&gt;@@ -41,7 +41,7 @@&lt;/span&gt; function create_vm_virsh() {
         --import \
         --features acpi=off \
         --disk path=&quot;${VM_DIR}/arm64_img.qcow2&quot; \
&lt;span class=&quot;gd&quot;&gt;-        --boot kernel=${BOOT_DIR}/&amp;lt;kernel&amp;gt;,initrd=${BOOT_DIR}/&amp;lt;initrd&amp;gt;,kernel_args=&quot;loglevel=8 root=/dev/&amp;lt;vdaX&amp;gt; rootwait&quot; \
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+        --boot kernel=${IIO_TREE}/arch/arm64/boot/Image,initrd=${BOOT_DIR}/&amp;lt;initrd&amp;gt;,kernel_args=&quot;loglevel=8 root=/dev/&amp;lt;vdaX&amp;gt; rootwait&quot; \
&lt;/span&gt;         --network bridge:virbr0 \
         --graphics none
 }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Rerun the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activate.sh&lt;/code&gt; script. Shutdown the VM and undefine it from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libvirt&lt;/code&gt;
managed VMs. Then, created it again&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@host
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;virsh shutdown arm64
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;virsh undefine arm64
create_vm_virsh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Log into the VM and run&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@VM
&lt;span class=&quot;nb&quot;&gt;uname&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--kernel-release&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;to check that you are now running the custom kernel we just built. The output of
this command should be something in the format of&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;major-release-nr&amp;gt;.&amp;lt;minor-release-nr&amp;gt;.&amp;lt;patch-release-nr&amp;gt;-rc&amp;lt;one-through-eight&amp;gt;-&amp;lt;the-name-you-wrote&amp;gt;+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;like, for example,&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;6.14.0-rc1-free-software+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Congratulations, you’ve just compiled and boot-tested a Linux kernel! From now
on, whenever you make a change on the Linux kernel tree, you can “just” compile
it, install the modules, and then shutdown, with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo virsh shutdown arm64&lt;/code&gt;,
and start the VM, with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo virsh start arm64&lt;/code&gt; (rebooting it doesn’t works). It
will run the new custom kernel we will be capable to run validations inside this
testing environment!&lt;/p&gt;

&lt;h4 id=&quot;61-installing-the-kernel-image&quot;&gt;6.1) Installing the kernel image&lt;/h4&gt;

&lt;p&gt;Often, kernel developers also need to explicitly install the Linux kernel image
to their target test machines. Notice that here, we are not copying or moving
the Linux kernel image to nowhere inside the VM like we did when installing
modules. Neither we are dealing with a physical machine.&lt;/p&gt;

&lt;p&gt;Essentially, installing a new kernel image would be to just replace the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vmlinuz/Image/zImage/bzImage/uImage&lt;/code&gt; file, which contains the Linux boot
executable program. However, some platforms (such as AMD64 and ARM64) have fancy
boot procedures with boot loaders that won’t find kernel images without very
specific configuration pointing to them (e.g., GRUB), which might mount
temporary file systems (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt;), load drivers prior to mounting the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rootfs&lt;/code&gt;,
and so on. To help setup those additional boot files and configuration, the
Linux kernel has a &lt;em&gt;install&lt;/em&gt; rule. So, kernel developers may also run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make
install&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make install INSTALL_PATH=&amp;lt;path_to_bootfs&amp;gt;&lt;/code&gt; when deploying kernels
to those platforms.&lt;/p&gt;

&lt;p&gt;For this setup, we shall not bother with that. We don’t need to run the
installation rule because we instructed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QEMU&lt;/code&gt; (with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-kernel&lt;/code&gt;) and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libvirt&lt;/code&gt;
(with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--boot kernel=...&lt;/code&gt;) to pick up the kernel image in the tree that resulted
from the compilation, and we are reusing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt; file from the original
guest OS that came with disk image.&lt;/p&gt;

&lt;p&gt;This shows the plurality of the umbrella Linux project; Linux is composed of
many subprojects (called &lt;em&gt;subsystems&lt;/em&gt;), each one with their own development
contexts, accomplishing similar tasks in the most varied ways, sometimes even
duplicating (or wasting) efforts.&lt;/p&gt;

&lt;h3 id=&quot;complementary-commands&quot;&gt;Complementary Commands&lt;/h3&gt;

&lt;p&gt;One may also download cross compiler toolchains from different vendors.
For instance, ARM provides an equivalent cross compiler that you may download
if having trouble finding a proper distro package.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;wget &lt;span class=&quot;nt&quot;&gt;-O&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LK_DEV_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/gcc-aarch64-linux-gnu.tar.xz&quot;&lt;/span&gt; https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu.tar.xz
&lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-xf&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$LK_DEV_DIR&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LK_DEV_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/gcc-aarch64-linux-gnu.tar.xz&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Sometimes identifying the cross compiler for your combination of host and target
machines may require some understanding of what is called the compiler triplet.
Conceptually, the compiler triplet should contain three fields:
the name of the CPU family/model, the vendor, and the operating system name
&lt;a name=&quot;cite-osdev:tt-back&quot; href=&quot;#cite-osdev:tt&quot;&gt;[3]&lt;/a&gt;.
However, sometimes the vendor is omitted so one may find a triplet like
&lt;em&gt;x86_64-freebsd&lt;/em&gt; (FreeBSD kernel for 64-bit x86 CPUs)
&lt;a name=&quot;cite-osdev:tt-back&quot; href=&quot;#cite-osdev:tt&quot;&gt;[3]&lt;/a&gt;.
It is also common to see the operating system information split into two
separate fields, one for indicating the kernel and the other for describing the
runtime environment or C library which is being used. The the debian package
for x86-64 gcc is an example of this triplet format mutation:
&lt;em&gt;gcc-x86-64-linux-gnu&lt;/em&gt; (compiler for 64-bit x86 targets that will run a Linux
kernel and have GNU glibc in their runtime). But things can get even more
unintuitive when system call conventions or Application Binary Interfaces (ABI)
are specified in the OS field as in &lt;em&gt;arm-linux-gnueabi&lt;/em&gt; (compiler for 32-bit ARM
targets that will run Linux using the EABI system call convention) or as in
&lt;em&gt;arm-none-eabi&lt;/em&gt; (compiler for 32-bit ARM that will run no OS (bare-metal) using
the EABI system call convention).&lt;/p&gt;

&lt;p&gt;Anyways, you may point to the generic cross compiler name when using compilers
not under your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PATH&lt;/code&gt;. For example:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CROSS_COMPILE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LK_DEV_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/gcc-aarch64-linux-gnu/bin/aarch64-none-linux-gnu-&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;This tutorial described how to configure and build a custom Linux kernel and
boot-test it into a VM. To accomplish that, we covered basic concepts of Linux
kernel build configuration to guide readers into generating feasible &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.config&lt;/code&gt;
files, and some cross-compilation concepts. By this point, you should be able to
configure, build, and boot-test a custom Linux kernel from source code in a
safe, while not-so-much efficient (we will work on that), testing environment.&lt;/p&gt;

&lt;p&gt;We also introduced &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kw,&lt;/code&gt; a feature-rich system with the mission of helping
kernel developers do their day-to-day tasks more efficiently, error-free, and
intuitively.&lt;/p&gt;

&lt;h1 id=&quot;history&quot;&gt;History&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;V1: Release&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;p&gt;&lt;a name=&quot;cite-linuxj:kbuild&quot;&gt;[1]&lt;/a&gt; Javier Martinez Canillas. “Kbuild: the Linux Kernel Build System”. (2012) URL: &lt;a href=&quot;https://www.linuxjournal.com/content/kbuild-linux-kernel-build-system&quot;&gt;https://www.linuxjournal.com/content/kbuild-linux-kernel-build-system&lt;/a&gt;. &lt;big&gt;&lt;big&gt;&lt;big&gt;&lt;a href=&quot;#cite-linuxj:kbuild-back&quot;&gt;⤴&lt;/a&gt;&lt;/big&gt;&lt;/big&gt;&lt;/big&gt;&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;cite-kdoc:kbuild&quot;&gt;[2]&lt;/a&gt; Michael Elizabeth Chastain and Kai Germaschewski and Sam Ravnborg. “Linux Kernel Makefiles”. (2023) URL: &lt;a href=&quot;https://www.kernel.org/doc/html/latest/kbuild/makefiles.html&quot;&gt;https://www.kernel.org/doc/html/latest/kbuild/makefiles.html&lt;/a&gt;. &lt;big&gt;&lt;big&gt;&lt;big&gt;&lt;a href=&quot;#cite-kdoc:kbuild-back&quot;&gt;⤴&lt;/a&gt;&lt;/big&gt;&lt;/big&gt;&lt;/big&gt;&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;cite-osdev:tt&quot;&gt;[3]&lt;/a&gt; . “Target Triplet”. (2019) URL: &lt;a href=&quot;https://wiki.osdev.org/Target_Triplet&quot;&gt;https://wiki.osdev.org/Target_Triplet&lt;/a&gt;. &lt;big&gt;&lt;big&gt;&lt;big&gt;&lt;a href=&quot;#cite-osdev:tt-back&quot;&gt;⤴&lt;/a&gt;&lt;/big&gt;&lt;/big&gt;&lt;/big&gt;&lt;/p&gt;

</content>
    </entry>
    
    <entry>
        <title type="html">Introduction to Linux kernel Character Device Drivers</title>
        <link href="https://flusp.ime.usp.br/kernel/char-drivers-intro/"/>
        <published>2024-02-15T00:00:00-03:00</published>
        <id isPermaLink="true">https://flusp.ime.usp.br/kernel/char-drivers-intro/</id>
        <category>kernel</category>
        <content type="html">&lt;p&gt;This tutorial explains a few aspects of Linux character devices with a basic
character device driver example.
It is best enjoyed as a continuation of “&lt;a href=&quot;/kernel/modules-intro/&quot;&gt;Introduction to Linux kernel build
configuration and modules&lt;/a&gt;” tutorial.&lt;/p&gt;

&lt;!--end-abstract--&gt;

&lt;!--begin-references--&gt;

&lt;!--end-references--&gt;

&lt;h3 id=&quot;command-summary&quot;&gt;Command Summary&lt;/h3&gt;

&lt;p class=&quot;warning&quot;&gt;Skip this section if you have not completed this tutorial yet. This is a
reference for those who have gone through this tutorial and want to remember
specific commands.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /proc/devices
&lt;span class=&quot;nb&quot;&gt;stat&lt;/span&gt; &amp;lt;file&amp;gt;
&lt;span class=&quot;nb&quot;&gt;mknod&lt;/span&gt; &amp;lt;file_name&amp;gt; &amp;lt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &amp;lt;major_num&amp;gt; &amp;lt;minor_num&amp;gt;
dmesg &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;introduction&quot;&gt;Introduction&lt;/h1&gt;

&lt;p&gt;In Linux, character devices facilitate sequential data exchange between
user space and the system, handling dynamic data streams. They provide a
flexible interface for interacting with hardware or software components.&lt;/p&gt;

&lt;p&gt;Character device drivers define how these devices operate, managing data flow
and access. They serve as an abstraction layer, enabling controlled and
efficient communication between applications and the underlying system.&lt;/p&gt;

&lt;h1 id=&quot;introduction-to-linux-kernel-character-device-drivers&quot;&gt;Introduction to Linux kernel character device drivers&lt;/h1&gt;

&lt;p&gt;This tutorial presents and explains a few key concepts related to Linux
character devices, then presents an example Linux kernel character device driver
that is built on top of the presented ideas.&lt;/p&gt;

&lt;p&gt;Summary of the parts of this tutorial:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Character devices&lt;/li&gt;
  &lt;li&gt;Major and Minor Numbers&lt;/li&gt;
  &lt;li&gt;File operations&lt;/li&gt;
  &lt;li&gt;Bringing device IDs and file operations together&lt;/li&gt;
  &lt;li&gt;A character device driver example&lt;/li&gt;
  &lt;li&gt;Testing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;simple_char&lt;/code&gt; driver&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;1-character-devices&quot;&gt;1) Character devices&lt;/h3&gt;

&lt;p&gt;A character device is an abstraction provided by Linux operating systems to
support devices that can be read from or written to with relatively small data
transfers which are usually byte size or few bytes size.
They are often abstracted as files in the file
system and accessed through conventional file access system calls.
Devices supported as character devices are serial ports, keyboards, mice, etc.
Example of character device files are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/ttyS0&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dev/input/mouse0&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/kmsg&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/zero&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;2-major-and-minor-numbers&quot;&gt;2) Major and Minor Numbers&lt;/h3&gt;

&lt;p&gt;The files associated with character devices (like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/ttyS0&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dev/input/mouse0&lt;/code&gt;) are special types of files which allow users to interface
with devices from the user space. Under the hood of character device files are
the device drivers that handle the system calls for them.&lt;/p&gt;

&lt;p&gt;The association between device files and devices is made with
a device ID that consists of two parts: a major and a minor number
&lt;a name=&quot;cite-makedev:man-back&quot; href=&quot;#cite-makedev:man&quot;&gt;[1]&lt;/a&gt;.
The &lt;strong&gt;minor number&lt;/strong&gt; is only used within the device driver to distinguish between
multiple devices of same type (such as the first and the second display) or to
switch between operation modes of a device. The &lt;strong&gt;major number&lt;/strong&gt; can be requested
to be a specific number or allocated dynamically.
The device ID formed from the major/minor number combination is what
the kernel uses to choose which driver to run to support a particular device.
Inside the Linux kernel, the device ID is stored as a 32-bit unsigned integer
defined by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dev_t&lt;/code&gt; type. The 12 most significant bits of a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dev_t&lt;/code&gt; variable
store the major device number while the 20 remaining bits store the minor
number.&lt;/p&gt;

&lt;p&gt;In old versions of the Linux kernel, once a major number was registered for a
driver, no other driver could use the same major number and all minor numbers
associated with that major number were owned by the driver. Back then, one could
state that a major number was unique for a driver. That might not hold always
true nowadays since, in modern kernels, drivers allocate a range (not all) of minor
numbers within the set of possible minor numbers. With that, it is now
possible for more than one driver to have the same major number as long as their
range of minor numbers do not intersect.&lt;/p&gt;

&lt;p&gt;Within the Linux kernel, one can use the functions declared in
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;include/linux/fs.h&lt;/code&gt; to allocate device major and minor numbers for a device.
For example, to dynamically allocate a device major number along with a range of
minor numbers one can call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alloc_chrdev_region()&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;linux/fs.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;alloc_chrdev_region&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;baseminor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The macros &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MAJOR()&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MINOR()&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MKDEV()&lt;/code&gt; from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;include/linux/kdev_t.h&lt;/code&gt;
can be used to extract the major/minor number from a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dev_t&lt;/code&gt; variable and
to make a device ID from a pair of major and minor numbers, respectively.&lt;/p&gt;

&lt;p&gt;At any moment, a list of character and block devices in the system can be
retrieved from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/proc/devices&lt;/code&gt; file.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /proc/devices
Character devices:
  1 mem
  4 /dev/vc/0
  4 &lt;span class=&quot;nb&quot;&gt;tty
  &lt;/span&gt;4 ttyS
  5 /dev/tty
  5 /dev/console
  5 /dev/ptmx
  6 lp
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The numbers on the left are the major device numbers and the strings on the
right correspond to the registered names of the device drivers that handle the
respective device. Notice in the example above that the devices represented by
the files &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/tty&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/console&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/ptmx&lt;/code&gt; share the same major
number. That is possible thanks to each driver only registering a subset of the
available minor numbers.&lt;/p&gt;

&lt;p&gt;One can use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stat&lt;/code&gt; to get major and minor numbers for the device backing a file.
For example:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;stat&lt;/span&gt; /boot/vmlinuz-6.5.0-5-amd64
  File: /boot/vmlinuz-6.5.0-5-amd64
  Size: 9127904         Blocks: 17832      IO Block: 4096   regular file
Device: 8,1     Inode: 4981079     Links: 1
Access: &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;0644/-rw-r--r--&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;  Uid: &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;    0/    root&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;   Gid: &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;    0/    root&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
Access: 2024-01-04 10:51:19.000000000 &lt;span class=&quot;nt&quot;&gt;-0300&lt;/span&gt;
Modify: 2023-11-29 04:45:07.000000000 &lt;span class=&quot;nt&quot;&gt;-0300&lt;/span&gt;
Change: 2024-01-04 10:53:32.315343926 &lt;span class=&quot;nt&quot;&gt;-0300&lt;/span&gt;
 Birth: 2024-01-04 10:53:29.707343958 &lt;span class=&quot;nt&quot;&gt;-0300&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The output of stat shows that the Linux image (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vmlinuz-6.5.0-5-amd64&lt;/code&gt;) is
stored as a regular file and the device responsible for it has major number 8
and minor number 1 (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/sda1&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;To get major and minor numbers of character devices we must look at the
&lt;em&gt;Device type&lt;/em&gt; field.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;stat&lt;/span&gt; /dev/ttyS0
  File: /dev/ttyS0
  Size: 0               Blocks: 0          IO Block: 4096   character special file
Device: 0,5     Inode: 94          Links: 1     Device &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;: 4,64
Access: &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;0660/crw-rw----&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;  Uid: &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;    0/    root&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;   Gid: &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;   20/ dialout&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
Access: 2024-03-29 09:14:38.329879779 &lt;span class=&quot;nt&quot;&gt;-0300&lt;/span&gt;
Modify: 2024-03-29 09:14:57.329879779 &lt;span class=&quot;nt&quot;&gt;-0300&lt;/span&gt;
Change: 2024-03-29 09:14:38.329879779 &lt;span class=&quot;nt&quot;&gt;-0300&lt;/span&gt;
 Birth: 2024-03-29 09:14:32.192000051 &lt;span class=&quot;nt&quot;&gt;-0300&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So, that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tty&lt;/code&gt; character device has major number 4 and minor number 64.&lt;/p&gt;

&lt;p&gt;We can manually create files to interface with character devices using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mknod&lt;/code&gt;
&lt;a name=&quot;cite-mknode1:man-back&quot; href=&quot;#cite-mknode1:man&quot;&gt;[2]&lt;/a&gt;.
A file that serves as interface for a device is often called a &lt;strong&gt;device node&lt;/strong&gt;,
&lt;strong&gt;device file&lt;/strong&gt;, or &lt;strong&gt;device special file&lt;/strong&gt; &lt;a name=&quot;cite-devicenode:deb-back&quot; href=&quot;#cite-devicenode:deb&quot;&gt;[3]&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;3-file-operations&quot;&gt;3) File operations&lt;/h3&gt;

&lt;p&gt;Since character devices may interface with user space through files, character
device drivers may implement functions to handle file access system calls.
The set of those syscalls implemented by a device driver is set into a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct
file_operations&lt;/code&gt; object.
There are several different file operations a character driver can
implement. In this tutorial we will focus on the most basic system calls for a
character device: &lt;strong&gt;open&lt;/strong&gt;, &lt;strong&gt;close&lt;/strong&gt;, &lt;strong&gt;read&lt;/strong&gt;, &lt;strong&gt;write&lt;/strong&gt;. All of those have
manual pages of same name. Whithin the Linux kernel, these operations are
respectively handled by &lt;strong&gt;open&lt;/strong&gt;, &lt;strong&gt;release&lt;/strong&gt;, &lt;strong&gt;read&lt;/strong&gt;, and &lt;strong&gt;write&lt;/strong&gt; functions
stored in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct file_operations&lt;/code&gt; objects.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_operations&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;owner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;loff_t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;llseek&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;loff_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;ssize_t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;size_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;loff_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;ssize_t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;size_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;loff_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;snipped&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flush&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fl_owner_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;release&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;snipped&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;See the definition of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct file_operations&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;include/linux/fs.h&lt;/code&gt; for a
complete list of entry points a driver can implement.&lt;/p&gt;

&lt;h4 id=&quot;file-readwrite-operations&quot;&gt;File read/write operations&lt;/h4&gt;

&lt;p&gt;Kernel code should not directly de-reference pointers to memory in user space
(i.e., we should not access the __user buffer with conventional C memory access
operations).
Kernel and user space memory addresses may be (and often are) in separate
address regions, offset by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PAGE_OFFSET&lt;/code&gt; physical memory addresses.
Because of that, the address of a user space pointer might not lead
to the memory address of user space data when de-referencing it from kernel
space. Furthermore, most modern systems provide virtualised memory address
for user space memory and memory paging, meaning that a user space
memory address may not be valid at a given moment either because
its page has not been allocated yet or it has been swapped out.
If you got interested about Linux memory management, watch Matt Porter’s
&lt;a href=&quot;https://www.youtube.com/watch?v=7aONIVSXiJ8&quot;&gt;Introduction to Memory Management in Linux&lt;/a&gt;
after finishing this tutorial.&lt;/p&gt;

&lt;p&gt;To implement the &lt;em&gt;read&lt;/em&gt; and &lt;em&gt;write&lt;/em&gt; entry points we will use memory access
functions from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;include/linux/uaccess.h&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;linux/uaccess.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;copy_from_user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;copy_to_user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The semantics of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;copy_from_user()&lt;/code&gt; function are the same as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memcpy()&lt;/code&gt;.
It copies &lt;em&gt;n&lt;/em&gt; bytes of data from the source (&lt;em&gt;from&lt;/em&gt;) memory area to the
destination one (&lt;em&gt;to&lt;/em&gt;). One important difference though is that the
return of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;copy_from_user()&lt;/code&gt; is the number of bytes not successfully copied.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;copy_to_user()&lt;/code&gt; is analogous to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;copy_from_user()&lt;/code&gt; but with opposite
direction.&lt;/p&gt;

&lt;h3 id=&quot;4-bringing-device-ids-and-file-operations-together&quot;&gt;4) Bringing device IDs and file operations together&lt;/h3&gt;

&lt;p&gt;For a character device, we have major/minor numbers (combined into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dev_t&lt;/code&gt;) to
identify the driver to handle system calls for files/nodes linking to it. We
also have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct file_operations&lt;/code&gt; to store the set of operations supported for
the character device. To tie together device IDs and file operations, the kernel
uses the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct cdev&lt;/code&gt; structure (&lt;strong&gt;c&lt;/strong&gt;haracter &lt;strong&gt;dev&lt;/strong&gt;ice) defined in
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;include/linux/cdev.h&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cdev&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kobject&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kobj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;owner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_operations&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ops&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list_head&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;dev_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__randomize_layout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct kobject kobj&lt;/code&gt; is the embedded kobject struct of the cdev structure used
for reference counting.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct module *owner&lt;/code&gt; holds the owner of the resource within the kernel.
Later, we will use the character device  module as resource owner.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;const struct file_operations *ops&lt;/code&gt; is the file operations structure discussed
earlier.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct list_head list&lt;/code&gt; is a double linked list for traversing character devices.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dev_t dev&lt;/code&gt; is the device ID.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unsigned int count&lt;/code&gt; holds the amount of minor numbers owned by the character
device.&lt;/p&gt;

&lt;p&gt;The rudimentary functions for registering a cdev are:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;linux/cdev.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cdev&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cdev_alloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cdev_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cdev&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cdev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_operations&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fops&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cdev_add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cdev&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dev_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cdev_del&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cdev&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct cdev *cdev_alloc(void)&lt;/code&gt; allocates and initializes a cdev struct object.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;void cdev_init(struct cdev *cdev, const struct file_operations *fops)&lt;/code&gt; is
equivalent to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cdev_alloc()&lt;/code&gt; except it expects the caller to pass a pointer to
an already allocated cdev object and it also sets the file operations field for
it. If using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cdev_init()&lt;/code&gt;, the caller is responsible for freeing the cdev
object after the character device is removed from the system.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int cdev_add(struct cdev *p, dev_t dev, unsigned count)&lt;/code&gt; registers/adds the
character device to the system by creating an entry for it in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct
kobj_map *cdev_map&lt;/code&gt; array kept in &lt;em&gt;fs/char_dev.c&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;void cdev_del(struct cdev *p)&lt;/code&gt; removes the character device from the system by
removing its entry from the cdev_map array. It also decrement the reference
count of the character device which will free the cdev struct if it was
allocated with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cdev_alloc()&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;5-a-character-device-driver-example&quot;&gt;5) A character device driver example&lt;/h3&gt;

&lt;p&gt;Let’s create an example character device driver to see how it all works. Create
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${IIO_TREE}/drivers/char/simple_char.c&lt;/code&gt; in the Linux kernel sources and add the code for
it. Notice most of the ideas within it have been covered in previous sections.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;linux/init.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;linux/module.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;linux/kdev_t.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt; /* for MAJOR */&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;linux/cdev.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt; /* for cdev */&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;linux/fs.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt; /* for chrdev functions */&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;linux/slab.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt; /* for malloc */&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;linux/string.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt; /* for strlen() */&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;linux/uaccess.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt; /* copy_to_user() */&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cdev&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s_cdev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dev_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dev_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;#define S_BUFF_SIZE 4096
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;#define MINOR_NUMS 1
&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;simple_char_open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;pr_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%s: %s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;KBUILD_MODNAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__func__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ssize_t&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;simple_char_read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
				&lt;span class=&quot;kt&quot;&gt;size_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;loff_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ppos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n_bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;pr_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%s: %s about to read %ld bytes from buffer position %lld&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;KBUILD_MODNAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__func__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ppos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;n_bytes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;copy_to_user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s_buf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ppos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ppos&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n_bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n_bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ssize_t&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;simple_char_write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
				&lt;span class=&quot;kt&quot;&gt;size_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;loff_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ppos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n_bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;pr_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%s: %s about to write %ld bytes to buffer position %lld&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;KBUILD_MODNAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__func__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ppos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;n_bytes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;copy_from_user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s_buf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ppos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n_bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;simple_char_release&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;pr_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%s: %s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;KBUILD_MODNAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__func__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_operations&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;simple_char_fops&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;owner&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;THIS_MODULE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;simple_char_open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;release&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;simple_char_release&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;simple_char_read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;simple_char_write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__init&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;simple_char_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;pr_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Initialize %s module.&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;KBUILD_MODNAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/* Allocate an internal buffer for reads and writes. */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;s_buf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kmalloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;S_BUFF_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GFP_KERNEL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ENOMEM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;strcpy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;This is data from simple_char buffer.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/* Dynamically allocate character device device numbers. */&lt;/span&gt;
	&lt;span class=&quot;cm&quot;&gt;/* The name passed here will appear in /proc/devices. */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alloc_chrdev_region&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MINOR_NUMS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;simple_char&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/* Allocate and initialize the character device cdev structure */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;s_cdev&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cdev_alloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;s_cdev&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ops&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;simple_char_fops&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;s_cdev&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;owner&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;simple_char_fops&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;owner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/* Adds a mapping for the device ID into the system. */&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cdev_add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s_cdev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dev_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MINOR_NUMS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__exit&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;simple_char_exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;cm&quot;&gt;/*
	 * Undoes the device ID mapping and frees cdev struct, removing the
	 * character device from the system.
	 */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;cdev_del&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s_cdev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;cm&quot;&gt;/* Unregisters (disassociate) the device numbers allocated. */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;unregister_chrdev_region&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dev_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MINOR_NUMS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;kfree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s_buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;pr_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%s exiting.&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;KBUILD_MODNAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;module_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;simple_char_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;module_exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;simple_char_exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;MODULE_AUTHOR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;A Linux kernel student &amp;lt;name.surname@usp.br&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;MODULE_DESCRIPTION&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;A simple character device driver example.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;MODULE_LICENSE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;GPL&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Don’t forget to add a configuration symbol for the simple_char driver within
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${IIO_TREE}/drivers/char/Kconfig&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;config SIMPLE_CHAR
       tristate &quot;Simple character driver example&quot;
       default m
       help
         This option enables a simple character driver that implements basic
         file access operations.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Also add a build rule for it in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${IIO_TREE}/drivers/char/Makefile&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;obj-$(CONFIG_SIMPLE_CHAR)      += simple_char.o
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Configure and build the Linux kernel with the simple_char driver as explained in
previous
&lt;a href=&quot;/kernel/build-linux-for-arm/&quot;&gt;build&lt;/a&gt;
and
&lt;a href=&quot;/kernel/modules-intro/&quot;&gt;configuration&lt;/a&gt;
tutorials.&lt;/p&gt;

&lt;p class=&quot;warning&quot;&gt;If you get prompted by many config options after running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make -C &quot;$IIO_TREE&quot;
Image.gz modules&lt;/code&gt;, consider interrupting the kernel build and running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make -C
&quot;$TREE_IIO&quot; olddefconfig&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;6-testing-the-simple_char-driver&quot;&gt;6) Testing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;simple_char&lt;/code&gt; driver&lt;/h3&gt;

&lt;p&gt;Install the simple_char driver in a Linux OS. If you have followed the previous
tutorials, you can install it to the arm64 virtual machine.
Load the driver module and inspect &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/proc/devices&lt;/code&gt; to get what major number
the character device got. Then use that major number to create a file
to interface with your character device.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@VM
root@localhost:~# modprobe simple_char
root@localhost:~# &lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /proc/devices | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;simp
511 simple_char
root@localhost:~# &lt;span class=&quot;nb&quot;&gt;mknod &lt;/span&gt;simple_char_node c 511 0
root@localhost:~# &lt;span class=&quot;nb&quot;&gt;stat &lt;/span&gt;simple_char_node
  File: simple_char_node
  Size: 0               Blocks: 0          IO Block: 4096   character special file
Device: 254,2   Inode: 2142        Links: 1     Device &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;: 511,0
Access: &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;0644/crw-r--r--&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;  Uid: &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;    0/    root&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;   Gid: &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;    0/    root&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
Access: 2024-03-16 18:26:55.133581798 +0000
Modify: 2024-03-16 18:26:55.133581798 +0000
Change: 2024-03-16 18:26:55.133581798 +0000
 Birth: 2024-03-16 18:26:55.133581798 +0000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Create &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${LK_DEV_DIR}/read_prog.c&lt;/code&gt; to test reading from our character device.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;fcntl.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#define BUF_SIZE 256
&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/* Example inspired from open(2) */&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BUF_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;22&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;O_RDONLY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BUF_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Read buffer: %s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Although it is advisable to handle possible errors that may happen when
accessing files, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${LK_DEV_DIR}/read_prog.c&lt;/code&gt; was left with no error handling to keep the
example small and simple.
Compile the read test program for your Linux test machine.
If you have followed the previous tutorials, you can use the GCC from the cross
compiler toolchain you have for building the kernel to compile the test program.
Send the binary to the virtual machine and run it there.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@host
aarch64-linux-gnu-gcc read_prog.c &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; read_prog
scp read_prog root@&amp;lt;VM-IP-ADDRESS&amp;gt;:~/
@VM
root@localhost:~# ./read_prog simple_char_node
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${LK_DEV_DIR}/write_prog.c&lt;/code&gt; test program for writing to the character device.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;fcntl.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;errno.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#define BUF_SIZE 256
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BUF_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;errsv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;EINVAL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;sprintf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;A new message for simple_char.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;O_RDWR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BUF_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;errsv&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;errno&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Error: %d&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;errsv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;wrote %d bytes to buffer&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Build and run the same way done for the read test program.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@host
aarch64-linux-gnu-gcc write_prog.c &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; write_prog
scp write_prog root@&amp;lt;VM-IP-ADDRESS&amp;gt;:~/
@VM
root@localhost:~# ./write_prog simple_char_node
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;proposed-exercises&quot;&gt;Proposed Exercises&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Printing device numbers:
Modify the simple_char driver to make it print major and minor device
numbers on device open.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Device private data:
Modify the simple_char driver to register more than one minor device number
and make it keep separate buffers for each of them.
Check the device minor number on device open and allocate a buffer for it if
it doesn’t have one. Also, make the read/write operations run over the buffer
for the particular major/minor device number pair.
Access &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f_inode&lt;/code&gt; field of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct file&lt;/code&gt; to get a pointer to the device inode
then access &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i_rdev&lt;/code&gt; field of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct inode&lt;/code&gt; to get the device ID (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dev_t&lt;/code&gt;) from
which you can extract the device minor number.
On module unload, free all allocated buffers.
With that, we can think of each pair of major/minor numbers as a different
character device and each of them will have their own data.
Finally, create device nodes with different minor numbers to test you
implementation.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;This post presented a few key concepts related to Linux kernel character devices
and provided a character device driver example that shows how the covered
concepts apply in practice.&lt;/p&gt;

&lt;h1 id=&quot;history&quot;&gt;History&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;V1: Release&lt;/li&gt;
  &lt;li&gt;V2: Review for the Free Software Development course offered in 2025-1 at IME-USP&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;p&gt;&lt;a name=&quot;cite-makedev:man&quot;&gt;[1]&lt;/a&gt; . “makedev(3)”. URL: &lt;a href=&quot;https://man.archlinux.org/man/makedev.3.en&quot;&gt;https://man.archlinux.org/man/makedev.3.en&lt;/a&gt;. &lt;big&gt;&lt;big&gt;&lt;big&gt;&lt;a href=&quot;#cite-makedev:man-back&quot;&gt;⤴&lt;/a&gt;&lt;/big&gt;&lt;/big&gt;&lt;/big&gt;&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;cite-mknode1:man&quot;&gt;[2]&lt;/a&gt; David MacKenzie. “MKNOD(1)”. URL: &lt;a href=&quot;https://man.archlinux.org/man/mknod.1&quot;&gt;https://man.archlinux.org/man/mknod.1&lt;/a&gt;. &lt;big&gt;&lt;big&gt;&lt;big&gt;&lt;a href=&quot;#cite-mknode1:man-back&quot;&gt;⤴&lt;/a&gt;&lt;/big&gt;&lt;/big&gt;&lt;/big&gt;&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;cite-devicenode:deb&quot;&gt;[3]&lt;/a&gt; David MacKenzie. “device_node”. URL: &lt;a href=&quot;https://wiki.debian.org/device_node&quot;&gt;https://wiki.debian.org/device_node&lt;/a&gt;. &lt;big&gt;&lt;big&gt;&lt;big&gt;&lt;a href=&quot;#cite-devicenode:deb-back&quot;&gt;⤴&lt;/a&gt;&lt;/big&gt;&lt;/big&gt;&lt;/big&gt;&lt;/p&gt;

</content>
    </entry>
    
    <entry>
        <title type="html">Introduction to Linux kernel build configuration and modules</title>
        <link href="https://flusp.ime.usp.br/kernel/modules-intro/"/>
        <published>2023-10-14T00:00:00-03:00</published>
        <id isPermaLink="true">https://flusp.ime.usp.br/kernel/modules-intro/</id>
        <category>kernel</category>
        <content type="html">&lt;p&gt;This tutorial shows how to make a simple Linux kernel module and how to create
build configurations for new kernel features.&lt;/p&gt;

&lt;p&gt;This tutorial was originally thought to be part of a set of tutorials tailored
to aid newcomers to develop for the Linux kernel Industrial I/O subsystem. This
is a continuation for the “&lt;a href=&quot;/kernel/build-linux-for-arm/&quot;&gt;Building and booting a custom Linux kernel for
ARM&lt;/a&gt;” and “&lt;a href=&quot;/kernel/build-linux-for-arm-kw/&quot;&gt;Building and booting a custom Linux kernel for ARM using kw&lt;/a&gt;”
tutorial.&lt;/p&gt;

&lt;!--end-abstract--&gt;

&lt;!--begin-references--&gt;

&lt;!--
DEPMOD(8) https://linux.die.net/man/8/depmod
--&gt;

&lt;!--end-references--&gt;

&lt;h3 id=&quot;command-summary&quot;&gt;Command Summary&lt;/h3&gt;

&lt;p class=&quot;info&quot;&gt;If you did not read this tutorial yet, skip this section. This section was added
as a summary for those that already went through this tutorial and just want to
remember a specific command.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;### MAKE COMMANDS TO CONFIGURE, COMPILE, AND INSTALL MODULES&lt;/span&gt;
make &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; menuconfig &lt;span class=&quot;c&quot;&gt;# manage `.config` w/ a TUI&lt;/span&gt;
make &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;nproc&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; Image.gz modules &lt;span class=&quot;c&quot;&gt;# compile kernel image and modules&lt;/span&gt;
make &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; modules_install &lt;span class=&quot;c&quot;&gt;# install modules&lt;/span&gt;
make &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; modules_prepare &lt;span class=&quot;c&quot;&gt;# refresh modules for compilation&lt;/span&gt;
make &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&amp;lt;path-of-dir-to-build&amp;gt; &lt;span class=&quot;c&quot;&gt;# compile only a subset of the tree&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;### MANIPULATING MODULES&lt;/span&gt;
modinfo &amp;lt;module_name&amp;gt; &lt;span class=&quot;c&quot;&gt;# see information about module of given name&lt;/span&gt;
insmod &amp;lt;module_file.ko&amp;gt; &lt;span class=&quot;c&quot;&gt;# loads module at given location&lt;/span&gt;
rmmod &amp;lt;module_name&amp;gt; &lt;span class=&quot;c&quot;&gt;# unloads module of given name&lt;/span&gt;
modprobe &amp;lt;module_name&amp;gt; &lt;span class=&quot;c&quot;&gt;# loads module of given name and its dependencies &lt;/span&gt;
modprobe &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; &amp;lt;module_name&amp;gt; &lt;span class=&quot;c&quot;&gt;# unloads module of given name&lt;/span&gt;
depmod &lt;span class=&quot;nt&quot;&gt;--quick&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# updates the module dependency list only if a module is added or removed&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;### SEE KERNEL LOGS&lt;/span&gt;
dmesg | &lt;span class=&quot;nb&quot;&gt;tail&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# see last logs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;introduction&quot;&gt;Introduction&lt;/h1&gt;

&lt;p&gt;Kernel modules are code segments that can be dynamically inserted into or
removed from the kernel as needed. They enhance the kernel’s capabilities
without requiring a system reboot. A prime example is a device driver module,
which enables the kernel to communicate with connected hardware. Without
modules, systems typically rely on monolithic kernels, where new features must
be directly incorporated into the kernel image. This results in larger kernel
sizes and demands recompilation and a system restart whenever additional
functionality is introduced.&lt;/p&gt;

&lt;p&gt;Starting to tinker with the Linux codebase through modules is interesting as we
can have an isolated context to understand other concepts about Linux
development, and this is precisely what we will do in this tutorial.&lt;/p&gt;

&lt;h1 id=&quot;introduction-to-linux-kernel-build-configuration-and-modules&quot;&gt;Introduction to Linux kernel build configuration and modules&lt;/h1&gt;

&lt;p&gt;This part shows how to build and test a simple kernel module and explores the
Linux kernel build configuration further by explaining how to use &lt;em&gt;menuconfig&lt;/em&gt;
to enable kernel features and how to create your own build configuration for a
simple example module.&lt;/p&gt;

&lt;p&gt;Summary of the parts of this tutorial:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Creating a simple example module&lt;/li&gt;
  &lt;li&gt;Creating Linux kernel configuration symbols&lt;/li&gt;
  &lt;li&gt;Configuring the Linux kernel build with menuconfig&lt;/li&gt;
  &lt;li&gt;Installing Linux kernel modules&lt;/li&gt;
  &lt;li&gt;Dependencies between kernel features&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;1-creating-a-simple-example-module&quot;&gt;1) Creating a simple example module&lt;/h3&gt;

&lt;p class=&quot;warning&quot;&gt;Don’t forget to have the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activate.sh&lt;/code&gt; script built in the last tutorials
running.&lt;/p&gt;

&lt;p&gt;From the root of the Linux kernel source code, create the file
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${IIO_TREE}/drivers/misc/simple_mod.c&lt;/code&gt; and add the code for the simple mod in
there.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;linux/module.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;linux/init.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__init&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;simple_mod_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;pr_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello world&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__exit&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;simple_mod_exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;pr_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Goodbye world&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;module_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;simple_mod_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;module_exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;simple_mod_exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;MODULE_LICENSE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;GPL&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;2-creating-linux-kernel-configuration-symbols&quot;&gt;2) Creating Linux kernel configuration symbols&lt;/h3&gt;

&lt;p&gt;Now, let’s create a Kconfig configuration symbol for our simple module and add
the associated Kbuild configuration option to build it.
When adding new Kconfig symbols we usually write them in the Kconfig file
that stands in the same directory of the thing we want to build.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;simple_mod.c&lt;/code&gt; module is under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${IIO_TREE}/drivers/misc/&lt;/code&gt; so we will add a configuration
symbol for that in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${IIO_TREE}/drivers/misc/Kconfig&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When adding entries to kbuild Kconfig and Makefiles we also follow the
convention of keeping the entries in alphabetical order. The convention is not
enforced by the build system so out of order entries will not prevent us from
building the kernel. Nevertheless, keeping entries in order definitely helps
developers find build configurations when looking for them. Also, the Linux
kernel community will ask code submitters to keep things organized when
upstreaming new configuration symbols. Let’s keep the good practices.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;config SIMPLE_MOD
	tristate &quot;Simple example Linux kernel module&quot;
	default	n
	help
	  This option enables a simple module that says hello upon load and
	  bye on unloading.

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;strong&gt;config&lt;/strong&gt; keyword defines a new configuration symbol. Further, Kbuild
will generate a configuration option for that symbol which in turn will be
stored as a configuration entry in the &lt;strong&gt;.config&lt;/strong&gt; file. Configuration options
will also show in kernel configuration tools such as &lt;em&gt;menuconfig&lt;/em&gt;, &lt;em&gt;nconfig&lt;/em&gt;, or
during the compilation process.
In particular, the SIMPLE_MOD configuration symbol has the following attributes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;tristate&lt;/strong&gt;: the type for the configuration option. It declares that this
symbol stands for something that may be compiled as a module (&lt;em&gt;m&lt;/em&gt;), built-in
compiled (&lt;em&gt;y&lt;/em&gt;) (i.e., included in the kernel image), or not compiled at all (&lt;em&gt;n&lt;/em&gt;).
The type definition also accepts an optional input prompt to set the option
name that kernel configuration tools display.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;default&lt;/strong&gt;: the value that should be selected by kernel config tools if no
explicit value has been assigned to the associated configuration option (such as
when applying a &lt;em&gt;defconfig&lt;/em&gt;).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;help&lt;/strong&gt;: defines a help text to be displayed as auxiliary info.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Other common attributes for configuration symbols are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;bool&lt;/strong&gt;: type for features that can only be either enabled or disabled.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;depends on&lt;/strong&gt;: list of dependency symbols. If its dependencies are not
satisfied, this symbol may become non-visible during configuration or
compilation time. As an experiment, try to disable SPI support at Device
Drivers. Many ADCs will no longer be listed at
&lt;em&gt;Device Drivers -&amp;gt; Industrial I/O support -&amp;gt; Analog to digital converters&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;select&lt;/strong&gt;: when the symbol containing the select list is enabled, the symbols
from its select list will also be enabled. Note the symbols in this list will
not be disabled if the symbol containing the select list is later disabled.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now we add the simple_mod module to the list of build objects in
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${IIO_TREE}/drivers/misc/Makefile&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;obj-$(CONFIG_SIMPLE_MOD)		+= simple_mod.o
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That’s all we need for enabling the configuration of our simple_mod with
&lt;em&gt;kbuild&lt;/em&gt;.&lt;/p&gt;

&lt;h3 id=&quot;3-configuring-the-linux-kernel-build-with-menuconfig&quot;&gt;3) Configuring the Linux kernel build with menuconfig&lt;/h3&gt;

&lt;p&gt;Run &lt;em&gt;menuconfig&lt;/em&gt; and enable our example module.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;make &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; menuconfig
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Type forward slash (&lt;em&gt;/&lt;/em&gt;) to search by symbol name. In the search screen, type
&lt;em&gt;simple_mod&lt;/em&gt; then enter. The description of the simple_mod will appear.
Type &lt;em&gt;1&lt;/em&gt; to go to the configuration option. With selection over the simple_mod
option, type &lt;em&gt;m&lt;/em&gt; to enable it as a module. Save the configuration and exit
menuconfig.&lt;/p&gt;

&lt;figure&gt;

  &lt;a href=&quot;/img/posts/tutorials/kernel/modules_intro/2023-10-14-modules-intro/menuconfig_usage.png&quot;&gt;

&lt;img class=&quot;img-center&quot; src=&quot;/img/posts/tutorials/kernel/modules_intro/2023-10-14-modules-intro/menuconfig_usage.png&quot; alt=&quot;Enabling simple_mod with menuconfig&quot; /&gt;

&lt;/a&gt;


  
  &lt;figcaption class=&quot;fig-center&quot;&gt;
    &lt;b&gt;Figure 1.&lt;/b&gt;
    Enabling simple_mod with menuconfig

  &lt;/figcaption&gt;
  

&lt;/figure&gt;

&lt;p&gt;Before building the image and modules, let’s clean any artifacts from previous
compilations. This isn’t strictly necessary, but it helps us ensure we are on
the same page as much as possible.&lt;/p&gt;

&lt;ul id=&quot;kw-1&quot; class=&quot;tab&quot; data-tab=&quot;6b5a27dc-5a6d-44d5-bd0f-3939a85969a9&quot; data-name=&quot;kw-1&quot;&gt;
  
      &lt;li class=&quot;active&quot; id=&quot;kw-1-with-kw&quot;&gt;
          &lt;a href=&quot;#&quot;&gt;with kw &lt;/a&gt;
      &lt;/li&gt;
  
      &lt;li id=&quot;kw-1-without-kw&quot;&gt;
          &lt;a href=&quot;#&quot;&gt;without kw &lt;/a&gt;
      &lt;/li&gt;
  
&lt;/ul&gt;
&lt;ul class=&quot;tab-content&quot; id=&quot;6b5a27dc-5a6d-44d5-bd0f-3939a85969a9&quot; data-name=&quot;kw-1&quot;&gt;
  
      &lt;li class=&quot;active&quot;&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
kw build &lt;span class=&quot;nt&quot;&gt;--clean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/li&gt;
  
      &lt;li&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;make &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;nproc&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; clean
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/li&gt;
  
&lt;/ul&gt;

&lt;p&gt;Build image and modules again.&lt;/p&gt;

&lt;ul id=&quot;kw-2&quot; class=&quot;tab&quot; data-tab=&quot;b2b95b3c-ef8b-44af-baeb-ecb3dbec5713&quot; data-name=&quot;kw-2&quot;&gt;
  
      &lt;li class=&quot;active&quot; id=&quot;kw-2-with-kw&quot;&gt;
          &lt;a href=&quot;#&quot;&gt;with kw &lt;/a&gt;
      &lt;/li&gt;
  
      &lt;li id=&quot;kw-2-without-kw&quot;&gt;
          &lt;a href=&quot;#&quot;&gt;without kw &lt;/a&gt;
      &lt;/li&gt;
  
&lt;/ul&gt;
&lt;ul class=&quot;tab-content&quot; id=&quot;b2b95b3c-ef8b-44af-baeb-ecb3dbec5713&quot; data-name=&quot;kw-2&quot;&gt;
  
      &lt;li class=&quot;active&quot;&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
kw build
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/li&gt;
  
      &lt;li&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;make &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;nproc&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; Image.gz modules
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/li&gt;
  
&lt;/ul&gt;

&lt;p&gt;Install new kernel modules. No need to copy or install the kernel image since
virt will pick the generated image file at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${IIO_TREE}/arch/arm/boot/Image&lt;/code&gt;.&lt;/p&gt;

&lt;ul id=&quot;kw-3&quot; class=&quot;tab&quot; data-tab=&quot;8dece400-3e7e-42da-8a63-d55cfca1e625&quot; data-name=&quot;kw-3&quot;&gt;
  
      &lt;li class=&quot;active&quot; id=&quot;kw-3-with-kw&quot;&gt;
          &lt;a href=&quot;#&quot;&gt;with kw &lt;/a&gt;
      &lt;/li&gt;
  
      &lt;li id=&quot;kw-3-without-kw&quot;&gt;
          &lt;a href=&quot;#&quot;&gt;without kw &lt;/a&gt;
      &lt;/li&gt;
  
&lt;/ul&gt;
&lt;ul class=&quot;tab-content&quot; id=&quot;8dece400-3e7e-42da-8a63-d55cfca1e625&quot; data-name=&quot;kw-3&quot;&gt;
  
      &lt;li class=&quot;active&quot;&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;VM_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/arm64_rootfs&quot;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;### ADAPT THE COMMAND BELOW ###&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;guestmount &lt;span class=&quot;nt&quot;&gt;--rw&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--add&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;VM_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/arm64_img.qcow2&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--mount&lt;/span&gt; /dev/&amp;lt;rootfs&amp;gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;VM_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/arm64_rootfs&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# mount the VM `rootfs` to the given mount point in read and write mode (this could take a while)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--preserve-env&lt;/span&gt; make &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IIO_TREE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;INSTALL_MOD_PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;VM_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/arm64_rootfs&quot;&lt;/span&gt; modules_install &lt;span class=&quot;c&quot;&gt;# install modules to inside the VM&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;guestunmount &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;VM_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/arm64_rootfs&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# unmount the VM `rootfs`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/li&gt;
  
      &lt;li&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;### ADAPT THE COMMAND BELOW ###&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;guestmount &lt;span class=&quot;nt&quot;&gt;--rw&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--add&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;VM_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/arm64_img.qcow2&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--mount&lt;/span&gt; /dev/&amp;lt;rootfs&amp;gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;VM_MOUNT_POINT&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# mount the VM `rootfs` to the given mount point in read and write mode (this could take a while)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--preserve-env&lt;/span&gt; make &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IIO_TREE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; modules_install &lt;span class=&quot;c&quot;&gt;# install modules to inside the VM&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;guestunmount &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$VM_MOUNT_POINT&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# unmount the VM `rootfs`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/li&gt;
  
&lt;/ul&gt;

&lt;p&gt;Connect to the VM with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh&lt;/code&gt;.&lt;/p&gt;

&lt;ul id=&quot;kw-4&quot; class=&quot;tab&quot; data-tab=&quot;1f22d440-f8cd-4a1b-b36e-1f3133c01ae3&quot; data-name=&quot;kw-4&quot;&gt;
  
      &lt;li class=&quot;active&quot; id=&quot;kw-4-with-kw&quot;&gt;
          &lt;a href=&quot;#&quot;&gt;with kw &lt;/a&gt;
      &lt;/li&gt;
  
      &lt;li id=&quot;kw-4-without-kw&quot;&gt;
          &lt;a href=&quot;#&quot;&gt;without kw &lt;/a&gt;
      &lt;/li&gt;
  
&lt;/ul&gt;
&lt;ul class=&quot;tab-content&quot; id=&quot;1f22d440-f8cd-4a1b-b36e-1f3133c01ae3&quot; data-name=&quot;kw-4&quot;&gt;
  
      &lt;li class=&quot;active&quot;&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;virsh start arm64
kw ssh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/li&gt;
  
      &lt;li&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;virsh start arm64
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;virsh start arm64
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;virsh net-dhcp-leases default
ssh root@&amp;lt;VM-IP-address&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/li&gt;
  
&lt;/ul&gt;

&lt;p&gt;Verify the kernel version.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@VM
&lt;span class=&quot;nb&quot;&gt;uname&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--all&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /proc/version
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;4-installing-linux-kernel-modules&quot;&gt;4) Installing Linux kernel modules&lt;/h3&gt;

&lt;p&gt;Run &lt;strong&gt;modinfo&lt;/strong&gt; which shows main info related to a kernel module.
When known, &lt;em&gt;modinfo&lt;/em&gt; will show the module file name, module author, module
description, license, ailas, dependencies, signature, and signer.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@VM
modinfo simple_mod
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;List currently loaded kernel modules.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@VM
lsmod
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You should have an output in similar to the below.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-output&quot;&gt;root@localhost:~# lsmod
Module                  Size  Used by
crct10dif_ce           12288  1
cfg80211              409600  0
rfkill                 28672  2 cfg80211
drm                   577536  0
dm_mod                131072  0
ip_tables              28672  0
x_tables               40960  1 ip_tables
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Notice our simple_mod is not loaded. Let’s take care of it.
There are two ways of loading a Linux kernel module: &lt;strong&gt;insmod&lt;/strong&gt; and &lt;strong&gt;modprobe&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;insmod&lt;/em&gt; takes a path to a module file (.ko) and loads that into the running
kernel. The kernel object file doesn’t really need to have been installed
as we did with &lt;em&gt;modules_install&lt;/em&gt;. &lt;strong&gt;rmmod&lt;/strong&gt; unloads the module. Load our example
module with &lt;em&gt;insmod&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@VM
insmod /lib/modules/&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;uname&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;/kernel/drivers/misc/simple_mod.ko &lt;span class=&quot;c&quot;&gt;# loads module at given location&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then run &lt;strong&gt;dmesg&lt;/strong&gt; to see kernel log messages. You should have something like
this&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-output&quot;&gt;root@localhost:~# dmesg | tail
&amp;lt;snipped&amp;gt;
[ 3962.547283] Hello world
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Remove the module with &lt;strong&gt;rmmod&lt;/strong&gt;.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@VM
rmmod simple_mod &lt;span class=&quot;c&quot;&gt;# unloads module of name `simple_mod`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then run &lt;strong&gt;dmesg&lt;/strong&gt; again to see kernel log messages. You should have something
like this&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-output&quot;&gt;root@localhost:~# dmesg | tail
&amp;lt;snipped&amp;gt;
[ 3973.986089] Goodbye world
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can do the same with &lt;em&gt;modprobe&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@VM
modprobe simple_mod &lt;span class=&quot;c&quot;&gt;# loads module of name `simple_mod` &lt;/span&gt;
dmesg | &lt;span class=&quot;nb&quot;&gt;tail
&lt;/span&gt;modprobe &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; simple_mod &lt;span class=&quot;c&quot;&gt;# unloads module of name `simple_mod` &lt;/span&gt;
dmesg | &lt;span class=&quot;nb&quot;&gt;tail&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Instead of a module file, &lt;em&gt;modprobe&lt;/em&gt; takes the module name as argument. For
that to work, the module has to be installed within the kernel and module
tracking files (such as &lt;em&gt;modules.dep&lt;/em&gt;) must contain references to the requested
module. The advantage of having that is that &lt;em&gt;modprobe&lt;/em&gt; will look for module
dependencies and (if any) properly load them before loading the requested
module &lt;a name=&quot;cite-modprobe:man-back&quot; href=&quot;#cite-modprobe:man&quot;&gt;[1]&lt;/a&gt;. &lt;em&gt;insmod&lt;/em&gt; does not check for
any module dependencies.&lt;/p&gt;

&lt;h3 id=&quot;5-dependencies-between-kernel-features&quot;&gt;5) Dependencies between kernel features&lt;/h3&gt;

&lt;p&gt;Let’s increment our example module to export a function that can be called
by other modules.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;linux/module.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;linux/init.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;simple_mod_func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;simple_mod_func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;pr_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Called %s, %s function&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;KBUILD_MODNAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__func__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;EXPORT_SYMBOL_NS_GPL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;simple_mod_func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;IIO_WORKSHOP_SIMPLE_MOD&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__init&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;simple_mod_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;pr_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello from %s module&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;KBUILD_MODNAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__exit&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;simple_mod_exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;pr_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Goodbye from %s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;KBUILD_MODNAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;module_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;simple_mod_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;module_exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;simple_mod_exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;MODULE_LICENSE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;GPL&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Rebuild the example module and copy it to the virtual machine.&lt;/p&gt;

&lt;ul id=&quot;kw-5&quot; class=&quot;tab&quot; data-tab=&quot;2c2c8fc4-8020-49e9-bf80-a5d7fffbf6c6&quot; data-name=&quot;kw-5&quot;&gt;
  
      &lt;li class=&quot;active&quot; id=&quot;kw-5-with-kw&quot;&gt;
          &lt;a href=&quot;#&quot;&gt;with kw &lt;/a&gt;
      &lt;/li&gt;
  
      &lt;li id=&quot;kw-5-without-kw&quot;&gt;
          &lt;a href=&quot;#&quot;&gt;without kw &lt;/a&gt;
      &lt;/li&gt;
  
&lt;/ul&gt;
&lt;ul class=&quot;tab-content&quot; id=&quot;2c2c8fc4-8020-49e9-bf80-a5d7fffbf6c6&quot; data-name=&quot;kw-5&quot;&gt;
  
      &lt;li class=&quot;active&quot;&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
kw build
kw ssh &lt;span class=&quot;nt&quot;&gt;--send&lt;/span&gt; drivers/misc/simple_mod.ko
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/li&gt;
  
      &lt;li&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;make &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IIO_TREE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/drivers/misc/&quot;&lt;/span&gt;
scp &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IIO_TREE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/drivers/misc/simple_mod.ko&quot;&lt;/span&gt; root@&amp;lt;VM-IP-address&amp;gt;:~/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/li&gt;
  
&lt;/ul&gt;

&lt;p&gt;The &lt;em&gt;M=&lt;/em&gt; option specify a directory for external module build. With that, we can
only rebuild the modules of a child directory such as
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${IIO_TREE}/drivers/misc&lt;/code&gt;.  Inside the virtual machine, test the new
&lt;em&gt;simple_mod&lt;/em&gt; version. No need to reboot.&lt;/p&gt;

&lt;p&gt;Inside the VM, do&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@VM
&lt;span class=&quot;nb&quot;&gt;cp &lt;/span&gt;simple_mod.ko /lib/modules/&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;uname&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;/kernel/drivers/misc/
depmod &lt;span class=&quot;nt&quot;&gt;--quick&lt;/span&gt;
modprobe simple_mod
modprobe &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; simple_mod
dmesg | &lt;span class=&quot;nb&quot;&gt;tail&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, let’s add another module to call the exported &lt;em&gt;simple_mod&lt;/em&gt; function. Create
a file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${IIO_TREE}/drivers/misc/simple_mod_part.c&lt;/code&gt; with the following contents.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;linux/module.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;linux/init.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;simple_mod_func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__init&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;simple_mod_part_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;pr_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello from %s module&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;KBUILD_MODNAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;simple_mod_func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__exit&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;simple_mod_part_exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;pr_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Goodbye from %s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;KBUILD_MODNAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;module_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;simple_mod_part_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;module_exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;simple_mod_part_exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;MODULE_LICENSE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;GPL&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;MODULE_IMPORT_NS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;IIO_WORKSHOP_SIMPLE_MOD&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Also add entries to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${IIO_TREE}/drivers/misc/Kconfig&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${IIO_TREE}/drivers/misc/Makefile&lt;/code&gt; as we did for &lt;em&gt;simple_mod&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;config SIMPLE_MOD_PART
	tristate &quot;Simple Test Partner Module&quot;
	depends on SIMPLE_MOD
	help
	   Enable this configuration option to enable the simple test partern
	   module.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;obj-$(CONFIG_SIMPLE_MOD_PART) += simple_mod_part.o
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Run &lt;em&gt;menuconfig&lt;/em&gt; again to enable &lt;em&gt;simple_mod_part&lt;/em&gt; to build as a module.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;make &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; menuconfig
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You will notice though, if you try to build the modules with
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make M=drivers/misc/&lt;/code&gt; that it will build &lt;em&gt;simple_mod&lt;/em&gt; but won’t build
&lt;em&gt;simple_mod_part&lt;/em&gt;. To get &lt;em&gt;simple_mod_part&lt;/em&gt; built and setup as we have
&lt;em&gt;simple_mod&lt;/em&gt;, run the &lt;em&gt;modules_prepare&lt;/em&gt; rule. Alternatively, we can rebuild the
kernel and install the modules again. Let’s go for the first option which is
faster.&lt;/p&gt;

&lt;ul id=&quot;kw-6&quot; class=&quot;tab&quot; data-tab=&quot;48474165-0137-4726-a52b-f86292f7c3f9&quot; data-name=&quot;kw-6&quot;&gt;
  
      &lt;li class=&quot;active&quot; id=&quot;kw-6-with-kw&quot;&gt;
          &lt;a href=&quot;#&quot;&gt;with kw &lt;/a&gt;
      &lt;/li&gt;
  
      &lt;li id=&quot;kw-6-without-kw&quot;&gt;
          &lt;a href=&quot;#&quot;&gt;without kw &lt;/a&gt;
      &lt;/li&gt;
  
&lt;/ul&gt;
&lt;ul class=&quot;tab-content&quot; id=&quot;48474165-0137-4726-a52b-f86292f7c3f9&quot; data-name=&quot;kw-6&quot;&gt;
  
      &lt;li class=&quot;active&quot;&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
kw build
kw ssh &lt;span class=&quot;nt&quot;&gt;--send&lt;/span&gt; drivers/misc/simple_mod_part.ko
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/li&gt;
  
      &lt;li&gt;
&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;make &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; modules_prepare
make &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;drivers/misc/
scp &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IIO_TREE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/drivers/misc/simple_mod_part.ko&quot;&lt;/span&gt; root@&amp;lt;VM-IP-address&amp;gt;:~/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/li&gt;
  
&lt;/ul&gt;

&lt;p&gt;Load &lt;em&gt;simple_mod_part&lt;/em&gt; and check out the output in kernel logs.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@VM
&lt;span class=&quot;nb&quot;&gt;cp &lt;/span&gt;simple_mod_part.ko /lib/modules/&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;uname&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;/kernel/drivers/misc/
depmod &lt;span class=&quot;nt&quot;&gt;--quick&lt;/span&gt;
modinfo simple_mod_part
modprobe simple_mod_part
modprobe &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; simple_mod_part
dmesg | &lt;span class=&quot;nb&quot;&gt;tail&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You should have an output like&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-output&quot;&gt;root@localhost:~# dmesg | tail
[  119.775025] Hello from simple_mod module
[  119.777102] Hello from simple_mod_part module
[  119.777290] Called simple_mod, simple_mod_func function
[  128.551064] Goodbye from simple_mod_part
[  128.563960] Goodbye from simple_mod
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note you don’t have to explicitly ask to load &lt;em&gt;simple_mod&lt;/em&gt; if using &lt;em&gt;modprobe&lt;/em&gt;.
To summarize, when adding new modules we need to prepare them for inclusion or
rebuild the whole kernel to get the modules correctly setup. After the modules
have been setup, we can modify modules, build only those that were updated, copy
them to the VM, update module dependancies with depmod, then test.&lt;/p&gt;

&lt;h2 id=&quot;proposed-exercices&quot;&gt;Proposed Exercices&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;The &lt;em&gt;.config&lt;/em&gt; file that comes with the arm64 VM is bloated with features
built together with the kernel image (&lt;em&gt;y&lt;/em&gt; config value) which is why even
after &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make localmodconfig&lt;/code&gt; the &lt;em&gt;.config&lt;/em&gt; file did not reduce significantly and
the build took a lot of time. Run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make allmodconfig&lt;/code&gt; to turn builtin
configuration values into module values when possible. After that, boot the VM,
regenerate the list of needed modules as described in Part 1, run
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make localmodconfig&lt;/code&gt; with new list of modules. Did it reduce &lt;em&gt;.config&lt;/em&gt; size further?
How much? Does the whole kernel build take less time with the new &lt;em&gt;.config&lt;/em&gt;?
Does the resulting kernel still boot?&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Sometimes developers lose track of what &lt;em&gt;.config&lt;/em&gt; was used to generate a
running kernel after messing arround for enough time. The in kernel
configuration config (IKCONFIG) exports (imports?) the &lt;em&gt;.config&lt;/em&gt; file used to
build the kernel into the kernel image and make it later availabe as
&lt;em&gt;/proc/config.gz&lt;/em&gt; file. Enable IKCONFIG, rebuild the kernel and read your
&lt;em&gt;.config&lt;/em&gt; from &lt;em&gt;/proc/config.gz&lt;/em&gt; within the VM.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Customize the log messages for &lt;em&gt;simple_mod&lt;/em&gt; and &lt;em&gt;simple_mod_part&lt;/em&gt;.  Add
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#define pr_fmt(fmt) KBUILD_MODNAME &quot;: &quot; fmt&lt;/code&gt; at the top of the module source
files. KBUILD_MODNAME will expand to the module source file name resulting
in every message logged through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pr_info()&lt;/code&gt; (and friends) being prepended by the
module name. See &lt;em&gt;include/linux/printk.h&lt;/em&gt; for documentation.
Tip, add the above define before header inclusions to avoid build warnings.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;This tutorial described how to add a module to the Linux codebase, create a
configuration for it, enable it to be compiled as a module, and install it. We
also covered how to dynamically load and unload modules, and how to use modules
functionalities in other modules.&lt;/p&gt;

&lt;h1 id=&quot;history&quot;&gt;History&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;V1: Release&lt;/li&gt;
  &lt;li&gt;V2: Review for the Free Software Development course offered in 2025-1 at IME-USP&lt;/li&gt;
&lt;/ol&gt;
</content>
    </entry>
    
    <entry>
        <title type="html">Building and booting a custom Linux kernel for ARM</title>
        <link href="https://flusp.ime.usp.br/kernel/build-linux-for-arm/"/>
        <published>2023-08-17T00:00:00-03:00</published>
        <id isPermaLink="true">https://flusp.ime.usp.br/kernel/build-linux-for-arm/</id>
        <category>kernel</category>
        <content type="html">&lt;p&gt;This tutorial describes how to build - in other words, compile - the Linux
kernel for the &lt;a href=&quot;https://www.arm.com/architecture/cpu&quot;&gt;ARM architecture&lt;/a&gt; and boot
test it in a Virtual Machine (VM). Basic kernel build configuration is covered
too.&lt;/p&gt;

&lt;p&gt;This tutorial was originally thought to be part of a set of tutorials tailored
to aid newcomers to develop for the Linux kernel Industrial I/O subsystem (IIO).
It is the second in the series and a continuation of the
“&lt;a href=&quot;/kernel/qemu-libvirt-setup/&quot;&gt;Setting up a test environment for Linux Kernel Dev using QEMU and libvirt&lt;/a&gt;”
 tutorial.&lt;/p&gt;

&lt;!--end-abstract--&gt;

&lt;!--begin-references--&gt;

&lt;!--url=&quot;https://docs.kernel.org/kbuild/makefiles.html#descending-down-in-directories&quot; %}
--&gt;

&lt;!--
[1]: https://docs.kernel.org/kbuild/modules.html
[2]: https://www.linuxjournal.com/content/kbuild-linux-kernel-build-system
[3]: https://docs.kernel.org/kbuild/kconfig-language.html
[4]: https://docs.kernel.org/kbuild/makefiles.html#descending-down-in-directories
--&gt;

&lt;!--end-references--&gt;

&lt;h3 id=&quot;command-summary&quot;&gt;Command Summary&lt;/h3&gt;

&lt;p class=&quot;warning&quot;&gt;Skip this section if you have not completed this tutorial yet. This is a
reference for those who have gone through this tutorial and want to remember
specific commands.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;### SHALLOWLY CLONING THE IIO TREE W/ ACTIVE DEVELOPMENT BRANCH&lt;/span&gt;
git clone git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IIO_TREE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--branch&lt;/span&gt; testing &lt;span class=&quot;nt&quot;&gt;--single-branch&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--depth&lt;/span&gt; 10

&lt;span class=&quot;c&quot;&gt;### CREATING A LEAN `.config` file&lt;/span&gt;
make &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; defconfig &lt;span class=&quot;c&quot;&gt;# create predefined defconfig&lt;/span&gt;
make &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; olddefconfig &lt;span class=&quot;c&quot;&gt;# update defconfig with new default values&lt;/span&gt;
make &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; localmodconfig &lt;span class=&quot;c&quot;&gt;# reduce compilation to minimal set of modules&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;### SAFELY MODIFYING THE `.config` W/ A TUI&lt;/span&gt;
make &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; nconfig

&lt;span class=&quot;c&quot;&gt;### BUILDING A LINUX KERNEL FROM SOURCE CODE&lt;/span&gt;
make &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;nproc&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; Image.gz modules

&lt;span class=&quot;c&quot;&gt;### MOUNTING VM `rootfs` AND INSTALLING MODULES&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;guestmount &lt;span class=&quot;nt&quot;&gt;--rw&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--add&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;VM_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/arm64_img.qcow2&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--mount&lt;/span&gt; /dev/&amp;lt;rootfs&amp;gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;VM_MOUNT_POINT&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# mount the VM `rootfs` to the given mount point in read and write mode (this could take a while)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--preserve-env&lt;/span&gt; make &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IIO_TREE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; modules_install &lt;span class=&quot;c&quot;&gt;# install modules to inside the VM&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;guestunmount &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$VM_MOUNT_POINT&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# unmount the VM `rootfs`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;introduction&quot;&gt;Introduction&lt;/h1&gt;

&lt;p&gt;After setting up a test environment with VMs using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QEMU&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libvirt&lt;/code&gt;, we
begin compiling (also called &lt;em&gt;building&lt;/em&gt;) a custom Linux kernel from source and
booting it. This involves taking the source code developed by the Linux
community, compiling it into a monolithic executable that can be loaded into
memory and run on hardware (virtualized or not), and using it to start a system.
Additionally, we will compile and install kernel modules, smaller units that can
be dynamically loaded and unloaded while the system is running.
Cross-compilation will also be a factor, as we assume that the machine used to
compile the source code to these artifacts has an AMD64 architecture, while the
target architecture is ARM64.&lt;/p&gt;

&lt;h1 id=&quot;configuring-building-and-booting-a-custom-linux-kernel&quot;&gt;Configuring, building, and booting a custom Linux kernel&lt;/h1&gt;

&lt;p&gt;In this section we will go through the steps on how to configure, compile, and
boot customized Linux images in ARM64 VMs.&lt;/p&gt;

&lt;p&gt;Summary of this tutorial:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Cloning a Linux kernel tree&lt;/li&gt;
  &lt;li&gt;Configuring the Linux kernel compilation&lt;/li&gt;
  &lt;li&gt;Building a custom Linux kernel&lt;/li&gt;
  &lt;li&gt;Installing modules and booting the custom-built Linux kernel&lt;/li&gt;
&lt;/ol&gt;

&lt;p class=&quot;warning&quot;&gt;Before proceding remember to have the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activate.sh&lt;/code&gt; script we’ve created
available to be modified and active for all the commands run in the host system.
Also assure that you have your testing environment set up from the last
tutorial.&lt;/p&gt;

&lt;h3 id=&quot;1-cloning-a-linux-kernel-tree&quot;&gt;1) Cloning a Linux kernel tree&lt;/h3&gt;

&lt;p&gt;There are several repositories that contain the source code for the Linux
kernel. These repositories are known as &lt;em&gt;Linux kernel trees&lt;/em&gt;, in short, kernel
trees or just trees, because, as every software project, its source code is
arranged in a tree-like file hierarchy. Some trees are widely known such as
Linus Torvalds’ tree (known as &lt;em&gt;mainline&lt;/em&gt;) that represent the most updated
official version of Linux and the Linux stable tree that represents the stable
releases (the 6.10, 6.11, 6.12, etc.). In general, a Linux tree is a repository
where some development for the kernel happens and each tree follows its own
development ruled by its own community. Many of those repos are at
&lt;a href=&quot;https://git.kernel.org/&quot;&gt;kernel.org&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Some examples of Linux kernel trees are:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/&quot;&gt;Linus Torvalds’ tree (mainline)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git&quot;&gt;Linux-stable tree&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git&quot;&gt;Linux-next tree&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git/&quot;&gt;IIO subsystem tree&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/raspberrypi/linux&quot;&gt;Raspberry Pi tree&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/analogdevicesinc/linux&quot;&gt;Analog Devices tree&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this workshop, we’ll be using the &lt;em&gt;Industrial I/O&lt;/em&gt; (IIO) subsystem tree so
download (clone) it with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt;. First, modify your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activate.sh&lt;/code&gt; script&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;--- a/activate.sh
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+++ b/activate.sh
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@@ -4,6 +4,7 @@&lt;/span&gt;
 export LK_DEV_DIR=&apos;/home/lk_dev&apos; # path to testing environment directory
 export VM_DIR=&quot;${LK_DEV_DIR}/vm&quot; # path to VM directory
 export BOOT_DIR=&quot;${VM_DIR}/arm64_boot&quot; # path to boot artifacts
&lt;span class=&quot;gi&quot;&gt;+export IIO_TREE=&quot;${LK_DEV_DIR}/iio&quot; # path to IIO subsystem Linux kernel tree
&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt; # utility functions
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;then rerun the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activate.sh&lt;/code&gt; script and clone the tree.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IIO_TREE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--branch&lt;/span&gt; testing &lt;span class=&quot;nt&quot;&gt;--single-branch&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--depth&lt;/span&gt; 10
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In terms of source code, Linux kernel trees are already huge (a couple of GB in
disk space), but the git history is even bigger at this point (around 5GB). To
(hopefully) not use too much disk space and avoid longer download times, we use
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--branch&lt;/code&gt; option, which tells git we want the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;testing&lt;/code&gt; branch of the
remote pointed by the URL, and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--depth=10&lt;/code&gt; option, which limits the git
history to the latest 10 commits in the branch to be fetched. We’ve chosen the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;testing&lt;/code&gt; branch instead of the default &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; because the former is where the
actual development happens. Hence, as in this series, we aim to (possibly)
develop and propose changes to IIO, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;testing&lt;/code&gt; branch is the one we are
interested in.&lt;/p&gt;

&lt;p&gt;If you have plenty of disk space (and probably some spare time), I suggest you
clone the tree without the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--branch&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--depth&lt;/code&gt; flags because commit logs
are often a good source of information when trying to understand kernel code. By
the time this post was written, the IIO tree (with its entire git history) was
sizing roughly 5GB.&lt;/p&gt;

&lt;h3 id=&quot;2-configuring-the-linux-kernel-compilation&quot;&gt;2) Configuring the Linux kernel compilation&lt;/h3&gt;

&lt;p&gt;The &lt;em&gt;Kernel Build System&lt;/em&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kbuild&lt;/code&gt;) is based on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make&lt;/code&gt; and other GNU tools and
allows a highly modular and customizable build process for the Linux kernel. By
default, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kbuild&lt;/code&gt; uses the configuration options stored in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.config&lt;/code&gt; file
under the root directory of the Linux kernel tree, which isn’t present in
a freshly cloned tree. Those options hold values for configuration symbols
associated with kernel resources such as drivers, tools, and features in
general. Nearly all directories inside a kernel tree have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Kconfig&lt;/code&gt; file,
which defines the symbols for the resources at the same level. Top &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Kconfig&lt;/code&gt;
files include (&lt;em&gt;source&lt;/em&gt;) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Kconfig&lt;/code&gt; files from subdirectories thus creating a
tree of configuration symbols. When needed, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kbuild&lt;/code&gt; generates configuration
options from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Kconfig&lt;/code&gt; symbols and stores their values in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.config&lt;/code&gt; file.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kbuild&lt;/code&gt; Makefiles then use these configuration values to compile code
conditionally and to decide which objects to include in the monolithic kernel
image and which objects to become modules
&lt;a name=&quot;cite-linuxj:kbuild-back&quot; href=&quot;#cite-linuxj:kbuild&quot;&gt;[1]&lt;/a&gt;
&lt;a name=&quot;cite-kdoc:kbuild-back&quot; href=&quot;#cite-kdoc:kbuild&quot;&gt;[2]&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are predefined &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.config&lt;/code&gt;s for building kernels for different architectures
and purposes. These are called &lt;em&gt;defconfig&lt;/em&gt; (default configuration) files.
defconfig files store only specific non-default values for configuration
symbols. For instance, one can find defconfig files for ARM architecture
machines under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;arch/arm/configs&lt;/code&gt;. We will create a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.config&lt;/code&gt; file from the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;arm64&lt;/code&gt; defconfig. For it, we must specify our target architecture for the
build. Once again, modify the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activate.sh&lt;/code&gt; script and rerun it.&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;--- a/activate.sh
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+++ b/activate.sh
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@@ -5,6 +5,8 @@&lt;/span&gt; export LK_DEV_DIR=&apos;/home/lk_dev&apos; # path to testing environment directory
 export VM_DIR=&quot;${LK_DEV_DIR}/vm&quot; # path to VM directory
 export BOOT_DIR=&quot;${VM_DIR}/arm64_boot&quot; # path to boot artifacts
 export IIO_TREE=&quot;${LK_DEV_DIR}/iio&quot; # path to IIO subsystem Linux kernel tree
&lt;span class=&quot;gi&quot;&gt;+## Linux kernel tree build variables
+export ARCH=arm64 # variable defining target architecture
&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt; # utility functions
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then create the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.config&lt;/code&gt; defconfig file for the ARM architecture.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;make &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; defconfig &lt;span class=&quot;c&quot;&gt;# create predefined defconfig&lt;/span&gt;
make &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; olddefconfig &lt;span class=&quot;c&quot;&gt;# update defconfig with new default values&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-alFh&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IIO_TREE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/.config&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# list file infos of generated `.config`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-C&lt;/code&gt; option, like with git, tells &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make&lt;/code&gt; to run the commands as if it was in
the path passed as value. This series of tutorials does this (and other things)
to avoid requiring commands to be run in implied directories. Ideally, you
should always be aware of where you are executing a command and if it makes
sense. Nevertheless, to avoid unexpected troubles, we present &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make&lt;/code&gt; commands
with “mistake mitigation” flags.&lt;/p&gt;

&lt;p&gt;Before moving forward, let’s start the VM running ARM64, which we set up in the
last tutorial. Note that if either &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libvirtd&lt;/code&gt;, the default network, or the VM
are already started, some commands will raise errors, indicating that these are
already active.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@host
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl start libvirtd &lt;span class=&quot;c&quot;&gt;# starts the libvirt daemon&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;virsh net-start default &lt;span class=&quot;c&quot;&gt;# starts `virsh` default network&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;virsh start &lt;span class=&quot;nt&quot;&gt;--console&lt;/span&gt; arm64 &lt;span class=&quot;c&quot;&gt;# start a registered instance attaching console&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After the VM is running, fetch the saved list of modules you’ve generated in the
first tutorial of the series. Refer to section 4 of the first tutorial, in case
you don’t have this file.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@host
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;virsh net-dhcp-leases default &lt;span class=&quot;c&quot;&gt;# list `default` network to get VM IP&lt;/span&gt;
scp root@&amp;lt;VM-IP-address&amp;gt;:~/vm_mod_list &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IIO_TREE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# copy VM modules list to IIO tree&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, use this file to make a minimal set of modules selected for compilation,
thus reducing the time to build the kernel and the amount of VM disk space
required to install the modules. First, modify and rerun the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activate.sh&lt;/code&gt;
script&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;--- a/activate.sh
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+++ b/activate.sh
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@@ -7,6 +7,7 @@&lt;/span&gt; export BOOT_DIR=&quot;${VM_DIR}/arm64_boot&quot; # path to boot artifacts
 export IIO_TREE=&quot;${LK_DEV_DIR}/iio&quot; # path to IIO subsystem Linux kernel tree
 ## Linux kernel tree build variables
 export ARCH=arm64 # variable defining target architecture
&lt;span class=&quot;gi&quot;&gt;+export LSMOD=&quot;${IIO_TREE}/vm_mod_list&quot; # path to list of minimal set of modules
&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt; # utility functions
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;then, optimize the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.config&lt;/code&gt; file with the minimal set of modules to be built&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;make &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; localmodconfig
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p class=&quot;info&quot;&gt;New options might be prompted due to the differences in the files. You can just
spam the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ENTER&lt;/code&gt; key for the default values.&lt;/p&gt;

&lt;p&gt;It is possible to open the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.config&lt;/code&gt; file and directly edit it, but this isn’t
recommended. A safer and more palatable way is to use &lt;strong&gt;one of&lt;/strong&gt; the &lt;em&gt;Terminal
User Interfaces&lt;/em&gt; (TUI) provided by the Linux project&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;make &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; nconfig
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Use the arrow keys to navigate and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ENTER&lt;/code&gt; to change/toggle a configuration. You
can take some time to familiarize with these menus and see the available
configurations.&lt;/p&gt;

&lt;p&gt;For this tutorial, we want to make a tiny customization: change the kernel image
name. In the menu, select &lt;em&gt;General setup&lt;/em&gt;, then in &lt;em&gt;Local version - append to
kernel release&lt;/em&gt;, put whatever you want to be appended after the kernel version,
and disable &lt;em&gt;Automatically append version information to the version string&lt;/em&gt;.
Be aware that the string you input will be part of the name of your first custom
kernel, so treat it well :)&lt;/p&gt;

&lt;p&gt;To exit, hit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;F9&lt;/code&gt;, which will prompt you to save the changes. The figure below
illustrates the steps.&lt;/p&gt;

&lt;figure&gt;

  &lt;a href=&quot;/img/posts/tutorials/kernel/build_linux_for_arm/2023-08-17-build-linux-for-arm/change_name.png&quot;&gt;

&lt;img class=&quot;img-center&quot; src=&quot;/img/posts/tutorials/kernel/build_linux_for_arm/2023-08-17-build-linux-for-arm/change_name.png&quot; alt=&quot;Changing the kernel name with `nconfig`&quot; /&gt;

&lt;/a&gt;


  
  &lt;figcaption class=&quot;fig-center&quot;&gt;
    &lt;b&gt;Figure 1.&lt;/b&gt;
    Changing the kernel name with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nconfig&lt;/code&gt;

  &lt;/figcaption&gt;
  

&lt;/figure&gt;

&lt;h3 id=&quot;3-building-a-custom-linux-kernel&quot;&gt;3) Building a custom Linux kernel&lt;/h3&gt;

&lt;p&gt;Different processor architectures have distinct instruction sets and register
names. Due to that, the binaries produced by a compiler for architecture &lt;em&gt;A&lt;/em&gt;
will not work on a machine of architecture &lt;em&gt;B&lt;/em&gt;. So, we need to use a compiler
that produces binaries compatible with the instruction set of the machine we
want to run our kernel. Essentially, this concept is called
&lt;a href=&quot;https://www.gnu.org/software/automake/manual/html_node/Cross_002dCompilation.html&quot;&gt;&lt;em&gt;Cross-Compilation&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In our case, we assume we have a development system of the AMD64 (x86_64)
architecture, and the target machine is a VM of the ARM64 architecture.&lt;/p&gt;

&lt;p&gt;Most distros should have a GCC package with a compiler for AMD64 host machines
that produces binaries for ARM64 targets. On Debian and Fedora, the package name
is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc-aarch64-linux-gnu&lt;/code&gt;, while in Arch the package name is
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aarch64-linux-gnu-gcc&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Arch-based distros&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-Syy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; aarch64-linux-gnu-gcc
&lt;span class=&quot;c&quot;&gt;# Debian-based distros&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt update &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;gcc-aarch64-linux-gnu
&lt;span class=&quot;c&quot;&gt;# Fedora-based distros&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dnf update &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dnf &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;gcc-aarch64-linux-gnu
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;See the &lt;em&gt;Complementary Commands&lt;/em&gt; section for advice if you are having
difficulties in finding an equivalent package to your distro.&lt;/p&gt;

&lt;p&gt;Modify the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activate.sh&lt;/code&gt; script (don’t forget to rerun it) to include a env
variable that defines our cross-compiler&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;--- a/activate.sh
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+++ b/activate.sh
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@@ -5,10 +5,12 @@&lt;/span&gt; export IIO_TREE=&quot;${LK_DEV_DIR}/iio&quot; # path to IIO subsystem Linux kernel tree
 ## Linux kernel tree build variables
 export ARCH=arm64 # variable defining target architecture
 export LSMOD=&quot;${IIO_TREE}/vm_mod_list&quot; # path to list of minimal set of modules
&lt;span class=&quot;gi&quot;&gt;+export CROSS_COMPILE=aarch64-linux-gnu- # cross-compiler
&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt;# utility functions
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The kernel has many build targets, though we will only use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Image.gz&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;modules&lt;/code&gt; targets. Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make help&lt;/code&gt; to view a list of available targets. Finally,
let’s build our custom Linux kernel from source code. Mind that, although we
made a really lean &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.config&lt;/code&gt;, compiling the kernel still is a heavy task, and
even more so when cross-compiling.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;make &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IIO_TREE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;nproc&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; Image.gz modules
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It is likely that the above command will fail due to the software required for
the build being missing. Yet, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kbuild&lt;/code&gt; does a good job of telling what is
missing from the Linux build. So, one may often identify what to install after
analyzing the errors in the build output. On Debian-based OSes, developers often
need to install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flex&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bison&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ncurses&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There is also a &lt;a href=&quot;https://www.kernel.org/doc/html/latest/process/changes.html&quot;&gt;minimal requirements to compile the
kernel&lt;/a&gt; page with a
list of software required to build Linux and how to check your system has the
minimal required versions of them.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make&lt;/code&gt; command will instruct &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kbuild&lt;/code&gt; Makefiles to start the build process.
The main goal of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kbuild&lt;/code&gt; Makefiles is to produce the kernel image
(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vmlinuz&lt;/code&gt;) and modules &lt;a name=&quot;cite-kdoc:kbuild-back&quot; href=&quot;#cite-kdoc:kbuild&quot;&gt;[2]&lt;/a&gt;. Akin to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Kconfig&lt;/code&gt; files, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kbuild&lt;/code&gt; Makefiles are also present in most kernel directories,
often working with the values assigned for the symbols defined by the former.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The whole build is done recursively — a top Makefile descends into its sub-
directories and executes each subdirectory’s Makefile to generate the binary
objects for the files in that directory. Then, these objects are used to generate
the modules and the Linux kernel image.
&lt;a name=&quot;cite-linuxj:kbuild-back&quot; href=&quot;#cite-linuxj:kbuild&quot;&gt;[1]&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If everything goes right, you should see an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;arch/arm64/boot/Image&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;modules.order&lt;/code&gt; and alike files under the Linux source root directory.&lt;/p&gt;

&lt;h3 id=&quot;4-installing-modules-and-booting-the-custom-built-linux-kernel&quot;&gt;4) Installing modules and booting the custom-built Linux kernel&lt;/h3&gt;

&lt;p&gt;Before booting the custom-built kernel, we need to install the modules into the
VM, i.e., we need to move the module objects compiled to the right place inside
the VM’s filesystem. To do this, we mount the VM &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rootfs&lt;/code&gt; (it should be the same
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdaX&lt;/code&gt; partition from the first tutorial), which essentially attaches the
virtual disk representing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rootfs&lt;/code&gt; into a mount point that can be accessed
by our host filesystem.&lt;/p&gt;

&lt;p&gt;First, alter the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activate.sh&lt;/code&gt; script to include an env variable for the mount
point and the path to install the modules used by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make&lt;/code&gt; command we will
run.&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;--- a/activate.sh
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+++ b/activate.sh
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@@ -5,10 +5,12 @@&lt;/span&gt; export LK_DEV_DIR=&apos;/home/lk_dev&apos; # path to testing environment directory
 export VM_DIR=&quot;${LK_DEV_DIR}/vm&quot; # path to VM directory
 export BOOT_DIR=&quot;${VM_DIR}/arm64_boot&quot; # path to boot artifacts
 export IIO_TREE=&quot;${LK_DEV_DIR}/iio&quot; # path to IIO subsystem Linux kernel tree
&lt;span class=&quot;gi&quot;&gt;+export VM_MOUNT_POINT=&quot;${VM_DIR}/arm64_rootfs&quot; # path to mount point for VM rootfs
&lt;/span&gt; ## Linux kernel tree build variables
 export ARCH=arm64 # variable defining target architecture
 export LSMOD=&quot;${IIO_TREE}/vm_mod_list&quot; # path to list of minimal set of modules
 export CROSS_COMPILE=aarch64-linux-gnu- # cross-compiler
&lt;span class=&quot;gi&quot;&gt;+export INSTALL_MOD_PATH=&quot;$VM_MOUNT_POINT&quot; # path to install modules inside VM
&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt; # utility functions
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Rerun the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activate.sh&lt;/code&gt; script, then create a mount point, mount the VM, and
install the modules. The commands below are being run with superuser privileges
due to actions related to mounting, manipulating mounted directories, and
unmounting not being available for normal users. &lt;strong&gt;ASSURE THAT THE VM IS SHUT
DOWN BEFORE PROCEEDING&lt;/strong&gt;.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$VM_MOUNT_POINT&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# creates mount point&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;### ADAPT THE COMMAND BELOW ###&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;guestmount &lt;span class=&quot;nt&quot;&gt;--rw&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--add&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;VM_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/arm64_img.qcow2&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--mount&lt;/span&gt; /dev/&amp;lt;rootfs&amp;gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;VM_MOUNT_POINT&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# mount the VM `rootfs` to the given mount point in read and write mode (this could take a while)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--preserve-env&lt;/span&gt; make &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IIO_TREE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; modules_install &lt;span class=&quot;c&quot;&gt;# install modules to inside the VM&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;guestunmount &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$VM_MOUNT_POINT&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# unmount the VM `rootfs`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;ASSURE THAT THE VM &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ROOTFS&lt;/code&gt; IS UNMOUNTED BEFORE PROCEDING&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Finally, update your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activate.sh&lt;/code&gt; script to boot the VM (both through pure
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QEMU&lt;/code&gt; and with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libvirt&lt;/code&gt;) with the custom-built kernel. Don’t forget to adapt
the modification to have the correct &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt; and the correct &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vda&lt;/code&gt; partition
depending on your VM particularities!&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;--- a/activate.sh
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+++ b/activate.sh
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@@ -23,7 +23,7 @@&lt;/span&gt; function launch_vm_qemu() {
         -smp 2 \
         -netdev user,id=net0 -device virtio-net-device,netdev=net0 \
         -initrd &quot;${BOOT_DIR}/&amp;lt;initrd&amp;gt;&quot; \
&lt;span class=&quot;gd&quot;&gt;-        -kernel &quot;${BOOT_DIR}/&amp;lt;kernel&amp;gt;&quot; \
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+        -kernel &quot;${IIO_TREE}/arch/arm64/boot/Image&quot; \
&lt;/span&gt;         -append &quot;loglevel=8 root=/dev/&amp;lt;vdaX&amp;gt; rootwait&quot; \
         -device virtio-blk-pci,drive=hd \
         -drive if=none,file=&quot;${VM_DIR}/arm64_img.qcow2&quot;,format=qcow2,id=hd \
&lt;span class=&quot;p&quot;&gt;@@ -41,7 +41,7 @@&lt;/span&gt; function create_vm_virsh() {
         --import \
         --features acpi=off \
         --disk path=&quot;${VM_DIR}/arm64_img.qcow2&quot; \
&lt;span class=&quot;gd&quot;&gt;-        --boot kernel=${BOOT_DIR}/&amp;lt;kernel&amp;gt;,initrd=${BOOT_DIR}/&amp;lt;initrd&amp;gt;,kernel_args=&quot;loglevel=8 root=/dev/&amp;lt;vdaX&amp;gt; rootwait&quot; \
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+        --boot kernel=${IIO_TREE}/arch/arm64/boot/Image,initrd=${BOOT_DIR}/&amp;lt;initrd&amp;gt;,kernel_args=&quot;loglevel=8 root=/dev/&amp;lt;vdaX&amp;gt; rootwait&quot; \
&lt;/span&gt;         --network bridge:virbr0 \
         --graphics none
 }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Rerun the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activate.sh&lt;/code&gt; script. We need to undefine our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libvirt&lt;/code&gt; managed VM,
then created it again&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@host
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;virsh undefine arm64
create_vm_virsh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Log into the VM and run&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@VM
&lt;span class=&quot;nb&quot;&gt;uname&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--kernel-release&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;to check that you are now running the custom kernel we just built. The output of
this command should be something in the format of&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;major-release-nr&amp;gt;.&amp;lt;minor-release-nr&amp;gt;.&amp;lt;patch-release-nr&amp;gt;-rc&amp;lt;one-through-eight&amp;gt;-&amp;lt;the-name-you-wrote&amp;gt;+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;like, for example,&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;6.14.0-rc1-free-software+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Congratulations, you’ve just compiled and boot-tested a Linux kernel! From now
on, whenever you make a change on the Linux kernel tree, you can “just” compile
it, install the modules, and then start the VM to boot the new custom kernel and
be able to run validations inside the testing environment!&lt;/p&gt;

&lt;h4 id=&quot;41-installing-the-kernel-image&quot;&gt;4.1) Installing the kernel image&lt;/h4&gt;

&lt;p&gt;Often, kernel developers also need to explicitly install the Linux kernel image
to their target test machines. Notice that here, we are not copying or moving
the Linux kernel image to nowhere inside the VM like we did when installing
modules. Neither we are dealing with a physical machine.&lt;/p&gt;

&lt;p&gt;Essentially, installing a new kernel image would be to just replace the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vmlinuz/Image/zImage/bzImage/uImage&lt;/code&gt; file, which contains the Linux boot
executable program. However, some platforms (such as AMD64 and ARM64) have fancy
boot procedures with boot loaders that won’t find kernel images without very
specific configuration pointing to them (e.g., GRUB), which might mount
temporary file systems (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt;), load drivers prior to mounting the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rootfs&lt;/code&gt;,
and so on. To help setup those additional boot files and configuration, the
Linux kernel has a &lt;em&gt;install&lt;/em&gt; rule. So, kernel developers may also run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make
install&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make install INSTALL_PATH=&amp;lt;path_to_bootfs&amp;gt;&lt;/code&gt; when deploying kernels
to those platforms.&lt;/p&gt;

&lt;p&gt;For this setup, we shall not bother with that. We don’t need to run the
installation rule because we instructed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QEMU&lt;/code&gt; (with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-kernel&lt;/code&gt;) and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libvirt&lt;/code&gt;
(with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--boot kernel=...&lt;/code&gt;) to pick up the kernel image that resulted from the
compilation, and we are reusing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt; file from the original guest OS
that came with the disk image.&lt;/p&gt;

&lt;h3 id=&quot;complementary-commands&quot;&gt;Complementary Commands&lt;/h3&gt;

&lt;p&gt;One may also download cross compiler toolchains from different vendors.
For instance, ARM provides an equivalent cross compiler that you may download
if having trouble finding a proper distro package.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;wget &lt;span class=&quot;nt&quot;&gt;-O&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LK_DEV_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/gcc-aarch64-linux-gnu.tar.xz&quot;&lt;/span&gt; https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu.tar.xz
&lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-xf&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$LK_DEV_DIR&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LK_DEV_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/gcc-aarch64-linux-gnu.tar.xz&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Sometimes identifying the cross compiler for your combination of host and target
machines may require some understanding of what is called the compiler triplet.
Conceptually, the compiler triplet should contain three fields:
the name of the CPU family/model, the vendor, and the operating system name
&lt;a name=&quot;cite-osdev:tt-back&quot; href=&quot;#cite-osdev:tt&quot;&gt;[3]&lt;/a&gt;.
However, sometimes the vendor is omitted so one may find a triplet like
&lt;em&gt;x86_64-freebsd&lt;/em&gt; (FreeBSD kernel for 64-bit x86 CPUs)
&lt;a name=&quot;cite-osdev:tt-back&quot; href=&quot;#cite-osdev:tt&quot;&gt;[3]&lt;/a&gt;.
It is also common to see the operating system information split into two
separate fields, one for indicating the kernel and the other for describing the
runtime environment or C library which is being used. The the debian package
for x86-64 gcc is an example of this triplet format mutation:
&lt;em&gt;gcc-x86-64-linux-gnu&lt;/em&gt; (compiler for 64-bit x86 targets that will run a Linux
kernel and have GNU glibc in their runtime). But things can get even more
unintuitive when system call conventions or Application Binary Interfaces (ABI)
are specified in the OS field as in &lt;em&gt;arm-linux-gnueabi&lt;/em&gt; (compiler for 32-bit ARM
targets that will run Linux using the EABI system call convention) or as in
&lt;em&gt;arm-none-eabi&lt;/em&gt; (compiler for 32-bit ARM that will run no OS (bare-metal) using
the EABI system call convention).&lt;/p&gt;

&lt;p&gt;Anyways, you may point to the generic cross compiler name when using compilers
not under your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PATH&lt;/code&gt;. For example:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CROSS_COMPILE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LK_DEV_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/gcc-aarch64-linux-gnu/bin/aarch64-none-linux-gnu-&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;This tutorial described how to configure and build a custom Linux kernel and
boot-test it into a VM. To accomplish that, we covered basic concepts of Linux
kernel build configuration to guide readers into generating feasible &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.config&lt;/code&gt;
files, and some cross-compilation concepts. By this point, you should be able to
configure, build, and boot-test a custom Linux kernel from source code in a
safe testing environment.&lt;/p&gt;

&lt;h1 id=&quot;history&quot;&gt;History&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;V1: Release&lt;/li&gt;
  &lt;li&gt;V2: Review for the &lt;em&gt;Free Software Development&lt;/em&gt; course offered in 2025-1 at
IME-USP&lt;/li&gt;
  &lt;li&gt;V3: Incorporate Marcelo Schmitt feedbacks from &lt;a href=&quot;https://gitlab.com/flusp/flusp.gitlab.io/-/merge_requests/135&quot;&gt;Merge Request
135&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;p&gt;&lt;a name=&quot;cite-linuxj:kbuild&quot;&gt;[1]&lt;/a&gt; Javier Martinez Canillas. “Kbuild: the Linux Kernel Build System”. (2012) URL: &lt;a href=&quot;https://www.linuxjournal.com/content/kbuild-linux-kernel-build-system&quot;&gt;https://www.linuxjournal.com/content/kbuild-linux-kernel-build-system&lt;/a&gt;. &lt;big&gt;&lt;big&gt;&lt;big&gt;&lt;a href=&quot;#cite-linuxj:kbuild-back&quot;&gt;⤴&lt;/a&gt;&lt;/big&gt;&lt;/big&gt;&lt;/big&gt;&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;cite-kdoc:kbuild&quot;&gt;[2]&lt;/a&gt; Michael Elizabeth Chastain and Kai Germaschewski and Sam Ravnborg. “Linux Kernel Makefiles”. (2023) URL: &lt;a href=&quot;https://www.kernel.org/doc/html/latest/kbuild/makefiles.html&quot;&gt;https://www.kernel.org/doc/html/latest/kbuild/makefiles.html&lt;/a&gt;. &lt;big&gt;&lt;big&gt;&lt;big&gt;&lt;a href=&quot;#cite-kdoc:kbuild-back&quot;&gt;⤴&lt;/a&gt;&lt;/big&gt;&lt;/big&gt;&lt;/big&gt;&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;cite-osdev:tt&quot;&gt;[3]&lt;/a&gt; . “Target Triplet”. (2019) URL: &lt;a href=&quot;https://wiki.osdev.org/Target_Triplet&quot;&gt;https://wiki.osdev.org/Target_Triplet&lt;/a&gt;. &lt;big&gt;&lt;big&gt;&lt;big&gt;&lt;a href=&quot;#cite-osdev:tt-back&quot;&gt;⤴&lt;/a&gt;&lt;/big&gt;&lt;/big&gt;&lt;/big&gt;&lt;/p&gt;

</content>
    </entry>
    
  </channel>
</feed>
