* [patch 2/2] KVM: PIT: provide an option to disable interrupt reinjection
2008-12-30 17:55 [patch 0/2] PIT: optionally disable interrupt reinjection (v2) Marcelo Tosatti
2008-12-30 17:55 ` [patch 1/2] KVM: PIT: fix i8254 pending count read Marcelo Tosatti
@ 2008-12-30 17:55 ` Marcelo Tosatti
2008-12-31 9:52 ` [patch 0/2] PIT: optionally disable interrupt reinjection (v2) Avi Kivity
2 siblings, 0 replies; 4+ messages in thread
From: Marcelo Tosatti @ 2008-12-30 17:55 UTC (permalink / raw)
To: kvm; +Cc: avi, sheng, Marcelo Tosatti
[-- Attachment #1: i8254-disable-reinject --]
[-- Type: text/plain, Size: 3516 bytes --]
Certain clocks (such as TSC) in older 2.6 guests overaccount for lost
ticks, causing severe time drift. Interrupt reinjection magnifies the
problem.
Provide an option to disable it.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Index: kvm/arch/x86/kvm/i8254.c
===================================================================
--- kvm.orig/arch/x86/kvm/i8254.c
+++ kvm/arch/x86/kvm/i8254.c
@@ -201,6 +201,9 @@ static int __pit_timer_fn(struct kvm_kpi
if (!atomic_inc_and_test(&pt->pending))
set_bit(KVM_REQ_PENDING_TIMER, &vcpu0->requests);
+ if (!pt->reinject)
+ atomic_set(&pt->pending, 1);
+
if (vcpu0 && waitqueue_active(&vcpu0->wq))
wake_up_interruptible(&vcpu0->wq);
@@ -580,6 +583,7 @@ struct kvm_pit *kvm_create_pit(struct kv
pit_state->irq_ack_notifier.gsi = 0;
pit_state->irq_ack_notifier.irq_acked = kvm_pit_ack_irq;
kvm_register_irq_ack_notifier(kvm, &pit_state->irq_ack_notifier);
+ pit_state->pit_timer.reinject = true;
mutex_unlock(&pit->pit_state.lock);
kvm_pit_reset(pit);
Index: kvm/arch/x86/kvm/i8254.h
===================================================================
--- kvm.orig/arch/x86/kvm/i8254.h
+++ kvm/arch/x86/kvm/i8254.h
@@ -9,6 +9,7 @@ struct kvm_kpit_timer {
s64 period; /* unit: ns */
s64 scheduled;
atomic_t pending;
+ bool reinject;
};
struct kvm_kpit_channel_state {
Index: kvm/arch/x86/kvm/x86.c
===================================================================
--- kvm.orig/arch/x86/kvm/x86.c
+++ kvm/arch/x86/kvm/x86.c
@@ -991,6 +991,7 @@ int kvm_dev_ioctl_check_extension(long e
case KVM_CAP_NOP_IO_DELAY:
case KVM_CAP_MP_STATE:
case KVM_CAP_SYNC_MMU:
+ case KVM_CAP_PIT_REINJECT_CONTROL:
r = 1;
break;
case KVM_CAP_COALESCED_MMIO:
@@ -1723,6 +1724,13 @@ static int kvm_vm_ioctl_set_pit(struct k
return r;
}
+static int kvm_vm_ioctl_pit_reinject(struct kvm *kvm,
+ struct kvm_pit_reinject_control *control)
+{
+ kvm->arch.vpit->pit_state.pit_timer.reinject = control->reinject;
+ return 0;
+}
+
/*
* Get (and clear) the dirty memory log for a memory slot.
*/
@@ -1920,6 +1928,20 @@ long kvm_arch_vm_ioctl(struct file *filp
r = 0;
break;
}
+ case KVM_PIT_REINJECT_CONTROL: {
+ struct kvm_pit_reinject_control control;
+ r = -EFAULT;
+ if (copy_from_user(&control, argp, sizeof(control)))
+ goto out;
+ r = -ENXIO;
+ if (!kvm->arch.vpit)
+ goto out;
+ r = kvm_vm_ioctl_pit_reinject(kvm, &control);
+ if (r)
+ goto out;
+ r = 0;
+ break;
+ }
default:
;
}
Index: kvm/include/linux/kvm.h
===================================================================
--- kvm.orig/include/linux/kvm.h
+++ kvm/include/linux/kvm.h
@@ -396,6 +396,9 @@ struct kvm_trace_rec {
#if defined(CONFIG_X86)
#define KVM_CAP_SET_GUEST_DEBUG 23
#endif
+#if defined(CONFIG_X86)
+#define KVM_CAP_PIT_REINJECT_CONTROL 24
+#endif
/*
* ioctls for VM fds
@@ -429,6 +432,7 @@ struct kvm_trace_rec {
struct kvm_assigned_pci_dev)
#define KVM_ASSIGN_IRQ _IOR(KVMIO, 0x70, \
struct kvm_assigned_irq)
+#define KVM_PIT_REINJECT_CONTROL _IO(KVMIO, 0x71)
/*
* ioctls for vcpu fds
Index: kvm/arch/x86/include/asm/kvm.h
===================================================================
--- kvm.orig/arch/x86/include/asm/kvm.h
+++ kvm/arch/x86/include/asm/kvm.h
@@ -226,4 +226,8 @@ struct kvm_guest_debug_arch {
struct kvm_pit_state {
struct kvm_pit_channel_state channels[3];
};
+
+struct kvm_pit_reinject_control {
+ __u8 reinject;
+};
#endif /* _ASM_X86_KVM_H */
--
^ permalink raw reply [flat|nested] 4+ messages in thread