Floating point math in kernel interrupt -- am I doing this right?(repost)

Jeremy Friesner jaf at lcsaudio.com
Wed Feb 8 19:32:12 EST 2006


Hi all,

I figured out what was wrong with my FPU save/restore code:  I was neglecting to save and restore the state of the FPSCR register.  Thanks to all who helped me figure it out!

For the sake of the list archives, I've pasted my fixed FP save/restore routines below.

-Jeremy

---------------------- snip -------------------------------

/* macros to save and restore floating point register state */
# define SAVE_FPR(x)    {__asm__ __volatile__ ("stfd " #x ", " #x "*8(%0)\n" : : "b" (saved_fpr));}
# define RESTORE_FPR(x) {__asm__ __volatile__ ("lfd  " #x ", " #x "*8(%0)\n" : : "b" (saved_fpr));}    

/* Set up floating-point-enabled-mode */
uint32 saved_msr;        /* space for the MSR register (32 bits) */
uint32 saved_fpscr[1*2]; /* space for the FPSCR register (64 bits) */
uint32 saved_fpr[14*2];  /* space for the 14 floating point registers I'll use (64 bits each) */
{
   uint32 msr;

   /* Save existing MSR for later */
   __asm__ __volatile__ ("mfmsr %0" : "=r" (msr) : );
   saved_msr = msr;

   /* Enable floating point */
   msr |= MSR_FP;
   msr &= ~(MSR_FE0 | MSR_FE1);
   __asm__ __volatile__ ("mtmsr %0\n\tisync" : : "r" (msr));

   /* Save the floating point registers that will be used, so that we won't screw up user processes */
   SAVE_FPR(0);  SAVE_FPR(1);  SAVE_FPR(2);  SAVE_FPR(3);  SAVE_FPR(4);
   SAVE_FPR(5);  SAVE_FPR(6);  SAVE_FPR(7);  SAVE_FPR(8);  SAVE_FPR(9);
   SAVE_FPR(10); SAVE_FPR(11); SAVE_FPR(12); SAVE_FPR(13);

   /* Save existing FPSCR, by first retrieving it into FPR0, then storing FPR0 to the stack */
   __asm__ __volatile__ ("mffs 0\n\tstfd 0, 0(%0)\n" : : "b" (saved_fpscr));
}                

DoFloatingPointMathHere();

/* End floating-point-enabled-mode */
{
   /* Restore FPSCR, by first loading it into FPR0, then calling mtfsf to put it back into the register */
   __asm__ __volatile__ ("lfd 0, 0(%0)\n\tmtfsf 0xFF,0" : : "b" (saved_fpscr));

   /* Restore the FP registers that may have been munged */
   RESTORE_FPR(0);  RESTORE_FPR(1);  RESTORE_FPR(2);  RESTORE_FPR(3);  RESTORE_FPR(4);
   RESTORE_FPR(5);  RESTORE_FPR(6);  RESTORE_FPR(7);  RESTORE_FPR(8);  RESTORE_FPR(9);
   RESTORE_FPR(10); RESTORE_FPR(11); RESTORE_FPR(12); RESTORE_FPR(13);

   /* Restore MSR */
   __asm__ __volatile__ ("mtmsr %0\n" "isync" : : "r" (saved_msr));
}
 




More information about the Linuxppc-embedded mailing list