Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 68413
b: refs/heads/master
c: 1b9778d
h: refs/heads/master
i:
  68411: 134a74d
v: v3
  • Loading branch information
Eddie Dong authored and Avi Kivity committed Oct 13, 2007
1 parent dac8598 commit d93065f
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 26 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 6e5d865c0b9679b00b5e5f0754c9fc2b6b9894d6
refs/heads/master: 1b9778dae71dc64d3678d766c0f1fbed79c80f9f
13 changes: 13 additions & 0 deletions trunk/drivers/kvm/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,16 @@ void kvm_vcpu_kick(struct kvm_vcpu *vcpu)
smp_call_function_single(ipi_pcpu, vcpu_kick_intr, vcpu, 0, 0);
}

void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu)
{
kvm_inject_apic_timer_irqs(vcpu);
/* TODO: PIT, RTC etc. */
}
EXPORT_SYMBOL_GPL(kvm_inject_pending_timer_irqs);

void kvm_timer_intr_post(struct kvm_vcpu *vcpu, int vec)
{
kvm_apic_timer_intr_post(vcpu, vec);
/* TODO: PIT, RTC etc. */
}
EXPORT_SYMBOL_GPL(kvm_timer_intr_post);
4 changes: 4 additions & 0 deletions trunk/drivers/kvm/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,5 +154,9 @@ int kvm_ioapic_init(struct kvm *kvm);
void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level);
int kvm_lapic_enabled(struct kvm_vcpu *vcpu);
int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
void kvm_apic_timer_intr_post(struct kvm_vcpu *vcpu, int vec);
void kvm_timer_intr_post(struct kvm_vcpu *vcpu, int vec);
void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu);
void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu);

