diff --git a/docker.html b/docker.html index f44e6d5..e11cf44 100644 --- a/docker.html +++ b/docker.html @@ -470,6 +470,7 @@ pre{ white-space:pre }
sudo apt-get install docker
+./setup
 ./run-docker create && \
 ./run-docker sh -- ./build --download-dependencies qemu-buildroot
 ./run-docker
diff --git a/fatal-kernel-too-old-failure-in-userland-simulation.html b/fatal-kernel-too-old-failure-in-userland-simulation.html index 8e213af..36fa6db 100644 --- a/fatal-kernel-too-old-failure-in-userland-simulation.html +++ b/fatal-kernel-too-old-failure-in-userland-simulation.html @@ -462,7 +462,7 @@ pre{ white-space:pre }

glibc has a check for kernel version, likely obtained from the uname syscall, and if the kernel is not new enough, it quits.

-

Both gem5 and QEMU however allow setting the reported uname version from the command line, which we do to always match our toolchain.

+

Both gem5 and QEMU however allow setting the reported uname version from the command line for User mode simulation, which we do to always match our toolchain.

QEMU by default copies the host uname value, but we always override it in our scripts.

@@ -479,7 +479,7 @@ pre{ white-space:pre }

Source: userland/posix/uname.c.

-

The QEMU source that does this is at: https://github.com/qemu/qemu/blob/v3.1.0/linux-user/syscall.c#L8931

+

The QEMU source that does this is at: https://github.com/qemu/qemu/blob/v3.1.0/linux-user/syscall.c#L8931 The default ID is just hardcoded on the source.

Bibliography:

@@ -497,9 +497,6 @@ pre{ white-space:pre }
-
-

The ID is just hardcoded on the source:

-
diff --git a/index.html b/index.html index a3a05e4..8665852 100644 --- a/index.html +++ b/index.html @@ -3386,6 +3386,7 @@ j = 0
sudo apt-get install docker
+./setup
 ./run-docker create && \
 ./run-docker sh -- ./build --download-dependencies qemu-buildroot
 ./run-docker
@@ -7017,6 +7018,14 @@ cr3 = 0xFFFFF0DCDC000

This just counts every second forever and does not give you a shell.

+

And to pass command line arguments to the program, you can use --kernel-cli-after-dash:

+
+
+
+
./run --kernel-cli 'init=/bin/sh' --kernel-cli-after-dash '-c "echo asdf; pwd; ls"'
+
+
+

This method is not very flexible however, as it is hard to reliably pass multiple commands and command line arguments to the init with it, as explained at: Section 7.4, “Init environment”.

@@ -7274,29 +7283,31 @@ vim rootfs_overlay/etc/init.d/S99.gitignore

7.4. Init environment

-

The kernel parses parameters from the kernel command line up to "-"; if it doesn’t recognize a parameter and it doesn’t contain a '.', the parameter gets passed to init: parameters with '=' go into init’s environment, others are passed as command line arguments to init. Everything after "-" is passed as an argument to init.

+

The kernel parses parameters from the kernel command line up to "--"; if it doesn’t recognize a parameter and it doesn’t contain a '.', the parameter gets passed to init: parameters with '=' go into init’s environment, others are passed as command line arguments to init. Everything after "--" is passed as an argument to init.

-

And you can try it out with:

+

And you can try it out with our userland/linux/init_env_poweroff.c program:

-
./run --kernel-cli 'init=/lkmc/linux/init_env_poweroff.out' --kernel-cli-after-dash 'asdf=qwer zxcv'
+
./run --kernel-cli 'init=/lkmc/linux/init_env_poweroff.out loglevel=8 go_in_env=val1 with_dot.before=val2' \
+      --kernel-cli-after-dash 'go_in_arg=val3 with_dot.after=val4 zxcv'
-

From the generated QEMU command, we see that the kernel CLI at LKMC 69f5745d3df11d5c741551009df86ea6c61a09cf now contains:

+

