<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
Isaku Yamahata wrote:
<blockquote TYPE=CITE>On Wed, Dec 20, 2006 at 10:15:32AM -0500, Dave Anderson
wrote:
<p>> - Introduced support for xendumps of para-virtualized ia64 kernels.
<br>>   It should be noted that currently the ia64 Xen kernel
does not
<br>>   lay down a switch_stack for the panic task, so only raw
"bt -t"
<br>>   backtraces can be done on the panic task.  (anderson@redhat.com)
<p>Hi Dave.
<p>The current "xm dump-core" on ia64 loses some registers infomation
<br>which is saved on xen register stack.
<br>e.g. r33, ... aren't saved in domU xendump file.
<br>Probably ia64 specific code would be necessarry for it.
<br>This will be addressed as post-3.0.4 effort and the format will be
changed.
<p>--
<br>yamahata</blockquote>
I'm not sure exactly what the ramifications are of an ia64 "xm dump-core"
<br>on a paravirtualized kernel.  It would seem to depend upon what,
if anything,
<br>was "active" at the time.
<p>My reference to the switch_stack above was for an ia64 kernel that panicked
<br>on its own account; the test dump I used was killed with a write to
<br>/proc/sysrq-trigger:
<p>.crash> bt
<br>PID: 1554   TASK: e000000000988000  CPU: 0  
COMMAND: "bash"
<br>bt: xendump: switch_stack possibly not saved -- try "bt -t"
<br> #0 [BSP:e000000000988f00] schedule at a0000001005e0420
<br>crash>
<p>It uses the stale information from the last time it called schedule(),
<br>so the backtrace fails.
<p>Using "bt -t" walks the process stack for kernel return addresses,
<br>and the "reverse" BSP information just above the task_struct shows
<br>the path taken:
<p>crash> bt -t
<br>PID: 1554   TASK: e000000000988000  CPU: 0  
COMMAND: "bash"
<br>             
START: schedule at a0000001005e0420
<br>  [e000000000989238] xen_trace_syscall at a000000100065020
<br>  [e000000000989288] sys_write at a000000100155d30
<br>  [e0000000009892b8] vfs_write at a0000001001551e0
<br>  [e000000000989308] write_sysrq_trigger at a0000001001e3250
<br>  [e000000000989320] __handle_sysrq at a00000010039bca0
<br>  [e000000000989380] sysrq_handle_crashdump at a00000010039c460
<br>  [e0000000009893e8] do_wait at a00000010008b080
<br>  [e000000000989438] schedule_timeout at a0000001005e22a0
<br>  [e000000000989450] ext3_lookup at a0000002001eb7d0
<br>  [e000000000989460] cleanup_module at a000000200202a10
<br>  [e000000000989470] ext3_find_entry at a0000002001e77c0
<br>  [e0000000009894b0] __wait_on_buffer at a00000010015b580
<br>  [e0000000009894c0] ll_rw_block at a00000010015c2b0
<br>  [e000000000989500] out_of_line_wait_on_bit at a0000001005e2940
<br>  [e000000000989520] __wait_on_bit at a0000001005e27d0
<br>  [e000000000989540] sync_buffer at a00000010015b7c0
<br>  [e000000000989558] io_schedule at a0000001005e2170
<br>  [e000000000989588] __delayacct_blkio_start at a0000001000fa4b0
<br>  [e000000000989608] io_schedule at a0000001005e21a0
<br>  [e000000000989630] __do_IRQ at a0000001000f2450
<br>  [e000000000989660] do_softirq at a000000100093100
<br>  [e000000000989698] blkif_int at a000000200152070
<br>  [e000000000989710] end_that_request_first at a00000010027ae30
<br>  [e000000000989748] __end_that_request_first at a00000010027a460
<br>  [e000000000989778] bio_endio at a0000001001622b0
<br>  [e00000000098fca0] schedule at a0000001005e0420
<br>  [e00000000098fd10] vhpt_miss at a000000100000002
<br>  [e00000000098fd60] vhpt_miss at a000000100000002
<br>  [e00000000098fdc8] dummycon_dummy at a0000001002dd380
<br>  [e00000000098fdd0] vhpt_miss at a000000100000003
<br>crash>
<p>Well, it at least shows it going as far as sysrq_handle_crashdump(),
<br>and any further addresses of function calls were never pushed into
<br>the BSP.  (?)
<p>Anyway, the problem is that the ia64 shutdown path in a para-virtualized
ia64
<br>kernel does not lay down a switch_stack -- as is done by the netdump,
<br>diskdump and kdump facilities.  Without a switch_stack register
dump,
<br>a backtrace is impossible.
<p>It's a simple thing to do -- at some point during the shutdown
<br>path, presumably xen_panic_event(), the panicking process would
<br>need to make a call to the unw_init_running() function, which lays
<br>down a switch_stack on the kernel stack, and then continues on to
<br>the next function in the shutdown path.  For example, the kdump
<br>facility for ia64 does this:
<p>[ system crashes ]
<br>  crash_kexec()
<br>    machine_kexec()
<br>       ...
<p>The ia64 version of machine_kexec() does this:
<p>void machine_kexec(struct kimage *image)
<br>{
<br>        unw_init_running(ia64_machine_kexec,
image);
<br>        for(;;);
<br>}
<p>The call to unw_init_running() never returns, but rather
<br>it lays down a switch_stack on the kernel stack, and then
<br>calls the ia64_machine_kexec() function:
<p>extern void *efi_get_pal_addr(void);
<br>static void ia64_machine_kexec(struct unw_frame_info *info, void *arg)
<br>{
<br>        struct kimage *image = arg;
<br>        relocate_new_kernel_t rnk;
<br>        void *pal_addr = efi_get_pal_addr();
<br>        unsigned long code_addr
= (unsigned long)page_address(image->control_code_page);
<br>        unsigned long vector;
<br>        int ii;
<p>        if (image->type == KEXEC_TYPE_CRASH)
{
<br>               
crash_save_this_cpu();
<br>               
<b>current->thread.ksp = (__u64)info->sw - 16;</b>
<br>        }
<p>        ... (continue shutdown path)
<p>The address of the switch stack address is found in the unw_frame_info
<br>structure passed in, and gets stored in the current->thread.ksp of
<br>the panicking task.  With that simple procedure, the crash utility
<br>will then have all that it needs to do a backtrace of the panicking
task.
<p>Since the para-virtualized ia64 kernel shuts down when panic()
<br>calls atomic_notifier_call_chain(), which in turn goes through the
<br>panic_notifier list -- which leads to the ia64 version of xen_panic_event():
<p>static int
<br>xen_panic_event(struct notifier_block *this, unsigned long event, void
*ptr)
<br>{
<br>        HYPERVISOR_shutdown(SHUTDOWN_crash);
<br>        /* we're never actually
going to get here... */
<br>        return NOTIFY_DONE;
<br>}
<p>The ia64 would need to "jump through the hoop" of a call to
<br>unw_init_running() before it calls HYPERVISOR_shutdown()
<p>Thanks,
<br>  Dave</html>