mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-23 02:05: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
|
==== 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
|
./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
|
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
|
=== Kernel panic and oops
|
||||||
|
|
||||||
To test out kernel panics and oops in controlled circumstances, try out the modules:
|
To test out kernel panics and oops in controlled circumstances, try out the modules:
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import shutil
|
|||||||
|
|
||||||
import common
|
import common
|
||||||
from shell_helpers import LF
|
from shell_helpers import LF
|
||||||
|
import path_properties
|
||||||
|
|
||||||
class Main(common.BuildCliFunction):
|
class Main(common.BuildCliFunction):
|
||||||
def __init__(self):
|
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.
|
Place the modules on a separate magic directory from non --host builds.
|
||||||
''',
|
''',
|
||||||
)
|
)
|
||||||
|
self._add_argument('--force-rebuild')
|
||||||
self.add_argument(
|
self.add_argument(
|
||||||
'kernel-modules',
|
'kernel-modules',
|
||||||
default=[],
|
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='*',
|
nargs='*',
|
||||||
)
|
)
|
||||||
self._add_argument('--force-rebuild')
|
|
||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
build_dir = self.get_build_dir()
|
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 = []
|
all_kernel_modules = []
|
||||||
for basename in os.listdir(self.env['kernel_modules_source_dir']):
|
for basename in os.listdir(self.env['kernel_modules_source_dir']):
|
||||||
src = os.path.join(self.env['kernel_modules_source_dir'], basename)
|
abspath = os.path.join(self.env['kernel_modules_source_dir'], basename)
|
||||||
if os.path.isfile(src):
|
if os.path.isfile(abspath):
|
||||||
noext, ext = os.path.splitext(basename)
|
noext, ext = os.path.splitext(basename)
|
||||||
if ext == self.env['c_ext']:
|
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'] == []:
|
if self.env['kernel_modules'] == []:
|
||||||
kernel_modules = all_kernel_modules
|
kernel_modules = all_kernel_modules
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -13,6 +13,11 @@ ccflags-y := \
|
|||||||
-Wno-declaration-after-statement \
|
-Wno-declaration-after-statement \
|
||||||
$(CCFLAGS)
|
$(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
|
.PHONY: all
|
||||||
|
|
||||||
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
|
self['allowed_archs'] is None or
|
||||||
env['arch'] in self['allowed_archs']
|
env['arch'] in self['allowed_archs']
|
||||||
) and
|
) and
|
||||||
(
|
not (
|
||||||
(
|
(
|
||||||
env['mode'] == 'userland' and
|
env['mode'] == 'userland' and
|
||||||
(
|
(
|
||||||
self['userland'] and
|
not self['userland'] or
|
||||||
ext in env['build_in_exts']
|
not ext in env['build_in_exts']
|
||||||
)
|
)
|
||||||
) or
|
) or
|
||||||
(
|
(
|
||||||
env['mode'] == 'baremetal' and (
|
env['mode'] == 'baremetal' and (
|
||||||
self['baremetal'] and
|
not self['baremetal'] or
|
||||||
ext in env['baremetal_build_in_exts']
|
not ext in env['baremetal_build_in_exts']
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
) and
|
) and
|
||||||
@@ -311,6 +311,12 @@ path_properties_tuples = (
|
|||||||
'getchar.c': {'interactive': True},
|
'getchar.c': {'interactive': True},
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
'kernel_modules': (
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
'float.c': {'allowed_archs': 'x86_64'}
|
||||||
|
},
|
||||||
|
),
|
||||||
'lkmc.c': {
|
'lkmc.c': {
|
||||||
'baremetal': True,
|
'baremetal': True,
|
||||||
'userland': True,
|
'userland': True,
|
||||||
|
|||||||
Reference in New Issue
Block a user