kernel modules: hack up quick floating point example

This commit is contained in:
Ciro Santilli 六四事件 法轮功
2019-06-02 00:00:01 +00:00
parent 7f917af66b
commit 819ef42ea4
5 changed files with 121 additions and 11 deletions

View File

@@ -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:

View File

@@ -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:

View File

@@ -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
View 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");

View File

@@ -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,