ia64/xen-unstable

changeset 16109:3d11c7ad9e87

[IA64] vti domain save/restore: fix stack unwinder

fix stack unwinder.
- fix find_save_locs() and unw_unwind().
instruction pointer check should be suite for xen.
- fix unw_unwind_to_user()
VTi domain fault handler doesn't always updatevcpu->on_stack so that
the pUStk check fails. Add more checking to stop winding.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author Alex Williamson <alex.williamson@hp.com>
date Fri Oct 12 14:27:51 2007 -0600 (2007-10-12)
parents 64ffc61b940b
children e120054bf0ac
files xen/arch/ia64/linux-xen/unwind.c
line diff
     1.1 --- a/xen/arch/ia64/linux-xen/unwind.c	Fri Oct 12 14:23:38 2007 -0600
     1.2 +++ b/xen/arch/ia64/linux-xen/unwind.c	Fri Oct 12 14:27:51 2007 -0600
     1.3 @@ -1847,6 +1847,16 @@ run_script (struct unw_script *script, s
     1.4  	goto redo;
     1.5  }
     1.6  
     1.7 +#ifdef XEN
     1.8 +static inline int
     1.9 +is_hypervisor_virt(unsigned long addr)
    1.10 +{
    1.11 +	return IS_VMM_ADDRESS(addr) &&
    1.12 +		(HYPERVISOR_VIRT_START <= addr) &&
    1.13 +		(addr < HYPERVISOR_VIRT_END);
    1.14 +}
    1.15 +#endif
    1.16 +
    1.17  static int
    1.18  find_save_locs (struct unw_frame_info *info)
    1.19  {
    1.20 @@ -1857,6 +1867,8 @@ find_save_locs (struct unw_frame_info *i
    1.21  	if ((info->ip & (local_cpu_data->unimpl_va_mask | 0xf))
    1.22  #ifndef XEN
    1.23  	    || info->ip < TASK_SIZE
    1.24 +#else
    1.25 +	    || !is_hypervisor_virt(info->ip)
    1.26  #endif
    1.27  		) {
    1.28  		/* don't let obviously bad addresses pollute the cache */
    1.29 @@ -1915,7 +1927,11 @@ unw_unwind (struct unw_frame_info *info)
    1.30  		return -1;
    1.31  	}
    1.32  	ip = info->ip = *info->rp_loc;
    1.33 +#ifndef XEN
    1.34  	if (ip < GATE_ADDR) {
    1.35 +#else
    1.36 +	if (!is_hypervisor_virt(info->ip)) {
    1.37 +#endif
    1.38  		UNW_DPRINT(2, "unwind.%s: reached user-space (ip=0x%lx)\n", __FUNCTION__, ip);
    1.39  		STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
    1.40  		return -1;
    1.41 @@ -1993,6 +2009,21 @@ unw_unwind_to_user (struct unw_frame_inf
    1.42  		if (unw_is_intr_frame(info) &&
    1.43  		    (pr & (1UL << PRED_USER_STACK)))
    1.44  			return 0;
    1.45 +#ifdef XEN
    1.46 +		/*
    1.47 +		 * vmx fault handlers don't always update vcpu->on_stack
    1.48 +		 * so that the above (pr & (1UL << PRED_USER_STACK)) condition
    1.49 +		 * isn't always true.
    1.50 +		 * hypercall path of break_fault does set pUStk=1,
    1.51 +		 * other fault paths don't set.
    1.52 +		 *
    1.53 +		 * we need to stop unwinding somehow.
    1.54 +		 */
    1.55 +		if (unw_is_intr_frame(info) &&
    1.56 +		    info->task->domain->arch.is_vti &&
    1.57 +		    info->pr_loc == &vcpu_regs(info->task)->pr)
    1.58 +			return 0;
    1.59 +#endif
    1.60  		if (unw_get_pr (info, &pr) < 0) {
    1.61  			unw_get_rp(info, &ip);
    1.62  			UNW_DPRINT(0, "unwind.%s: failed to read "