ia64/xen-unstable

changeset 8368:f998426f9069

Under some specific conditions, dom0 will lose guest timer interrupt.
Signed-off-by Anthony Xu <anthony.xu@intel.com>
Signed-off-by Kevin Tian <kevin.tian@intel.com>
The reason is that Xen/ia64 will try to pend guest timer interrupt to dom0
within each machine timer interrupt handler. To avoid duplicated delivery,
domain_itm_last recorded domain_itm of last injection. If two are identical,
it means interrupt injected but guest has not set new itm value. Or else
corresponding pending irr bit will be turned on. That works in most cases.

However currently guest linux may try to set itm multiple times within one
handler before turn on psr.i again. Among first few settings, new guest timer
interrupt may be pended. Then once guest linux enables interrupt, a new
timer interrupt will be injected immediately. However this injection may have
itc still smaller than the domain_itm set at the last round of last handle.
In this case, guest linux will set same domain_itm as last again. However
since domain_itm_last already equals to domain_itm at last read ivr, later
no guest timer interrupt can be injected any more since Xen always thinks
an instance already injected without guest's response.

Attahced patch fixed this issue by adding sanity check upon guest timer
vector when deciding to inject interrupt into dom0. We always compare current
itc with latest domain_itm that guest really wants. So if itc < domain_itm
at this point, we simply clear the pending bit and no injection.

There's also a small fix to vcpu_read_ivr, where domain_itm_last should
be updated before clearing irr bit. Or els a small window still remains
to add a duplicate interrupt.
author djm@kirby.fc.hp.com
date Thu Dec 15 16:07:47 2005 -0600 (2005-12-15)
parents dda94d6dce94
children b57ed8182812
files xen/arch/ia64/xen/vcpu.c
line diff
     1.1 --- a/xen/arch/ia64/xen/vcpu.c	Thu Dec 15 14:51:10 2005 -0600
     1.2 +++ b/xen/arch/ia64/xen/vcpu.c	Thu Dec 15 16:07:47 2005 -0600
     1.3 @@ -676,6 +676,7 @@ UINT64 vcpu_check_pending_interrupts(VCP
     1.4  	 * event injection without handle. Later guest may throw out
     1.5  	 * the event itself.
     1.6  	 */
     1.7 +check_start:
     1.8  	if (event_pending(vcpu) && 
     1.9  		!test_bit(vcpu->vcpu_info->arch.evtchn_vector,
    1.10  			&PSCBX(vcpu, insvc[0])))
    1.11 @@ -702,6 +703,15 @@ UINT64 vcpu_check_pending_interrupts(VCP
    1.12  //printf("XXXXXXX vcpu_check_pending_interrupts: got bitnum=%p...",bitnum);
    1.13  	vector = bitnum+(i*64);
    1.14  	mask = 1L << bitnum;
    1.15 +	/* sanity check for guest timer interrupt */
    1.16 +	if (vector == (PSCB(vcpu,itv) & 0xff)) {
    1.17 +		uint64_t now = ia64_get_itc();
    1.18 +		if (now < PSCBX(vcpu,domain_itm)) {
    1.19 +			printk("Ooops, pending guest timer before its due\n");
    1.20 +			PSCBX(vcpu,irr[i]) &= ~mask;
    1.21 +			goto check_start;
    1.22 +		}
    1.23 +	}
    1.24  //printf("XXXXXXX vcpu_check_pending_interrupts: got vector=%p...",vector);
    1.25  	if (*r >= mask) {
    1.26  		// masked by equal inservice
    1.27 @@ -798,6 +808,13 @@ IA64FAULT vcpu_get_ivr(VCPU *vcpu, UINT6
    1.28  		firsttime[vector]=0;
    1.29  	}
    1.30  #endif
    1.31 +	/* if delivering a timer interrupt, remember domain_itm, which
    1.32 +	 * needs to be done before clearing irr
    1.33 +	 */
    1.34 +	if (vector == (PSCB(vcpu,itv) & 0xff)) {
    1.35 +		PSCBX(vcpu,domain_itm_last) = PSCBX(vcpu,domain_itm);
    1.36 +	}
    1.37 +
    1.38  	i = vector >> 6;
    1.39  	mask = 1L << (vector & 0x3f);
    1.40  //printf("ZZZZZZ vcpu_get_ivr: setting insvc mask for vector %ld\n",vector);
    1.41 @@ -805,10 +822,6 @@ IA64FAULT vcpu_get_ivr(VCPU *vcpu, UINT6
    1.42  	PSCBX(vcpu,irr[i]) &= ~mask;
    1.43  	//PSCB(vcpu,pending_interruption)--;
    1.44  	*pval = vector;
    1.45 -	// if delivering a timer interrupt, remember domain_itm
    1.46 -	if (vector == (PSCB(vcpu,itv) & 0xff)) {
    1.47 -		PSCBX(vcpu,domain_itm_last) = PSCBX(vcpu,domain_itm);
    1.48 -	}
    1.49  	return IA64_NO_FAULT;
    1.50  }
    1.51