static int kgdb_get_blocked_state(struct vcpu *p, struct cpu_user_regs *regs, struct unw_frame_info *unw) #endif { unsigned long ip; int count = 0; #ifndef XEN unw_init_from_blocked_task(unw, p); #endif ip = 0UL; do { if (unw_unwind(unw) < 0) return -1; unw_get_ip(unw, &ip); #ifndef XEN if (!in_sched_functions(ip)) break; #else dbg_printk("ip 0x%lx cr_iip 0x%lx\n", ip, regs->cr_iip); if (ip == regs->cr_iip) break; #endif } while (count++ < 16); if (!ip) return -1; else return 0; }
static void ia64_do_save_stack(struct unw_frame_info *info, void *arg) { struct stack_trace *trace = arg; unsigned long ip; int skip = trace->skip; trace->nr_entries = 0; do { unw_get_ip(info, &ip); if (ip == 0) break; if (skip == 0) { trace->entries[trace->nr_entries++] = ip; if (trace->nr_entries == trace->max_entries) break; } else skip--; } while (unw_unwind(info) >= 0); }
static void do_ia64_backtrace(struct unw_frame_info *info, void *vdata) { ia64_backtrace_t *bt = vdata; struct switch_stack *sw; int count = 0; u_long pc, sp; sw = (struct switch_stack *)(info+1); /* */ sw = (struct switch_stack *)(((unsigned long)sw + 15) & ~15); unw_init_frame_info(&bt->frame, current, sw); /* */ do { unw_get_sp(&bt->frame, &sp); if (sp >= (u_long)bt->regs) break; if (!next_frame(bt)) return; } while (count++ < 200); /* */ while (bt->depth-- && next_frame(bt)) { unw_get_ip(&bt->frame, &pc); oprofile_add_trace(pc); if (unw_is_intr_frame(&bt->frame)) { /* */ /* */ break; } } }
static void do_ia64_backtrace(struct unw_frame_info *info, void *vdata) { ia64_backtrace_t *bt = vdata; struct switch_stack *sw; int count = 0; u_long pc, sp; sw = (struct switch_stack *)(info+1); /* padding from unw_init_running */ sw = (struct switch_stack *)(((unsigned long)sw + 15) & ~15); unw_init_frame_info(&bt->frame, current, sw); /* skip over interrupt frame and oprofile calls */ do { unw_get_sp(&bt->frame, &sp); if (sp >= (u_long)bt->regs) break; if (!next_frame(bt)) return; } while (count++ < 200); /* finally, grab the actual sample */ while (bt->depth-- && next_frame(bt)) { unw_get_ip(&bt->frame, &pc); oprofile_add_trace(pc); if (unw_is_intr_frame(&bt->frame)) { /* * Interrupt received on kernel stack; this can * happen when timer interrupt fires while processing * a softirq from the tail end of a hardware interrupt * which interrupted a system call. Don't laugh, it * happens! Splice the backtrace into two parts to * avoid spurious cycles in the gprof output. */ /* TODO: split rather than drop the 2nd half */ break; } } }
void kgdb_get_reg(char *outbuffer, int regnum, struct unw_frame_info *info, struct pt_regs *ptregs) { unsigned long reg, size = 0, *mem = ® char nat; struct ia64_fpreg freg; int i; if ((regnum >= IA64_GR0_REGNUM && regnum <= (IA64_GR0_REGNUM + 1)) || (regnum >= (IA64_GR0_REGNUM + 4) && regnum <= (IA64_GR0_REGNUM + 7)) || (regnum >= (IA64_GR0_REGNUM + 16) && regnum <= (IA64_GR0_REGNUM + 31))) { unw_access_gr(info, regnum - IA64_GR0_REGNUM, ®, &nat, 0); size = sizeof(reg); } else if ((regnum >= (IA64_GR0_REGNUM + 2) && regnum <= (IA64_GR0_REGNUM + 3)) || (regnum >= (IA64_GR0_REGNUM + 8) && regnum <= (IA64_GR0_REGNUM + 15))) { if (ptregs) { for (i = 0; i < (sizeof(gr_reg_to_ptreg_index) / sizeof(gr_reg_to_ptreg_index[0])); i++) if (gr_reg_to_ptreg_index[0].reg == regnum) { reg = *((unsigned long *) (((void *)ptregs) + gr_reg_to_ptreg_index[i].ptregoff)); break; } } else unw_access_gr(info, regnum - IA64_GR0_REGNUM, ®, &nat, 0); size = sizeof(reg); } else if (regnum >= IA64_BR0_REGNUM && regnum <= (IA64_BR0_REGNUM + 7)) switch (regnum) { case IA64_BR0_REGNUM: case IA64_BR0_REGNUM + 6: case IA64_BR0_REGNUM + 7: if (ptregs) { for (i = 0; i < (sizeof(br_reg_to_ptreg_index) / sizeof(br_reg_to_ptreg_index [0])); i++) if (br_reg_to_ptreg_index[i].reg == regnum) { reg = *((unsigned long *) (((void *)ptregs) + br_reg_to_ptreg_index [i].ptregoff)); break; } } else unw_access_br(info, regnum - IA64_BR0_REGNUM, ®, 0); size = sizeof(reg); break; case IA64_BR0_REGNUM + 1: case IA64_BR0_REGNUM + 2: case IA64_BR0_REGNUM + 3: case IA64_BR0_REGNUM + 4: case IA64_BR0_REGNUM + 5: unw_access_br(info, regnum - IA64_BR0_REGNUM, ®, 0); size = sizeof(reg); break; } else if (regnum >= IA64_FR0_REGNUM && regnum <= (IA64_FR0_REGNUM + 127)) switch (regnum) { case IA64_FR0_REGNUM + 6: case IA64_FR0_REGNUM + 7: case IA64_FR0_REGNUM + 8: case IA64_FR0_REGNUM + 9: case IA64_FR0_REGNUM + 10: case IA64_FR0_REGNUM + 11: case IA64_FR0_REGNUM + 12: if (!ptregs) unw_access_fr(info, regnum - IA64_FR0_REGNUM, &freg, 0); else { freg = *(&ptregs->f6 + (regnum - (IA64_FR0_REGNUM + 6))); } size = sizeof(freg); mem = (unsigned long *)&freg; break; default: unw_access_fr(info, regnum - IA64_FR0_REGNUM, &freg, 0); break; } else if (regnum == IA64_IP_REGNUM) { if (!ptregs) unw_get_ip(info, ®); else reg = ptregs->cr_iip; size = sizeof(reg); } else if (regnum == IA64_CFM_REGNUM) { if (!ptregs) unw_get_cfm(info, ®); else reg = ptregs->cr_ifs; size = sizeof(reg); } else if (regnum == IA64_PSR_REGNUM) { if (!ptregs && kgdb_usethread) ptregs = (struct pt_regs *) ((unsigned long)kgdb_usethread + IA64_STK_OFFSET) - 1; if (ptregs) reg = ptregs->cr_ipsr; size = sizeof(reg); } else if (regnum == IA64_PR_REGNUM) { if (ptregs) reg = ptregs->pr; else unw_access_pr(info, ®, 0); size = sizeof(reg); } else if (regnum == IA64_BSP_REGNUM) { unw_get_bsp(info, ®); size = sizeof(reg); } else if (regnum >= IA64_AR0_REGNUM && regnum <= IA64_EC_REGNUM) switch (regnum) { case IA64_CSD_REGNUM: if (ptregs) reg = ptregs->ar_csd; else unw_access_ar(info, UNW_AR_CSD, ®, 0); size = sizeof(reg); break; case IA64_SSD_REGNUM: if (ptregs) reg = ptregs->ar_ssd; else unw_access_ar(info, UNW_AR_SSD, ®, 0); size = sizeof(reg); break; case IA64_UNAT_REGNUM: if (ptregs) reg = ptregs->ar_unat; else unw_access_ar(info, UNW_AR_UNAT, ®, 0); size = sizeof(reg); break; case IA64_RNAT_REGNUM: unw_access_ar(info, UNW_AR_RNAT, ®, 0); size = sizeof(reg); break; case IA64_BSPSTORE_REGNUM: unw_access_ar(info, UNW_AR_BSPSTORE, ®, 0); size = sizeof(reg); break; case IA64_PFS_REGNUM: unw_access_ar(info, UNW_AR_PFS, ®, 0); size = sizeof(reg); break; case IA64_LC_REGNUM: unw_access_ar(info, UNW_AR_LC, ®, 0); size = sizeof(reg); break; case IA64_EC_REGNUM: unw_access_ar(info, UNW_AR_EC, ®, 0); size = sizeof(reg); break; case IA64_FPSR_REGNUM: if (ptregs) reg = ptregs->ar_fpsr; else unw_access_ar(info, UNW_AR_FPSR, ®, 0); size = sizeof(reg); break; case IA64_RSC_REGNUM: if (ptregs) reg = ptregs->ar_rsc; else unw_access_ar(info, UNW_AR_RNAT, ®, 0); size = sizeof(reg); break; case IA64_CCV_REGNUM: unw_access_ar(info, UNW_AR_CCV, ®, 0); size = sizeof(reg); break; } if (size) { kgdb_mem2hex((char *)mem, outbuffer, size); outbuffer[size * 2] = 0; } else strcpy(outbuffer, "E0"); return; }
static int kgdb_get_reg(int regnum, struct unw_frame_info *info, struct cpu_user_regs* ptregs, unsigned long* __reg, struct ia64_fpreg* __freg) #endif { unsigned long reg, size = 0, *mem = ® struct ia64_fpreg freg; if (kgdb_gr_reg(regnum, info, ®, 0) || kgdb_gr_ptreg(regnum, ptregs, info, ®, 0) || kgdb_br_reg(regnum, ptregs, info, ®, 0) || kgdb_ar_reg(regnum, ptregs, info, ®, 0)) size = sizeof(reg); else if (kgdb_fr_reg(regnum, NULL, ptregs, info, ®, &freg, 0)) { size = sizeof(freg); mem = (unsigned long *)&freg; } else if (regnum == IA64_IP_REGNUM) { if (!ptregs) { unw_get_ip(info, ®); size = sizeof(reg); } else { reg = ptregs->cr_iip; size = sizeof(reg); } } else if (regnum == IA64_CFM_REGNUM) { if (!ptregs) unw_get_cfm(info, ®); else reg = ptregs->cr_ifs; size = sizeof(reg); } else if (regnum == IA64_PSR_REGNUM) { #ifndef XEN if (!ptregs && kgdb_usethread) ptregs = (struct pt_regs *) ((unsigned long)kgdb_usethread + IA64_STK_OFFSET) - 1; #endif if (ptregs) reg = ptregs->cr_ipsr; size = sizeof(reg); } else if (regnum == IA64_PR_REGNUM) { if (ptregs) reg = ptregs->pr; else unw_access_pr(info, ®, 0); size = sizeof(reg); } else if (regnum == IA64_BSP_REGNUM) { unw_get_bsp(info, ®); size = sizeof(reg); } #ifndef XEN if (size) { kgdb_mem2hex((char *) mem, outbuffer, size); outbuffer[size*2] = 0; } else strlcpy(outbuffer, "E0", sizeof("E0")); return; #else if (size) { if (size == sizeof(reg)) { *__reg = reg; } else { BUG_ON(size != sizeof(freg)); *__freg = freg; } return 0; } return -1; #endif }