[svn-commits] kpfleming: linux/trunk r6791 - /linux/trunk/drivers/dahdi/dahdi-base.c
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Mon Jun 29 15:05:48 CDT 2009
Author: kpfleming
Date: Mon Jun 29 15:05:43 2009
New Revision: 6791
URL: http://svn.asterisk.org/svn-view/dahdi?view=rev&rev=6791
Log:
Improve MMX safety for DAHDI echo cancellers on 32-bit x86 systems.
Replaces the standard kernel FPU save/restore operations with custom written
versions for 32-bit x86 CPUs, which have been tested to be reliable and safe
to use.
(closes issue #13500)
Reported by: tzafrir
Patches:
dahdi_mmx_fix.diff uploaded by tzafrir (license 46)
Modified:
linux/trunk/drivers/dahdi/dahdi-base.c
Modified: linux/trunk/drivers/dahdi/dahdi-base.c
URL: http://svn.asterisk.org/svn-view/dahdi/linux/trunk/drivers/dahdi/dahdi-base.c?view=diff&rev=6791&r1=6790&r2=6791
==============================================================================
--- linux/trunk/drivers/dahdi/dahdi-base.c (original)
+++ linux/trunk/drivers/dahdi/dahdi-base.c Mon Jun 29 15:05:43 2009
@@ -289,7 +289,56 @@
static int dahdi_chan_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data, int unit);
#if defined(CONFIG_DAHDI_MMX) || defined(ECHO_CAN_FP)
+#if (defined(CONFIG_X86) && !defined(CONFIG_X86_64)) || defined(CONFIG_I386)
+struct fpu_save_buf {
+ unsigned long cr0;
+ unsigned long fpu_buf[128];
+};
+
+static DEFINE_PER_CPU(struct fpu_save_buf, fpu_buf);
+
+/** dahdi_kernel_fpu_begin() - Save floating point registers
+ *
+ * This function is similar to kernel_fpu_begin() . However it is
+ * designed to work in an interrupt context. Restoring must be done with
+ * dahdi_kernel_fpu_end().
+ *
+ * Furthermore, the whole code between the call to
+ * dahdi_kernel_fpu_begin() and dahdi_kernel_fpu_end() must reside
+ * inside a spinlock. Otherwise the context might be restored to the
+ * wrong process.
+ *
+ * Current implementation is x86/ia32-specific and will not even build on
+ * x86_64)
+ * */
+static inline void dahdi_kernel_fpu_begin(void)
+{
+ struct fpu_save_buf *buf = &__get_cpu_var(fpu_buf);
+ __asm__ __volatile__ ("movl %%cr0,%0; clts" : "=r" (buf->cr0));
+ __asm__ __volatile__ ("fnsave %0" : "=m" (buf->fpu_buf));
+}
+
+/** dahdi_kernel_fpu_end() - restore floating point context
+ *
+ * Must be used with context saved by dahdi_kernel_fpu_begin(). See its
+ * documentation for further information.
+ */
+static inline void dahdi_kernel_fpu_end(void)
+{
+ struct fpu_save_buf *buf = &__get_cpu_var(fpu_buf);
+ __asm__ __volatile__ ("frstor %0" : "=m" (buf->fpu_buf));
+ __asm__ __volatile__ ("movl %0,%%cr0" : : "r" (buf->cr0));
+}
+
+#else /* We haven't fixed FP context saving/restoring yet */
+/* Very strange things can happen when the context is not properly
+ * restored. OTOH, some people do report success with this. Hence we
+ * so far just issue a warning */
+#warning CONFIG_DAHDI_MMX may behave randomly on this platform
#define dahdi_kernel_fpu_begin kernel_fpu_begin
+#define dahdi_kernel_fpu_end kernel_fpu_end
+#endif
+
#endif
struct dahdi_timer {
@@ -6659,7 +6708,7 @@
}
#if defined(CONFIG_DAHDI_MMX) || defined(ECHO_CAN_FP)
- kernel_fpu_end();
+ dahdi_kernel_fpu_end();
#endif
}
spin_unlock_irqrestore(&ss->lock, flags);
@@ -6991,6 +7040,7 @@
int abort=0;
int res;
int left, x;
+
while(bytes) {
#if defined(CONFIG_DAHDI_NET) || defined(CONFIG_DAHDI_PPP)
@@ -7553,7 +7603,7 @@
#endif
__dahdi_process_getaudio_chunk(chan, buf);
#ifdef CONFIG_DAHDI_MMX
- kernel_fpu_end();
+ dahdi_kernel_fpu_end();
#endif
}
}
@@ -7638,7 +7688,7 @@
#endif
__dahdi_process_putaudio_chunk(chan, buf);
#ifdef CONFIG_DAHDI_MMX
- kernel_fpu_end();
+ dahdi_kernel_fpu_end();
#endif
}
__dahdi_putbuf_chunk(chan, buf);
@@ -7860,7 +7910,7 @@
}
}
#ifdef CONFIG_DAHDI_MMX
- kernel_fpu_end();
+ dahdi_kernel_fpu_end();
#endif
}
/* do all the pseudo/conferenced channel transmits (putbuf's) */
More information about the svn-commits
mailing list