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

📄 vcpu.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 4 页
字号:
IA64FAULT vcpu_get_psr_masked(VCPU * vcpu, u64 * pval){  	u64 psr = vcpu_get_psr(vcpu);	*pval = psr & (MASK(0, 32) | MASK(35, 2));	return IA64_NO_FAULT;}BOOLEAN vcpu_get_psr_ic(VCPU * vcpu){	return !!PSCB(vcpu, interrupt_collection_enabled);}BOOLEAN vcpu_get_psr_i(VCPU * vcpu){	return !vcpu->vcpu_info->evtchn_upcall_mask;}/************************************************************************** VCPU interrupt control register access routines**************************************************************************/void vcpu_pend_unspecified_interrupt(VCPU * vcpu){	PSCB(vcpu, pending_interruption) = 1;}void vcpu_pend_interrupt(VCPU * vcpu, u64 vector){	if (vector & ~0xff) {		printk("vcpu_pend_interrupt: bad vector\n");		return;	}	if (vcpu->arch.event_callback_ip) {		printk("Deprecated interface. Move to new event based "		       "solution\n");		return;	}	if (VMX_DOMAIN(vcpu)) {		set_bit(vector, VCPU(vcpu, irr));	} else {		set_bit(vector, PSCBX(vcpu, irr));		PSCB(vcpu, pending_interruption) = 1;	}}#define	IA64_TPR_MMI	0x10000#define	IA64_TPR_MIC	0x000f0/* checks to see if a VCPU has any unmasked pending interrupts * if so, returns the highest, else returns SPURIOUS_VECTOR *//* NOTE: Since this gets called from vcpu_get_ivr() and the * semantics of "mov rx=cr.ivr" ignore the setting of the psr.i bit, * this routine also ignores pscb.interrupt_delivery_enabled * and this must be checked independently; see vcpu_deliverable interrupts() */u64 vcpu_check_pending_interrupts(VCPU * vcpu){	u64 *p, *r, bits, bitnum, mask, i, vector;	if (vcpu->arch.event_callback_ip)		return SPURIOUS_VECTOR;	/* Always check pending event, since guest may just ack the	 * event injection without handle. Later guest may throw out	 * the event itself.	 */ check_start:	if (event_pending(vcpu) &&	    !test_bit(vcpu->domain->shared_info->arch.evtchn_vector,		      &PSCBX(vcpu, insvc[0])))		vcpu_pend_interrupt(vcpu,		                    vcpu->domain->shared_info->arch.		                    evtchn_vector);	p = &PSCBX(vcpu, irr[3]);	r = &PSCBX(vcpu, insvc[3]);	for (i = 3 ;; p--, r--, i--) {		bits = *p;		if (bits)			break;	// got a potential interrupt		if (*r) {			// nothing in this word which is pending+inservice			// but there is one inservice which masks lower			return SPURIOUS_VECTOR;		}		if (i == 0) {			// checked all bits... nothing pending+inservice			return SPURIOUS_VECTOR;		}	}	// have a pending,deliverable interrupt... see if it is masked	bitnum = ia64_fls(bits);//printk("XXXXXXX vcpu_check_pending_interrupts: got bitnum=%p...\n",bitnum);	vector = bitnum + (i * 64);	mask = 1L << bitnum;	/* sanity check for guest timer interrupt */	if (vector == (PSCB(vcpu, itv) & 0xff)) {		uint64_t now = ia64_get_itc();		if (now < PSCBX(vcpu, domain_itm)) {//			printk("Ooops, pending guest timer before its due\n");			PSCBX(vcpu, irr[i]) &= ~mask;			goto check_start;		}	}//printk("XXXXXXX vcpu_check_pending_interrupts: got vector=%p...\n",vector);	if (*r >= mask) {		// masked by equal inservice//printk("but masked by equal inservice\n");		return SPURIOUS_VECTOR;	}	if (PSCB(vcpu, tpr) & IA64_TPR_MMI) {		// tpr.mmi is set//printk("but masked by tpr.mmi\n");		return SPURIOUS_VECTOR;	}	if (((PSCB(vcpu, tpr) & IA64_TPR_MIC) + 15) >= vector) {		//tpr.mic masks class//printk("but masked by tpr.mic\n");		return SPURIOUS_VECTOR;	}//printk("returned to caller\n");	return vector;}u64 vcpu_deliverable_interrupts(VCPU * vcpu){	return (vcpu_get_psr_i(vcpu) &&		vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR);}u64 vcpu_deliverable_timer(VCPU * vcpu){	return (vcpu_get_psr_i(vcpu) &&		vcpu_check_pending_interrupts(vcpu) == PSCB(vcpu, itv));}IA64FAULT vcpu_get_lid(VCPU * vcpu, u64 * pval){	/* Use EID=0, ID=vcpu_id.  */	*pval = vcpu->vcpu_id << 24;	return IA64_NO_FAULT;}IA64FAULT vcpu_get_ivr(VCPU * vcpu, u64 * pval){	int i;	u64 vector, mask;#define HEARTBEAT_FREQ 16	// period in seconds#ifdef HEARTBEAT_FREQ#define N_DOMS 16		// period in seconds#if 0	static long count[N_DOMS] = { 0 };#endif	static long nonclockcount[N_DOMS] = { 0 };	unsigned domid = vcpu->domain->domain_id;#endif#ifdef IRQ_DEBUG	static char firstivr = 1;	static char firsttime[256];	if (firstivr) {		int i;		for (i = 0; i < 256; i++)			firsttime[i] = 1;		firstivr = 0;	}#endif	vector = vcpu_check_pending_interrupts(vcpu);	if (vector == SPURIOUS_VECTOR) {		PSCB(vcpu, pending_interruption) = 0;		*pval = vector;		return IA64_NO_FAULT;	}#ifdef HEARTBEAT_FREQ	if (domid >= N_DOMS)		domid = N_DOMS - 1;#if 0	if (vector == (PSCB(vcpu, itv) & 0xff)) {		if (!(++count[domid] & ((HEARTBEAT_FREQ * 1024) - 1))) {			printk("Dom%d heartbeat... ticks=%lx,nonticks=%lx\n",			       domid, count[domid], nonclockcount[domid]);			//count[domid] = 0;			//dump_runq();		}	}#endif	else		nonclockcount[domid]++;#endif	// now have an unmasked, pending, deliverable vector!	// getting ivr has "side effects"#ifdef IRQ_DEBUG	if (firsttime[vector]) {		printk("*** First get_ivr on vector=%lu,itc=%lx\n",		       vector, ia64_get_itc());		firsttime[vector] = 0;	}#endif	/* if delivering a timer interrupt, remember domain_itm, which	 * needs to be done before clearing irr	 */	if (vector == (PSCB(vcpu, itv) & 0xff)) {		PSCBX(vcpu, domain_itm_last) = PSCBX(vcpu, domain_itm);	}	i = vector >> 6;	mask = 1L << (vector & 0x3f);//printk("ZZZZZZ vcpu_get_ivr: setting insvc mask for vector %lu\n",vector);	PSCBX(vcpu, insvc[i]) |= mask;	PSCBX(vcpu, irr[i]) &= ~mask;	//PSCB(vcpu,pending_interruption)--;	*pval = vector;	return IA64_NO_FAULT;}IA64FAULT vcpu_get_tpr(VCPU * vcpu, u64 * pval){	*pval = PSCB(vcpu, tpr);	return IA64_NO_FAULT;}IA64FAULT vcpu_get_eoi(VCPU * vcpu, u64 * pval){	*pval = 0L;		// reads of eoi always return 0	return IA64_NO_FAULT;}IA64FAULT vcpu_get_irr0(VCPU * vcpu, u64 * pval){	*pval = PSCBX(vcpu, irr[0]);	return IA64_NO_FAULT;}IA64FAULT vcpu_get_irr1(VCPU * vcpu, u64 * pval){	*pval = PSCBX(vcpu, irr[1]);	return IA64_NO_FAULT;}IA64FAULT vcpu_get_irr2(VCPU * vcpu, u64 * pval){	*pval = PSCBX(vcpu, irr[2]);	return IA64_NO_FAULT;}IA64FAULT vcpu_get_irr3(VCPU * vcpu, u64 * pval){	*pval = PSCBX(vcpu, irr[3]);	return IA64_NO_FAULT;}IA64FAULT vcpu_get_itv(VCPU * vcpu, u64 * pval){	*pval = PSCB(vcpu, itv);	return IA64_NO_FAULT;}IA64FAULT vcpu_get_pmv(VCPU * vcpu, u64 * pval){	*pval = PSCB(vcpu, pmv);	return IA64_NO_FAULT;}IA64FAULT vcpu_get_cmcv(VCPU * vcpu, u64 * pval){	*pval = PSCB(vcpu, cmcv);	return IA64_NO_FAULT;}IA64FAULT vcpu_get_lrr0(VCPU * vcpu, u64 * pval){	// fix this when setting values other than m-bit is supported	gdprintk(XENLOG_DEBUG,		 "vcpu_get_lrr0: Unmasked interrupts unsupported\n");	*pval = (1L << 16);	return IA64_NO_FAULT;}IA64FAULT vcpu_get_lrr1(VCPU * vcpu, u64 * pval){	// fix this when setting values other than m-bit is supported	gdprintk(XENLOG_DEBUG,		 "vcpu_get_lrr1: Unmasked interrupts unsupported\n");	*pval = (1L << 16);	return IA64_NO_FAULT;}IA64FAULT vcpu_set_lid(VCPU * vcpu, u64 val){	printk("vcpu_set_lid: Setting cr.lid is unsupported\n");	return IA64_ILLOP_FAULT;}IA64FAULT vcpu_set_tpr(VCPU * vcpu, u64 val){	if (val & 0xff00)		return IA64_RSVDREG_FAULT;	PSCB(vcpu, tpr) = val;	/* This can unmask interrupts.  */	if (vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)		PSCB(vcpu, pending_interruption) = 1;	return IA64_NO_FAULT;}IA64FAULT vcpu_set_eoi(VCPU * vcpu, u64 val){	u64 *p, bits, vec, bitnum;	int i;	p = &PSCBX(vcpu, insvc[3]);	for (i = 3; (i >= 0) && !(bits = *p); i--, p--)		;	if (i < 0) {		printk("Trying to EOI interrupt when none are in-service.\n");		return IA64_NO_FAULT;	}	bitnum = ia64_fls(bits);	vec = bitnum + (i * 64);	/* clear the correct bit */	bits &= ~(1L << bitnum);	*p = bits;	/* clearing an eoi bit may unmask another pending interrupt... */	if (!vcpu->vcpu_info->evtchn_upcall_mask) {	// but only if enabled...		// worry about this later... Linux only calls eoi		// with interrupts disabled		printk("Trying to EOI interrupt with interrupts enabled\n");	}	if (vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)		PSCB(vcpu, pending_interruption) = 1;//printk("YYYYY vcpu_set_eoi: Successful\n");	return IA64_NO_FAULT;}IA64FAULT vcpu_set_lrr0(VCPU * vcpu, u64 val){	if (!(val & (1L << 16))) {		printk("vcpu_set_lrr0: Unmasked interrupts unsupported\n");		return IA64_ILLOP_FAULT;	}	// no place to save this state but nothing to do anyway	return IA64_NO_FAULT;}IA64FAULT vcpu_set_lrr1(VCPU * vcpu, u64 val){	if (!(val & (1L << 16))) {		printk("vcpu_set_lrr0: Unmasked interrupts unsupported\n");		return IA64_ILLOP_FAULT;	}	// no place to save this state but nothing to do anyway	return IA64_NO_FAULT;}IA64FAULT vcpu_set_itv(VCPU * vcpu, u64 val){	/* Check reserved fields.  */	if (val & 0xef00)		return IA64_ILLOP_FAULT;	PSCB(vcpu, itv) = val;	if (val & 0x10000) {		/* Disable itm.  */		PSCBX(vcpu, domain_itm) = 0;	} else		vcpu_set_next_timer(vcpu);	return IA64_NO_FAULT;}IA64FAULT vcpu_set_pmv(VCPU * vcpu, u64 val){	if (val & 0xef00)	/* reserved fields */		return IA64_RSVDREG_FAULT;	PSCB(vcpu, pmv) = val;	return IA64_NO_FAULT;}IA64FAULT vcpu_set_cmcv(VCPU * vcpu, u64 val){	if (val & 0xef00)	/* reserved fields */		return IA64_RSVDREG_FAULT;	PSCB(vcpu, cmcv) = val;	return IA64_NO_FAULT;}/************************************************************************** VCPU temporary register access routines**************************************************************************/u64 vcpu_get_tmp(VCPU * vcpu, u64 index){	if (index > 7)		return 0;	return PSCB(vcpu, tmp[index]);}void vcpu_set_tmp(VCPU * vcpu, u64 index, u64 val){	if (index <= 7)		PSCB(vcpu, tmp[index]) = val;}/**************************************************************************Interval timer routines**************************************************************************/BOOLEAN vcpu_timer_disabled(VCPU * vcpu){	u64 itv = PSCB(vcpu, itv);	return (!itv || !!(itv & 0x10000));}BOOLEAN vcpu_timer_inservice(VCPU * vcpu){	u64 itv = PSCB(vcpu, itv);	return test_bit(itv, PSCBX(vcpu, insvc));}BOOLEAN vcpu_timer_expired(VCPU * vcpu){	unsigned long domain_itm = PSCBX(vcpu, domain_itm);	unsigned long now = ia64_get_itc();	if (!domain_itm)		return FALSE;	if (now < domain_itm)		return FALSE;	if (vcpu_timer_disabled(vcpu))		return FALSE;	return TRUE;}void vcpu_safe_set_itm(unsigned long val){	unsigned long epsilon = 100;	unsigned long flags;	u64 now = ia64_get_itc();	local_irq_save(flags);	while (1) {//printk("*** vcpu_safe_set_itm: Setting itm to %lx, itc=%lx\n",val,now);		ia64_set_itm(val);		if (val > (now = ia64_get_itc()))			break;		val = now + epsilon;		epsilon <<= 1;	}	local_irq_restore(flags);}void vcpu_set_next_timer(VCPU * vcpu){	u64 d = PSCBX(vcpu, domain_itm);	//u64 s = PSCBX(vcpu,xen_itm);	u64 s = local_cpu_data->itm_next;	u64 now = ia64_get_itc();	/* gloss over the wraparound problem for now... we know it exists	 * but it doesn't matter right now */	if (is_idle_domain(vcpu->domain)) {//		printk("****** vcpu_set_next_timer called during idle!!\n");		vcpu_safe_set_itm(s);		return;	}	//s = PSCBX(vcpu,xen_itm);	if (d && (d > now) && (d < s)) {		vcpu_safe_set_itm(d);		//using_domain_as_itm++;	} else {		vcpu_safe_set_itm(s);		//using_xen_as_itm++;	}}IA64FAULT vcpu_set_itm(VCPU * vcpu, u64 val){	//UINT now = ia64_get_itc();	//if (val < now) val = now + 1000;//printk("*** vcpu_set_itm: called with %lx\n",val);	PSCBX(vcpu, domain_itm) = val;	vcpu_set_next_timer(vcpu);	return IA64_NO_FAULT;}IA64FAULT vcpu_set_itc(VCPU * vcpu, u64 val){#define DISALLOW_SETTING_ITC_FOR_NOW#ifdef DISALLOW_SETTING_ITC_FOR_NOW	static int did_print;	if (!did_print) {		printk("vcpu_set_itc: Setting ar.itc is currently disabled "		       "(this message is only displayed once)\n");		did_print = 1;	}#else	u64 oldnow = ia64_get_itc();	u64 olditm = PSCBX(vcpu, domain_itm);	unsigned long d = olditm - oldnow;	unsigned long x = local_cpu_data->itm_next - oldnow;	u64 newnow = val, min_delta;	local_irq_disable();	if (olditm) {		printk("**** vcpu_set_itc(%lx): vitm changed to %lx\n", val,		       newnow + d);		PSCBX(vcpu, domain_itm) = newnow + d;	}	local_cpu_data->itm_next = newnow + x;	d = PSCBX(vcpu, domain_itm);	x = local_cpu_data->itm_next;	ia64_set_itc(newnow);	if (d && (d > newnow) && (d < x)) {		vcpu_safe_set_itm(d);		//using_domain_as_itm++;	} else {		vcpu_safe_set_itm(x);		//using_xen_as_itm++;	}	local_irq_enable();#endif	return IA64_NO_FAULT;}IA64FAULT vcpu_get_itm(VCPU * vcpu, u64 * pval){	//FIXME: Implement this	printk("vcpu_get_itm: Getting cr.itm is unsupported... continuing\n");	return IA64_NO_FAULT;	//return IA64_ILLOP_FAULT;}IA64FAULT vcpu_get_itc(VCPU * vcpu, u64 * pval){	//TODO: Implement this	printk("vcpu_get_itc: Getting ar.itc is unsupported\n");	return IA64_ILLOP_FAULT;}void vcpu_pend_timer(VCPU * vcpu){	u64 itv = PSCB(vcpu, itv) & 0xff;	if (vcpu_timer_disabled(vcpu))		return;	//if (vcpu_timer_inservice(vcpu)) return;	if (PSCBX(vcpu, domain_itm_last) == PSCBX(vcpu, domain_itm)) {		// already delivered an interrupt for this so		// don't deliver another		return;	}	if (vcpu->arch.event_callback_ip) {		/* A small window may occur when injecting vIRQ while related		 * handler has not been registered. Don't fire in such case.		 */		if (vcpu->virq_to_evtchn[VIRQ_ITC]) {			send_guest_vcpu_virq(vcpu, VIRQ_ITC);			PSCBX(vcpu, domain_itm_last) = PSCBX(vcpu, domain_itm);		}	} else		vcpu_pend_interrupt(vcpu, itv);}// returns true if ready to deliver a timer interrupt too earlyu64 vcpu_timer_pending_early(VCPU * vcpu){	u64 now = ia64_get_itc();	u64 itm = PSCBX(vcpu, domain_itm);	if (vcpu_timer_disabled(vcpu))		return 0;	if (!itm)		return 0;	return (vcpu_deliverable_timer(vcpu) && (now < itm));}

⌨️ 快捷键说明

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