From aea97698c3e6070392ecb8fac2349d87f806e97c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciro=20Santilli=20=E5=85=AD=E5=9B=9B=E4=BA=8B=E4=BB=B6=20?= =?UTF-8?q?=E6=B3=95=E8=BD=AE=E5=8A=9F?= Date: Sun, 5 May 2019 00:00:00 +0000 Subject: [PATCH] bak --- README.adoc | 171 ++--- build | 8 + build-userland | 185 ++--- build-userland-in-tree | 1 + common.py | 5 +- rootfs_overlay/{lkmc => }/README.adoc | 0 rootfs_overlay/lkmc/anonymous_inode.sh | 3 +- rootfs_overlay/lkmc/ioctl.sh | 5 +- rootfs_overlay/lkmc/netlink.sh | 7 +- rootfs_overlay/lkmc/poll.sh | 3 +- rootfs_overlay/lkmc/uio_read.sh | 2 +- thread_pool.py | 3 +- userland/anonymous_inode.c | 46 -- userland/arch/aarch64/common_arch.h | 8 +- userland/arch/arm/common_arch.h | 8 +- userland/arch/common.h | 4 +- userland/arch/x86_64/c/binutils_hack.c | 22 +- userland/arch/x86_64/c/binutils_nohack.c | 22 +- userland/bst_vs_heap.cpp | 14 +- userland/c/false.c | 2 +- userland/c/hello.c | 4 +- userland/c/print_argv.c | 14 + userland/common.h | 6 +- userland/init_env_poweroff.c | 26 - userland/ioctl.c | 67 -- userland/kernel_modules/anonymous_inode.c | 45 ++ userland/kernel_modules/ioctl.c | 66 ++ userland/{ => kernel_modules}/netlink.c | 2 +- userland/kernel_modules/poll.c | 41 ++ userland/{ => kernel_modules}/uio_read.c | 20 +- userland/libs/eigen/build | 1 + .../libs/{eigen_hello.cpp => eigen/hello.cpp} | 15 +- userland/libs/libdrm/build | 1 + .../{libdrm_modeset.c => libdrm/modeset.c} | 652 +++++++++--------- userland/libs/openblas/build | 1 + .../{openblas_hello.c => openblas/hello.c} | 0 userland/linux/README.adoc | 4 +- userland/linux/init_env_poweroff.c | 25 + userland/{ => linux}/myinsmod.c | 0 userland/{ => linux}/myrmmod.c | 0 userland/linux/poweroff.c | 2 +- userland/{ => linux}/proc_events.c | 0 userland/linux/rand_check.c | 42 +- userland/{ => linux}/sched_getaffinity.c | 0 .../{ => linux}/sched_getaffinity_threads.c | 20 +- userland/poll.c | 41 -- userland/{ => posix}/virt_to_phys_test.c | 14 +- userland/print_argv.c | 10 - 48 files changed, 840 insertions(+), 798 deletions(-) rename rootfs_overlay/{lkmc => }/README.adoc (100%) delete mode 100644 userland/anonymous_inode.c create mode 100644 userland/c/print_argv.c delete mode 100644 userland/init_env_poweroff.c delete mode 100644 userland/ioctl.c create mode 100644 userland/kernel_modules/anonymous_inode.c create mode 100644 userland/kernel_modules/ioctl.c rename userland/{ => kernel_modules}/netlink.c (97%) create mode 100644 userland/kernel_modules/poll.c rename userland/{ => kernel_modules}/uio_read.c (89%) create mode 120000 userland/libs/eigen/build rename userland/libs/{eigen_hello.cpp => eigen/hello.cpp} (57%) create mode 120000 userland/libs/libdrm/build rename userland/libs/{libdrm_modeset.c => libdrm/modeset.c} (59%) create mode 120000 userland/libs/openblas/build rename userland/libs/{openblas_hello.c => openblas/hello.c} (100%) create mode 100644 userland/linux/init_env_poweroff.c rename userland/{ => linux}/myinsmod.c (100%) rename userland/{ => linux}/myrmmod.c (100%) rename userland/{ => linux}/proc_events.c (100%) rename userland/{ => linux}/sched_getaffinity.c (100%) rename userland/{ => linux}/sched_getaffinity_threads.c (75%) delete mode 100644 userland/poll.c rename userland/{ => posix}/virt_to_phys_test.c (60%) delete mode 100644 userland/print_argv.c diff --git a/README.adoc b/README.adoc index da8ee72..c8ad141 100644 --- a/README.adoc +++ b/README.adoc @@ -977,23 +977,38 @@ Build, run and example, and clean it in-tree with: .... cd userland -./build +./build c/hello ./c/hello.out ./build --clean .... Source: link:userland/c/hello.c[]. -Or build just one directory: +Build an entire directory: .... ./build c .... -or just one executable: +Build the current directory: .... -./build c/hello +./build +.... + +Note however that this would try to build the link:userland/libs/[] folder, which depends on certain libraries being installed on the host, e.g. <>. + +You can install those libraries and do the build in one go with: + +.... +cd linux-kernel-module-cheat +./build --download-dependencies userland-host +.... + +If you modify a dependency that is not currently considered such as a header file, force the rebuild with: + +.... +./build --force-rebuild .... Do a more clean out of tree build and run the program instead: @@ -1003,11 +1018,7 @@ Do a more clean out of tree build and run the program instead: "$(./getvar --userland-build-id host userland_build_dir)/hello.out" .... -If you modify a dependency that is not currently considered such as a header file, force the rebuild with: - -.... -./build --force-rebuild -.... +Here we put the host executables in a separate <> to avoid conflict with Buildroot builds. ===== Userland setup getting started full system @@ -1699,7 +1710,7 @@ Alternatively, if the module panics before you can read `/proc/modules`, there i .... echo 8 > /proc/sys/kernel/printk echo 'file kernel/module.c +p' > /sys/kernel/debug/dynamic_debug/control -./myinsmod.out hello.ko +./linux/myinsmod.out hello.ko .... And then search for a line of type: @@ -1874,12 +1885,12 @@ Non-init process: * Shell 2: + .... -./run-gdb-user myinsmod main +./run-gdb-user linux/myinsmod main .... * Shell 1 after the boot finishes: + .... -./myinsmod.out hello.ko +./linux/myinsmod.out hello.ko .... This is the least reliable setup as there might be other processes that use the given virtual address. @@ -1995,10 +2006,10 @@ For a more minimal baremetal multicore setup, see: <>. We can set and get which cores the Linux kernel allows a program to run on with `sched_getaffinity` and `sched_setaffinity`: .... -./run --cpus 2 --eval-after './sched_getaffinity.out' +./run --cpus 2 --eval-after './linux/sched_getaffinity.out' .... -Source: link:userland/sched_getaffinity.c[] +Source: link:userland/linux/sched_getaffinity.c[] Sample output: @@ -2025,7 +2036,7 @@ The number of cores is modified as explained at: <> --config 'BR2_PACKAGE_UTIL_LINUX=y' \ --config 'BR2_PACKAGE_UTIL_LINUX_SCHEDUTILS=y' \ ; -./run --eval-after 'taskset -c 1,1 ./sched_getaffinity.out' +./run --eval-after 'taskset -c 1,1 ./linux/sched_getaffinity.out' .... output: @@ -2041,20 +2052,20 @@ so we see that the affinity was restricted to the second core from the start. Let's do a QEMU observation to justify this example being in the repository with <>. -We will run our `./sched_getaffinity.out` infinitely many time, on core 0 and core 1 alternatively: +We will run our `./linux/sched_getaffinity.out` infinitely many time, on core 0 and core 1 alternatively: .... ./run \ --cpus 2 \ --wait-gdb \ - --eval-after 'i=0; while true; do taskset -c $i,$i ./sched_getaffinity.out; i=$((! $i)); done' \ + --eval-after 'i=0; while true; do taskset -c $i,$i ./linux/sched_getaffinity.out; i=$((! $i)); done' \ ; .... on another shell: .... -./run-gdb-user "$(./getvar userland_build_dir)/sched_getaffinity.out" main +./run-gdb-user "$(./getvar userland_build_dir)/linux/sched_getaffinity.out" main .... Then, inside GDB: @@ -2079,13 +2090,13 @@ We should also try it out with kernel modules: https://stackoverflow.com/questio TODO we then tried: .... -./run --cpus 2 --eval-after './sched_getaffinity_threads.out' +./run --cpus 2 --eval-after './linux/sched_getaffinity_threads.out' .... and: .... -./run-gdb-user "$(./getvar userland_build_dir)/sched_getaffinity_threads.out" +./run-gdb-user "$(./getvar userland_build_dir)/linux/sched_getaffinity_threads.out" .... to switch between two simultaneous live threads with different affinities, it just didn't break on our threads: @@ -2431,10 +2442,10 @@ First build `gdbserver` into the root filesystem: ./build-buildroot --config 'BR2_PACKAGE_GDB=y' .... -Then on guest, to debug link:userland/myinsmod.c[]: +Then on guest, to debug link:userland/linux/myinsmod.c[]: .... -./gdbserver.sh ./myinsmod.out hello.ko +./gdbserver.sh ./linux/myinsmod.out hello.ko .... Source: link:rootfs_overlay/lkmc/gdbserver.sh[]. @@ -2442,13 +2453,13 @@ Source: link:rootfs_overlay/lkmc/gdbserver.sh[]. And on host: .... -./run-gdbserver myinsmod +./run-gdbserver linux/myinsmod .... or alternatively with the full path: .... -./run-gdbserver "$(./getvar userland_build_dir)/myinsmod.out" +./run-gdbserver "$(./getvar userland_build_dir)/linux/myinsmod.out" .... https://reverseengineering.stackexchange.com/questions/8829/cross-debugging-for-arm-mips-elf-with-qemu-toolchain/16214#16214 @@ -2587,7 +2598,7 @@ traps: ring0.out[55] general protection ip:40054c sp:7fffffffec20 error:0 in rin Sources: * link:kernel_modules/ring0.c[] -* link:kernel_modules/ring0.h[] +* link:include/ring0.h[] * link:userland/ring0.c[] In both cases, we attempt to run the exact same code which is shared on the `ring0.h` header file. @@ -2832,14 +2843,14 @@ ____ And you can try it out with: .... -./run --kernel-cli 'init=/lkmc/init_env_poweroff.out - asdf=qwer zxcv' +./run --kernel-cli 'init=/lkmc/linux/init_env_poweroff.out - asdf=qwer zxcv' .... Output: .... args: -/lkmc/init_env_poweroff.out +/lkmc/linux/init_env_poweroff.out - zxcv @@ -2849,7 +2860,7 @@ TERM=linux asdf=qwer .... -Source: link:userland/init_env_poweroff.c[]. +Source: link:userland/linux/init_env_poweroff.c[]. ==== init arguments @@ -2858,14 +2869,14 @@ The annoying dash `-` gets passed as a parameter to `init`, which makes it impos Arguments with dots that come after `-` are still treated specially (of the form `subsystem.somevalue`) and disappear, from args, e.g.: .... -./run --kernel-cli 'init=/lkmc/init_env_poweroff.out - /lkmc/linux/poweroff.out' +./run --kernel-cli 'init=/lkmc/linux/init_env_poweroff.out - /lkmc/linux/poweroff.out' .... outputs: .... args -/lkmc/init_env_poweroff.out +/lkmc/linux/init_env_poweroff.out - ab .... @@ -3380,12 +3391,12 @@ See also: <> === QEMU user mode getting started -Let's run link:userland/print_argv.c[] built with the Buildroot toolchain on QEMU user mode: +Let's run link:userland/c/print_argv.c[] built with the Buildroot toolchain on QEMU user mode: .... ./build user-mode-qemu ./run \ - --userland print_argv \ + --userland c/print_argv \ --userland-args 'asdf "qw er"' \ ; .... @@ -3413,12 +3424,12 @@ The commands are analogous to full system <>, e.g. without tmux: .... ./run \ - --userland print_argv \ + --userland c/print_argv \ --userland-args 'asdf "qw er"' \ --wait-gdb \ ; ./run-gdb \ - --userland print_argv \ + --userland c/print_argv \ main ; .... @@ -3427,7 +3438,7 @@ or with <>: .... ./run \ - --userland print_argv \ + --userland c/print_argv \ --userland-args 'asdf "qw er"' \ --tmux-args main \ --wait-gdb \ @@ -3449,7 +3460,7 @@ sudo apt-get install gcc-aarch64-linux-gnu qemu-system-aarch64 --arch aarch64 \ --qemu-which host --userland-build-id host \ - --userland print_argv \ + --userland c/print_argv \ --userland-args 'asdf "qw er"' \ ; .... @@ -3544,7 +3555,7 @@ Example: ./run \ --arch aarch64 \ --static \ - --userland print_argv \ + --userland c/print_argv \ --userland-args 'asdf "qw er"' \ ; .... @@ -3567,7 +3578,7 @@ So programs that rely on those libraries might not compile as GCC can't find the For example, if we try to build <> statically: .... -./build-userland --has-package openblas --static -- libs/openblas_hello +./build-userland --has-package openblas --static -- libs/openblas/hello .... it fails with: @@ -3583,7 +3594,7 @@ It's nice when <> just works, right? .... ./run \ --arch aarch64 \ - --userland print_argv \ + --userland c/print_argv \ --userland-args 'asdf "qw er"' \ --wait-gdb \ ; @@ -3594,7 +3605,7 @@ and on another shell: .... ./run-gdb \ --arch aarch64 \ - --userland print_argv \ + --userland c/print_argv \ main \ ; .... @@ -3605,7 +3616,7 @@ Or alternatively, if you are using <>, do everything in one go with: ./run \ --arch aarch64 \ --tmux-args main \ - --userland print_argv \ + --userland c/print_argv \ --userland-args 'asdf "qw er"' \ --wait-gdb \ ; @@ -3643,7 +3654,7 @@ So let's just play with some static ones: ./run \ --arch aarch64 \ --emulator gem5 \ - --userland print_argv \ + --userland c/print_argv \ --userland-args 'asdf "qw er"' \ ; .... @@ -3657,7 +3668,7 @@ TODO: how to escape spaces on the command line arguments? --arch aarch64 \ --emulator gem5 \ --static \ - --userland print_argv \ + --userland c/print_argv \ --userland-args 'asdf "qw er"' \ --wait-gdb \ ; @@ -3665,7 +3676,7 @@ TODO: how to escape spaces on the command line arguments? --arch aarch64 \ --emulator gem5 \ --static \ - --userland print_argv \ + --userland c/print_argv \ main \ ; .... @@ -3794,18 +3805,18 @@ If you are feeling raw, you can insert and remove modules with our own minimal m .... # init_module -./myinsmod.out hello.ko +./linux/myinsmod.out hello.ko # finit_module -./myinsmod.out hello.ko "" 1 -./myrmmod.out hello +./linux/myinsmod.out hello.ko "" 1 +./linux/myrmmod.out hello .... which teaches you how it is done from C code. Source: -* link:userland/myinsmod.c[] -* link:userland/myrmmod.c[] +* link:userland/linux/myinsmod.c[] +* link:userland/linux/myrmmod.c[] The Linux kernel offers two system calls for module insertion: @@ -5252,7 +5263,7 @@ But the awesome `CONFIG_DYNAMIC_DEBUG=y` option which we enable by default allow .... echo 8 > /proc/sys/kernel/printk echo 'file kernel/module.c +p' > /sys/kernel/debug/dynamic_debug/control -./myinsmod.out hello.ko +./linux/myinsmod.out hello.ko .... and we have a shortcut at: @@ -6375,7 +6386,7 @@ Outcome: `jiffies` gets printed to stdout every second from userland. Sources: * link:kernel_modules/poll.c[] -* link:kernel_modules/poll.c[] +* link:include/poll.h[] * link:rootfs_overlay/lkmc/poll.sh[] Typically, we are waiting for some hardware to make some piece of data available available to the kernel. @@ -6404,8 +6415,8 @@ Outcome: the test passes: Sources: * link:kernel_modules/ioctl.c[] -* link:kernel_modules/ioctl.h[] -* link:userland/ioctl.c[] +* link:include/ioctl.h[] +* link:userland/kernel_modules/ioctl.c[] * link:rootfs_overlay/lkmc/ioctl.sh[] `ioctl` is one of the most important methods of communication with real device drivers, which often take several fields as input. @@ -6489,8 +6500,8 @@ Outcome: the test passes: Sources: * link:kernel_modules/anonymous_inode.c[] -* link:kernel_modules/anonymous_inode.h[] -* link:userland/anonymous_inode.c[] +* link:include/anonymous_inode.h[] +* link:userland/kernel_modules/anonymous_inode.c[] * link:rootfs_overlay/lkmc/anonymous_inode.sh[] This example gets an anonymous inode via <> from a debugfs entry by using `anon_inode_getfd`. @@ -6517,8 +6528,8 @@ Outcome: the test passes: Sources: * link:kernel_modules/netlink.c[] -* link:kernel_modules/netlink.h[] -* link:userland/netlink.c[] +* link:include/netlink.h[] +* link:userland/kernel_modules/netlink.c[] * link:rootfs_overlay/lkmc/netlink.sh[] Launch multiple user requests in parallel to stress our socket: @@ -6993,10 +7004,10 @@ In this section we will play with them. First get a virtual address to play with: .... -./virt_to_phys_test.out & +./posix/virt_to_phys_test.out & .... -Source: link:userland/virt_to_phys_test.c[] +Source: link:userland/posix/virt_to_phys_test.c[] Sample output: @@ -7091,7 +7102,7 @@ After one second, we see on the screen: .... i 9abcdef0 -[1]+ Done ./virt_to_phys_test.out +[1]+ Done ./posix/virt_to_phys_test.out .... so the value changed, and the `while` loop exited! @@ -7116,7 +7127,7 @@ Dump the physical address of all pages mapped to a given process using `/proc/

