Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 340e01248478ba8b78a6d4d1809b1eff > files > 521

kvm-83-270.el5_11.src.rpm

From 00741ee76dceb7b4410ae63afe2891819825d9ff Mon Sep 17 00:00:00 2001
From: Marcelo Tosatti <mtosatti@redhat.com>
Date: Fri, 30 Dec 2011 11:11:55 -0200
Subject: [PATCH] KVM: x86: Prevent starting PIT timers in the absence of
 irqchip support

(upstream commit 15c875cbb8748513f92aba35a7e5aa9d5026baa9)

From: Jan Kiszka <jan.kiszka@siemens.com>

User space may create the PIT and forgets about setting up the irqchips.

In that case, firing PIT IRQs will crash the host:

BUG: unable to handle kernel NULL pointer dereference at 0000000000000128
IP: [<ffffffffa10f6280>] kvm_set_irq+0x30/0x170 [kvm]
...
Call Trace:
 [<ffffffffa11228c1>] pit_do_work+0x51/0xd0 [kvm]
 [<ffffffff81071431>] process_one_work+0x111/0x4d0
 [<ffffffff81071bb2>] worker_thread+0x152/0x340
 [<ffffffff81075c8e>] kthread+0x7e/0x90
 [<ffffffff815a4474>] kernel_thread_helper+0x4/0x10

Prevent this by checking the irqchip mode before starting a timer.
We can't deny creating the PIT if the irqchips aren't set up yet as
current user land expects this order to work.

BZ: 770101
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Michal Novotny <mignov@gmail.com>
---
 arch/x86/kvm/i8254.c |   10 +++++++---
 1 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
index 4cc536a..229b30a 100644
--- a/arch/x86/kvm/i8254.c
+++ b/arch/x86/kvm/i8254.c
@@ -269,13 +269,17 @@ static void destroy_pit_timer(struct kvm_kpit_timer *pt)
 	hrtimer_cancel(&pt->timer);
 }
 
-static void create_pit_timer(struct kvm_kpit_state *ps, u32 val, int is_period)
+static void create_pit_timer(struct kvm *kvm, struct kvm_kpit_state *ps,
+			     u32 val, int is_period)
 {
 	struct kvm_kpit_timer *pt = &ps->pit_timer;
 	s64 interval;
 
 	interval = muldiv64(val, NSEC_PER_SEC, KVM_PIT_FREQ);
 
+	if (!irqchip_in_kernel(kvm))
+		return;
+
 	pr_debug("pit: create pit timer, interval is %llu nsec\n", interval);
 
 	/* TODO The new value only affected after the retriggered */
@@ -318,11 +322,11 @@ static void pit_load_count(struct kvm *kvm, int channel, u32 val)
 	case 1:
         /* FIXME: enhance mode 4 precision */
 	case 4:
-		create_pit_timer(ps, val, 0);
+		create_pit_timer(kvm, ps, val, 0);
 		break;
 	case 2:
 	case 3:
-		create_pit_timer(ps, val, 1);
+		create_pit_timer(kvm, ps, val, 1);
 		break;
 	default:
 		destroy_pit_timer(&ps->pit_timer);
-- 
1.7.7.4