From: Alex Williamson Date: Fri, 12 Oct 2007 20:27:51 +0000 (-0600) Subject: [IA64] vti domain save/restore: fix stack unwinder X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~14872 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=b22b572a3a50adff59855c147bcf463bd51ec535;p=xen.git [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 --- diff --git a/xen/arch/ia64/linux-xen/unwind.c b/xen/arch/ia64/linux-xen/unwind.c index 2933a5b02f..6c46e2b3f5 100644 --- a/xen/arch/ia64/linux-xen/unwind.c +++ b/xen/arch/ia64/linux-xen/unwind.c @@ -1847,6 +1847,16 @@ run_script (struct unw_script *script, struct unw_frame_info *state) goto redo; } +#ifdef XEN +static inline int +is_hypervisor_virt(unsigned long addr) +{ + return IS_VMM_ADDRESS(addr) && + (HYPERVISOR_VIRT_START <= addr) && + (addr < HYPERVISOR_VIRT_END); +} +#endif + static int find_save_locs (struct unw_frame_info *info) { @@ -1857,6 +1867,8 @@ find_save_locs (struct unw_frame_info *info) if ((info->ip & (local_cpu_data->unimpl_va_mask | 0xf)) #ifndef XEN || info->ip < TASK_SIZE +#else + || !is_hypervisor_virt(info->ip) #endif ) { /* don't let obviously bad addresses pollute the cache */ @@ -1915,7 +1927,11 @@ unw_unwind (struct unw_frame_info *info) return -1; } ip = info->ip = *info->rp_loc; +#ifndef XEN if (ip < GATE_ADDR) { +#else + if (!is_hypervisor_virt(info->ip)) { +#endif UNW_DPRINT(2, "unwind.%s: reached user-space (ip=0x%lx)\n", __FUNCTION__, ip); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); return -1; @@ -1993,6 +2009,21 @@ unw_unwind_to_user (struct unw_frame_info *info) if (unw_is_intr_frame(info) && (pr & (1UL << PRED_USER_STACK))) return 0; +#ifdef XEN + /* + * vmx fault handlers don't always update vcpu->on_stack + * so that the above (pr & (1UL << PRED_USER_STACK)) condition + * isn't always true. + * hypercall path of break_fault does set pUStk=1, + * other fault paths don't set. + * + * we need to stop unwinding somehow. + */ + if (unw_is_intr_frame(info) && + info->task->domain->arch.is_vti && + info->pr_loc == &vcpu_regs(info->task)->pr) + return 0; +#endif if (unw_get_pr (info, &pr) < 0) { unw_get_rp(info, &ip); UNW_DPRINT(0, "unwind.%s: failed to read "