On Tue, Aug 28, 2012 at 4:13 PM, Ralf Baechle <ralf@linux-mips.org> 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
|