Re: Oopses and invalid addresses under Hatari

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

(I'm not on linux-m68k list, that's why I included everybody in
mail thread to CC.)

On 4/9/19 6:59 AM, Michael Schmitz wrote:
Yep, works for me as well (030 so probably no surprise):

Ok, now that it's been confirmed on real HW, I'll add the details
I had earlier mailed to Finn.


I found this crash when investigating Hatari complains of accesses
to non-mapped memory, and some random Oopses I was seeing.

When I enabled kernel CPU symbols tracing, I found out that the access
warnings were related to user space <-> kernel interface:
------------------------------
ret_from_syscall:
DEBUG: Your Atari program just did something terribly stupid:
BusErrMem_xlate($800138b0)
DEBUG: Your Atari program just did something terribly stupid:
BusErrMem_xlate($800127ee)
DEBUG: Your Atari program just did something terribly stupid:
BusErrMem_xlate($80014270)
DEBUG: Your Atari program just did something terribly stupid:
BusErrMem_xlate($800149a6)
DEBUG: Your Atari program just did something terribly stupid:
BusErrMem_xlate($80015fca)
system_call:
------------------------------


Looking at the crashing code in Hatari, and the register dump,
the issues is that A0 gotten from stack is NULL:
------------------------------
> d __generic_copy_from_user
__generic_copy_from_user:
$00249f3c : 4e56 0000  link      a6,#0
$00249f40 : 2f02       move.l    d2,-(sp)
$00249f42 : 222e 0010  move.l    $10(a6),d1
$00249f46 : 2001       move.l    d1,d0
$00249f48 : e488       lsr.l     #2,d0
$00249f4a : 7403       moveq     #3,d2
$00249f4c : c282       and.l     d2,d1
$00249f4e : 206e 000c  movea.l   $c(a6),a0
$00249f52 : 226e 0008  movea.l   8(a6),a1
$00249f56 : 4a80       tst.l     d0
$00249f58 : 670a       beq.s     $249f64
$00249f5a : 0e98 2000  moves.l   (a0)+,d2 <= ***
------------------------------


Hatari profiling with suitable breakpoint:
------------------------------
> profile on
> b pc = "__generic_copy_from_user+0x1e" && a0 < 0x1000
> c
------------------------------

Gives more accurate backtrace than the kernel provided one:
------------------------------
- 0x249f3c: __generic_copy_from_user (return = 0x64f6a)
- 0x64f40: __probe_kernel_read (return = 0x37b0e)
- 0x37a84: print_worker_info (return = 0x3ef6c)
- 0x3eed2: sched_show_task (return = 0x3f020)
- 0x3ef88: show_state_filter (return = 0x149826)
- 0x14981a: sysrq_handle_showstate (return = 0x149d18)
- 0x149ca4: __handle_sysrq (return = 0x14a03a)
- 0x14a014: write_sysrq_trigger (return = 0xcf4b8)
- 0xcf472: proc_reg_write (return = 0x92506)
- 0x924d8: __vfs_write (return = 0x9277c)
- 0x926f6: vfs_write (return = 0x92922)
- 0x928e4: ksys_write (return = 0x92980)
- 0x9296a: __se_sys_write (return = 0x2874)
------------------------------


Looking at print_worker_info() code involved in the crash:
----------------------------
        /*
         * This function is called without any synchronization and @task
         * could be in any state.  Be careful with dereferences.
         */
        worker = kthread_probe_data(task);

        /*
         * Carefully copy the associated workqueue's workfn, name and desc.
         * Keep the original last '\0' in case the original is garbage.
         */
        probe_kernel_read(&fn, &worker->current_func, sizeof(fn));
        probe_kernel_read(&pwq, &worker->current_pwq, sizeof(pwq));
        probe_kernel_read(&wq, &pwq->wq, sizeof(wq));
        probe_kernel_read(name, wq->name, sizeof(name) - 1);
        probe_kernel_read(desc, worker->desc, sizeof(desc) - 1);
----------------------------

It seems that print_worker_info() got NULL from kthread_probe_data(),
but didn't have check for that, and went happily calling probe_kernel_read() with it.

A potentially good question is why kthread_probe_data() would return
NULL on 030:
----------------------------
/**
 * kthread_probe_data - speculative version of kthread_data()
 * @task: possible kthread task in question
 *
 * @task could be a kthread task.  Return the data value specified when it
 * was created if accessible.  If @task isn't a kthread task or its data is
 * inaccessible for any reason, %NULL is returned.  This function requires
 * that @task itself is safe to dereference.
 */
void *kthread_probe_data(struct task_struct *task)
{
        struct kthread *kthread = to_kthread(task);
        void *data = NULL;

        probe_kernel_read(&data, &kthread->data, sizeof(data));
        return data;
}
----------------------------

My guess would be that it's inaccessible, and warnings Hatari was
giving on every syscall are somehow related to it.


Btw. The reason why Hatari profiler gave better backtrace than kernel
unwinder, is that Hatari doesn't do unwinding.  It adds calls to its
callstack based when addresses listed in the kernel symbols list
are visited, and pops them from callstack on return.

However, kernel does something in schedule/idle to confuse latter.
Is kernel doing any explicit stack manipulation that would change
the return address?

(E.g. in EmuTOS ROM, "switchto" function changes its return address
in stack to divert CPU to next task on "switchto" function return.)


	- Eero



[Index of Archives]     [Video for Linux]     [Yosemite News]     [Linux S/390]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux