On Tue, Aug 28, 2012 at 4:13 PM, Ralf Baechle <ralf@xxxxxxxxxxxxxx> wrote: > On Tue, Aug 28, 2012 at 09:42:51AM +0800, Lin Ming wrote: > >> Hi list, >> >> I'm working on a board running 2.6.30 kernel. >> The panic log is attached in the end. >> >> 8002c098: 0c00aeaa jal 8002baa8 <__remove_hrtimer> >> 8002c09c: 00003821 move a3,zero >> 8002c0a0: 8e220020 lw v0,32(s1) >> 8002c0a4: 0040f809 jalr v0 >> 8002c0a8: 02202021 move a0,s1 >> 8002c0ac: 02002821 move a1,s0 >> ------> panic happens here. >> But this instruction just move data between registers. >> How could it cause memory access panic? > > in case of a jal or jalr instruction the return address will point to the > instruction of the jal(r) instruction plus 2 instruction as here. This > is where in case of a successful return from the subroutine execution > would continue. > > But in your case v0 (that's register $2) contains 0 and it's been loaded > from address 32(s1) before, so it would appear that memory at that > address has either been overwritten or not initialized. You are right. It should be panic at 8002c0a4. $ addr2line -i -e vmlinux 8002c0a4 linux-2.6.30/kernel/hrtimer.c:1164 Line 1164: fn = timer->function; restart = fn(timer); <---- line 1164 Seems "fn" is corrupted.... Thanks for the info! static void __run_hrtimer(struct hrtimer *timer) { struct hrtimer_clock_base *base = timer->base; struct hrtimer_cpu_base *cpu_base = base->cpu_base; enum hrtimer_restart (*fn)(struct hrtimer *); int restart; WARN_ON(!irqs_disabled()); debug_hrtimer_deactivate(timer); __remove_hrtimer(timer, base, HRTIMER_STATE_CALLBACK, 0); timer_stats_account_hrtimer(timer); fn = timer->function; /* * Because we run timers from hardirq context, there is no chance * they get migrated to another cpu, therefore its safe to unlock * the timer base. */ spin_unlock(&cpu_base->lock); restart = fn(timer); <----------- line 1164 spin_lock(&cpu_base->lock); /* * Note: We clear the CALLBACK bit after enqueue_hrtimer and * we do not reprogramm the event hardware. Happens either in * hrtimer_start_range_ns() or in hrtimer_interrupt() */ if (restart != HRTIMER_NORESTART) { BUG_ON(timer->state != HRTIMER_STATE_CALLBACK); enqueue_hrtimer(timer, base); } timer->state &= ~HRTIMER_STATE_CALLBACK; } > > Ralf