From: Hideo S. <sa...@de...> - 2007-02-20 05:43:31
|
On Tue, 20 Feb 2007 10:48:12 +0900, Paul Mundt <le...@li...> wrote: > Please also provide the n_aliases printk() from the boot log. Feb 17 08:31:05 shlinux kernel: [42949372.970000] I-cache : n_ways=4 n_sets=256 way_incr=8192 Feb 17 08:31:05 shlinux kernel: [42949372.970000] I-cache : entry_mask=0x00001fe0 alias_mask=0x00001000 n_aliases=2 Feb 17 08:31:05 shlinux kernel: [42949372.970000] D-cache : n_ways=4 n_sets=256 way_incr=8192 Feb 17 08:31:06 shlinux kernel: [42949372.970000] D-cache : entry_mask=0x00001fe0 alias_mask=0x00001000 n_aliases=2 Feb 17 08:31:06 shlinux kernel: [42949373.190000] Mount-cache hash table entries: 512 Feb 17 08:31:06 shlinux kernel: [42949373.190000] CPU: SH7780 > Can you move your __flush_wback_region() in to the else path in > flush_dcache_page() in arch/sh/mm/cache-sh4.c and see if the problem > persists? I backed out the change for install_arg_page() at fs/exec.c and applied following patch and tested it using appended test program. I can not see this problem by my test. --- arch/sh/mm/cache-sh4.c.org Mon Feb 5 03:44:54 2007 +++ arch/sh/mm/cache-sh4.c Tue Feb 20 12:59:46 2007 @@ -243,16 +243,21 @@ void flush_dcache_page(struct page *page unsigned long phys = PHYSADDR(page_address(page)); unsigned long addr = CACHE_OC_ADDRESS_ARRAY; int i, n; /* Loop all the D-cache */ n = cpu_data->dcache.n_aliases; for (i = 0; i < n; i++, addr += 4096) flush_cache_4096(addr, phys); + } else { + unsigned long phys = PHYSADDR(page_address(page)); + int size = cpu_data->dcache.n_aliases << PAGE_SHIFT; + + __flush_wback_region((void *)P1SEGADDR(phys), size); } wmb(); } /* TODO: Selective icache invalidation through IC address array.. */ static inline void flush_icache_all(void) { -error log if original code--------------------------- % ./vfork_test ******29 != 30 *stat = 0x100 -test programs---------------------------------------- % gcc -o args args.c % gcc -o vfork_test vfork_test.c -args.c----------------------------------------------- #include <stdio.h> #include <stdlib.h> int main(int ac, char **av) { int n = 1; int nn = 0; int err = 0; ac--, av++; while (ac > 0) { nn = atoi(*av); if (nn != n) { fprintf(stderr, "%d != %d\n", nn , n); err++; break; } n++; ac--, av++; } fprintf(stderr, "*"); exit(err); } -vfork_test.c------------------------------------------------- #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> #define ARGS 1000 char* argv[ARGS]; exec_test(int ac, char** av) { int id, stat; id = vfork(); if (id == 0) { execve("./args", argv, NULL); fprintf(stderr, "can not exec args command\n"); exit(0); } wait(&stat); return stat; } int main(int ac, char** av) { int i, stat; char* str; str = calloc(ARGS, 12); for (i = 0; i < ARGS; i++) { sprintf(str, "%010d", i); argv[i] = str; str += strlen(str) + 1; } for (;;) { stat = exec_test(ARGS, argv); if (WEXITSTATUS(stat) != 0) { printf("stat = 0x%x\n", stat); exit(1); } } } |