On Sat, Aug 17, 2019 at 03:12:41PM +0200, Philipp Richter wrote: > I added "memtest=4" to the kernel cmdline and I'm getting very quicky > a "Internal error: synchronous external abort" panic. [...] > [ 0.000000] early_memtest: # of tests: 4 > [ 0.000000] 0x0000000000200000 - 0x0000000002080000 pattern aaaaaaaaaaaaaaaa > [ 0.000000] 0x0000000003a95000 - 0x00000000f8400000 pattern aaaaaaaaaaaaaaaa > [ 0.000000] Internal error: synchronous external abort: 96000210 [#1] SMP At least it's a synchronous error ;). > [ 0.000000] pc : early_memtest+0x16c/0x23c [...] > [ 0.000000] Code: d2800002 d2800001 eb0400bf 54000309 (f9400080) decodecode says: 0: d2800002 mov x2, #0x0 // #0 4: d2800001 mov x1, #0x0 // #0 8: eb0400bf cmp x5, x4 c: 54000309 b.ls 0x6c // b.plast 10:* f9400080 ldr x0, [x4] <-- trapping instruction I guess that's the read of *p in memtest(). Writing *p probably generates asynchronous errors it you haven't seen it yet. > Is my board completely broken ? :( One possibility is that you don't have any memory where you think there is, so the mapping just doesn't translate to any valid physical location. Can you add some printk(addr) in do_sea() to see if it always faults on the same address? Another hack to hopefully track this down is to try to cope with such synchronous aborts and hopefully you won't hit an asynchronous one (SError). Quick hack below, only tested under kvm/qemu for booting and passing memtest: -----------8<------------------------- diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 2e6f42dc5a15..47efeedeccba 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -606,6 +606,9 @@ static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs) const struct fault_info *inf; void __user *siaddr; + if (!user_mode(regs) && fixup_exception(regs)) + return 0; + inf = esr_to_fault_info(esr); /* diff --git a/mm/memtest.c b/mm/memtest.c index f53ace709ccd..e878aa6bd1aa 100644 --- a/mm/memtest.c +++ b/mm/memtest.c @@ -3,6 +3,7 @@ #include <linux/types.h> #include <linux/init.h> #include <linux/memblock.h> +#include <linux/uaccess.h> static u64 patterns[] __initdata = { /* The first entry has to be 0 to leave memtest with zeroed memory */ @@ -38,6 +39,7 @@ static void __init memtest(u64 pattern, phys_addr_t start_phys, phys_addr_t size phys_addr_t start_bad, last_bad; phys_addr_t start_phys_aligned; const size_t incr = sizeof(pattern); + mm_segment_t old_fs; start_phys_aligned = ALIGN(start_phys, incr); start = __va(start_phys_aligned); @@ -45,12 +47,20 @@ static void __init memtest(u64 pattern, phys_addr_t start_phys, phys_addr_t size start_bad = 0; last_bad = 0; - for (p = start; p < end; p++) - *p = pattern; + old_fs = get_fs(); + set_fs(KERNEL_DS); + for (p = start; p < end; p++) { + u64 val; + if (!get_user(val, p)) + *p = pattern; + } for (p = start; p < end; p++, start_phys_aligned += incr) { - if (*p == pattern) - continue; + u64 val; + if (!get_user(val, p)) { + if (val == pattern) + continue; + } if (start_phys_aligned == last_bad + incr) { last_bad += incr; continue; @@ -61,6 +71,7 @@ static void __init memtest(u64 pattern, phys_addr_t start_phys, phys_addr_t size } if (start_bad) reserve_bad_mem(pattern, start_bad, last_bad + incr); + set_fs(old_fs); } static void __init do_one_pass(u64 pattern, phys_addr_t start, phys_addr_t end) _______________________________________________ Linux-rockchip mailing list Linux-rockchip@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/linux-rockchip