Skip to contentSkip to conversation

PIT: optionally disable interrupt reinjection (v2)

PATCH Applied Marcelo Tosatti 2 participants 4 messages Dec 30, 2008 – Dec 31, 2008

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover PIT: optionally disable interrupt reinjection (v2)

Addressing comments.

#1 lore raw

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.

arch/x86/kvm/i8254.c +1 -1
Index: kvm/arch/x86/kvm/i8254.c
===================================================================
@@ -207,7 +207,7 @@ static int __pit_timer_fn(struct kvm_kpi
 	hrtimer_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);
 }
#2 lore raw

PATCH 2/2 KVM: PIT: provide an option to disable interrupt reinjection

In reply to Marcelo Tosatti

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.

arch/x86/kvm/i8254.c +4 -0
Index: 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);
arch/x86/kvm/i8254.h +1 -0
Index: 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 {
arch/x86/kvm/x86.c +22 -0
Index: 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:
 		;
 	}
include/linux/kvm.h +4 -0
Index: 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
arch/x86/include/asm/kvm.h +4 -0
Index: 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 */
Applied
#3 lore raw
In reply to Marcelo Tosatti
Quoted 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