From: NIIBE Y. <gn...@m1...> - 2001-01-23 07:57:54
|
SUGIOKA Toshinobu wrote: > Currently flush_icache_range uses A-bit. but A-bit works only when > ITLB entry exists. UTLB entry should not work. > So every I-cache entry should be compared with physical address by hand > or all I-cache should be invalidated. Umm... I didn't know that. I've checked the hardware manual, and you're right. We need ITLB entry to flush I-cache with A-bit. While The Right Thing may be fixing flush_icache_range, I'm not sure about the semantics well, right now. It seems for me that we don't need to purge out the I-cache, but just write back D-cache, with newer scheme (Documentation/cachetlb.txt), but I'm not sure. Besides, currently, the arguments (START, END) to flush_icache_range is large one (i.e. mmap ranges) except signal handling, so we need to re-write the function anyway. Could you please try this out? This purges the entry regardless it's the page mapped or not. This also includes a bug fix of SH-3 shared page. X server worked quite badly in SH-3 implementation because of that. 2001-01-23 NIIBE Yutaka <gn...@m1...> * arch/sh/kernel/signal.c (setup_frame, setup_rt_frame): Use flush_cache_sigtramp. * arch/sh/mm/cache.c (flush_cache_sigtramp): Implemented. * include/asm-sh/pgtable.h (_PAGE_SHARED): Always _PAGE_U0_SHARED. (was conditionally _PAGE_HW_SHARED on SH-3). With _PAGE_HW_SHARED, all processes share the page, while proper semantics is "some processes share the page". (flush_cache_sigtramp): New function. Index: arch/sh/kernel/signal.c =================================================================== RCS file: /cvsroot/linuxsh/kernel/arch/sh/kernel/signal.c,v retrieving revision 1.13 diff -u -r1.13 signal.c --- arch/sh/kernel/signal.c 2000/09/04 06:41:45 1.13 +++ arch/sh/kernel/signal.c 2001/01/23 07:46:38 @@ -433,7 +433,7 @@ current->comm, current->pid, frame, regs->pc, regs->pr); #endif - flush_icache_range(regs->pr, regs->pr+4); + flush_cache_sigtramp(regs->pr); return; give_sigsegv: @@ -507,7 +507,7 @@ current->comm, current->pid, frame, regs->pc, regs->pr); #endif - flush_icache_range(regs->pr, regs->pr+4); + flush_cache_sigtramp(regs->pr); return; give_sigsegv: Index: arch/sh/mm/cache.c =================================================================== RCS file: /cvsroot/linuxsh/kernel/arch/sh/mm/cache.c,v retrieving revision 1.21 diff -u -r1.21 cache.c --- arch/sh/mm/cache.c 2000/09/18 05:15:35 1.21 +++ arch/sh/mm/cache.c 2001/01/23 07:46:38 @@ -244,6 +244,22 @@ } /* + * Write back the D-cache and purge the I-cache for signal trampoline. + */ +void flush_cache_sigtramp(unsigned long addr) +{ + unsigned long v, index; + + v = addr & ~(L1_CACHE_BYTES-1); + asm volatile("ocbwb %0" + : /* no output */ + : "m" (__m(v))); + + index = CACHE_IC_ADDRESS_ARRAY| (v&CACHE_IC_ENTRY_MASK); + ctrl_outl(0, index); /* Clear out Valid-bit */ +} + +/* * Invalidate the I-cache of the page (don't need to write back D-cache). * * Called from kernel/ptrace.c, mm/memory.c after flush_page_to_ram is called. Index: include/asm-sh/pgtable.h =================================================================== RCS file: /cvsroot/linuxsh/kernel/include/asm-sh/pgtable.h,v retrieving revision 1.16 diff -u -r1.16 pgtable.h --- include/asm-sh/pgtable.h 2000/11/22 07:05:18 1.16 +++ include/asm-sh/pgtable.h 2001/01/23 07:46:41 @@ -39,6 +39,7 @@ #define flush_dcache_page(page) do { } while (0) #define flush_icache_range(start, end) do { } while (0) #define flush_icache_page(vma,pg) do { } while (0) +#define flush_cache_sigtramp(vaddr) do { } while (0) #elif defined(__SH4__) /* * Caches are broken on SH-4, so we need them. @@ -52,6 +53,7 @@ extern void flush_dcache_page(struct page *pg); extern void flush_icache_range(unsigned long start, unsigned long end); extern void flush_icache_page(struct vm_area_struct *vma, struct page *pg); +extern void flush_cache_sigtramp(unsigned long addr); #endif /* @@ -125,11 +127,7 @@ /* Hardware flags: SZ=1 (4k-byte) */ #define _PAGE_FLAGS_HARD 0x00000010 -#if defined(__sh3__) -#define _PAGE_SHARED _PAGE_HW_SHARED -#elif defined(__SH4__) #define _PAGE_SHARED _PAGE_U0_SHARED -#endif #define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY) #define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) -- |