Floating point in interrupt handler

Issei Suzuki issei at issei.org
Mon Oct 22 23:20:44 PDT 2007


2007/10/23, Daan Vreeken [PA4DAN] <Danovitsch at vitsch.net>:

> So I've added asm inline functions to use the FPU's fsin and fcos operands. At
> the start of my loop function I (try to) save the FPU state with the
> following code :
>     td = curthread;
>     npxgetregs(td, &fpu_state);
> At the end of the function I restore the FPU state with :
>     npxsetregs(td, &fpu_state);
>
> In between I currently have :
>     // create a 500Hz sine wave, modulate it with a 2Hz sine wave and
>     // let it have a 10.0 Volt amplitude
>     t += 0.0001;
>     set_dac_voltage(card, 0,
>         fp_sin(500 * 2 * M_PI * t) * fp_sin(2 * 2 * M_PI * t) * 10.0);
>
> As uggly as the code may seem, it works and the output of the acquisition
> board shows the expected signal on a scope. While the code seems to do what
> it should, the kernel floods the console with the following message :
>     kernel trap 22 with interrupts disabled

In FreeBSD, FPU context switch is delayed until FPU is used for the
first time after user thread is switched. To achieve this, T_DNA
(FPU device not available trap) is used as follows.

(Before switching thread)
1. Save FPU state and enable DNA trap (npxsave() @ /sys/i386/isa/npx.c).
   After this, DNA trap occurs when you access FPU.
(Switch to another user thread)
2. User thread accesses FPU.
3. T_DNA trap occurs, and npxdna() @ /sys/i386/isa/npx.c is called.
4. Initialize FPU state (1st time) or restore FPU state (2nd times or later).
5. Return to user mode, and user thread access FPU again.

So, to use FPU in kernel, you must clear T_DNA trap and initialize FPU
registers first.

Reading these functions may help you, I think.

  /sys/i386/isa/npx.c
   start_emulating()
   stop_emulating()
   npxdna()

Regards,

-- 
Issei Suzuki <issei at issei.org>


More information about the freebsd-hackers mailing list