Update of /cvsroot/linux-mips/linux/arch/mips/mm
In directory usw-pr-cvs1:/tmp/cvs-serv23208/mips/mm
Modified Files:
c-sb1.c
Log Message:
Flushing the icache was possibly resulting in a pagefault. Fix negated condition.
Index: c-sb1.c
===================================================================
RCS file: /cvsroot/linux-mips/linux/arch/mips/mm/c-sb1.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- c-sb1.c 5 Feb 2002 17:03:53 -0000 1.12
+++ c-sb1.c 18 Mar 2002 22:19:21 -0000 1.13
@@ -23,6 +23,7 @@
#include <asm/bootinfo.h>
#include <asm/cacheops.h>
#include <asm/cpu.h>
+#include <asm/uaccess.h>
/* These are probed at ld_mmu time */
static unsigned int icache_size;
@@ -245,11 +246,11 @@
* If there's no context yet, or the page isn't executable, no icache flush
* is needed
*/
-static void sb1_flush_icache_page(struct vm_area_struct *vma, struct page *page)
+static void sb1_flush_icache_page(struct vm_area_struct *vma,
+ struct page *page)
{
- if ((vma->vm_mm->context == 0) || !(vma->vm_flags & VM_EXEC)) {
+ if (!(vma->vm_flags & VM_EXEC))
return;
- }
/*
* We're not sure of the virtual address(es) involved here, so
@@ -322,15 +323,12 @@
}
/*
- * XXX - Still need to really understand this. This is mostly just
- * derived from the r10k and r4k implementations, and seems to work
- * but things that "seem to work" when I don't understand *why* they
- * "seem to work" disturb me greatly...JDC
+ * A signal trampoline must fit into a single cacheline.
*/
-static void local_sb1_flush_cache_sigtramp(unsigned long addr)
+static inline void local_sb1_flush_cache_sigtramp(unsigned long addr)
{
unsigned long daddr, iaddr;
-
+
daddr = addr & ~(dcache_line_size - 1);
protected_writeback_dcache_line(daddr);
protected_writeback_dcache_line(daddr + dcache_line_size);
@@ -340,14 +338,30 @@
}
#ifdef CONFIG_SMP
-extern void sb1_flush_cache_sigtramp_ipi(void *ignored);
-asm("sb1_flush_cache_sigtramp_ipi = local_sb1_flush_cache_sigtramp");
+
+static void sb1_flush_cache_sigtramp_ipi(void *info)
+{
+ unsigned long iaddr = (unsigned long) info;
+
+ iaddr = iaddr & ~(icache_line_size - 1);
+ protected_flush_icache_line(iaddr);
+}
static void sb1_flush_cache_sigtramp(unsigned long addr)
{
- smp_call_function(sb1_flush_cache_sigtramp_ipi, (void *) addr, 1, 1);
+ unsigned long tmp;
+
+ /*
+ * Flush the local dcache, then load the instruction back into a
+ * register. That will make sure that any remote CPU also has
+ * written back it's data cache to memory.
+ */
local_sb1_flush_cache_sigtramp(addr);
+ __get_user(tmp, (unsigned long *)addr);
+
+ smp_call_function(sb1_flush_cache_sigtramp_ipi, (void *) addr, 1, 1);
}
+
#else
void sb1_flush_cache_sigtramp(unsigned long addr);
asm("sb1_flush_cache_sigtramp = local_sb1_flush_cache_sigtramp");
|