>. Suppose that the output was: .... -# ./virt_to_phys_test.out & +# ./posix/virt_to_phys_test.out & vaddr 0x601048 pid 63 # ./linux/virt_to_phys_user.out 63 0x601048 @@ -7133,9 +7144,9 @@ Sample output excerpt: .... vaddr pfn soft-dirty file/shared swapped present library -400000 1ede 0 1 0 1 ./virt_to_phys_test.out -600000 1a6f 0 0 0 1 ./virt_to_phys_test.out -601000 1a61 0 0 0 1 ./virt_to_phys_test.out +400000 1ede 0 1 0 1 ./posix/virt_to_phys_test.out +600000 1a6f 0 0 0 1 ./posix/virt_to_phys_test.out +601000 1a61 0 0 0 1 ./posix/virt_to_phys_test.out 602000 2208 0 0 0 1 [heap] 603000 220b 0 0 0 1 [heap] 7ffff78ec000 1fd4 0 1 0 1 /lib/libuClibc-1.0.30.so @@ -7150,7 +7161,7 @@ Meaning of the flags: * `vaddr`: first virtual address of a page the belongs to the process. Notably: + .... -./run-toolchain readelf -- -l "$(./getvar userland_build_dir)/virt_to_phys_test.out" +./run-toolchain readelf -- -l "$(./getvar userland_build_dir)/posix/virt_to_phys_test.out" .... + contains: @@ -7222,7 +7233,7 @@ Logs proc events such as process creation to a link:kernel_modules/netlink.c[net We then have a userland program that listens to the events and prints them out: .... -# ./proc_events.out & +# ./linux/proc_events.out & # set mcast listen ok # sleep 2 & sleep 1 fork: parent tid=48 pid=48 -> child tid=79 pid=79 @@ -7236,7 +7247,7 @@ a # .... -Source: link:userland/proc_events.c[] +Source: link:userland/linux/proc_events.c[] TODO: why `exit: tid=79` shows after `exit: tid=80`? @@ -7245,7 +7256,7 @@ Note how `echo a` is a Bash built-in, and therefore does not spawn a new process TODO: why does this produce no output? .... -./proc_events.out >f & +./linux/proc_events.out >f & .... * https://stackoverflow.com/questions/6075013/detect-launching-of-programs-on-linux-platform/8255487#8255487 @@ -7725,7 +7736,7 @@ UIO interface in a nutshell: Sources: -* link:userland/uio_read.c[] +* link:userland/kernel_modules/uio_read.c[] * link:rootfs_overlay/lkmc/uio_read.sh[] Bibliography: @@ -8169,8 +8180,8 @@ DRM / DRI is the new interface that supersedes `fbdev`: .... ./build-buildroot --config 'BR2_PACKAGE_LIBDRM=y' -./build-userland --has-package libdrm -- libs/libdrm_modeset -./run --eval-after './libs/libdrm_modeset.out' --graphic +./build-userland --has-package libdrm -- libs/libdrm/modeset +./run --eval-after './libs/libdrm/modeset.out' --graphic .... Source: link:userland/libs/libdrm_modeset.c[] @@ -8183,7 +8194,7 @@ TODO not working for `aarch64`, it takes over the screen for a few seconds and t ./build-buildroot --config 'BR2_PACKAGE_LIBDRM=y' ./build-userland --has-package libdrm ./build-buildroot -./run --eval-after './libs/libdrm_modeset.out' --graphic +./run --eval-after './libs/libdrm/modeset.out' --graphic .... <> however worked, which means that it must be a bug with this demo? @@ -8208,7 +8219,7 @@ Try creating new displays: to see multiple `/dev/dri/cardN`, and then use a different display with: .... -./run --eval-after './libs/libdrm_modeset.out' --graphic +./run --eval-after './libs/libdrm/modeset.out' --graphic .... Bibliography: @@ -9909,8 +9920,8 @@ Buildroot supports it, which makes everything just trivial: .... ./build-buildroot --config 'BR2_PACKAGE_OPENBLAS=y' -./build-userland --has-package openblas -- libs/openblas_hello -./run --eval-after './libs/openblas_hello.out; echo $?' +./build-userland --has-package openblas -- libs/openblas/hello +./run --eval-after './libs/openblas/hello.out; echo $?' .... Outcome: the test passes: @@ -9919,7 +9930,7 @@ Outcome: the test passes: 0 .... -Source: link:userland/libs/openblas.c[] +Source: link:userland/libs/openblas/hello.c[] The test performs a general matrix multiplication: @@ -9949,13 +9960,13 @@ Header only linear algebra library with a mainline Buildroot package: .... ./build-buildroot --config 'BR2_PACKAGE_EIGEN=y' -./build-userland --has-package eigen -- libs/eigen_hello +./build-userland --has-package eigen -- libs/eigen/hello .... Just create an array and print it: .... -./run --eval-after './libs/eigen_hello.out' +./run --eval-after './libs/eigen/hello.out' .... Output: @@ -9965,7 +9976,7 @@ Output: 2.5 1.5 .... -Source: link:userland/libs/eigen_hello.cpp[] +Source: link:userland/libs/eigen/hello.cpp[] This example just creates a matrix and prints it out. @@ -10192,7 +10203,7 @@ The alternative is to do as in <>. Next, follow the exact same steps explained at <>, but passing `-g` to every command as usual. -But then TODO (I'll still go crazy one of those days): for `arm`, while debugging `./myinsmod.out hello.ko`, after then line: +But then TODO (I'll still go crazy one of those days): for `arm`, while debugging `./linux/myinsmod.out hello.ko`, after then line: .... 23 if (argc < 3) { diff --git a/build b/build index a4adfed..62aaea0 100755 --- a/build +++ b/build @@ -339,6 +339,14 @@ so looping over all of them would waste time. self._build_file('build-userland'), dependencies=['buildroot'], ), + 'userland-host': _Component( + self._build_file('build-userland'), + apt_get_pkgs={ + 'libdrm-dev', + 'libeigen3-dev', + 'libopenblas-dev', + }, + ), 'userland-gem5': _Component( self._build_file('build-userland', static=True, userland_build_id='static'), dependencies=['buildroot'], diff --git a/build-userland b/build-userland index 8ec545d..8321e00 100755 --- a/build-userland +++ b/build-userland @@ -25,6 +25,13 @@ Build our compiled userland examples. help='''\ Indicate that a given package is present in the root filesystem, which allows us to build examples that rely on it. +''', + ) + self.add_argument( + '--has-all-packages', + action='store_true', + help='''\ +Indicate that all packages from --has-package are available. ''', ) self.add_argument( @@ -138,6 +145,7 @@ Default: build all examples that have their package dependencies met, e.g.: def build(self): build_dir = self.get_build_dir() has_packages = set(self.env['has_package']) + has_all_packages = self.env['has_all_packages'] ccflags = [ '-I', self.env['root_dir'], LF, '-O0', LF, @@ -179,6 +187,10 @@ Default: build all examples that have their package dependencies met, e.g.: extra_deps=[self.env['common_h']], link=False, ) + if self.env['gcc_which'] == 'host': + eigen_root = '/' + else: + eigen_root = self.env['buildroot_staging_dir'] pkgs = { 'eigen': { # TODO: was failing with: @@ -188,7 +200,7 @@ Default: build all examples that have their package dependencies met, e.g.: 'ccflags': [ '-I', os.path.join( - self.env['buildroot_staging_dir'], + eigen_root, 'usr', 'include', 'eigen3' @@ -217,26 +229,19 @@ Default: build all examples that have their package dependencies met, e.g.: dirpath_relative_root = path_abs[rootdir_abs_len + 1:] dirpath_relative_root_components = dirpath_relative_root.split(os.sep) dirpath_relative_root_components_len = len(dirpath_relative_root_components) - do_build_dir = True - in_arch = False + out_dir = os.path.join( + build_dir, + dirpath_relative_root + ) + common_objs_dir = [common_obj] + ccflags_after = [] + ccflags_dir = ccflags.copy() if dirpath_relative_root_components_len > 0: - if dirpath_relative_root_components[0] == 'arch': - if dirpath_relative_root_components_len > 1: - if dirpath_relative_root_components[1] == self.env['arch']: - in_arch = True - else: - do_build_dir = False - else: - do_build_dir = False - in_libs = dirpath_relative_root_components[0] == 'libs' - if do_build_dir: - out_dir = os.path.join( - build_dir, - dirpath_relative_root - ) - common_objs_dir = [common_obj] - ccflags_dir = ccflags.copy() - if dirpath_relative_root_components in ('gcc', 'kernel_modules', 'linux'): + if dirpath_relative_root_components[0] in ( + 'gcc', + 'kernel_modules', + 'linux', + ): cstd = 'gnu11' cxxstd = 'gnu++17' else: @@ -244,90 +249,94 @@ Default: build all examples that have their package dependencies met, e.g.: cxxstd = self.default_cxxstd # -pedantic complains even if we use -std=gnu11. ccflags_dir.extend(['-pedantic', LF]) - if in_arch: - ccflags_dir.extend([ - '-I', os.path.join(self.env['userland_source_arch_arch_dir']), LF, - '-I', os.path.join(self.env['userland_source_arch_dir']), LF, - '-fno-pie', LF, - '-no-pie', LF, - ]) - if 'freestanding' in dirpath_relative_root_components: - common_objs_dir = [] - ccflags_dir.extend([ - '-ffreestanding', LF, - '-nostdlib', LF, - '-static', LF, - ]) - else: - if 'c' in dirpath_relative_root_components: - common_objs_dir = [] + if dirpath_relative_root_components[0] == 'arch': + if dirpath_relative_root_components_len > 1: + if dirpath_relative_root_components[1] == self.env['arch']: + ccflags_dir.extend([ + '-I', os.path.join(self.env['userland_source_arch_arch_dir']), LF, + '-I', os.path.join(self.env['userland_source_arch_dir']), LF, + '-fno-pie', LF, + '-no-pie', LF, + ]) + if 'freestanding' in dirpath_relative_root_components: + common_objs_dir = [] + ccflags_dir.extend([ + '-ffreestanding', LF, + '-nostdlib', LF, + '-static', LF, + ]) + else: + if 'c' in dirpath_relative_root_components: + common_objs_dir = [] + else: + common_objs_dir = [common_obj_asm] + if self.env['arch'] == 'arm': + ccflags_dir.extend([ + '-Xassembler', '-mcpu=cortex-a72', LF, + # To prevent: + # > vfp.S: Error: selected processor does not support in ARM mode + # https://stackoverflow.com/questions/41131432/cross-compiling-error-selected-processor-does-not-support-fmrx-r3-fpexc-in/52875732#52875732 + # We aim to take the most extended mode currently available that works on QEMU. + '-Xassembler', '-mfpu=crypto-neon-fp-armv8.1', LF, + '-Xassembler', '-meabi=5', LF, + # Treat inline assembly as arm instead of thumb + # The opposite of -mthumb. + '-marm', LF, + # Make gcc generate .syntax unified for inline assembly. + # However, it gets ignored if -marm is given, which a GCC bug that was recently fixed: + # https://stackoverflow.com/questions/54078112/how-to-write-syntax-unified-ual-armv7-inline-assembly-in-gcc/54132097#54132097 + # So we just write divided inline assembly for now. + '-masm-syntax-unified', LF, + ]) else: - common_objs_dir = [common_obj_asm] - if self.env['arch'] == 'arm': - ccflags_dir.extend([ - '-Xassembler', '-mcpu=cortex-a72', LF, - # To prevent: - # > vfp.S: Error: selected processor does not support in ARM mode - # https://stackoverflow.com/questions/41131432/cross-compiling-error-selected-processor-does-not-support-fmrx-r3-fpexc-in/52875732#52875732 - # We aim to take the most extended mode currently available that works on QEMU. - '-Xassembler', '-mfpu=crypto-neon-fp-armv8.1', LF, - '-Xassembler', '-meabi=5', LF, - # Treat inline assembly as arm instead of thumb - # The opposite of -mthumb. - '-marm', LF, - # Make gcc generate .syntax unified for inline assembly. - # However, it gets ignored if -marm is given, which a GCC bug that was recently fixed: - # https://stackoverflow.com/questions/54078112/how-to-write-syntax-unified-ual-armv7-inline-assembly-in-gcc/54132097#54132097 - # So we just write divided inline assembly for now. - '-masm-syntax-unified', LF, - ]) - for in_filename in in_filenames: - path_relative_root = os.path.join(dirpath_relative_root, in_filename) - if path_relative_root == common_obj_asm_relpath: - continue - in_path = os.path.join(path, in_filename) - in_name, in_ext = os.path.splitext(in_filename) - out_path = os.path.join( - out_dir, - in_name + self.env['userland_build_ext'] - ) - ccflags_file = ccflags_dir.copy() - ccflags_after = [] - if in_libs: - pkg_key = in_name.split('_')[0] - if pkg_key in pkgs: - if pkg_key not in has_packages: + continue + else: + continue + elif dirpath_relative_root_components[0] == 'libs': + if dirpath_relative_root_components_len > 1: + pkg_key = dirpath_relative_root_components[1] + if not (has_all_packages or pkg_key in has_packages): continue pkg = pkgs[pkg_key] if 'ccflags' in pkg: - ccflags_file.extend(pkg['ccflags']) + ccflags_dir.extend(pkg['ccflags']) else: pkg_config_output = subprocess.check_output([ - self.env['buildroot_pkg_config'], + self.env['pkg_config'], '--cflags', pkg_key ]).decode() - ccflags_file.extend(self.sh.shlex_split(pkg_config_output)) + ccflags_dir.extend(self.sh.shlex_split(pkg_config_output)) if 'ccflags_after' in pkg: - ccflags_file.extend(pkg['ccflags_after']) + ccflags_dir.extend(pkg['ccflags_after']) else: pkg_config_output = subprocess.check_output([ - self.env['buildroot_pkg_config'], + self.env['pkg_config'], '--libs', pkg_key ]).decode() ccflags_after.extend(self.sh.shlex_split(pkg_config_output)) - error = thread_pool.submit({ - 'in_path': in_path, - 'out_path': out_path, - 'ccflags': ccflags_file, - 'cstd': cstd, - 'cxxstd': cxxstd, - 'extra_objs': common_objs_dir, - 'ccflags_after': ccflags_after, - }) - if error is not None: - raise ExitLoop() + for in_filename in in_filenames: + path_relative_root = os.path.join(dirpath_relative_root, in_filename) + if path_relative_root == common_obj_asm_relpath: + continue + in_path = os.path.join(path, in_filename) + in_name, in_ext = os.path.splitext(in_filename) + out_path = os.path.join( + out_dir, + in_name + self.env['userland_build_ext'] + ) + error = thread_pool.submit({ + 'in_path': in_path, + 'out_path': out_path, + 'ccflags': ccflags_dir, + 'cstd': cstd, + 'cxxstd': cxxstd, + 'extra_objs': common_objs_dir, + 'ccflags_after': ccflags_after, + }) + if error is not None: + raise ExitLoop() except ExitLoop: pass error = thread_pool.join() diff --git a/build-userland-in-tree b/build-userland-in-tree index b3af05d..64b3daa 100755 --- a/build-userland-in-tree +++ b/build-userland-in-tree @@ -1,6 +1,7 @@ #!/usr/bin/env bash "$(git rev-parse --show-toplevel)/build-userland" \ --gcc-which host \ + --has-all-packages \ --in-tree \ --target-cwd \ "$@" \ diff --git a/common.py b/common.py index 8edd576..ec8800d 100644 --- a/common.py +++ b/common.py @@ -10,7 +10,6 @@ import imp import inspect import json import math -import multiprocessing import os import platform import re @@ -824,6 +823,7 @@ lunch aosp_{}-eng env['buildroot_toolchain_prefix'] ) env['userland_library_dir'] = env['buildroot_target_dir'] + env['pkg_config'] = env['buildroot_pkg_config'] elif env['gcc_which'] == 'crosstool-ng': env['toolchain_prefix'] = os.path.join( env['crosstool_ng_bin_dir'], @@ -837,6 +837,7 @@ lunch aosp_{}-eng env['userland_library_dir'] = '/usr/arm-linux-gnueabihf' elif env['arch'] == 'aarch64': env['userland_library_dir'] = '/usr/aarch64-linux-gnu/' + env['pkg_config'] = 'pkg-config' elif env['gcc_which'] == 'host-baremetal': if env['arch'] == 'arm': env['toolchain_prefix'] = 'arm-none-eabi' @@ -1249,7 +1250,7 @@ TODO: not yet implemented on all scripts. self.add_argument( '-j', '--nproc', - default=multiprocessing.cpu_count(), + default=len(os.sched_getaffinity(0)), type=int, help='Number of processors to use for the build.', ) diff --git a/rootfs_overlay/lkmc/README.adoc b/rootfs_overlay/README.adoc similarity index 100% rename from rootfs_overlay/lkmc/README.adoc rename to rootfs_overlay/README.adoc diff --git a/rootfs_overlay/lkmc/anonymous_inode.sh b/rootfs_overlay/lkmc/anonymous_inode.sh index 630250f..89df545 100755 --- a/rootfs_overlay/lkmc/anonymous_inode.sh +++ b/rootfs_overlay/lkmc/anonymous_inode.sh @@ -1,5 +1,6 @@ #!/bin/sh +# https://github.com/cirosantilli/linux-kernel-module-cheat#anonymous-inode set -e insmod anonymous_inode.ko -[ "$(/anonymous_inode.out /sys/kernel/debug/lkmc_anonymous_inode 3)" = "$(printf '1\n10\n100')" ] +[ "$(./kernel_modules/anonymous_inode.out /sys/kernel/debug/lkmc_anonymous_inode 3)" = "$(printf '1\n10\n100')" ] rmmod anonymous_inode diff --git a/rootfs_overlay/lkmc/ioctl.sh b/rootfs_overlay/lkmc/ioctl.sh index 095b9ed..e5eaf30 100755 --- a/rootfs_overlay/lkmc/ioctl.sh +++ b/rootfs_overlay/lkmc/ioctl.sh @@ -1,7 +1,8 @@ #!/bin/sh +# https://github.com/cirosantilli/linux-kernel-module-cheat#ioctl set -e f=/sys/kernel/debug/lkmc_ioctl insmod ioctl.ko -[ "$(/ioctl.out "$f" 0 1)" = 2 ] -[ "$(/ioctl.out "$f" 1 1 1)" = '2 0' ] +[ "$(./kernel_modules/ioctl.out "$f" 0 1)" = 2 ] +[ "$(./kernel_modules/ioctl.out "$f" 1 1 1)" = '2 0' ] rmmod ioctl diff --git a/rootfs_overlay/lkmc/netlink.sh b/rootfs_overlay/lkmc/netlink.sh index 0698d79..58dc14d 100755 --- a/rootfs_overlay/lkmc/netlink.sh +++ b/rootfs_overlay/lkmc/netlink.sh @@ -1,7 +1,8 @@ #!/bin/sh +# https://github.com/cirosantilli/linux-kernel-module-cheat#netlink-sockets set -e insmod netlink.ko -[ "$(/netlink.out)" = 0 ] -[ "$(/netlink.out)" = 1 ] -[ "$(/netlink.out)" = 2 ] +[ "$(./linux/netlink.out)" = 0 ] +[ "$(./linux/netlink.out)" = 1 ] +[ "$(./linux/netlink.out)" = 2 ] rmmod netlink diff --git a/rootfs_overlay/lkmc/poll.sh b/rootfs_overlay/lkmc/poll.sh index d7586b4..b19363b 100755 --- a/rootfs_overlay/lkmc/poll.sh +++ b/rootfs_overlay/lkmc/poll.sh @@ -1,5 +1,6 @@ #!/bin/sh +# https://github.com/cirosantilli/linux-kernel-module-cheat#poll set -e insmod poll.ko -./poll.out /sys/kernel/debug/lkmc_poll +./kernel_modules/poll.out /sys/kernel/debug/lkmc_poll #rmmod poll diff --git a/rootfs_overlay/lkmc/uio_read.sh b/rootfs_overlay/lkmc/uio_read.sh index 499b874..b68a51b 100755 --- a/rootfs_overlay/lkmc/uio_read.sh +++ b/rootfs_overlay/lkmc/uio_read.sh @@ -4,7 +4,7 @@ set -e modprobe uio_pci_generic # pci_min device echo '1234 11e9' > /sys/bus/pci/drivers/uio_pci_generic/new_id -./uio_read.out & +./kernel_modules/uio_read.out & # Helper to observe interrupts. insmod irq.ko base="$(setpci -d 1234:11e9 BASE_ADDRESS_0)" diff --git a/thread_pool.py b/thread_pool.py index 2f4ba25..c88240d 100644 --- a/thread_pool.py +++ b/thread_pool.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 from typing import Any, Callable, Dict, Iterable, Union -import multiprocessing import queue import sys import threading @@ -66,7 +65,7 @@ class ThreadPool: handle_output = lambda input, output, exception: exception self.handle_output = handle_output if nthreads is None: - nthreads = multiprocessing.cpu_count() + nthreads = len(os.sched_getaffinity(0)) self.nthreads = nthreads self.error_output = None self.error_output_lock = threading.Lock() diff --git a/userland/anonymous_inode.c b/userland/anonymous_inode.c deleted file mode 100644 index 7049e36..0000000 --- a/userland/anonymous_inode.c +++ /dev/null @@ -1,46 +0,0 @@ -/* https://github.com/cirosantilli/linux-kernel-module-cheat#anonymous-inode */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include /* sleep */ - -#include "../include/anonymous_inode.h" - -int main(int argc, char **argv) -{ - char buf[1024]; - int fd_ioctl, fd_ioctl_anon, ret; - size_t i, nreads; - - if (argc < 2) { - puts("Usage: ./prog []"); - return EXIT_FAILURE; - } else if (argc > 2) { - nreads = strtol(argv[2], NULL, 10); - } else { - nreads = 3; - } - fd_ioctl = open(argv[1], O_RDONLY); - if (fd_ioctl == -1) { - perror("open"); - return EXIT_FAILURE; - } - ret = ioctl(fd_ioctl, LKMC_ANONYMOUS_INODE_GET_FD, &fd_ioctl_anon); - if (ret == -1) { - perror("ioctl"); - return EXIT_FAILURE; - } - for (i = 0; i < nreads; ++i) { - ret = read(fd_ioctl_anon, buf, sizeof(buf)); - printf("%.*s\n", ret, buf); - } - close(fd_ioctl_anon); - close(fd_ioctl); - return EXIT_SUCCESS; -} diff --git a/userland/arch/aarch64/common_arch.h b/userland/arch/aarch64/common_arch.h index 83151ff..f14d96e 100644 --- a/userland/arch/aarch64/common_arch.h +++ b/userland/arch/aarch64/common_arch.h @@ -5,13 +5,13 @@ #define ASSERT_EQ(reg, const) \ ldr x11, =const; \ - cmp reg, x11; \ - ASSERT(beq); \ + cmp reg, x11; \ + ASSERT(beq); \ ; #define ASSERT_MEMCMP(s1, s2, n) \ - MEMCMP(s1, s2, n); \ - ASSERT_EQ(x0, 0); \ + MEMCMP(s1, s2, n); \ + ASSERT_EQ(x0, 0); \ ; #define ENTRY \ diff --git a/userland/arch/arm/common_arch.h b/userland/arch/arm/common_arch.h index 6d0aacc..e019916 100644 --- a/userland/arch/arm/common_arch.h +++ b/userland/arch/arm/common_arch.h @@ -12,14 +12,14 @@ */ #define ASSERT_EQ(reg, const) \ ldr r11, =const; \ - cmp reg, r11; \ - ASSERT(beq); \ + cmp reg, r11; \ + ASSERT(beq); \ ; /* Assert that two arrays are the same. */ #define ASSERT_MEMCMP(s1, s2, n) \ - MEMCMP(s1, s2, n); \ - ASSERT_EQ(r0, 0); \ + MEMCMP(s1, s2, n); \ + ASSERT_EQ(r0, 0); \ ; /* Store all callee saved registers, and LR in case we make further BL calls. diff --git a/userland/arch/common.h b/userland/arch/common.h index 3355941..2ad672e 100644 --- a/userland/arch/common.h +++ b/userland/arch/common.h @@ -23,8 +23,8 @@ /* Assert that a register equals another register. */ #define ASSERT_EQ_REG(reg1, reg2) \ - cmp reg1, reg2; \ - ASSERT(beq); \ + cmp reg1, reg2; \ + ASSERT(beq); \ ; #endif diff --git a/userland/arch/x86_64/c/binutils_hack.c b/userland/arch/x86_64/c/binutils_hack.c index 6871f68..1432167 100644 --- a/userland/arch/x86_64/c/binutils_hack.c +++ b/userland/arch/x86_64/c/binutils_hack.c @@ -5,16 +5,16 @@ int main(void) { #if 0 - uint64_t in = 0xFFFFFFFF; - uint64_t out = 0; - __asm__ ( - "mov %[in], %%rax;" - "myinc %%rax;" - "movq %%rax, %[out]" - : [out] "=g" (out) - : [in] "g" (in) - : "rax" - ); - assert(out == in + 1); + uint64_t in = 0xFFFFFFFF; + uint64_t out = 0; + __asm__ ( + "mov %[in], %%rax;" + "myinc %%rax;" + "movq %%rax, %[out]" + : [out] "=g" (out) + : [in] "g" (in) + : "rax" + ); + assert(out == in + 1); #endif } diff --git a/userland/arch/x86_64/c/binutils_nohack.c b/userland/arch/x86_64/c/binutils_nohack.c index efa3249..892d20a 100644 --- a/userland/arch/x86_64/c/binutils_nohack.c +++ b/userland/arch/x86_64/c/binutils_nohack.c @@ -4,15 +4,15 @@ #include int main(void) { - uint64_t in = 0xFFFFFFFF; - uint64_t out = 0; - __asm__ ( - "mov %[in], %%rax;" - "inc %%rax;" - "movq %%rax, %[out]" - : [out] "=g" (out) - : [in] "g" (in) - : "rax" - ); - assert(out == in + 1); + uint64_t in = 0xFFFFFFFF; + uint64_t out = 0; + __asm__ ( + "mov %[in], %%rax;" + "inc %%rax;" + "movq %%rax, %[out]" + : [out] "=g" (out) + : [in] "g" (in) + : "rax" + ); + assert(out == in + 1); } diff --git a/userland/bst_vs_heap.cpp b/userland/bst_vs_heap.cpp index 2020714..29b0f11 100644 --- a/userland/bst_vs_heap.cpp +++ b/userland/bst_vs_heap.cpp @@ -29,16 +29,16 @@ int main(int argc, char **argv) { } std::shuffle(randoms.begin(), randoms.end(), std::mt19937(seed)); for (i = 0; i < n; ++i) { - auto random = randoms[i]; + auto random = randoms[i]; // Heap. - m5_resetstats(); - heap.emplace(random); - m5_dumpstats(); + m5_resetstats(); + heap.emplace(random); + m5_dumpstats(); // BST. - m5_resetstats(); - bst.insert(random); - m5_dumpstats(); + m5_resetstats(); + bst.insert(random); + m5_dumpstats(); } } diff --git a/userland/c/false.c b/userland/c/false.c index 8d481d9..0480f17 100644 --- a/userland/c/false.c +++ b/userland/c/false.c @@ -13,5 +13,5 @@ int main(int argc, char **argv) { } else { ret = strtoull(argv[1], NULL, 0); } - return ret; + return ret; } diff --git a/userland/c/hello.c b/userland/c/hello.c index 81f6976..3b0fee6 100644 --- a/userland/c/hello.c +++ b/userland/c/hello.c @@ -4,6 +4,6 @@ #include int main(void) { - puts("hello"); - return EXIT_SUCCESS; + puts("hello"); + return EXIT_SUCCESS; } diff --git a/userland/c/print_argv.c b/userland/c/print_argv.c new file mode 100644 index 0000000..6984aeb --- /dev/null +++ b/userland/c/print_argv.c @@ -0,0 +1,14 @@ +/* Print each command line argument received, one per line. + * + * Good sanity check for user mode: + * https://github.com/cirosantilli/linux-kernel-module-cheat#qemu-user-mode-getting-started + */ + +#include + +int main(int argc, char **argv) { + size_t i; + for (i = 0; i < (size_t)argc; ++i) + printf("%s\n", argv[i]); + return 0; +} diff --git a/userland/common.h b/userland/common.h index fbee7f4..3abd606 100644 --- a/userland/common.h +++ b/userland/common.h @@ -26,8 +26,7 @@ typedef struct { * @param[in] vaddr virtual address to get entry for * @return 0 for success, 1 for failure */ -int pagemap_get_entry(PagemapEntry *entry, int pagemap_fd, uintptr_t vaddr) -{ +int pagemap_get_entry(PagemapEntry *entry, int pagemap_fd, uintptr_t vaddr) { size_t nread; ssize_t ret; uint64_t data; @@ -62,8 +61,7 @@ int pagemap_get_entry(PagemapEntry *entry, int pagemap_fd, uintptr_t vaddr) * @param[in] vaddr virtual address to get entry for * @return 0 for success, 1 for failure */ -int virt_to_phys_user(uintptr_t *paddr, pid_t pid, uintptr_t vaddr) -{ +int virt_to_phys_user(uintptr_t *paddr, pid_t pid, uintptr_t vaddr) { char pagemap_file[BUFSIZ]; int pagemap_fd; diff --git a/userland/init_env_poweroff.c b/userland/init_env_poweroff.c deleted file mode 100644 index dc275f9..0000000 --- a/userland/init_env_poweroff.c +++ /dev/null @@ -1,26 +0,0 @@ -#define _XOPEN_SOURCE 700 -#include -#include -#include - -int main(int argc, char **argv) -{ - int i; - - puts("args:"); - for (i = 0; i < argc; ++i) - puts(argv[i]); - puts(""); - - puts("env:"); - extern char **environ; - char **env = environ; - while (*env) { - printf("%s\n", *env); - env++; - } - puts(""); - - /* Poweroff. */ - reboot(RB_POWER_OFF); -} diff --git a/userland/ioctl.c b/userland/ioctl.c deleted file mode 100644 index 7c0a811..0000000 --- a/userland/ioctl.c +++ /dev/null @@ -1,67 +0,0 @@ -/* https://github.com/cirosantilli/linux-kernel-module-cheat#ioctl */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../include/ioctl.h" - -int main(int argc, char **argv) -{ - char *ioctl_path; - int fd, request, arg0, arg1, arg_int, ret; - lkmc_ioctl_struct arg_struct; - - if (argc < 2) { - puts("Usage: ./prog [...]"); - return EXIT_FAILURE; - } - ioctl_path = argv[1]; - request = strtol(argv[2], NULL, 10); - if (argc > 3) { - arg0 = strtol(argv[3], NULL, 10); - } - if (argc > 4) { - arg1 = strtol(argv[4], NULL, 10); - } - - fd = open(ioctl_path, O_RDONLY); - if (fd == -1) { - perror("open"); - return EXIT_FAILURE; - } - switch (request) - { - case 0: - arg_int = arg0; - ret = ioctl(fd, LKMC_IOCTL_INC, &arg_int); - if (ret != -1) { - printf("%d\n", arg_int); - } - break; - case 1: - arg_struct.i = arg0; - arg_struct.j = arg1; - ret = ioctl(fd, LKMC_IOCTL_INC_DEC, &arg_struct); - if (ret != -1) { - printf("%d %d\n", arg_struct.i, arg_struct.j); - } - break; - default: - puts("error: unknown request"); - return EXIT_FAILURE; - } - if (ret == -1) { - perror("ioctl"); - printf("errno = %d\n", errno); - return EXIT_FAILURE; - } - close(fd); - return EXIT_SUCCESS; -} diff --git a/userland/kernel_modules/anonymous_inode.c b/userland/kernel_modules/anonymous_inode.c new file mode 100644 index 0000000..3e0d246 --- /dev/null +++ b/userland/kernel_modules/anonymous_inode.c @@ -0,0 +1,45 @@ +/* https://github.com/cirosantilli/linux-kernel-module-cheat#anonymous-inode */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include /* sleep */ + +#include + +int main(int argc, char **argv) { + char buf[1024]; + int fd_ioctl, fd_ioctl_anon, ret; + size_t i, nreads; + + if (argc < 2) { + puts("Usage: ./prog []"); + return EXIT_FAILURE; + } else if (argc > 2) { + nreads = strtol(argv[2], NULL, 10); + } else { + nreads = 3; + } + fd_ioctl = open(argv[1], O_RDONLY); + if (fd_ioctl == -1) { + perror("open"); + return EXIT_FAILURE; + } + ret = ioctl(fd_ioctl, LKMC_ANONYMOUS_INODE_GET_FD, &fd_ioctl_anon); + if (ret == -1) { + perror("ioctl"); + return EXIT_FAILURE; + } + for (i = 0; i < nreads; ++i) { + ret = read(fd_ioctl_anon, buf, sizeof(buf)); + printf("%.*s\n", ret, buf); + } + close(fd_ioctl_anon); + close(fd_ioctl); + return EXIT_SUCCESS; +} diff --git a/userland/kernel_modules/ioctl.c b/userland/kernel_modules/ioctl.c new file mode 100644 index 0000000..660e873 --- /dev/null +++ b/userland/kernel_modules/ioctl.c @@ -0,0 +1,66 @@ +/* https://github.com/cirosantilli/linux-kernel-module-cheat#ioctl */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +int main(int argc, char **argv) { + char *ioctl_path; + int fd, request, arg0, arg1, arg_int, ret; + lkmc_ioctl_struct arg_struct; + + if (argc < 2) { + puts("Usage: ./prog [...]"); + return EXIT_FAILURE; + } + ioctl_path = argv[1]; + request = strtol(argv[2], NULL, 10); + if (argc > 3) { + arg0 = strtol(argv[3], NULL, 10); + } + if (argc > 4) { + arg1 = strtol(argv[4], NULL, 10); + } + + fd = open(ioctl_path, O_RDONLY); + if (fd == -1) { + perror("open"); + return EXIT_FAILURE; + } + switch (request) + { + case 0: + arg_int = arg0; + ret = ioctl(fd, LKMC_IOCTL_INC, &arg_int); + if (ret != -1) { + printf("%d\n", arg_int); + } + break; + case 1: + arg_struct.i = arg0; + arg_struct.j = arg1; + ret = ioctl(fd, LKMC_IOCTL_INC_DEC, &arg_struct); + if (ret != -1) { + printf("%d %d\n", arg_struct.i, arg_struct.j); + } + break; + default: + puts("error: unknown request"); + return EXIT_FAILURE; + } + if (ret == -1) { + perror("ioctl"); + printf("errno = %d\n", errno); + return EXIT_FAILURE; + } + close(fd); + return EXIT_SUCCESS; +} diff --git a/userland/netlink.c b/userland/kernel_modules/netlink.c similarity index 97% rename from userland/netlink.c rename to userland/kernel_modules/netlink.c index fa37cfb..12912c0 100644 --- a/userland/netlink.c +++ b/userland/kernel_modules/netlink.c @@ -7,7 +7,7 @@ #include #include -#include "../include/netlink.h" +#include #define MAX_PAYLOAD 1024 diff --git a/userland/kernel_modules/poll.c b/userland/kernel_modules/poll.c new file mode 100644 index 0000000..491c4d5 --- /dev/null +++ b/userland/kernel_modules/poll.c @@ -0,0 +1,41 @@ +/* https://github.com/cirosantilli/linux-kernel-module-cheat#poll */ + +#define _XOPEN_SOURCE 700 +#include +#include /* creat, O_CREAT */ +#include /* poll */ +#include /* printf, puts, snprintf */ +#include /* EXIT_FAILURE, EXIT_SUCCESS */ +#include /* read */ + +int main(int argc, char **argv) { + char buf[1024]; + int fd, i, n; + short revents; + struct pollfd pfd; + + if (argc < 2) { + fprintf(stderr, "usage: %s \n", argv[0]); + exit(EXIT_FAILURE); + } + fd = open(argv[1], O_RDONLY | O_NONBLOCK); + if (fd == -1) { + perror("open"); + exit(EXIT_FAILURE); + } + pfd.fd = fd; + pfd.events = POLLIN; + while (1) { + puts("loop"); + i = poll(&pfd, 1, -1); + if (i == -1) { + perror("poll"); + assert(0); + } + revents = pfd.revents; + if (revents & POLLIN) { + n = read(pfd.fd, buf, sizeof(buf)); + printf("POLLIN n=%d buf=%.*s\n", n, n, buf); + } + } +} diff --git a/userland/uio_read.c b/userland/kernel_modules/uio_read.c similarity index 89% rename from userland/uio_read.c rename to userland/kernel_modules/uio_read.c index 6a272f1..f246861 100644 --- a/userland/uio_read.c +++ b/userland/kernel_modules/uio_read.c @@ -16,8 +16,7 @@ #include #include -int main(int argc, char **argv) -{ +int main(int argc, char **argv) { char *dev = "/dev/uio0"; if (argc > 1) { dev = argv[1]; @@ -30,12 +29,14 @@ int main(int argc, char **argv) } /* TODO not supported by this kernel module? */ - /*int *addr = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);*/ - /*if (addr == MAP_FAILED) {*/ - /*perror("mmap");*/ - /*assert(0);*/ - /*}*/ - /**addr = 0x12345678;*/ +#if 0 + int *addr = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (addr == MAP_FAILED) { + perror("mmap"); + assert(0); + } + *addr = 0x12345678; +#endif while (1) { uint32_t info = 1; @@ -66,8 +67,7 @@ int main(int argc, char **argv) #include #include -int main(void) -{ +int main(void) { int uiofd; int configfd; int err; diff --git a/userland/libs/eigen/build b/userland/libs/eigen/build new file mode 120000 index 0000000..ab18017 --- /dev/null +++ b/userland/libs/eigen/build @@ -0,0 +1 @@ +../build \ No newline at end of file diff --git a/userland/libs/eigen_hello.cpp b/userland/libs/eigen/hello.cpp similarity index 57% rename from userland/libs/eigen_hello.cpp rename to userland/libs/eigen/hello.cpp index ee79d86..dc29adc 100644 --- a/userland/libs/eigen_hello.cpp +++ b/userland/libs/eigen/hello.cpp @@ -1,13 +1,16 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#eigen * Adapted from: https://eigen.tuxfamily.org/dox/GettingStarted.html */ + #include + #include + int main() { - Eigen::MatrixXd m(2,2); - m(0,0) = 3; - m(1,0) = 2.5; - m(0,1) = -1; - m(1,1) = m(1,0) + m(0,1); - std::cout << m << std::endl; + Eigen::MatrixXd m(2,2); + m(0,0) = 3; + m(1,0) = 2.5; + m(0,1) = -1; + m(1,1) = m(1,0) + m(0,1); + std::cout << m << std::endl; } diff --git a/userland/libs/libdrm/build b/userland/libs/libdrm/build new file mode 120000 index 0000000..ab18017 --- /dev/null +++ b/userland/libs/libdrm/build @@ -0,0 +1 @@ +../build \ No newline at end of file diff --git a/userland/libs/libdrm_modeset.c b/userland/libs/libdrm/modeset.c similarity index 59% rename from userland/libs/libdrm_modeset.c rename to userland/libs/libdrm/modeset.c index 69e61eb..ca54f29 100644 --- a/userland/libs/libdrm_modeset.c +++ b/userland/libs/libdrm/modeset.c @@ -45,10 +45,10 @@ struct modeset_dev; static int modeset_find_crtc(int fd, drmModeRes *res, drmModeConnector *conn, - struct modeset_dev *dev); + struct modeset_dev *dev); static int modeset_create_fb(int fd, struct modeset_dev *dev); static int modeset_setup_dev(int fd, drmModeRes *res, drmModeConnector *conn, - struct modeset_dev *dev); + struct modeset_dev *dev); static int modeset_open(int *out, const char *node); static int modeset_prepare(int fd); static void modeset_draw(void); @@ -81,26 +81,26 @@ static void modeset_cleanup(int fd); static int modeset_open(int *out, const char *node) { - int fd, ret; - uint64_t has_dumb; + int fd, ret; + uint64_t has_dumb; - fd = open(node, O_RDWR | O_CLOEXEC); - if (fd < 0) { - ret = -errno; - fprintf(stderr, "cannot open '%s': %m\n", node); - return ret; - } + fd = open(node, O_RDWR | O_CLOEXEC); + if (fd < 0) { + ret = -errno; + fprintf(stderr, "cannot open '%s': %s\n", node, strerror(errno)); + return ret; + } - if (drmGetCap(fd, DRM_CAP_DUMB_BUFFER, &has_dumb) < 0 || - !has_dumb) { - fprintf(stderr, "drm device '%s' does not support dumb buffers\n", - node); - close(fd); - return -EOPNOTSUPP; - } + if (drmGetCap(fd, DRM_CAP_DUMB_BUFFER, &has_dumb) < 0 || + !has_dumb) { + fprintf(stderr, "drm device '%s' does not support dumb buffers\n", + node); + close(fd); + return -EOPNOTSUPP; + } - *out = fd; - return 0; + *out = fd; + return 0; } /* @@ -149,20 +149,20 @@ static int modeset_open(int *out, const char *node) */ struct modeset_dev { - struct modeset_dev *next; + struct modeset_dev *next; - uint32_t width; - uint32_t height; - uint32_t stride; - uint32_t size; - uint32_t handle; - uint8_t *map; + uint32_t width; + uint32_t height; + uint32_t stride; + uint32_t size; + uint32_t handle; + uint8_t *map; - drmModeModeInfo mode; - uint32_t fb; - uint32_t conn; - uint32_t crtc; - drmModeCrtc *saved_crtc; + drmModeModeInfo mode; + uint32_t fb; + uint32_t conn; + uint32_t crtc; + drmModeCrtc *saved_crtc; }; static struct modeset_dev *modeset_list = NULL; @@ -188,57 +188,57 @@ static struct modeset_dev *modeset_list = NULL; static int modeset_prepare(int fd) { - drmModeRes *res; - drmModeConnector *conn; - unsigned int i; - struct modeset_dev *dev; - int ret; + drmModeRes *res; + drmModeConnector *conn; + unsigned int i; + struct modeset_dev *dev; + int ret; - /* retrieve resources */ - res = drmModeGetResources(fd); - if (!res) { - fprintf(stderr, "cannot retrieve DRM resources (%d): %m\n", - errno); - return -errno; - } + /* retrieve resources */ + res = drmModeGetResources(fd); + if (!res) { + fprintf(stderr, "cannot retrieve DRM resources (%d): %s\n", + errno, strerror(errno)); + return -errno; + } - /* iterate all connectors */ - for (i = 0; i < (unsigned int)res->count_connectors; ++i) { - /* get information for each connector */ - conn = drmModeGetConnector(fd, res->connectors[i]); - if (!conn) { - fprintf(stderr, "cannot retrieve DRM connector %u:%u (%d): %m\n", - i, res->connectors[i], errno); - continue; - } + /* iterate all connectors */ + for (i = 0; i < (unsigned int)res->count_connectors; ++i) { + /* get information for each connector */ + conn = drmModeGetConnector(fd, res->connectors[i]); + if (!conn) { + fprintf(stderr, "cannot retrieve DRM connector %u:%u (%d): %s\n", + i, res->connectors[i], errno, strerror(errno)); + continue; + } - /* create a device structure */ - dev = malloc(sizeof(*dev)); - memset(dev, 0, sizeof(*dev)); - dev->conn = conn->connector_id; + /* create a device structure */ + dev = malloc(sizeof(*dev)); + memset(dev, 0, sizeof(*dev)); + dev->conn = conn->connector_id; - /* call helper function to prepare this connector */ - ret = modeset_setup_dev(fd, res, conn, dev); - if (ret) { - if (ret != -ENOENT) { - errno = -ret; - fprintf(stderr, "cannot setup device for connector %u:%u (%d): %m\n", - i, res->connectors[i], errno); - } - free(dev); - drmModeFreeConnector(conn); - continue; - } + /* call helper function to prepare this connector */ + ret = modeset_setup_dev(fd, res, conn, dev); + if (ret) { + if (ret != -ENOENT) { + errno = -ret; + fprintf(stderr, "cannot setup device for connector %u:%u (%d): %s\n", + i, res->connectors[i], errno, strerror(errno)); + } + free(dev); + drmModeFreeConnector(conn); + continue; + } - /* free connector data and link device into global list */ - drmModeFreeConnector(conn); - dev->next = modeset_list; - modeset_list = dev; - } + /* free connector data and link device into global list */ + drmModeFreeConnector(conn); + dev->next = modeset_list; + modeset_list = dev; + } - /* free resources again */ - drmModeFreeResources(res); - return 0; + /* free resources again */ + drmModeFreeResources(res); + return 0; } /* @@ -271,48 +271,48 @@ static int modeset_prepare(int fd) */ static int modeset_setup_dev(int fd, drmModeRes *res, drmModeConnector *conn, - struct modeset_dev *dev) + struct modeset_dev *dev) { - int ret; + int ret; - /* check if a monitor is connected */ - if (conn->connection != DRM_MODE_CONNECTED) { - fprintf(stderr, "ignoring unused connector %u\n", - conn->connector_id); - return -ENOENT; - } + /* check if a monitor is connected */ + if (conn->connection != DRM_MODE_CONNECTED) { + fprintf(stderr, "ignoring unused connector %u\n", + conn->connector_id); + return -ENOENT; + } - /* check if there is at least one valid mode */ - if (conn->count_modes == 0) { - fprintf(stderr, "no valid mode for connector %u\n", - conn->connector_id); - return -EFAULT; - } + /* check if there is at least one valid mode */ + if (conn->count_modes == 0) { + fprintf(stderr, "no valid mode for connector %u\n", + conn->connector_id); + return -EFAULT; + } - /* copy the mode information into our device structure */ - memcpy(&dev->mode, &conn->modes[0], sizeof(dev->mode)); - dev->width = conn->modes[0].hdisplay; - dev->height = conn->modes[0].vdisplay; - fprintf(stderr, "mode for connector %u is %ux%u\n", - conn->connector_id, dev->width, dev->height); + /* copy the mode information into our device structure */ + memcpy(&dev->mode, &conn->modes[0], sizeof(dev->mode)); + dev->width = conn->modes[0].hdisplay; + dev->height = conn->modes[0].vdisplay; + fprintf(stderr, "mode for connector %u is %ux%u\n", + conn->connector_id, dev->width, dev->height); - /* find a crtc for this connector */ - ret = modeset_find_crtc(fd, res, conn, dev); - if (ret) { - fprintf(stderr, "no valid crtc for connector %u\n", - conn->connector_id); - return ret; - } + /* find a crtc for this connector */ + ret = modeset_find_crtc(fd, res, conn, dev); + if (ret) { + fprintf(stderr, "no valid crtc for connector %u\n", + conn->connector_id); + return ret; + } - /* create a framebuffer for this CRTC */ - ret = modeset_create_fb(fd, dev); - if (ret) { - fprintf(stderr, "cannot create framebuffer for connector %u\n", - conn->connector_id); - return ret; - } + /* create a framebuffer for this CRTC */ + ret = modeset_create_fb(fd, dev); + if (ret) { + fprintf(stderr, "cannot create framebuffer for connector %u\n", + conn->connector_id); + return ret; + } - return 0; + return 0; } /* @@ -338,80 +338,80 @@ static int modeset_setup_dev(int fd, drmModeRes *res, drmModeConnector *conn, */ static int modeset_find_crtc(int fd, drmModeRes *res, drmModeConnector *conn, - struct modeset_dev *dev) + struct modeset_dev *dev) { - drmModeEncoder *enc; - unsigned int i, j; - int32_t crtc; - struct modeset_dev *iter; + drmModeEncoder *enc; + unsigned int i, j; + int32_t crtc; + struct modeset_dev *iter; - /* first try the currently conected encoder+crtc */ - if (conn->encoder_id) - enc = drmModeGetEncoder(fd, conn->encoder_id); - else - enc = NULL; + /* first try the currently conected encoder+crtc */ + if (conn->encoder_id) + enc = drmModeGetEncoder(fd, conn->encoder_id); + else + enc = NULL; - if (enc) { - if (enc->crtc_id) { - crtc = enc->crtc_id; - for (iter = modeset_list; iter; iter = iter->next) { - if ((int32_t)iter->crtc == crtc) { - crtc = -1; - break; - } - } + if (enc) { + if (enc->crtc_id) { + crtc = enc->crtc_id; + for (iter = modeset_list; iter; iter = iter->next) { + if ((int32_t)iter->crtc == crtc) { + crtc = -1; + break; + } + } - if (crtc >= 0) { - drmModeFreeEncoder(enc); - dev->crtc = crtc; - return 0; - } - } + if (crtc >= 0) { + drmModeFreeEncoder(enc); + dev->crtc = crtc; + return 0; + } + } - drmModeFreeEncoder(enc); - } + drmModeFreeEncoder(enc); + } - /* If the connector is not currently bound to an encoder or if the - * encoder+crtc is already used by another connector (actually unlikely - * but lets be safe), iterate all other available encoders to find a - * matching CRTC. */ - for (i = 0; i < (unsigned int)conn->count_encoders; ++i) { - enc = drmModeGetEncoder(fd, conn->encoders[i]); - if (!enc) { - fprintf(stderr, "cannot retrieve encoder %u:%u (%d): %m\n", - i, conn->encoders[i], errno); - continue; - } + /* If the connector is not currently bound to an encoder or if the + * encoder+crtc is already used by another connector (actually unlikely + * but lets be safe), iterate all other available encoders to find a + * matching CRTC. */ + for (i = 0; i < (unsigned int)conn->count_encoders; ++i) { + enc = drmModeGetEncoder(fd, conn->encoders[i]); + if (!enc) { + fprintf(stderr, "cannot retrieve encoder %u:%u (%d): %s\n", + i, conn->encoders[i], errno, strerror(errno)); + continue; + } - /* iterate all global CRTCs */ - for (j = 0; j < (unsigned int)res->count_crtcs; ++j) { - /* check whether this CRTC works with the encoder */ - if (!(enc->possible_crtcs & (1 << j))) - continue; + /* iterate all global CRTCs */ + for (j = 0; j < (unsigned int)res->count_crtcs; ++j) { + /* check whether this CRTC works with the encoder */ + if (!(enc->possible_crtcs & (1 << j))) + continue; - /* check that no other device already uses this CRTC */ - crtc = res->crtcs[j]; - for (iter = modeset_list; iter; iter = iter->next) { - if ((int32_t)iter->crtc == crtc) { - crtc = -1; - break; - } - } + /* check that no other device already uses this CRTC */ + crtc = res->crtcs[j]; + for (iter = modeset_list; iter; iter = iter->next) { + if ((int32_t)iter->crtc == crtc) { + crtc = -1; + break; + } + } - /* we have found a CRTC, so save it and return */ - if (crtc >= 0) { - drmModeFreeEncoder(enc); - dev->crtc = crtc; - return 0; - } - } + /* we have found a CRTC, so save it and return */ + if (crtc >= 0) { + drmModeFreeEncoder(enc); + dev->crtc = crtc; + return 0; + } + } - drmModeFreeEncoder(enc); - } + drmModeFreeEncoder(enc); + } - fprintf(stderr, "cannot find suitable CRTC for connector %u\n", - conn->connector_id); - return -ENOENT; + fprintf(stderr, "cannot find suitable CRTC for connector %u\n", + conn->connector_id); + return -ENOENT; } /* @@ -441,69 +441,69 @@ static int modeset_find_crtc(int fd, drmModeRes *res, drmModeConnector *conn, static int modeset_create_fb(int fd, struct modeset_dev *dev) { - struct drm_mode_create_dumb creq; - struct drm_mode_destroy_dumb dreq; - struct drm_mode_map_dumb mreq; - int ret; + struct drm_mode_create_dumb creq; + struct drm_mode_destroy_dumb dreq; + struct drm_mode_map_dumb mreq; + int ret; - /* create dumb buffer */ - memset(&creq, 0, sizeof(creq)); - creq.width = dev->width; - creq.height = dev->height; - creq.bpp = 32; - ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq); - if (ret < 0) { - fprintf(stderr, "cannot create dumb buffer (%d): %m\n", - errno); - return -errno; - } - dev->stride = creq.pitch; - dev->size = creq.size; - dev->handle = creq.handle; + /* create dumb buffer */ + memset(&creq, 0, sizeof(creq)); + creq.width = dev->width; + creq.height = dev->height; + creq.bpp = 32; + ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq); + if (ret < 0) { + fprintf(stderr, "cannot create dumb buffer (%d): %s\n", + errno, strerror(errno)); + return -errno; + } + dev->stride = creq.pitch; + dev->size = creq.size; + dev->handle = creq.handle; - /* create framebuffer object for the dumb-buffer */ - ret = drmModeAddFB(fd, dev->width, dev->height, 24, 32, dev->stride, - dev->handle, &dev->fb); - if (ret) { - fprintf(stderr, "cannot create framebuffer (%d): %m\n", - errno); - ret = -errno; - goto err_destroy; - } + /* create framebuffer object for the dumb-buffer */ + ret = drmModeAddFB(fd, dev->width, dev->height, 24, 32, dev->stride, + dev->handle, &dev->fb); + if (ret) { + fprintf(stderr, "cannot create framebuffer (%d): %s\n", + errno, strerror(errno)); + ret = -errno; + goto err_destroy; + } - /* prepare buffer for memory mapping */ - memset(&mreq, 0, sizeof(mreq)); - mreq.handle = dev->handle; - ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq); - if (ret) { - fprintf(stderr, "cannot map dumb buffer (%d): %m\n", - errno); - ret = -errno; - goto err_fb; - } + /* prepare buffer for memory mapping */ + memset(&mreq, 0, sizeof(mreq)); + mreq.handle = dev->handle; + ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq); + if (ret) { + fprintf(stderr, "cannot map dumb buffer (%d): %s\n", + errno, strerror(errno)); + ret = -errno; + goto err_fb; + } - /* perform actual memory mapping */ - dev->map = mmap(0, dev->size, PROT_READ | PROT_WRITE, MAP_SHARED, - fd, mreq.offset); - if (dev->map == MAP_FAILED) { - fprintf(stderr, "cannot mmap dumb buffer (%d): %m\n", - errno); - ret = -errno; - goto err_fb; - } + /* perform actual memory mapping */ + dev->map = mmap(0, dev->size, PROT_READ | PROT_WRITE, MAP_SHARED, + fd, mreq.offset); + if (dev->map == MAP_FAILED) { + fprintf(stderr, "cannot mmap dumb buffer (%d): %s\n", + errno, strerror(errno)); + ret = -errno; + goto err_fb; + } - /* clear the framebuffer to 0 */ - memset(dev->map, 0, dev->size); + /* clear the framebuffer to 0 */ + memset(dev->map, 0, dev->size); - return 0; + return 0; err_fb: - drmModeRmFB(fd, dev->fb); + drmModeRmFB(fd, dev->fb); err_destroy: - memset(&dreq, 0, sizeof(dreq)); - dreq.handle = dev->handle; - drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq); - return ret; + memset(&dreq, 0, sizeof(dreq)); + dreq.handle = dev->handle; + drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq); + return ret; } /* @@ -543,56 +543,56 @@ err_destroy: int main(int argc, char **argv) { - int ret, fd; - const char *card; - struct modeset_dev *iter; + int ret, fd; + const char *card; + struct modeset_dev *iter; - /* check which DRM device to open */ - if (argc > 1) - card = argv[1]; - else - card = "/dev/dri/card0"; + /* check which DRM device to open */ + if (argc > 1) + card = argv[1]; + else + card = "/dev/dri/card0"; - fprintf(stderr, "using card '%s'\n", card); + fprintf(stderr, "using card '%s'\n", card); - /* open the DRM device */ - ret = modeset_open(&fd, card); - if (ret) - goto out_return; + /* open the DRM device */ + ret = modeset_open(&fd, card); + if (ret) + goto out_return; - /* prepare all connectors and CRTCs */ - ret = modeset_prepare(fd); - if (ret) - goto out_close; + /* prepare all connectors and CRTCs */ + ret = modeset_prepare(fd); + if (ret) + goto out_close; - /* perform actual modesetting on each found connector+CRTC */ - for (iter = modeset_list; iter; iter = iter->next) { - iter->saved_crtc = drmModeGetCrtc(fd, iter->crtc); - ret = drmModeSetCrtc(fd, iter->crtc, iter->fb, 0, 0, - &iter->conn, 1, &iter->mode); - if (ret) - fprintf(stderr, "cannot set CRTC for connector %u (%d): %m\n", - iter->conn, errno); - } + /* perform actual modesetting on each found connector+CRTC */ + for (iter = modeset_list; iter; iter = iter->next) { + iter->saved_crtc = drmModeGetCrtc(fd, iter->crtc); + ret = drmModeSetCrtc(fd, iter->crtc, iter->fb, 0, 0, + &iter->conn, 1, &iter->mode); + if (ret) + fprintf(stderr, "cannot set CRTC for connector %u (%d): %s\n", + iter->conn, errno, strerror(errno)); + } - /* draw some colors for 5seconds */ - modeset_draw(); + /* draw some colors for 5seconds */ + modeset_draw(); - /* cleanup everything */ - modeset_cleanup(fd); + /* cleanup everything */ + modeset_cleanup(fd); - ret = 0; + ret = 0; out_close: - close(fd); + close(fd); out_return: - if (ret) { - errno = -ret; - fprintf(stderr, "modeset failed with error %d: %m\n", errno); - } else { - fprintf(stderr, "exiting\n"); - } - return ret; + if (ret) { + errno = -ret; + fprintf(stderr, "modeset failed with error %d: %s\n", errno, strerror(errno)); + } else { + fprintf(stderr, "exiting\n"); + } + return ret; } /* @@ -602,15 +602,15 @@ out_return: static uint8_t next_color(bool *up, uint8_t cur, unsigned int mod) { - uint8_t next; + uint8_t next; - next = cur + (*up ? 1 : -1) * (rand() % mod); - if ((*up && next < cur) || (!*up && next > cur)) { - *up = !*up; - next = cur; - } + next = cur + (*up ? 1 : -1) * (rand() % mod); + if ((*up && next < cur) || (!*up && next > cur)) { + *up = !*up; + next = cur; + } - return next; + return next; } /* @@ -635,34 +635,34 @@ static uint8_t next_color(bool *up, uint8_t cur, unsigned int mod) static void modeset_draw(void) { - uint8_t r, g, b; - bool r_up, g_up, b_up; - unsigned int i, j, k, off; - struct modeset_dev *iter; + uint8_t r, g, b; + bool r_up, g_up, b_up; + unsigned int i, j, k, off; + struct modeset_dev *iter; - srand(time(NULL)); - r = rand() % 0xff; - g = rand() % 0xff; - b = rand() % 0xff; - r_up = g_up = b_up = true; + srand(time(NULL)); + r = rand() % 0xff; + g = rand() % 0xff; + b = rand() % 0xff; + r_up = g_up = b_up = true; - for (i = 0; i < 50; ++i) { - r = next_color(&r_up, r, 20); - g = next_color(&g_up, g, 10); - b = next_color(&b_up, b, 5); + for (i = 0; i < 50; ++i) { + r = next_color(&r_up, r, 20); + g = next_color(&g_up, g, 10); + b = next_color(&b_up, b, 5); - for (iter = modeset_list; iter; iter = iter->next) { - for (j = 0; j < iter->height; ++j) { - for (k = 0; k < iter->width; ++k) { - off = iter->stride * j + k * 4; - *(uint32_t*)&iter->map[off] = - (r << 16) | (g << 8) | b; - } - } - } + for (iter = modeset_list; iter; iter = iter->next) { + for (j = 0; j < iter->height; ++j) { + for (k = 0; k < iter->width; ++k) { + off = iter->stride * j + k * 4; + *(uint32_t*)&iter->map[off] = + (r << 16) | (g << 8) | b; + } + } + } - usleep(100000); - } + usleep(100000); + } } /* @@ -674,39 +674,41 @@ static void modeset_draw(void) static void modeset_cleanup(int fd) { - struct modeset_dev *iter; - struct drm_mode_destroy_dumb dreq; + struct modeset_dev *iter; + struct drm_mode_destroy_dumb dreq; - while (modeset_list) { - /* remove from global list */ - iter = modeset_list; - modeset_list = iter->next; + while (modeset_list) { + /* remove from global list */ + iter = modeset_list; + modeset_list = iter->next; - /* restore saved CRTC configuration */ - drmModeSetCrtc(fd, - iter->saved_crtc->crtc_id, - iter->saved_crtc->buffer_id, - iter->saved_crtc->x, - iter->saved_crtc->y, - &iter->conn, - 1, - &iter->saved_crtc->mode); - drmModeFreeCrtc(iter->saved_crtc); + /* restore saved CRTC configuration */ + drmModeSetCrtc( + fd, + iter->saved_crtc->crtc_id, + iter->saved_crtc->buffer_id, + iter->saved_crtc->x, + iter->saved_crtc->y, + &iter->conn, + 1, + &iter->saved_crtc->mode + ); + drmModeFreeCrtc(iter->saved_crtc); - /* unmap buffer */ - munmap(iter->map, iter->size); + /* unmap buffer */ + munmap(iter->map, iter->size); - /* delete framebuffer */ - drmModeRmFB(fd, iter->fb); + /* delete framebuffer */ + drmModeRmFB(fd, iter->fb); - /* delete dumb buffer */ - memset(&dreq, 0, sizeof(dreq)); - dreq.handle = iter->handle; - drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq); + /* delete dumb buffer */ + memset(&dreq, 0, sizeof(dreq)); + dreq.handle = iter->handle; + drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq); - /* free allocated memory */ - free(iter); - } + /* free allocated memory */ + free(iter); + } } /* diff --git a/userland/libs/openblas/build b/userland/libs/openblas/build new file mode 120000 index 0000000..ab18017 --- /dev/null +++ b/userland/libs/openblas/build @@ -0,0 +1 @@ +../build \ No newline at end of file diff --git a/userland/libs/openblas_hello.c b/userland/libs/openblas/hello.c similarity index 100% rename from userland/libs/openblas_hello.c rename to userland/libs/openblas/hello.c diff --git a/userland/linux/README.adoc b/userland/linux/README.adoc index fd45463..346e888 100644 --- a/userland/linux/README.adoc +++ b/userland/linux/README.adoc @@ -1,3 +1,5 @@ -Programs in this directory rely on Linux kernel specific functionality such as `/proc`. +Programs in this directory rely on Linux kernel specific functionality such as `/proc` or raw system calls. These programs may also conform to ANSI C or POSIX, but we put them here because you can only observe them at work under Linux. + +Many of these programs use glibc or GCC extensions. diff --git a/userland/linux/init_env_poweroff.c b/userland/linux/init_env_poweroff.c new file mode 100644 index 0000000..07885b0 --- /dev/null +++ b/userland/linux/init_env_poweroff.c @@ -0,0 +1,25 @@ +#define _XOPEN_SOURCE 700 +#include +#include +#include + +int main(int argc, char **argv) { + int i; + + puts("args:"); + for (i = 0; i < argc; ++i) + puts(argv[i]); + puts(""); + + puts("env:"); + extern char **environ; + char **env = environ; + while (*env) { + printf("%s\n", *env); + env++; + } + puts(""); + + /* Poweroff. */ + reboot(RB_POWER_OFF); +} diff --git a/userland/myinsmod.c b/userland/linux/myinsmod.c similarity index 100% rename from userland/myinsmod.c rename to userland/linux/myinsmod.c diff --git a/userland/myrmmod.c b/userland/linux/myrmmod.c similarity index 100% rename from userland/myrmmod.c rename to userland/linux/myrmmod.c diff --git a/userland/linux/poweroff.c b/userland/linux/poweroff.c index de4a645..bcae5a9 100644 --- a/userland/linux/poweroff.c +++ b/userland/linux/poweroff.c @@ -5,5 +5,5 @@ #include int main(void) { - reboot(RB_POWER_OFF); + reboot(RB_POWER_OFF); } diff --git a/userland/proc_events.c b/userland/linux/proc_events.c similarity index 100% rename from userland/proc_events.c rename to userland/linux/proc_events.c diff --git a/userland/linux/rand_check.c b/userland/linux/rand_check.c index 7b5a5a5..bae03cc 100644 --- a/userland/linux/rand_check.c +++ b/userland/linux/rand_check.c @@ -13,29 +13,29 @@ int bss = 0; int data = 1; int main(__attribute__((unused)) int argc, char **argv) { - int i, *ip; - uint64_t uint64; - FILE *fp; + int i, *ip; + uint64_t uint64; + FILE *fp; - /* Loaded addresses. */ - printf("&i = %p\n", (void *)&i); - printf("&argv[0] = %p\n", (void *)&argv[0]); - printf("&main = %p\n", (void *)(intptr_t)main); - printf("&bss = %p\n", (void *)&bss); - printf("&data = %p\n", (void *)&data); + /* Loaded addresses. */ + printf("&i = %p\n", (void *)&i); + printf("&argv[0] = %p\n", (void *)&argv[0]); + printf("&main = %p\n", (void *)(intptr_t)main); + printf("&bss = %p\n", (void *)&bss); + printf("&data = %p\n", (void *)&data); - /* Misc syscalls. */ - printf("time(NULL) = %ju\n", (uintmax_t)time(NULL)); - printf("pid = %ju\n", (uintmax_t)getpid()); + /* Misc syscalls. */ + printf("time(NULL) = %ju\n", (uintmax_t)time(NULL)); + printf("pid = %ju\n", (uintmax_t)getpid()); - /* malloc */ - ip = malloc(sizeof(*ip)); - printf("&malloc = %p\n", (void *)ip); - free(ip); + /* malloc */ + ip = malloc(sizeof(*ip)); + printf("&malloc = %p\n", (void *)ip); + free(ip); - /* /dev/urandom */ - fp = fopen("/dev/urandom", "rb"); - fread(&uint64, sizeof(uint64), 1, fp); - printf("/dev/urandom = %" PRIx64 "\n", uint64); - fclose(fp); + /* /dev/urandom */ + fp = fopen("/dev/urandom", "rb"); + fread(&uint64, sizeof(uint64), 1, fp); + printf("/dev/urandom = %" PRIx64 "\n", uint64); + fclose(fp); } diff --git a/userland/sched_getaffinity.c b/userland/linux/sched_getaffinity.c similarity index 100% rename from userland/sched_getaffinity.c rename to userland/linux/sched_getaffinity.c diff --git a/userland/sched_getaffinity_threads.c b/userland/linux/sched_getaffinity_threads.c similarity index 75% rename from userland/sched_getaffinity_threads.c rename to userland/linux/sched_getaffinity_threads.c index 4e56996..293f4d5 100644 --- a/userland/sched_getaffinity_threads.c +++ b/userland/linux/sched_getaffinity_threads.c @@ -10,31 +10,31 @@ #include void* main_thread_0(void *arg) { - int i; + int i; cpu_set_t mask; CPU_ZERO(&mask); CPU_SET(*((int*)arg), &mask); sched_setaffinity(0, sizeof(cpu_set_t), &mask); i = 0; while (true) { - printf("0 %d\n", i); - sleep(1); - i++; + printf("0 %d\n", i); + sleep(1); + i++; } return NULL; } void* main_thread_1(void *arg) { - int i; + int i; cpu_set_t mask; CPU_ZERO(&mask); CPU_SET(*((int*)arg), &mask); sched_setaffinity(1, sizeof(cpu_set_t), &mask); i = 0; while (true) { - printf("1 %d\n", i); - sleep(1); - i++; + printf("1 %d\n", i); + sleep(1); + i++; } return NULL; } @@ -43,8 +43,8 @@ int main(void) { enum NUM_THREADS {NUM_THREADS = 2}; pthread_t threads[NUM_THREADS]; int thread_args[NUM_THREADS]; - pthread_create(&threads[0], NULL, main_thread_0, (void*)&thread_args[0]); - pthread_create(&threads[1], NULL, main_thread_1, (void*)&thread_args[1]); + pthread_create(&threads[0], NULL, main_thread_0, (void*)&thread_args[0]); + pthread_create(&threads[1], NULL, main_thread_1, (void*)&thread_args[1]); pthread_join(threads[0], NULL); pthread_join(threads[1], NULL); return EXIT_SUCCESS; diff --git a/userland/poll.c b/userland/poll.c deleted file mode 100644 index c15821b..0000000 --- a/userland/poll.c +++ /dev/null @@ -1,41 +0,0 @@ -/* https://github.com/cirosantilli/linux-kernel-module-cheat#poll */ - -#define _XOPEN_SOURCE 700 -#include -#include /* creat, O_CREAT */ -#include /* poll */ -#include /* printf, puts, snprintf */ -#include /* EXIT_FAILURE, EXIT_SUCCESS */ -#include /* read */ - -int main(int argc, char **argv) { - char buf[1024]; - int fd, i, n; - short revents; - struct pollfd pfd; - - if (argc < 2) { - fprintf(stderr, "usage: %s \n", argv[0]); - exit(EXIT_FAILURE); - } - fd = open(argv[1], O_RDONLY | O_NONBLOCK); - if (fd == -1) { - perror("open"); - exit(EXIT_FAILURE); - } - pfd.fd = fd; - pfd.events = POLLIN; - while (1) { - puts("loop"); - i = poll(&pfd, 1, -1); - if (i == -1) { - perror("poll"); - assert(0); - } - revents = pfd.revents; - if (revents & POLLIN) { - n = read(pfd.fd, buf, sizeof(buf)); - printf("POLLIN n=%d buf=%.*s\n", n, n, buf); - } - } -} diff --git a/userland/virt_to_phys_test.c b/userland/posix/virt_to_phys_test.c similarity index 60% rename from userland/virt_to_phys_test.c rename to userland/posix/virt_to_phys_test.c index 830b8f6..0f08c62 100644 --- a/userland/virt_to_phys_test.c +++ b/userland/posix/virt_to_phys_test.c @@ -11,11 +11,11 @@ enum { I0 = 0x12345678 }; static volatile uint32_t i = I0; int main(void) { - printf("vaddr %p\n", (void *)&i); - printf("pid %ju\n", (uintmax_t)getpid()); - while (i == I0) { - sleep(1); - } - printf("i %jx\n", (uintmax_t)i); - return EXIT_SUCCESS; + printf("vaddr %p\n", (void *)&i); + printf("pid %ju\n", (uintmax_t)getpid()); + while (i == I0) { + sleep(1); + } + printf("i %jx\n", (uintmax_t)i); + return EXIT_SUCCESS; } diff --git a/userland/print_argv.c b/userland/print_argv.c deleted file mode 100644 index da7bc6a..0000000 --- a/userland/print_argv.c +++ /dev/null @@ -1,10 +0,0 @@ -/* Print each command line argument received, one per line. */ - -#include - -int main(int argc, char **argv) { - size_t i; - for (i = 0; i < (size_t)argc; ++i) - printf("%s\n", argv[i]); - return 0; -}