Call kernel_fpu_begin twice before kernel_fpu_end

I use the function kernel_fpu_beginand kernel_fpu_endin asm / i387.h to protect the FPU register states for a simple floating-point arithmetic unit inside the Linux kernel.

I am curious about the behavior of a function call kernel_fpu_begintwice before a function kernel_fpu_endand vice versa. For instance:

#include <asm/i387.h>

double foo(unsigned num){
    kernel_fpu_begin();

    double x = 3.14;
    x += num;

    kernel_fpu_end();

    return x;
}

...

kernel_fpu_begin();

double y = 1.23;
unsigned z = 42;
y -= foo(z);

kernel_fpu_end();

In a function, fooI call kernel_fpu_beginand kernel_fpu_end; but kernel_fpu_beginalready called before the call foo. Will this lead to undefined behavior?

Also, should I even call kernel_fpu_endinside the function foo? I return double after the call kernel_fpu_end, which means that access to floating point registers is unsafe?

- kernel_fpu_begin kernel_fpu_end foo; , foo double unsigned - kernel_fpu_begin kernel_fpu_end foo?

0
3

: , kernel_fpu_begin(), FPU .

: , kernel_fpu_begin() struct task_struct FPU (task_struct , thread), x86, thread.fpu FPU ), kernel_fpu_begin() . kernel_fpu_end() FPU.

. , <asm/i387.h>, . (, 3.2, ), FPU "" - ​​ FPU, , FPU FPU. , kernel_fpu_end() TS, FPU FPU. , FPU , .

, (3.7 , ), , - "" FPU. , "" XSAVEOPT, FPU ( SSE memcpy ..). XSAVEOPT/XRSTOR , FPU , kernel_fpu_end() FPU. (

"" "" FPU task_struct , FPU, kernel_fpu_begin() FPU .

+4

asm/i387.h Linux ( 3.2) , , , .

static inline void kernel_fpu_begin(void)
{
        /* get thread_info structure for current thread */
        struct thread_info *me = current_thread_info();

        /* preempt_count is incremented by 1
         * (preempt_count > 0 disables preemption,
         *  while preempt_count < 0 signifies a bug) */
        preempt_disable();

        /* check if FPU has been used before by this thread */
        if (me->status & TS_USEDFPU)
                /* save the FPU state to prevent clobbering of
                 * FPU registers, then reset the TS_USEDFPU flag */
                __save_init_fpu(me->task);
        else
                /* clear the CR0.TS bit to prevent
                 * unnecessary FPU task context saving */
                clts();
}

static inline void kernel_fpu_end(void)
{
        /* set CR0.TS bit (signifying the processor switched
         * to a new task) to enable FPU task context saving */
        stts();

        /* attempt to re-enable preemption
         * (preempt_count is decremented by 1);
         * reschedule thread if needed
         * (thread will not be preempted if preempt_count != 0) */
        preempt_enable();
}

FXSAVE FPU. , , , kernel_fpu_begin ; , , FXSAVE FPU.

, kernel_fpu_begin.

, , , FPU, kernel_fpu_end FXRSTOR. , CR0.TS kernel_fpu_end, FPU?

0

Yes, since you defined some double variable, and fooalso returns a double value; you have to use kernel_fpu_beginand kernel_fpu_endcall out foo .


A similar problem also has this, which have certain instances where you can encode without using calls kernel_fpu_beginand kernel_fpu_end.

-1
source

Source: https://habr.com/ru/post/1687279/


All Articles