Esempio n. 1
0
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;
}
Esempio n. 2
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;
		}
	}
}
Esempio n. 5
0
void kgdb_get_reg(char *outbuffer, int regnum, struct unw_frame_info *info,
		  struct pt_regs *ptregs)
{
	unsigned long reg, size = 0, *mem = &reg;
	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, &reg, &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, &reg,
				      &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,
					      &reg, 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, &reg, 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, &reg);
		else
			reg = ptregs->cr_iip;
		size = sizeof(reg);
	} else if (regnum == IA64_CFM_REGNUM) {
		if (!ptregs)
			unw_get_cfm(info, &reg);
		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, &reg, 0);
		size = sizeof(reg);
	} else if (regnum == IA64_BSP_REGNUM) {
		unw_get_bsp(info, &reg);
		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, &reg, 0);
			size = sizeof(reg);
			break;
		case IA64_SSD_REGNUM:
			if (ptregs)
				reg = ptregs->ar_ssd;
			else
				unw_access_ar(info, UNW_AR_SSD, &reg, 0);
			size = sizeof(reg);
			break;
		case IA64_UNAT_REGNUM:
			if (ptregs)
				reg = ptregs->ar_unat;
			else
				unw_access_ar(info, UNW_AR_UNAT, &reg, 0);
			size = sizeof(reg);
			break;
		case IA64_RNAT_REGNUM:
			unw_access_ar(info, UNW_AR_RNAT, &reg, 0);
			size = sizeof(reg);
			break;
		case IA64_BSPSTORE_REGNUM:
			unw_access_ar(info, UNW_AR_BSPSTORE, &reg, 0);
			size = sizeof(reg);
			break;
		case IA64_PFS_REGNUM:
			unw_access_ar(info, UNW_AR_PFS, &reg, 0);
			size = sizeof(reg);
			break;
		case IA64_LC_REGNUM:
			unw_access_ar(info, UNW_AR_LC, &reg, 0);
			size = sizeof(reg);
			break;
		case IA64_EC_REGNUM:
			unw_access_ar(info, UNW_AR_EC, &reg, 0);
			size = sizeof(reg);
			break;
		case IA64_FPSR_REGNUM:
			if (ptregs)
				reg = ptregs->ar_fpsr;
			else
				unw_access_ar(info, UNW_AR_FPSR, &reg, 0);
			size = sizeof(reg);
			break;
		case IA64_RSC_REGNUM:
			if (ptregs)
				reg = ptregs->ar_rsc;
			else
				unw_access_ar(info, UNW_AR_RNAT, &reg, 0);
			size = sizeof(reg);
			break;
		case IA64_CCV_REGNUM:
			unw_access_ar(info, UNW_AR_CCV, &reg, 0);
			size = sizeof(reg);
			break;
		}

	if (size) {
		kgdb_mem2hex((char *)mem, outbuffer, size);
		outbuffer[size * 2] = 0;
	} else
		strcpy(outbuffer, "E0");

	return;
}
Esempio n. 6
0
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 = &reg;
	struct ia64_fpreg freg;

	if (kgdb_gr_reg(regnum, info, &reg, 0) ||
		kgdb_gr_ptreg(regnum, ptregs, info, &reg, 0) ||
		kgdb_br_reg(regnum, ptregs, info, &reg, 0) ||
		kgdb_ar_reg(regnum, ptregs, info, &reg, 0))
			size = sizeof(reg);
	else if (kgdb_fr_reg(regnum, NULL, ptregs, info, &reg, &freg, 0)) {
		size = sizeof(freg);
		mem = (unsigned long *)&freg;
	} else if (regnum == IA64_IP_REGNUM) {
		if (!ptregs) {
			unw_get_ip(info, &reg);
			size = sizeof(reg);
		} else {
			reg = ptregs->cr_iip;
			size = sizeof(reg);
		}
	} else if (regnum == IA64_CFM_REGNUM) {
		if (!ptregs)
			unw_get_cfm(info, &reg);
		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, &reg, 0);
		size = sizeof(reg);
	} else if (regnum == IA64_BSP_REGNUM) {
		unw_get_bsp(info, &reg);
		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
}