From the generated QEMU command, we see that the kernel CLI at LKMC 69f5745d3df11d5c741551009df86ea6c61a09cf now contains (or at least would if it weren’t for https://github.com/cirosantilli/linux-kernel-module-cheat/issues/110 oh God), manually indented for readability:

-
init=/lkmc/linux/init_env_poweroff.out console=ttyS0 - lkmc_home=/lkmc asdf=qwer zxcv
+
<6>[    0.000000] Command line: root=/dev/vda nopat console_msg_format=syslog nokaslr norandmaps panic=-1 printk.devkmsg=on printk.time=y rw
+  init=/lkmc/linux/init_env_poweroff.out loglevel=8 go_in_env=val1 with_dot.before=val2 -- go_in_arg=val3 with_dot.after=val4 zxcv
@@ -7304,38 +7315,55 @@ vim rootfs_overlay/etc/init.d/S99.gitignore
-
args:
-/lkmc/linux/init_env_poweroff.out
--
-zxcv
-
-env:
-HOME=/
-TERM=linux
-lkmc_home=/lkmc
-asdf=qwer
+
<6>[    2.728992] Run /lkmc/linux/init_env_poweroff.out as init process
+<7>[    2.729587]   with arguments:
+<7>[    2.729820]     /lkmc/linux/init_env_poweroff.out
+<7>[    2.730085]     lkmc_home=/lkmc
+<7>[    2.730259]     go_in_arg=val3
+<7>[    2.730432]     with_dot.after=val4
+<7>[    2.730623]     zxcv
+<7>[    2.730767]   with environment:
+<7>[    2.730960]     HOME=/
+<7>[    2.731115]     TERM=linux
+<7>[    2.731267]     go_in_env=val
-
-

As of the Linux kernel v5.7 (possibly earlier, I’ve skipped a few releases), boot also shows the init arguments and environment very clearly, which is a great addition:

+

Tested as of the Linux kernel v5.7 and possibly earlier, boot also shows the init arguments and environment very clearly when using printk at loglevel=8, which is a great addition:

-
<6>[    0.309984] Run /sbin/init as init process
-<7>[    0.309991]   with arguments:
-<7>[    0.309997]     /sbin/init
-<7>[    0.310004]     nokaslr
-<7>[    0.310010]     -
-<7>[    0.310016]   with environment:
-<7>[    0.310022]     HOME=/
-<7>[    0.310028]     TERM=linux
-<7>[    0.310035]     earlyprintk=pl011,0x1c090000
-<7>[    0.310041]     lkmc_home=/lkmc
+
<6>[    2.777265] Run /lkmc/linux/init_env_poweroff.out as init process
+<7>[    2.777729]   with arguments:
+<7>[    2.777953]     /lkmc/linux/init_env_poweroff.out
+<7>[    2.778212]     lkmc_home=/lkmc
+<7>[    2.778391]     go_in_arg=val2
+<7>[    2.778554]     zxcv
+<7>[    2.778705]   with environment:
+<7>[    2.778901]     HOME=/
+<7>[    2.779065]     TERM=linux
+<7>[    2.779223]     go_in_env=val1
+
+

As we can see, the passing of environment variables to init is a bit wonky:

+
+
+
    +
  • +

    init and loglevel didn’t go because they were recognized

    +
  • +
  • +

    go_in_env went because it wasn’t

    +
  • +
+
+
+

so things can always break in future kernel releases…​ The only way to guard from this a bit is to use some unique prefix and hope the kernel never decides to use it. We of course use lkmc_* for our variables.

+
+
+

And it is also impossible to pass environment variables that contain dots in them: our with_dot.before is simply gone. Not a common use case, but still, quite insane.

+

7.4.1. init arguments

@@ -8381,7 +8409,7 @@ qw er

glibc has a check for kernel version, likely obtained from the uname syscall, and if the kernel is not new enough, it quits.

-

Both gem5 and QEMU however allow setting the reported uname version from the command line, which we do to always match our toolchain.

+

Both gem5 and QEMU however allow setting the reported uname version from the command line for User mode simulation, which we do to always match our toolchain.

QEMU by default copies the host uname value, but we always override it in our scripts.

@@ -8398,7 +8426,7 @@ qw er

Source: userland/posix/uname.c.

-

The QEMU source that does this is at: https://github.com/qemu/qemu/blob/v3.1.0/linux-user/syscall.c#L8931

+

The QEMU source that does this is at: https://github.com/qemu/qemu/blob/v3.1.0/linux-user/syscall.c#L8931 The default ID is just hardcoded on the source.

Bibliography:

@@ -8416,9 +8444,6 @@ qw er
-
-

The ID is just hardcoded on the source:

-

11.4.2. stack smashing detected when using glibc

@@ -11244,7 +11269,7 @@ git log | grep -E ' Linux [0-9]+\.' | head
-

The arguments are documented in the kernel documentation: https://www.kernel.org/doc/html/v4.14/admin-guide/kernel-parameters.html

+

The arguments are documented in the kernel documentation: https://www.kernel.org/doc/html/v5.9/admin-guide/kernel-parameters.html

When dealing with real boards, extra command line options are provided on some magic bootloader configuration file, e.g.:

@@ -13553,6 +13578,27 @@ echo $?

17.8.2. seq_file

+

TODO these examples broke in kernel 5.0 and we didn’t notice because they just added a flimsy warning and nothing else:

+
+ +
+

Fix with ifdef for kernel 4/5. The error message is:

+
+
+
+
seq_file: buggy .next function next [module-name] did not update position index
+
+
+

Writing trivial read File operations is repetitive and error prone. The seq_file API makes the process much easier for those trivial cases:

@@ -30203,6 +30249,9 @@ gensim/models/armv8/isa.ac
  • it is written in Make and Bash rather than Python like LKMC

  • +
  • +

    it downloads packages from upstream mirrors rather than having its own copy of them. Therefore, whenever some random French research institute decides to break links, your build also breaks. This is not acceptable. There are some mirroring options: https://risc-a-day.blogspot.com/2015/10/creating-local-mirror-for-buildroot.html but it’s not on by default it seems, Buildroot has to have their own official and default mirror of everything.

    +
  • diff --git a/init-environment.html b/init-environment.html index 9a1d129..23804fe 100644 --- a/init-environment.html +++ b/init-environment.html @@ -459,29 +459,31 @@ pre{ white-space:pre }

    7.4. Init environment

    -

    The kernel parses parameters from the kernel command line up to "-"; if it doesn’t recognize a parameter and it doesn’t contain a '.', the parameter gets passed to init: parameters with '=' go into init’s environment, others are passed as command line arguments to init. Everything after "-" is passed as an argument to init.

    +

    The kernel parses parameters from the kernel command line up to "--"; if it doesn’t recognize a parameter and it doesn’t contain a '.', the parameter gets passed to init: parameters with '=' go into init’s environment, others are passed as command line arguments to init. Everything after "--" is passed as an argument to init.

    -

    And you can try it out with:

    +

    And you can try it out with our userland/linux/init_env_poweroff.c program:

    -
    ./run --kernel-cli 'init=/lkmc/linux/init_env_poweroff.out' --kernel-cli-after-dash 'asdf=qwer zxcv'
    +
    ./run --kernel-cli 'init=/lkmc/linux/init_env_poweroff.out loglevel=8 go_in_env=val1 with_dot.before=val2' \
    +      --kernel-cli-after-dash 'go_in_arg=val3 with_dot.after=val4 zxcv'
    -

    From the generated QEMU command, we see that the kernel CLI at LKMC 69f5745d3df11d5c741551009df86ea6c61a09cf now contains:

    +

    From the generated QEMU command, we see that the kernel CLI at LKMC 69f5745d3df11d5c741551009df86ea6c61a09cf now contains (or at least would if it weren’t for https://github.com/cirosantilli/linux-kernel-module-cheat/issues/110 oh God), manually indented for readability:

    -
    init=/lkmc/linux/init_env_poweroff.out console=ttyS0 - lkmc_home=/lkmc asdf=qwer zxcv
    +
    <6>[    0.000000] Command line: root=/dev/vda nopat console_msg_format=syslog nokaslr norandmaps panic=-1 printk.devkmsg=on printk.time=y rw
    +  init=/lkmc/linux/init_env_poweroff.out loglevel=8 go_in_env=val1 with_dot.before=val2 -- go_in_arg=val3 with_dot.after=val4 zxcv
    @@ -489,38 +491,55 @@ pre{ white-space:pre }
    -
    args:
    -/lkmc/linux/init_env_poweroff.out
    --
    -zxcv
    -
    -env:
    -HOME=/
    -TERM=linux
    -lkmc_home=/lkmc
    -asdf=qwer
    +
    <6>[    2.728992] Run /lkmc/linux/init_env_poweroff.out as init process
    +<7>[    2.729587]   with arguments:
    +<7>[    2.729820]     /lkmc/linux/init_env_poweroff.out
    +<7>[    2.730085]     lkmc_home=/lkmc
    +<7>[    2.730259]     go_in_arg=val3
    +<7>[    2.730432]     with_dot.after=val4
    +<7>[    2.730623]     zxcv
    +<7>[    2.730767]   with environment:
    +<7>[    2.730960]     HOME=/
    +<7>[    2.731115]     TERM=linux
    +<7>[    2.731267]     go_in_env=val
    -
    -

    As of the Linux kernel v5.7 (possibly earlier, I’ve skipped a few releases), boot also shows the init arguments and environment very clearly, which is a great addition:

    +

    Tested as of the Linux kernel v5.7 and possibly earlier, boot also shows the init arguments and environment very clearly when using printk at loglevel=8, which is a great addition:

    -
    <6>[    0.309984] Run /sbin/init as init process
    -<7>[    0.309991]   with arguments:
    -<7>[    0.309997]     /sbin/init
    -<7>[    0.310004]     nokaslr
    -<7>[    0.310010]     -
    -<7>[    0.310016]   with environment:
    -<7>[    0.310022]     HOME=/
    -<7>[    0.310028]     TERM=linux
    -<7>[    0.310035]     earlyprintk=pl011,0x1c090000
    -<7>[    0.310041]     lkmc_home=/lkmc
    +
    <6>[    2.777265] Run /lkmc/linux/init_env_poweroff.out as init process
    +<7>[    2.777729]   with arguments:
    +<7>[    2.777953]     /lkmc/linux/init_env_poweroff.out
    +<7>[    2.778212]     lkmc_home=/lkmc
    +<7>[    2.778391]     go_in_arg=val2
    +<7>[    2.778554]     zxcv
    +<7>[    2.778705]   with environment:
    +<7>[    2.778901]     HOME=/
    +<7>[    2.779065]     TERM=linux
    +<7>[    2.779223]     go_in_env=val1
    +
    +

    As we can see, the passing of environment variables to init is a bit wonky:

    +
    +
    +
      +
    • +

      init and loglevel didn’t go because they were recognized

      +
    • +
    • +

      go_in_env went because it wasn’t

      +
    • +
    +
    +
    +

    so things can always break in future kernel releases…​ The only way to guard from this a bit is to use some unique prefix and hope the kernel never decides to use it. We of course use lkmc_* for our variables.

    +
    +
    +

    And it is also impossible to pass environment variables that contain dots in them: our with_dot.before is simply gone. Not a common use case, but still, quite insane.

    +
    diff --git a/kernel-command-line-parameters.html b/kernel-command-line-parameters.html index 6cf7dda..ac20ad7 100644 --- a/kernel-command-line-parameters.html +++ b/kernel-command-line-parameters.html @@ -502,7 +502,7 @@ pre{ white-space:pre }
    -

    The arguments are documented in the kernel documentation: https://www.kernel.org/doc/html/v4.14/admin-guide/kernel-parameters.html

    +

    The arguments are documented in the kernel documentation: https://www.kernel.org/doc/html/v5.9/admin-guide/kernel-parameters.html

    When dealing with real boards, extra command line options are provided on some magic bootloader configuration file, e.g.:

    diff --git a/replace-init.html b/replace-init.html index 0fb37fa..cac9ab2 100644 --- a/replace-init.html +++ b/replace-init.html @@ -473,6 +473,14 @@ pre{ white-space:pre }

    This just counts every second forever and does not give you a shell.

    +

    And to pass command line arguments to the program, you can use --kernel-cli-after-dash:

    +
    +
    +
    +
    ./run --kernel-cli 'init=/bin/sh' --kernel-cli-after-dash '-c "echo asdf; pwd; ls"'
    +
    +
    +

    This method is not very flexible however, as it is hard to reliably pass multiple commands and command line arguments to the init with it, as explained at: Section 7.4, “Init environment”.

    diff --git a/seq-file.html b/seq-file.html index 7ca564d..6ecfbb4 100644 --- a/seq-file.html +++ b/seq-file.html @@ -459,6 +459,27 @@ pre{ white-space:pre }

    17.8.2. seq_file

    +

    TODO these examples broke in kernel 5.0 and we didn’t notice because they just added a flimsy warning and nothing else:

    +
    + +
    +

    Fix with ifdef for kernel 4/5. The error message is:

    +
    +
    +
    +
    seq_file: buggy .next function next [module-name] did not update position index
    +
    +
    +

    Writing trivial read File operations is repetitive and error prone. The seq_file API makes the process much easier for those trivial cases:

    diff --git a/submodules/buildroot b/submodules/buildroot index b8c14b5..ccebc33 160000 --- a/submodules/buildroot +++ b/submodules/buildroot @@ -1 +1 @@ -Subproject commit b8c14b5bcac5c1a742401ece15fafe755a06ab03 +Subproject commit ccebc33040455ffb79038161e3bd22f428ed174e