From: Hideo S. <sa...@de...> - 2007-02-20 01:03:28
|
Hi, I am H.Saito. It seems that a synonym problem issues on linux-2.6.20 for SH4. The problem is that some virtual addresses are mapped onto a single physical address as follows. The following log is our debugger's log when broke at line 257 in fs/binfmt_elf.c. #d 8eab33c0 LOC. 0 4 8 c ASCII-CODE ---------------------------------------------------------------------- 8eab 33c0 : 3334 3330 3030 3000 3030 3030 0034 3433 / 0343.0000000344. 8eab 33d0 : 3030 3030 3330 3030 3000 3534 3030 3030 / 0000000345.00000 8eab 33e0 : 3433 3030 3030 0036 3030 3030 3734 3330 / 00346.0000000347 8eab 33f0 : 3030 3000 3030 3030 0038 3433 3030 3030 / .0000000348.0000 8eab 3400 : 3330 3030 3000 3934 3030 3030 3533 3030 / 000349.000000035 8eab 3410 : 3030 0030 3030 3030 3135 3330 3030 3000 / 0.0000000351.000 8eab 3420 : 3030 3030 0032 3533 3030 3030 3330 3030 / 0000352.00000003 8eab 3430 : 3000 3335 3030 3030 3533 3030 3030 0034 / 53.0000000354.00 #d 7bd823c0 LOC. 0 4 8 c ASCII-CODE ---------------------------------------------------------------------- 7bd8 23c0 : 0000 0000 0000 0000 0000 0000 0000 0000 / ................ 7bd8 23d0 : 0000 0000 0000 0000 0000 0000 0000 0000 / ................ 7bd8 23e0 : 3433 3030 3030 0036 3030 3030 3734 3330 / 00346.0000000347 7bd8 23f0 : 3030 3000 3030 3030 0038 3433 3030 3030 / .0000000348.0000 7bd8 2400 : 3330 3030 3000 3934 3030 3030 3533 3030 / 000349.000000035 7bd8 2410 : 3030 0030 3030 3030 3135 3330 3030 3000 / 0.0000000351.000 7bd8 2420 : 3030 3030 0032 3533 3030 3030 3330 3030 / 0000352.00000003 7bd8 2430 : 3000 3335 3030 3030 3533 3030 3030 0034 / 53.0000000354.00 #s f40053c0 f400 53c0 : 4eab 3003 #s f40043c0 f400 43c0 : 4eab 3001 OC address array for 0x8eab33c0 is 0xf40053c0 on way2. OC address array for 0x7bd823c0 is 0xf40043c0 on way2. The physical memory area is in from 0x48000000 to 0x48ffffff. The cached data line on 0x7bd823c0 can not be read because the data line on 0x8eab33c0 is not moved to the physical address yet. This problem is caused when a process is executed after vfork. In the result, the executed process can not read the arguments correctly. I think that the copied arguments from parent process should be copied back to the physical memory as following patch, in other words, a mapped page to process should be copied back to the physical memory unconditionally. --- fs/exec.c.org Mon Feb 5 03:44:54 2007 +++ fs/exec.c Sat Feb 17 17:54:53 2007 @@ -308,17 +308,21 @@ void install_arg_page(struct vm_area_str { struct mm_struct *mm = vma->vm_mm; pte_t * pte; spinlock_t *ptl; if (unlikely(anon_vma_prepare(vma))) goto out; +#if 0 flush_dcache_page(page); +#else + __flush_wback_region((void *)P1SEGADDR(PHYSADDR(page_address(page))), PA GE_SIZE); +#endif pte = get_locked_pte(mm, address, &ptl); if (!pte) goto out; if (!pte_none(*pte)) { pte_unmap_unlock(pte, ptl); goto out; } inc_mm_counter(mm, anon_rss); |
From: Paul M. <le...@li...> - 2007-02-20 01:50:35
|
Saito-san, On Tue, Feb 20, 2007 at 10:03:15AM +0900, Hideo Saito wrote: > This problem is caused when a process is executed after vfork. In the > result, the executed process can not read the arguments correctly. > > I think that the copied arguments from parent process should be copied > back to the physical memory as following patch, in other words, a > mapped page to process should be copied back to the physical memory > unconditionally. > This is quite interesting. These are anonymous pages, so page->mapping will be NULL unless you've got a swap cache page. The writeback should not be deferred in this case. 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? Please also provide the n_aliases printk() from the boot log. |
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); } } } |
From: Paul M. <le...@li...> - 2007-03-05 11:01:37
|
On Tue, Feb 20, 2007 at 02:43:12PM +0900, Hideo Saito wrote: > On Tue, 20 Feb 2007 10:48:12 +0900, Paul Mundt <le...@li...> wrote: > > 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. > Now that we've reverted to PG_mapped, can you try current git and verify whether your test program causes any problems for you or not? I've not been able to reproduce your crash.. |