#endif
2 changes: 2 additions & 0 deletions trunk/drivers/kvm/kvm_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,8 @@ EXPORT_SYMBOL_GPL(kvm_vcpu_init);
void kvm_vcpu_uninit(struct kvm_vcpu *vcpu)
{
kvm_mmu_destroy(vcpu);
if (vcpu->apic)
hrtimer_cancel(&vcpu->apic->timer.dev);
kvm_free_apic(vcpu->apic);
free_page((unsigned long)vcpu->pio_data);
free_page((unsigned long)vcpu->run);
Expand Down
58 changes: 38 additions & 20 deletions trunk/drivers/kvm/lapic.c
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
int vector, int level, int trig_mode)
{
int result = 0;
int orig_irr;

switch (delivery_mode) {
case APIC_DM_FIXED:
Expand All @@ -321,7 +322,8 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
if (unlikely(!apic_enabled(apic)))
break;

if (apic_test_and_set_irr(vector, apic) && trig_mode) {
orig_irr = apic_test_and_set_irr(vector, apic);
if (orig_irr && trig_mode) {
apic_debug("level trig mode repeatedly for vector %d",
vector);
break;
Expand All @@ -335,7 +337,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,

kvm_vcpu_kick(apic->vcpu);

result = 1;
result = (orig_irr == 0);
break;

case APIC_DM_REMRD:
Expand Down Expand Up @@ -831,38 +833,33 @@ EXPORT_SYMBOL_GPL(kvm_lapic_enabled);
* timer interface
*----------------------------------------------------------------------
*/

/* TODO: make sure __apic_timer_fn runs in current pCPU */
static int __apic_timer_fn(struct kvm_lapic *apic)
{
u32 vector;
int result = 0;
wait_queue_head_t *q = &apic->vcpu->wq;

if (unlikely(!apic_enabled(apic) ||
!apic_lvt_enabled(apic, APIC_LVTT))) {
apic_debug("%s: time interrupt although apic is down\n",
__FUNCTION__);
return 0;
}

vector = apic_lvt_vector(apic, APIC_LVTT);
apic->timer.last_update = apic->timer.dev.expires;
atomic_inc(&apic->timer.pending);
__apic_accept_irq(apic, APIC_DM_FIXED, vector, 1, 0);

if (waitqueue_active(q))
wake_up_interruptible(q);
if (apic_lvtt_period(apic)) {
u32 offset;
u32 tmict = apic_get_reg(apic, APIC_TMICT);

offset = APIC_BUS_CYCLE_NS * apic->timer.divide_count * tmict;

result = 1;
apic->timer.dev.expires = ktime_add_ns(
apic->timer.dev.expires,
apic->timer.period);
}

return result;
}

static int __inject_apic_timer_irq(struct kvm_lapic *apic)
{
int vector;

vector = apic_lvt_vector(apic, APIC_LVTT);
return __apic_accept_irq(apic, APIC_DM_FIXED, vector, 1, 0);
}

static enum hrtimer_restart apic_timer_fn(struct hrtimer *data)
{
struct kvm_lapic *apic;
Expand Down Expand Up @@ -935,6 +932,27 @@ int kvm_apic_has_interrupt(struct kvm_vcpu *vcpu)
return highest_irr;
}

void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu)
{
struct kvm_lapic *apic = vcpu->apic;

if (apic && apic_lvt_enabled(apic, APIC_LVTT) &&
atomic_read(&apic->timer.pending) > 0) {
if (__inject_apic_timer_irq(apic))
atomic_dec(&apic->timer.pending);
}
}

void kvm_apic_timer_intr_post(struct kvm_vcpu *vcpu, int vec)
{
struct kvm_lapic *apic = vcpu->apic;

if (apic && apic_lvt_vector(apic, APIC_LVTT) == vec)
apic->timer.last_update = ktime_add_ns(
apic->timer.last_update,
apic->timer.period);
}

int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu)
{
int vector = kvm_apic_has_interrupt(vcpu);
Expand Down
7 changes: 5 additions & 2 deletions trunk/drivers/kvm/svm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1331,7 +1331,9 @@ static void svm_intr_assist(struct vcpu_svm *svm)
{
struct vmcb *vmcb = svm->vmcb;
int intr_vector = -1;
struct kvm_vcpu *vcpu = &svm->vcpu;

kvm_inject_pending_timer_irqs(vcpu);
if ((vmcb->control.exit_int_info & SVM_EVTINJ_VALID) &&
((vmcb->control.exit_int_info & SVM_EVTINJ_TYPE_MASK) == 0)) {
intr_vector = vmcb->control.exit_int_info &
Expand All @@ -1344,7 +1346,7 @@ static void svm_intr_assist(struct vcpu_svm *svm)
if (vmcb->control.int_ctl & V_IRQ_MASK)
return;

if (!kvm_cpu_has_interrupt(&svm->vcpu))
if (!kvm_cpu_has_interrupt(vcpu))
return;

if (!(vmcb->save.rflags & X86_EFLAGS_IF) ||
Expand All @@ -1356,8 +1358,9 @@ static void svm_intr_assist(struct vcpu_svm *svm)
return;
}
/* Okay, we can deliver the interrupt: grab it and update PIC state. */
intr_vector = kvm_cpu_get_interrupt(&svm->vcpu);
intr_vector = kvm_cpu_get_interrupt(vcpu);
svm_inject_irq(svm, intr_vector);
kvm_timer_intr_post(vcpu, intr_vector);
}

static void kvm_reput_irq(struct vcpu_svm *svm)
Expand Down
10 changes: 7 additions & 3 deletions trunk/drivers/kvm/vmx.c
Original file line number Diff line number Diff line change
Expand Up @@ -2151,7 +2151,9 @@ static void vmx_intr_assist(struct kvm_vcpu *vcpu)
{
u32 idtv_info_field, intr_info_field;
int has_ext_irq, interrupt_window_open;
int vector;

kvm_inject_pending_timer_irqs(vcpu);
update_tpr_threshold(vcpu);

has_ext_irq = kvm_cpu_has_interrupt(vcpu);
Expand Down Expand Up @@ -2183,9 +2185,11 @@ static void vmx_intr_assist(struct kvm_vcpu *vcpu)
interrupt_window_open =
((vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) &&
(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & 3) == 0);
if (interrupt_window_open)
vmx_inject_irq(vcpu, kvm_cpu_get_interrupt(vcpu));
else
if (interrupt_window_open) {
vector = kvm_cpu_get_interrupt(vcpu);
vmx_inject_irq(vcpu, vector);
kvm_timer_intr_post(vcpu, vector);
} else
enable_irq_window(vcpu);
}

Expand Down

0 comments on commit d93065f

Please sign in to comment.