⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unwind.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (regnum <= 5) {		addr = *(&info->f2_loc + (regnum - 2));		if (!addr)			addr = &info->sw->f2 + (regnum - 2);	} else if (regnum <= 15) {		if (regnum <= 11) {			pt = get_scratch_regs(info);			//XXX struct ia64_fpreg and struct pt_fpreg are same.			addr = (struct ia64_fpreg*)(&pt->f6  + (regnum - 6));		}		else			addr = &info->sw->f12 + (regnum - 12);	} else if (regnum <= 31) {		addr = info->fr_loc[regnum - 16];		if (!addr)			addr = &info->sw->f16 + (regnum - 16);	} else {		struct task_struct *t = info->task;		if (write)			ia64_sync_fph(t);		else			ia64_flush_fph(t);#ifdef XEN		addr = t->arch._thread.fph + (regnum - 32);#else		addr = t->thread.fph + (regnum - 32);#endif	}	if (write)		if (read_only(addr)) {			UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n",				__FUNCTION__);		} else			*addr = *val;	else		*val = *addr;	return 0;}EXPORT_SYMBOL(unw_access_fr);intunw_access_ar (struct unw_frame_info *info, int regnum, unsigned long *val, int write){	unsigned long *addr;	struct pt_regs *pt;	switch (regnum) {	      case UNW_AR_BSP:		addr = info->bsp_loc;		if (!addr)			addr = &info->sw->ar_bspstore;		break;	      case UNW_AR_BSPSTORE:		addr = info->bspstore_loc;		if (!addr)			addr = &info->sw->ar_bspstore;		break;	      case UNW_AR_PFS:		addr = info->pfs_loc;		if (!addr)			addr = &info->sw->ar_pfs;		break;	      case UNW_AR_RNAT:		addr = info->rnat_loc;		if (!addr)			addr = &info->sw->ar_rnat;		break;	      case UNW_AR_UNAT:		addr = info->unat_loc;		if (!addr)			addr = &info->sw->caller_unat;		break;	      case UNW_AR_LC:		addr = info->lc_loc;		if (!addr)			addr = &info->sw->ar_lc;		break;	      case UNW_AR_EC:		if (!info->cfm_loc)			return -1;		if (write)			*info->cfm_loc =				(*info->cfm_loc & ~(0x3fUL << 52)) | ((*val & 0x3f) << 52);		else			*val = (*info->cfm_loc >> 52) & 0x3f;		return 0;	      case UNW_AR_FPSR:		addr = info->fpsr_loc;		if (!addr)			addr = &info->sw->ar_fpsr;		break;	      case UNW_AR_RSC:		pt = get_scratch_regs(info);		addr = &pt->ar_rsc;		break;	      case UNW_AR_CCV:		pt = get_scratch_regs(info);		addr = &pt->ar_ccv;		break;	      case UNW_AR_CSD:		pt = get_scratch_regs(info);		addr = &pt->ar_csd;		break;	      case UNW_AR_SSD:		pt = get_scratch_regs(info);		addr = &pt->ar_ssd;		break;	      default:		UNW_DPRINT(0, "unwind.%s: trying to access non-existent ar%u\n",			   __FUNCTION__, regnum);		return -1;	}	if (write) {		if (read_only(addr)) {			UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n",				__FUNCTION__);		} else			*addr = *val;	} else		*val = *addr;	return 0;}EXPORT_SYMBOL(unw_access_ar);intunw_access_pr (struct unw_frame_info *info, unsigned long *val, int write){	unsigned long *addr;	addr = info->pr_loc;	if (!addr)		addr = &info->sw->pr;	if (write) {		if (read_only(addr)) {			UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n",				__FUNCTION__);		} else			*addr = *val;	} else		*val = *addr;	return 0;}EXPORT_SYMBOL(unw_access_pr);/* Routines to manipulate the state stack.  */static inline voidpush (struct unw_state_record *sr){	struct unw_reg_state *rs;	rs = alloc_reg_state();	if (!rs) {		printk(KERN_ERR "unwind: cannot stack reg state!\n");		return;	}	memcpy(rs, &sr->curr, sizeof(*rs));	sr->curr.next = rs;}static voidpop (struct unw_state_record *sr){	struct unw_reg_state *rs = sr->curr.next;	if (!rs) {		printk(KERN_ERR "unwind: stack underflow!\n");		return;	}	memcpy(&sr->curr, rs, sizeof(*rs));	free_reg_state(rs);}/* Make a copy of the state stack.  Non-recursive to avoid stack overflows.  */static struct unw_reg_state *dup_state_stack (struct unw_reg_state *rs){	struct unw_reg_state *copy, *prev = NULL, *first = NULL;	while (rs) {		copy = alloc_reg_state();		if (!copy) {			printk(KERN_ERR "unwind.dup_state_stack: out of memory\n");			return NULL;		}		memcpy(copy, rs, sizeof(*copy));		if (first)			prev->next = copy;		else			first = copy;		rs = rs->next;		prev = copy;	}	return first;}/* Free all stacked register states (but not RS itself).  */static voidfree_state_stack (struct unw_reg_state *rs){	struct unw_reg_state *p, *next;	for (p = rs->next; p != NULL; p = next) {		next = p->next;		free_reg_state(p);	}	rs->next = NULL;}/* Unwind decoder routines */static enum unw_register_index __attribute_const__decode_abreg (unsigned char abreg, int memory){	switch (abreg) {	      case 0x04 ... 0x07: return UNW_REG_R4 + (abreg - 0x04);	      case 0x22 ... 0x25: return UNW_REG_F2 + (abreg - 0x22);	      case 0x30 ... 0x3f: return UNW_REG_F16 + (abreg - 0x30);	      case 0x41 ... 0x45: return UNW_REG_B1 + (abreg - 0x41);	      case 0x60: return UNW_REG_PR;	      case 0x61: return UNW_REG_PSP;	      case 0x62: return memory ? UNW_REG_PRI_UNAT_MEM : UNW_REG_PRI_UNAT_GR;	      case 0x63: return UNW_REG_RP;	      case 0x64: return UNW_REG_BSP;	      case 0x65: return UNW_REG_BSPSTORE;	      case 0x66: return UNW_REG_RNAT;	      case 0x67: return UNW_REG_UNAT;	      case 0x68: return UNW_REG_FPSR;	      case 0x69: return UNW_REG_PFS;	      case 0x6a: return UNW_REG_LC;	      default:		break;	}	UNW_DPRINT(0, "unwind.%s: bad abreg=0x%x\n", __FUNCTION__, abreg);	return UNW_REG_LC;}static voidset_reg (struct unw_reg_info *reg, enum unw_where where, int when, unsigned long val){	reg->val = val;	reg->where = where;	if (reg->when == UNW_WHEN_NEVER)		reg->when = when;}static voidalloc_spill_area (unsigned long *offp, unsigned long regsize,		  struct unw_reg_info *lo, struct unw_reg_info *hi){	struct unw_reg_info *reg;	for (reg = hi; reg >= lo; --reg) {		if (reg->where == UNW_WHERE_SPILL_HOME) {			reg->where = UNW_WHERE_PSPREL;			*offp -= regsize;			reg->val = *offp;		}	}}static inline voidspill_next_when (struct unw_reg_info **regp, struct unw_reg_info *lim, unw_word t){	struct unw_reg_info *reg;	for (reg = *regp; reg <= lim; ++reg) {		if (reg->where == UNW_WHERE_SPILL_HOME) {			reg->when = t;			*regp = reg + 1;			return;		}	}	UNW_DPRINT(0, "unwind.%s: excess spill!\n",  __FUNCTION__);}static inline voidfinish_prologue (struct unw_state_record *sr){	struct unw_reg_info *reg;	unsigned long off;	int i;	/*	 * First, resolve implicit register save locations (see Section "11.4.2.3 Rules	 * for Using Unwind Descriptors", rule 3):	 */	for (i = 0; i < (int) ARRAY_SIZE(unw.save_order); ++i) {		reg = sr->curr.reg + unw.save_order[i];		if (reg->where == UNW_WHERE_GR_SAVE) {			reg->where = UNW_WHERE_GR;			reg->val = sr->gr_save_loc++;		}	}	/*	 * Next, compute when the fp, general, and branch registers get	 * saved.  This must come before alloc_spill_area() because	 * we need to know which registers are spilled to their home	 * locations.	 */	if (sr->imask) {		unsigned char kind, mask = 0, *cp = sr->imask;		int t;		static const unsigned char limit[3] = {			UNW_REG_F31, UNW_REG_R7, UNW_REG_B5		};		struct unw_reg_info *(regs[3]);		regs[0] = sr->curr.reg + UNW_REG_F2;		regs[1] = sr->curr.reg + UNW_REG_R4;		regs[2] = sr->curr.reg + UNW_REG_B1;		for (t = 0; t < sr->region_len; ++t) {			if ((t & 3) == 0)				mask = *cp++;			kind = (mask >> 2*(3-(t & 3))) & 3;			if (kind > 0)				spill_next_when(&regs[kind - 1], sr->curr.reg + limit[kind - 1],						sr->region_start + t);		}	}	/*	 * Next, lay out the memory stack spill area:	 */	if (sr->any_spills) {		off = sr->spill_offset;		alloc_spill_area(&off, 16, sr->curr.reg + UNW_REG_F2, sr->curr.reg + UNW_REG_F31);		alloc_spill_area(&off,  8, sr->curr.reg + UNW_REG_B1, sr->curr.reg + UNW_REG_B5);		alloc_spill_area(&off,  8, sr->curr.reg + UNW_REG_R4, sr->curr.reg + UNW_REG_R7);	}}/* * Region header descriptors. */static voiddesc_prologue (int body, unw_word rlen, unsigned char mask, unsigned char grsave,	       struct unw_state_record *sr){	int i, region_start;	if (!(sr->in_body || sr->first_region))		finish_prologue(sr);	sr->first_region = 0;	/* check if we're done: */	if (sr->when_target < sr->region_start + sr->region_len) {		sr->done = 1;		return;	}	region_start = sr->region_start + sr->region_len;	for (i = 0; i < sr->epilogue_count; ++i)		pop(sr);	sr->epilogue_count = 0;	sr->epilogue_start = UNW_WHEN_NEVER;	sr->region_start = region_start;	sr->region_len = rlen;	sr->in_body = body;	if (!body) {		push(sr);		for (i = 0; i < 4; ++i) {			if (mask & 0x8)				set_reg(sr->curr.reg + unw.save_order[i], UNW_WHERE_GR,					sr->region_start + sr->region_len - 1, grsave++);			mask <<= 1;		}		sr->gr_save_loc = grsave;		sr->any_spills = 0;		sr->imask = NULL;		sr->spill_offset = 0x10;	/* default to psp+16 */	}}/* * Prologue descriptors. */static inline voiddesc_abi (unsigned char abi, unsigned char context, struct unw_state_record *sr){	if (abi == 3 && context == 'i') {		sr->flags |= UNW_FLAG_INTERRUPT_FRAME;		UNW_DPRINT(3, "unwind.%s: interrupt frame\n",  __FUNCTION__);	}	else		UNW_DPRINT(0, "unwind%s: ignoring unwabi(abi=0x%x,context=0x%x)\n",				__FUNCTION__, abi, context);}static inline voiddesc_br_gr (unsigned char brmask, unsigned char gr, struct unw_state_record *sr){	int i;	for (i = 0; i < 5; ++i) {		if (brmask & 1)			set_reg(sr->curr.reg + UNW_REG_B1 + i, UNW_WHERE_GR,				sr->region_start + sr->region_len - 1, gr++);		brmask >>= 1;	}}static inline voiddesc_br_mem (unsigned char brmask, struct unw_state_record *sr){	int i;	for (i = 0; i < 5; ++i) {		if (brmask & 1) {			set_reg(sr->curr.reg + UNW_REG_B1 + i, UNW_WHERE_SPILL_HOME,				sr->region_start + sr->region_len - 1, 0);			sr->any_spills = 1;		}		brmask >>= 1;	}}static inline voiddesc_frgr_mem (unsigned char grmask, unw_word frmask, struct unw_state_record *sr){	int i;	for (i = 0; i < 4; ++i) {		if ((grmask & 1) != 0) {			set_reg(sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_SPILL_HOME,				sr->region_start + sr->region_len - 1, 0);			sr->any_spills = 1;		}		grmask >>= 1;	}	for (i = 0; i < 20; ++i) {		if ((frmask & 1) != 0) {			int base = (i < 4) ? UNW_REG_F2 : UNW_REG_F16 - 4;			set_reg(sr->curr.reg + base + i, UNW_WHERE_SPILL_HOME,				sr->region_start + sr->region_len - 1, 0);			sr->any_spills = 1;		}		frmask >>= 1;	}}static inline voiddesc_fr_mem (unsigned char frmask, struct unw_state_record *sr){	int i;	for (i = 0; i < 4; ++i) {		if ((frmask & 1) != 0) {			set_reg(sr->curr.reg + UNW_REG_F2 + i, UNW_WHERE_SPILL_HOME,				sr->region_start + sr->region_len - 1, 0);			sr->any_spills = 1;		}		frmask >>= 1;	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -