]> err.no Git - linux-2.6/blobdiff - arch/x86/kernel/kvmclock.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[linux-2.6] / arch / x86 / kernel / kvmclock.c
index b999f5e5b3bfd9dae4996798cebca7e1cf87cfaf..4bc1be5d5472432e642dc491dc9821a55f57abad 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/msr.h>
 #include <asm/apic.h>
 #include <linux/percpu.h>
+#include <asm/reboot.h>
 
 #define KVM_SCALE 22
 
@@ -132,6 +133,7 @@ static int kvm_register_clock(void)
        return native_write_msr_safe(MSR_KVM_SYSTEM_TIME, low, high);
 }
 
+#ifdef CONFIG_X86_LOCAL_APIC
 static void kvm_setup_secondary_clock(void)
 {
        /*
@@ -142,6 +144,29 @@ static void kvm_setup_secondary_clock(void)
        /* ok, done with our trickery, call native */
        setup_secondary_APIC_clock();
 }
+#endif
+
+/*
+ * After the clock is registered, the host will keep writing to the
+ * registered memory location. If the guest happens to shutdown, this memory
+ * won't be valid. In cases like kexec, in which you install a new kernel, this
+ * means a random memory location will be kept being written. So before any
+ * kind of shutdown from our side, we unregister the clock by writting anything
+ * that does not have the 'enable' bit set in the msr
+ */
+#ifdef CONFIG_KEXEC
+static void kvm_crash_shutdown(struct pt_regs *regs)
+{
+       native_write_msr_safe(MSR_KVM_SYSTEM_TIME, 0, 0);
+       native_machine_crash_shutdown(regs);
+}
+#endif
+
+static void kvm_shutdown(void)
+{
+       native_write_msr_safe(MSR_KVM_SYSTEM_TIME, 0, 0);
+       native_machine_shutdown();
+}
 
 void __init kvmclock_init(void)
 {
@@ -154,7 +179,13 @@ void __init kvmclock_init(void)
                pv_time_ops.get_wallclock = kvm_get_wallclock;
                pv_time_ops.set_wallclock = kvm_set_wallclock;
                pv_time_ops.sched_clock = kvm_clock_read;
+#ifdef CONFIG_X86_LOCAL_APIC
                pv_apic_ops.setup_secondary_clock = kvm_setup_secondary_clock;
+#endif
+               machine_ops.shutdown  = kvm_shutdown;
+#ifdef CONFIG_KEXEC
+               machine_ops.crash_shutdown  = kvm_crash_shutdown;
+#endif
                clocksource_register(&kvm_clock);
        }
 }