From: James S. <jsi...@us...> - 2002-03-18 22:25:58
|
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"); |