0

I'm trying to use float and double data types inside the kernel module. As part of satisfying my curiosity, I have written simple LKM. Here it is,

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>

static int __init hello_start(void)
{
        float x,y,z;
        x = 22.27;
        y = 7.25;
        z = x/y;                                                                

        unsigned int *u;
        u = (unsigned int *)&z;
        printk(KERN_INFO "0x%x\n", *u);

        return 0;
}

static void __exit hello_end(void)
{
        printk(KERN_INFO "Unload...\n");
}

module_init(hello_start);
module_exit(hello_end);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("XYZ");

As float will store a value into memory/register by IEEE754 format so I can assign it into 32-bit wide data types like unsigned int. And inside code same things I did and I got perfect HEX values of IEEE754 spec. In this case 22.27/7.25 = 3.071724138 and 3.071724138 normalize IEEE754 value in hex is 0x40449721. The dmesg shows me 0x40449721 while loading module.

So now questions are,

1) How can a see disassembly of my kernel module? so I can verify for float data store and division which instruction is used. (my platform is x86_64).

2) If I can able to see perfect hex value of division, then what is the role of API like kernel_fpu_begin()/kernel_fpu_end() because without using it I can perform float division? the division is performed by which hardware? what about hardware FPU?

3) This division is performed by SSE2 instructions or something else (that why I need assembly file of LKM)

Claudio
  • 10,614
  • 4
  • 31
  • 71
  • 1
    1) `objdump -d .../foo.ko`. Re: everything else: it works, but you've corrupted the XMM or x87 register state of a user-space context switch. – Peter Cordes Jun 21 '18 at 05:52
  • yes! duplication. but @Peter I had one more question on this. for x/y kind of things which instruction is used. I have did objdump -D of my .ko file and inside that there is no "divsd" kind of instruction present. which group of instruction are performed this division? – Bhoomil Chavda Jun 21 '18 at 09:25
  • 1
    You only have compile-time constants, so unless you disable optimization, make `x` and `y` `volatile`, or do something else to prevent it, gcc will do constant-propagation and effectively turn your code into `float z=3.07172413793103448276f` (i.e. just put the nearest representable float bit pattern into your program with no `divsd`, `divss`, `fdiv`, or `rcpps` + newton iteration.) It turns out that your example isn't a duplicate; you aren't actually using any FP math, just printing a 32-bit integer, so look for a `mov esi, 0x????` before the `call printk`. – Peter Cordes Jun 21 '18 at 12:17
  • 1
    Also note that pointer-casting is not a safe way to type-pun, with strict-aliasing enabled. Use `memcpy` or a union. – Peter Cordes Jun 21 '18 at 12:20
  • thanks for providing above useful information. I have one more doubt that inside the linux kernel src, there are bunch of files which using kernel_fpu_begin()/end(). I have notice that between these two calls... rather than writing normal C code, developer choose assembly. why it so ? – Bhoomil Chavda Jun 22 '18 at 09:41
  • because it's not worth using kernel_fpu_begin/end unless you're going to use SIMD, not just for some FP calculation. Linux probably even uses `-mno-sse` to stop it from using vectors for copying structs and so on. (And gcc won't use x87 on its own.) – Peter Cordes Jul 04 '18 at 10:14

0 Answers0