mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-22 17:55:57 +01:00
kernel modules: hack up quick floating point example
This commit is contained in:
64
README.adoc
64
README.adoc
@@ -5537,7 +5537,23 @@ This likely comes from the ifdef split at `init/main.c`:
|
||||
|
||||
==== Kernel module parameters
|
||||
|
||||
The Linux kernel allows passing module parameters at insertion time <<myinsmod,through the `init_module` and `finit_module` system calls>>:
|
||||
The Linux kernel allows passing module parameters at insertion time <<myinsmod,through the `init_module` and `finit_module` system calls>>.
|
||||
|
||||
The `insmod` tool exposes that as:
|
||||
|
||||
....
|
||||
insmod params.ko i=3 j=4
|
||||
....
|
||||
|
||||
Parameters are declared in the module as:
|
||||
|
||||
....
|
||||
static u32 i = 0;
|
||||
module_param(i, int, S_IRUSR | S_IWUSR);
|
||||
MODULE_PARM_DESC(i, "my favorite int");
|
||||
....
|
||||
|
||||
Automated test:
|
||||
|
||||
....
|
||||
./params.sh
|
||||
@@ -5890,6 +5906,52 @@ Source: link:kernel_modules/init_module.c[]
|
||||
|
||||
TODO why were `module_init` and `module_exit` created? https://stackoverflow.com/questions/3218320/what-is-the-difference-between-module-init-and-init-module-in-a-linux-kernel-mod
|
||||
|
||||
==== Floating point in kernel modules
|
||||
|
||||
It is generally hard / impossible to use floating point operations in the kernel. TODO understand details.
|
||||
|
||||
A quick (x86-only for now because lazy) example is shown at: link:kernel_modules/float.c[]
|
||||
|
||||
Usage:
|
||||
|
||||
....
|
||||
insmod float.ko myfloat=1 enable_fpu=1
|
||||
....
|
||||
|
||||
We have to call: `kernel_fpu_begin()` before starting FPU operations, and `kernel_fpu_end()` when we are done. This particular example however did not blow up without it at lkmc 7f917af66b17373505f6c21d75af9331d624b3a9 + 1:
|
||||
|
||||
....
|
||||
insmod float.ko myfloat=1 enable_fpu=0
|
||||
....
|
||||
|
||||
The v5.1 documentation under link:https://github.com/cirosantilli/linux/blob/v5.1/arch/x86/include/asm/fpu/api.h#L15[arch/x86/include/asm/fpu/api.h] reads:
|
||||
|
||||
....
|
||||
* Use kernel_fpu_begin/end() if you intend to use FPU in kernel context. It
|
||||
* disables preemption so be careful if you intend to use it for long periods
|
||||
* of time.
|
||||
....
|
||||
|
||||
The example sets in the link:kernel_modules/Makefile[]:
|
||||
|
||||
....
|
||||
CFLAGS_REMOVE_float.o += -mno-sse -mno-sse2
|
||||
....
|
||||
|
||||
to avoid:
|
||||
|
||||
....
|
||||
error: SSE register return with SSE disabled
|
||||
....
|
||||
|
||||
We found those flags with `./build-modules --verbose`.
|
||||
|
||||
Bibliography:
|
||||
|
||||
* https://stackoverflow.com/questions/13886338/use-of-floating-point-in-the-linux-kernel
|
||||
* https://stackoverflow.com/questions/15883947/why-am-i-able-to-perform-floating-point-operations-inside-a-linux-kernel-module/47056242
|
||||
* https://stackoverflow.com/questions/1556142/sse-register-return-with-sse-disabled
|
||||
|
||||
=== Kernel panic and oops
|
||||
|
||||
To test out kernel panics and oops in controlled circumstances, try out the modules:
|
||||
|
||||
@@ -8,6 +8,7 @@ import shutil
|
||||
|
||||
import common
|
||||
from shell_helpers import LF
|
||||
import path_properties
|
||||
|
||||
class Main(common.BuildCliFunction):
|
||||
def __init__(self):
|
||||
@@ -32,13 +33,15 @@ Build the Linux kernel modules against the host kernel.
|
||||
Place the modules on a separate magic directory from non --host builds.
|
||||
''',
|
||||
)
|
||||
self._add_argument('--force-rebuild')
|
||||
self.add_argument(
|
||||
'kernel-modules',
|
||||
default=[],
|
||||
help='Which kernel modules to build. Default: build all',
|
||||
help='''\
|
||||
Which kernel modules to build. Default: build all.
|
||||
Can be either the path to the C file, or its basename without extension.''',
|
||||
nargs='*',
|
||||
)
|
||||
self._add_argument('--force-rebuild')
|
||||
|
||||
def build(self):
|
||||
build_dir = self.get_build_dir()
|
||||
@@ -63,11 +66,14 @@ Place the modules on a separate magic directory from non --host builds.
|
||||
)
|
||||
all_kernel_modules = []
|
||||
for basename in os.listdir(self.env['kernel_modules_source_dir']):
|
||||
src = os.path.join(self.env['kernel_modules_source_dir'], basename)
|
||||
if os.path.isfile(src):
|
||||
abspath = os.path.join(self.env['kernel_modules_source_dir'], basename)
|
||||
if os.path.isfile(abspath):
|
||||
noext, ext = os.path.splitext(basename)
|
||||
if ext == self.env['c_ext']:
|
||||
all_kernel_modules.append(noext)
|
||||
relpath = abspath[len(self.env['root_dir']) + 1:]
|
||||
my_path_properties = path_properties.get(relpath)
|
||||
if my_path_properties.should_be_built(self.env):
|
||||
all_kernel_modules.append(noext)
|
||||
if self.env['kernel_modules'] == []:
|
||||
kernel_modules = all_kernel_modules
|
||||
else:
|
||||
|
||||
@@ -13,6 +13,11 @@ ccflags-y := \
|
||||
-Wno-declaration-after-statement \
|
||||
$(CCFLAGS)
|
||||
|
||||
ifeq ($(ARCH),x86)
|
||||
# https://github.com/cirosantilli/linux-kernel-module-cheat#floating-point-in-kernel-modules
|
||||
CFLAGS_REMOVE_float.o += -mno-sse -mno-sse2
|
||||
endif
|
||||
|
||||
.PHONY: all
|
||||
|
||||
all:
|
||||
|
||||
31
kernel_modules/float.c
Normal file
31
kernel_modules/float.c
Normal file
@@ -0,0 +1,31 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#floating-point-in-kernel-modules */
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <asm/fpu/api.h> /* kernel_fpu_begin, kernel_fpu_end */
|
||||
|
||||
/* float params are not supported, so we just go with int. */
|
||||
static int myfloat = 1;
|
||||
static int enable_fpu = 1;
|
||||
module_param(myfloat, int, S_IRUSR | S_IWUSR);
|
||||
module_param(enable_fpu, int, S_IRUSR | S_IWUSR);
|
||||
|
||||
static int myinit(void)
|
||||
{
|
||||
if (enable_fpu) {
|
||||
kernel_fpu_begin();
|
||||
}
|
||||
if ((float)myfloat + 1.5f == 2.5f) {
|
||||
pr_info("magic value\n");
|
||||
}
|
||||
if (enable_fpu) {
|
||||
kernel_fpu_end();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void myexit(void) {}
|
||||
|
||||
module_init(myinit)
|
||||
module_exit(myexit)
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -128,18 +128,18 @@ class PathProperties:
|
||||
self['allowed_archs'] is None or
|
||||
env['arch'] in self['allowed_archs']
|
||||
) and
|
||||
(
|
||||
not (
|
||||
(
|
||||
env['mode'] == 'userland' and
|
||||
(
|
||||
self['userland'] and
|
||||
ext in env['build_in_exts']
|
||||
not self['userland'] or
|
||||
not ext in env['build_in_exts']
|
||||
)
|
||||
) or
|
||||
(
|
||||
env['mode'] == 'baremetal' and (
|
||||
self['baremetal'] and
|
||||
ext in env['baremetal_build_in_exts']
|
||||
not self['baremetal'] or
|
||||
not ext in env['baremetal_build_in_exts']
|
||||
)
|
||||
)
|
||||
) and
|
||||
@@ -311,6 +311,12 @@ path_properties_tuples = (
|
||||
'getchar.c': {'interactive': True},
|
||||
}
|
||||
),
|
||||
'kernel_modules': (
|
||||
{},
|
||||
{
|
||||
'float.c': {'allowed_archs': 'x86_64'}
|
||||
},
|
||||
),
|
||||
'lkmc.c': {
|
||||
'baremetal': True,
|
||||
'userland': True,
|
||||
|
||||
Reference in New Issue
Block a user