# HG changeset patch
# User awilliam@xxxxxxxxxxx
# Node ID d5a46e4cc340dfaf6c638a64ae536d917065e2ba
# Parent a7c6b1c5507c4365862d171edb7feb7a84c25060
[IA64] Fix Windows Timer stop issue.
When doing HCT testing on Guest Windows, Windows Timer might stop,
if there is no mouse activity.
When implementing vhpi acceleration, I didn't think of below situation.
windows uses "epc" instruction to implement system call like linux,
In a very small code sequence including "epc" instruction, if there is
an external interrupt, Windows will defer handling this external interrupt
by rfi with ipsr.i=0.
Signed-off-by, Anthony Xu <anthony.xu@xxxxxxxxx>
---
xen/arch/ia64/vmx/vlsapic.c | 159 +++++++++++++++++++++-------------------
xen/arch/ia64/vmx/vmx_process.c | 5 -
xen/arch/ia64/xen/xentime.c | 43 ++++------
3 files changed, 105 insertions(+), 102 deletions(-)
diff -r a7c6b1c5507c -r d5a46e4cc340 xen/arch/ia64/vmx/vlsapic.c
--- a/xen/arch/ia64/vmx/vlsapic.c Sun Oct 22 14:14:58 2006 -0600
+++ b/xen/arch/ia64/vmx/vlsapic.c Sun Oct 22 14:39:15 2006 -0600
@@ -57,6 +57,59 @@ static void update_last_itc(vtime_t *vtm
}
/*
+ * Next for vLSapic
+ */
+
+#define NMI_VECTOR 2
+#define ExtINT_VECTOR 0
+#define NULL_VECTOR -1
+
+static void update_vhpi(VCPU *vcpu, int vec)
+{
+ u64 vhpi;
+
+ if (vec == NULL_VECTOR)
+ vhpi = 0;
+ else if (vec == NMI_VECTOR)
+ vhpi = 32;
+ else if (vec == ExtINT_VECTOR)
+ vhpi = 16;
+ else
+ vhpi = vec >> 4;
+
+ VCPU(vcpu,vhpi) = vhpi;
+ // TODO: Add support for XENO
+ if (VCPU(vcpu,vac).a_int)
+ ia64_call_vsa(PAL_VPS_SET_PENDING_INTERRUPT,
+ (uint64_t)vcpu->arch.privregs, 0, 0, 0, 0, 0, 0);
+}
+
+
+/*
+ * May come from virtualization fault or
+ * nested host interrupt.
+ */
+static int vmx_vcpu_unpend_interrupt(VCPU *vcpu, uint8_t vector)
+{
+ uint64_t spsr;
+ int ret;
+
+ if (vector & ~0xff) {
+ DPRINTK("vmx_vcpu_pend_interrupt: bad vector\n");
+ return -1;
+ }
+
+ local_irq_save(spsr);
+ ret = test_and_clear_bit(vector, &VCPU(vcpu, irr[0]));
+ local_irq_restore(spsr);
+
+ if (ret)
+ vcpu->arch.irq_new_pending = 1;
+
+ return ret;
+}
+
+/*
* ITC value saw in guest (host+offset+drift).
*/
static uint64_t now_itc(vtime_t *vtm)
@@ -107,9 +160,6 @@ static void vtm_timer_fn(void *data)
}
vtm=&(vcpu->arch.arch_vmx.vtm);
cur_itc = now_itc(vtm);
- // vitm =VCPU(vcpu, itm);
- //fire_itc2 = cur_itc;
- //fire_itm2 = vitm;
update_last_itc(vtm,cur_itc); // pseudo read to update vITC
}
@@ -137,6 +187,7 @@ uint64_t vtm_get_itc(VCPU *vcpu)
vtm=&(vcpu->arch.arch_vmx.vtm);
guest_itc = now_itc(vtm);
+ update_last_itc(vtm, guest_itc); // update vITC
return guest_itc;
}
@@ -158,7 +209,7 @@ void vtm_set_itc(VCPU *vcpu, uint64_t ne
vtm->last_itc = new_itc;
}
if(vitm < new_itc){
- clear_bit(ITV_VECTOR(vitv), &VCPU(vcpu, irr[0]));
+ vmx_vcpu_unpend_interrupt(vcpu, ITV_VECTOR(vitv));
stop_timer(&vtm->vtm_timer);
}
}
@@ -175,12 +226,12 @@ void vtm_set_itm(VCPU *vcpu, uint64_t va
vitv = VCPU(vcpu, itv);
vtm=&(vcpu->arch.arch_vmx.vtm);
// TODO; need to handle VHPI in future
- clear_bit(ITV_VECTOR(vitv), &VCPU(vcpu, irr[0]));
+ vmx_vcpu_unpend_interrupt(vcpu, ITV_VECTOR(vitv));
VCPU(vcpu,itm)=val;
- cur_itc =now_itc(vtm);
- if(time_before(val, cur_itc))
- val = cur_itc;
- if(val > vtm->last_itc){
+ if (val >= vtm->last_itc) {
+ cur_itc = now_itc(vtm);
+ if (time_before(val, cur_itc))
+ val = cur_itc;
expires = NOW() + cycle_to_ns(val-cur_itc) + TIMER_SLOP;
set_timer(&vtm->vtm_timer, expires);
}else{
@@ -195,10 +246,10 @@ void vtm_set_itv(VCPU *vcpu, uint64_t va
olditv = VCPU(vcpu, itv);
VCPU(vcpu, itv) = val;
if(ITV_IRQ_MASK(val)){
- clear_bit(ITV_VECTOR(olditv), &VCPU(vcpu, irr[0]));
+ vmx_vcpu_unpend_interrupt(vcpu, ITV_VECTOR(olditv));
}else if(ITV_VECTOR(olditv)!=ITV_VECTOR(val)){
- if(test_and_clear_bit(ITV_VECTOR(olditv), &VCPU(vcpu, irr[0])))
- set_bit(ITV_VECTOR(val), &VCPU(vcpu, irr[0]));
+ if (vmx_vcpu_unpend_interrupt(vcpu, ITV_VECTOR(olditv)))
+ vmx_vcpu_pend_interrupt(vcpu, ITV_VECTOR(val));
}
}
@@ -271,36 +322,6 @@ void vtm_domain_in(VCPU *vcpu)
}
}
*/
-
-/*
- * Next for vLSapic
- */
-
-#define NMI_VECTOR 2
-#define ExtINT_VECTOR 0
-#define NULL_VECTOR -1
-static void update_vhpi(VCPU *vcpu, int vec)
-{
- u64 vhpi;
- if ( vec == NULL_VECTOR ) {
- vhpi = 0;
- }
- else if ( vec == NMI_VECTOR ) { // NMI
- vhpi = 32;
- } else if (vec == ExtINT_VECTOR) { //ExtINT
- vhpi = 16;
- }
- else {
- vhpi = vec >> 4;
- }
-
- VCPU(vcpu,vhpi) = vhpi;
- // TODO: Add support for XENO
- if ( VCPU(vcpu,vac).a_int ) {
- ia64_call_vsa ( PAL_VPS_SET_PENDING_INTERRUPT,
- (uint64_t)vcpu->arch.privregs, 0, 0, 0, 0, 0, 0);
- }
-}
#ifdef V_IOSAPIC_READY
/* Assist to check virtual interrupt lines */
@@ -524,9 +545,13 @@ int vmx_vcpu_pend_interrupt(VCPU *vcpu,
local_irq_save(spsr);
ret = test_and_set_bit(vector, &VCPU(vcpu, irr[0]));
local_irq_restore(spsr);
- vcpu->arch.irq_new_pending = 1;
+
+ if (!ret)
+ vcpu->arch.irq_new_pending = 1;
+
return ret;
}
+
/*
* Add batch of pending interrupt.
@@ -559,14 +584,13 @@ void vmx_vcpu_pend_batch_interrupt(VCPU
*/
int vmx_check_pending_irq(VCPU *vcpu)
{
- uint64_t spsr, mask;
- int h_pending, h_inservice;
- uint64_t isr;
- IA64_PSR vpsr;
+ int mask, h_pending, h_inservice;
+ uint64_t isr;
+ IA64_PSR vpsr;
REGS *regs=vcpu_regs(vcpu);
- local_irq_save(spsr);
h_pending = highest_pending_irq(vcpu);
if ( h_pending == NULL_VECTOR ) {
+ update_vhpi(vcpu, NULL_VECTOR);
h_pending = SPURIOUS_VECTOR;
goto chk_irq_exit;
}
@@ -578,13 +602,11 @@ int vmx_check_pending_irq(VCPU *vcpu)
isr = vpsr.val & IA64_PSR_RI;
if ( !vpsr.ic )
panic_domain(regs,"Interrupt when IC=0\n");
+ update_vhpi(vcpu, h_pending);
+ vmx_reflect_interruption(0, isr, 0, 12, regs); // EXT IRQ
+ } else if (mask == IRQ_MASKED_BY_INSVC) {
if (VCPU(vcpu, vhpi))
update_vhpi(vcpu, NULL_VECTOR);
- vmx_reflect_interruption(0,isr,0, 12, regs ); // EXT IRQ
- }
- else if ( mask == IRQ_MASKED_BY_INSVC ) {
- // cann't inject VHPI
-// DPRINTK("IRQ masked by higher inservice\n");
}
else {
// masked by vpsr.i or vtpr.
@@ -592,7 +614,6 @@ int vmx_check_pending_irq(VCPU *vcpu)
}
chk_irq_exit:
- local_irq_restore(spsr);
return h_pending;
}
@@ -602,17 +623,13 @@ void guest_write_eoi(VCPU *vcpu)
void guest_write_eoi(VCPU *vcpu)
{
int vec;
- uint64_t spsr;
vec = highest_inservice_irq(vcpu);
if ( vec == NULL_VECTOR )
- panic_domain(vcpu_regs(vcpu),"Wrong vector to EOI\n");
- local_irq_save(spsr);
+ panic_domain(vcpu_regs(vcpu), "Wrong vector to EOI\n");
VLSAPIC_INSVC(vcpu,vec>>6) &= ~(1UL <<(vec&63));
- local_irq_restore(spsr);
VCPU(vcpu, eoi)=0; // overwrite the data
vcpu->arch.irq_new_pending=1;
-// vmx_check_pending_irq(vcpu);
}
int is_unmasked_irq(VCPU *vcpu)
@@ -631,23 +648,21 @@ int is_unmasked_irq(VCPU *vcpu)
uint64_t guest_read_vivr(VCPU *vcpu)
{
- int vec, h_inservice;
- uint64_t spsr;
-
- local_irq_save(spsr);
+ int vec, h_inservice, mask;
vec = highest_pending_irq(vcpu);
h_inservice = highest_inservice_irq(vcpu);
- if ( vec == NULL_VECTOR ||
- irq_masked(vcpu, vec, h_inservice) != IRQ_NO_MASKED ) {
- local_irq_restore(spsr);
+ mask = irq_masked(vcpu, vec, h_inservice);
+ if (vec == NULL_VECTOR || mask == IRQ_MASKED_BY_INSVC) {
+ if (VCPU(vcpu, vhpi))
+ update_vhpi(vcpu, NULL_VECTOR);
return IA64_SPURIOUS_INT_VECTOR;
}
-
+ if (mask == IRQ_MASKED_BY_VTPR) {
+ update_vhpi(vcpu, vec);
+ return IA64_SPURIOUS_INT_VECTOR;
+ }
VLSAPIC_INSVC(vcpu,vec>>6) |= (1UL <<(vec&63));
- VCPU(vcpu, irr[vec>>6]) &= ~(1UL <<(vec&63));
- if (VCPU(vcpu, vhpi))
- update_vhpi(vcpu, NULL_VECTOR); // clear VHPI till EOI or IRR write
- local_irq_restore(spsr);
+ vmx_vcpu_unpend_interrupt(vcpu, vec);
return (uint64_t)vec;
}
@@ -657,7 +672,6 @@ static void generate_exirq(VCPU *vcpu)
uint64_t isr;
REGS *regs=vcpu_regs(vcpu);
vpsr.val = VCPU(vcpu, vpsr);
- update_vhpi(vcpu, NULL_VECTOR);
isr = vpsr.val & IA64_PSR_RI;
if ( !vpsr.ic )
panic_domain(regs,"Interrupt when IC=0\n");
@@ -669,7 +683,6 @@ void vhpi_detection(VCPU *vcpu)
uint64_t threshold,vhpi;
tpr_t vtpr;
IA64_PSR vpsr;
-
vpsr.val = VCPU(vcpu, vpsr);
vtpr.val = VCPU(vcpu, tpr);
diff -r a7c6b1c5507c -r d5a46e4cc340 xen/arch/ia64/vmx/vmx_process.c
--- a/xen/arch/ia64/vmx/vmx_process.c Sun Oct 22 14:14:58 2006 -0600
+++ b/xen/arch/ia64/vmx/vmx_process.c Sun Oct 22 14:39:15 2006 -0600
@@ -242,10 +242,7 @@ void leave_hypervisor_tail(struct pt_reg
vmx_check_pending_irq(v);
return;
}
- if (VCPU(v, vac).a_int) {
- vhpi_detection(v);
- return;
- }
+
if (v->arch.irq_new_condition) {
v->arch.irq_new_condition = 0;
vhpi_detection(v);
diff -r a7c6b1c5507c -r d5a46e4cc340 xen/arch/ia64/xen/xentime.c
--- a/xen/arch/ia64/xen/xentime.c Sun Oct 22 14:14:58 2006 -0600
+++ b/xen/arch/ia64/xen/xentime.c Sun Oct 22 14:39:15 2006 -0600
@@ -109,7 +109,6 @@ xen_timer_interrupt (int irq, void *dev_
xen_timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
{
unsigned long new_itm, old_itc;
- int f_setitm = 0;
#if 0
#define HEARTBEAT_FREQ 16 // period in seconds
@@ -125,20 +124,9 @@ xen_timer_interrupt (int irq, void *dev_
#endif
#endif
- if (!is_idle_domain(current->domain)&&!VMX_DOMAIN(current))
- if (vcpu_timer_expired(current)) {
- vcpu_pend_timer(current);
- // ensure another timer interrupt happens even if
domain doesn't
- vcpu_set_next_timer(current);
- f_setitm = 1;
- }
new_itm = local_cpu_data->itm_next;
-
- if (f_setitm && !time_after(ia64_get_itc(), new_itm))
- return;
-
- while (1) {
+ while (time_after(ia64_get_itc(), new_itm)) {
new_itm += local_cpu_data->itm_delta;
if (smp_processor_id() == TIME_KEEPER_ID) {
@@ -148,27 +136,32 @@ xen_timer_interrupt (int irq, void *dev_
* another CPU. We need to avoid to SMP race by
acquiring the
* xtime_lock.
*/
-//#ifdef TURN_ME_OFF_FOR_NOW_IA64_XEN
write_seqlock(&xtime_lock);
-//#endif
#ifdef TURN_ME_OFF_FOR_NOW_IA64_XEN
do_timer(regs);
#endif
- local_cpu_data->itm_next = new_itm;
-
- /* Updates system time (nanoseconds since boot). */
+ /* Updates system time (nanoseconds since boot). */
old_itc = itc_at_irq;
itc_at_irq = ia64_get_itc();
stime_irq += cycle_to_ns(itc_at_irq - old_itc);
-//#ifdef TURN_ME_OFF_FOR_NOW_IA64_XEN
write_sequnlock(&xtime_lock);
-//#endif
- } else
- local_cpu_data->itm_next = new_itm;
-
- if (time_after(new_itm, ia64_get_itc()))
- break;
+ }
+
+ local_cpu_data->itm_next = new_itm;
+
+ }
+
+ if (!is_idle_domain(current->domain) && !VMX_DOMAIN(current)) {
+ if (vcpu_timer_expired(current)) {
+ vcpu_pend_timer(current);
+ } else {
+ // ensure another timer interrupt happens
+ // even if domain doesn't
+ vcpu_set_next_timer(current);
+ raise_softirq(TIMER_SOFTIRQ);
+ return;
+ }
}
do {
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|