PIT: optionally disable interrupt reinjection (v2)
cover PIT: optionally disable interrupt reinjection (v2)
Addressing comments.
PATCH 1/2 KVM: PIT: fix i8254 pending count read
count_load_time assignment is bogus: its supposed to contain what it means, not the expiration time.
Signed-off-by Marcelo Tosatti <[email protected]>
arch/x86/kvm/i8254.c +1 -1
@@ -207,7 +207,7 @@ static int __pit_timer_fn(struct kvm_kpihrtimer_add_expires_ns (&pt->timer, pt->period); pt->scheduled =hrtimer_get_expires_ns (&pt->timer);if (pt->period) - ps->channels[0 ].count_load_time =hrtimer_get_expires (&pt->timer); + ps->channels[0 ].count_load_time =ktime_get ();return (pt->period ==0 ?0 :1 ); }
PATCH 2/2 KVM: PIT: provide an option to disable interrupt reinjection
In reply to Marcelo TosattiCertain 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 <[email protected]>
arch/x86/kvm/i8254.c +4 -0
@@ -201,6 +201,9 @@ static int __pit_timer_fn(struct kvm_kpiif (!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);
arch/x86/kvm/i8254.h +1 -0
@@ -9,6 +9,7 @@ struct kvm_kpit_timer {s64 period;/* unit: ns */ s64 scheduled;atomic_t pending; +bool reinject; };struct kvm_kpit_channel_state {
arch/x86/kvm/x86.c +22 -0
@@ -991,6 +991,7 @@ int kvm_dev_ioctl_check_extension(long ecase 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 kreturn 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 : ; }
include/linux/kvm.h +4 -0
@@ -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
arch/x86/include/asm/kvm.h +4 -0
@@ -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 */
Avi Kivity
AppliedQuoted 3 lines · Marcelo Tosatti
Addressing comments.
Applied, thanks. I removed PIT_ everywhere and added some reserved space, so we can control reinjection of other timers using the same ioctl.
Signature · 1 line
error compiling committee.c: too many arguments to function