[PATCH] KVM: cpu hotplug support
[safe/jmp/linux-2.6] / drivers / kvm / kvm_main.c
index 9f24f22..291d298 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/highmem.h>
 #include <linux/file.h>
 #include <asm/desc.h>
+#include <linux/cpu.h>
 
 #include "x86_emulate.h"
 #include "segment_descriptor.h"
@@ -41,6 +42,9 @@
 MODULE_AUTHOR("Qumranet");
 MODULE_LICENSE("GPL");
 
+static DEFINE_SPINLOCK(kvm_lock);
+static LIST_HEAD(vm_list);
+
 struct kvm_arch_ops *kvm_arch_ops;
 struct kvm_stat kvm_stat;
 EXPORT_SYMBOL_GPL(kvm_stat);
@@ -58,8 +62,11 @@ static struct kvm_stats_debugfs_item {
        { "io_exits", &kvm_stat.io_exits },
        { "mmio_exits", &kvm_stat.mmio_exits },
        { "signal_exits", &kvm_stat.signal_exits },
+       { "irq_window", &kvm_stat.irq_window_exits },
+       { "halt_exits", &kvm_stat.halt_exits },
+       { "request_irq", &kvm_stat.request_irq_exits },
        { "irq_exits", &kvm_stat.irq_exits },
-       { 0, 0 }
+       { NULL, NULL }
 };
 
 static struct dentry *debugfs_dir;
@@ -202,7 +209,7 @@ static struct kvm_vcpu *vcpu_load(struct kvm *kvm, int vcpu_slot)
        mutex_lock(&vcpu->mutex);
        if (unlikely(!vcpu->vmcs)) {
                mutex_unlock(&vcpu->mutex);
-               return 0;
+               return NULL;
        }
        return kvm_arch_ops->vcpu_load(vcpu);
 }
@@ -227,8 +234,13 @@ static int kvm_dev_open(struct inode *inode, struct file *filp)
                struct kvm_vcpu *vcpu = &kvm->vcpus[i];
 
                mutex_init(&vcpu->mutex);
+               vcpu->cpu = -1;
+               vcpu->kvm = kvm;
                vcpu->mmu.root_hpa = INVALID_PAGE;
                INIT_LIST_HEAD(&vcpu->free_pages);
+               spin_lock(&kvm_lock);
+               list_add(&kvm->vm_list, &vm_list);
+               spin_unlock(&kvm_lock);
        }
        filp->private_data = kvm;
        return 0;
@@ -245,16 +257,17 @@ static void kvm_free_physmem_slot(struct kvm_memory_slot *free,
        if (!dont || free->phys_mem != dont->phys_mem)
                if (free->phys_mem) {
                        for (i = 0; i < free->npages; ++i)
-                               __free_page(free->phys_mem[i]);
+                               if (free->phys_mem[i])
+                                       __free_page(free->phys_mem[i]);
                        vfree(free->phys_mem);
                }
 
        if (!dont || free->dirty_bitmap != dont->dirty_bitmap)
                vfree(free->dirty_bitmap);
 
-       free->phys_mem = 0;
+       free->phys_mem = NULL;
        free->npages = 0;
-       free->dirty_bitmap = 0;
+       free->dirty_bitmap = NULL;
 }
 
 static void kvm_free_physmem(struct kvm *kvm)
@@ -262,13 +275,17 @@ static void kvm_free_physmem(struct kvm *kvm)
        int i;
 
        for (i = 0; i < kvm->nmemslots; ++i)
-               kvm_free_physmem_slot(&kvm->memslots[i], 0);
+               kvm_free_physmem_slot(&kvm->memslots[i], NULL);
 }
 
 static void kvm_free_vcpu(struct kvm_vcpu *vcpu)
 {
-       kvm_arch_ops->vcpu_free(vcpu);
+       if (!vcpu_load(vcpu->kvm, vcpu_slot(vcpu)))
+               return;
+
        kvm_mmu_destroy(vcpu);
+       vcpu_put(vcpu);
+       kvm_arch_ops->vcpu_free(vcpu);
 }
 
 static void kvm_free_vcpus(struct kvm *kvm)
@@ -283,6 +300,9 @@ static int kvm_dev_release(struct inode *inode, struct file *filp)
 {
        struct kvm *kvm = filp->private_data;
 
+       spin_lock(&kvm_lock);
+       list_del(&kvm->vm_list);
+       spin_unlock(&kvm_lock);
        kvm_free_vcpus(kvm);
        kvm_free_physmem(kvm);
        kfree(kvm);
@@ -294,14 +314,17 @@ static void inject_gp(struct kvm_vcpu *vcpu)
        kvm_arch_ops->inject_gp(vcpu, 0);
 }
 
-static int pdptrs_have_reserved_bits_set(struct kvm_vcpu *vcpu,
-                                        unsigned long cr3)
+/*
+ * Load the pae pdptrs.  Return true is they are all valid.
+ */
+static int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3)
 {
        gfn_t pdpt_gfn = cr3 >> PAGE_SHIFT;
-       unsigned offset = (cr3 & (PAGE_SIZE-1)) >> 5;
+       unsigned offset = ((cr3 & (PAGE_SIZE-1)) >> 5) << 2;
        int i;
        u64 pdpte;
        u64 *pdpt;
+       int ret;
        struct kvm_memory_slot *memslot;
 
        spin_lock(&vcpu->kvm->lock);
@@ -309,16 +332,23 @@ static int pdptrs_have_reserved_bits_set(struct kvm_vcpu *vcpu,
        /* FIXME: !memslot - emulate? 0xff? */
        pdpt = kmap_atomic(gfn_to_page(memslot, pdpt_gfn), KM_USER0);
 
+       ret = 1;
        for (i = 0; i < 4; ++i) {
                pdpte = pdpt[offset + i];
-               if ((pdpte & 1) && (pdpte & 0xfffffff0000001e6ull))
-                       break;
+               if ((pdpte & 1) && (pdpte & 0xfffffff0000001e6ull)) {
+                       ret = 0;
+                       goto out;
+               }
        }
 
+       for (i = 0; i < 4; ++i)
+               vcpu->pdptrs[i] = pdpt[offset + i];
+
+out:
        kunmap_atomic(pdpt, KM_USER0);
        spin_unlock(&vcpu->kvm->lock);
 
-       return i != 4;
+       return ret;
 }
 
 void set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
@@ -364,8 +394,7 @@ void set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
                        }
                } else
 #endif
-               if (is_pae(vcpu) &&
-                           pdptrs_have_reserved_bits_set(vcpu, vcpu->cr3)) {
+               if (is_pae(vcpu) && !load_pdptrs(vcpu, vcpu->cr3)) {
                        printk(KERN_DEBUG "set_cr0: #GP, pdptrs "
                               "reserved bits\n");
                        inject_gp(vcpu);
@@ -386,6 +415,7 @@ EXPORT_SYMBOL_GPL(set_cr0);
 
 void lmsw(struct kvm_vcpu *vcpu, unsigned long msw)
 {
+       kvm_arch_ops->decache_cr0_cr4_guest_bits(vcpu);
        set_cr0(vcpu, (vcpu->cr0 & ~0x0ful) | (msw & 0x0f));
 }
 EXPORT_SYMBOL_GPL(lmsw);
@@ -398,7 +428,7 @@ void set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
                return;
        }
 
-       if (kvm_arch_ops->is_long_mode(vcpu)) {
+       if (is_long_mode(vcpu)) {
                if (!(cr4 & CR4_PAE_MASK)) {
                        printk(KERN_DEBUG "set_cr4: #GP, clearing PAE while "
                               "in long mode\n");
@@ -406,7 +436,7 @@ void set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
                        return;
                }
        } else if (is_paging(vcpu) && !is_pae(vcpu) && (cr4 & CR4_PAE_MASK)
-                  && pdptrs_have_reserved_bits_set(vcpu, vcpu->cr3)) {
+                  && !load_pdptrs(vcpu, vcpu->cr3)) {
                printk(KERN_DEBUG "set_cr4: #GP, pdptrs reserved bits\n");
                inject_gp(vcpu);
        }
@@ -425,7 +455,7 @@ EXPORT_SYMBOL_GPL(set_cr4);
 
 void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
 {
-       if (kvm_arch_ops->is_long_mode(vcpu)) {
+       if (is_long_mode(vcpu)) {
                if ( cr3 & CR3_L_MODE_RESEVED_BITS) {
                        printk(KERN_DEBUG "set_cr3: #GP, reserved bits\n");
                        inject_gp(vcpu);
@@ -438,7 +468,7 @@ void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
                        return;
                }
                if (is_paging(vcpu) && is_pae(vcpu) &&
-                   pdptrs_have_reserved_bits_set(vcpu, cr3)) {
+                   !load_pdptrs(vcpu, cr3)) {
                        printk(KERN_DEBUG "set_cr3: #GP, pdptrs "
                               "reserved bits\n");
                        inject_gp(vcpu);
@@ -448,7 +478,19 @@ void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
 
        vcpu->cr3 = cr3;
        spin_lock(&vcpu->kvm->lock);
-       vcpu->mmu.new_cr3(vcpu);
+       /*
+        * Does the new cr3 value map to physical memory? (Note, we
+        * catch an invalid cr3 even in real-mode, because it would
+        * cause trouble later on when we turn on paging anyway.)
+        *
+        * A real CPU would silently accept an invalid cr3 and would
+        * attempt to use it - with largely undefined (and often hard
+        * to debug) behavior on the guest side.
+        */
+       if (unlikely(!gfn_to_memslot(vcpu->kvm, cr3 >> PAGE_SHIFT)))
+               inject_gp(vcpu);
+       else
+               vcpu->mmu.new_cr3(vcpu);
        spin_unlock(&vcpu->kvm->lock);
 }
 EXPORT_SYMBOL_GPL(set_cr3);
@@ -515,18 +557,18 @@ static int kvm_dev_ioctl_create_vcpu(struct kvm *kvm, int n)
                                           FX_IMAGE_ALIGN);
        vcpu->guest_fx_image = vcpu->host_fx_image + FX_IMAGE_SIZE;
 
-       vcpu->cpu = -1;  /* First load will set up TR */
-       vcpu->kvm = kvm;
        r = kvm_arch_ops->vcpu_create(vcpu);
        if (r < 0)
                goto out_free_vcpus;
 
-       kvm_arch_ops->vcpu_load(vcpu);
+       r = kvm_mmu_create(vcpu);
+       if (r < 0)
+               goto out_free_vcpus;
 
-       r = kvm_arch_ops->vcpu_setup(vcpu);
+       kvm_arch_ops->vcpu_load(vcpu);
+       r = kvm_mmu_setup(vcpu);
        if (r >= 0)
-               r = kvm_mmu_init(vcpu);
-
+               r = kvm_arch_ops->vcpu_setup(vcpu);
        vcpu_put(vcpu);
 
        if (r < 0)
@@ -610,11 +652,11 @@ raced:
 
        /* Deallocate if slot is being removed */
        if (!npages)
-               new.phys_mem = 0;
+               new.phys_mem = NULL;
 
        /* Free page dirty bitmap if unneeded */
        if (!(new.flags & KVM_MEM_LOG_DIRTY_PAGES))
-               new.dirty_bitmap = 0;
+               new.dirty_bitmap = NULL;
 
        r = -ENOMEM;
 
@@ -631,6 +673,7 @@ raced:
                                                     | __GFP_ZERO);
                        if (!new.phys_mem[i])
                                goto out_free;
+                       new.phys_mem[i]->private = 0;
                }
        }
 
@@ -685,6 +728,13 @@ out:
        return r;
 }
 
+static void do_remove_write_access(struct kvm_vcpu *vcpu, int slot)
+{
+       spin_lock(&vcpu->kvm->lock);
+       kvm_mmu_slot_remove_write_access(vcpu, slot);
+       spin_unlock(&vcpu->kvm->lock);
+}
+
 /*
  * Get (and clear) the dirty memory log for a memory slot.
  */
@@ -694,6 +744,7 @@ static int kvm_dev_ioctl_get_dirty_log(struct kvm *kvm,
        struct kvm_memory_slot *memslot;
        int r, i;
        int n;
+       int cleared;
        unsigned long any = 0;
 
        spin_lock(&kvm->lock);
@@ -724,15 +775,17 @@ static int kvm_dev_ioctl_get_dirty_log(struct kvm *kvm,
 
 
        if (any) {
-               spin_lock(&kvm->lock);
-               kvm_mmu_slot_remove_write_access(kvm, log->slot);
-               spin_unlock(&kvm->lock);
-               memset(memslot->dirty_bitmap, 0, n);
+               cleared = 0;
                for (i = 0; i < KVM_MAX_VCPUS; ++i) {
                        struct kvm_vcpu *vcpu = vcpu_load(kvm, i);
 
                        if (!vcpu)
                                continue;
+                       if (!cleared) {
+                               do_remove_write_access(vcpu, log->slot);
+                               memset(memslot->dirty_bitmap, 0, n);
+                               cleared = 1;
+                       }
                        kvm_arch_ops->tlb_flush(vcpu);
                        vcpu_put(vcpu);
                }
@@ -758,14 +811,14 @@ struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn)
                    && gfn < memslot->base_gfn + memslot->npages)
                        return memslot;
        }
-       return 0;
+       return NULL;
 }
 EXPORT_SYMBOL_GPL(gfn_to_memslot);
 
 void mark_page_dirty(struct kvm *kvm, gfn_t gfn)
 {
        int i;
-       struct kvm_memory_slot *memslot = 0;
+       struct kvm_memory_slot *memslot = NULL;
        unsigned long rel_gfn;
 
        for (i = 0; i < kvm->nmemslots; ++i) {
@@ -860,6 +913,27 @@ static int emulator_read_emulated(unsigned long addr,
        }
 }
 
+static int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
+                              unsigned long val, int bytes)
+{
+       struct kvm_memory_slot *m;
+       struct page *page;
+       void *virt;
+
+       if (((gpa + bytes - 1) >> PAGE_SHIFT) != (gpa >> PAGE_SHIFT))
+               return 0;
+       m = gfn_to_memslot(vcpu->kvm, gpa >> PAGE_SHIFT);
+       if (!m)
+               return 0;
+       page = gfn_to_page(m, gpa >> PAGE_SHIFT);
+       kvm_mmu_pre_write(vcpu, gpa, bytes);
+       virt = kmap_atomic(page, KM_USER0);
+       memcpy(virt + offset_in_page(gpa), &val, bytes);
+       kunmap_atomic(virt, KM_USER0);
+       kvm_mmu_post_write(vcpu, gpa, bytes);
+       return 1;
+}
+
 static int emulator_write_emulated(unsigned long addr,
                                   unsigned long val,
                                   unsigned int bytes,
@@ -871,6 +945,9 @@ static int emulator_write_emulated(unsigned long addr,
        if (gpa == UNMAPPED_GVA)
                return X86EMUL_PROPAGATE_FAULT;
 
+       if (emulator_write_phys(vcpu, gpa, val, bytes))
+               return X86EMUL_CONTINUE;
+
        vcpu->mmio_needed = 1;
        vcpu->mmio_phys_addr = gpa;
        vcpu->mmio_size = bytes;
@@ -895,6 +972,30 @@ static int emulator_cmpxchg_emulated(unsigned long addr,
        return emulator_write_emulated(addr, new, bytes, ctxt);
 }
 
+#ifdef CONFIG_X86_32
+
+static int emulator_cmpxchg8b_emulated(unsigned long addr,
+                                      unsigned long old_lo,
+                                      unsigned long old_hi,
+                                      unsigned long new_lo,
+                                      unsigned long new_hi,
+                                      struct x86_emulate_ctxt *ctxt)
+{
+       static int reported;
+       int r;
+
+       if (!reported) {
+               reported = 1;
+               printk(KERN_WARNING "kvm: emulating exchange8b as write\n");
+       }
+       r = emulator_write_emulated(addr, new_lo, 4, ctxt);
+       if (r != X86EMUL_CONTINUE)
+               return r;
+       return emulator_write_emulated(addr+4, new_hi, 4, ctxt);
+}
+
+#endif
+
 static unsigned long get_segment_base(struct kvm_vcpu *vcpu, int seg)
 {
        return kvm_arch_ops->get_segment_base(vcpu, seg);
@@ -902,18 +1003,15 @@ static unsigned long get_segment_base(struct kvm_vcpu *vcpu, int seg)
 
 int emulate_invlpg(struct kvm_vcpu *vcpu, gva_t address)
 {
-       spin_lock(&vcpu->kvm->lock);
-       vcpu->mmu.inval_page(vcpu, address);
-       spin_unlock(&vcpu->kvm->lock);
-       kvm_arch_ops->invlpg(vcpu, address);
        return X86EMUL_CONTINUE;
 }
 
 int emulate_clts(struct kvm_vcpu *vcpu)
 {
-       unsigned long cr0 = vcpu->cr0;
+       unsigned long cr0;
 
-       cr0 &= ~CR0_TS_MASK;
+       kvm_arch_ops->decache_cr0_cr4_guest_bits(vcpu);
+       cr0 = vcpu->cr0 & ~CR0_TS_MASK;
        kvm_arch_ops->set_cr0(vcpu, cr0);
        return X86EMUL_CONTINUE;
 }
@@ -972,6 +1070,9 @@ struct x86_emulate_ops emulate_ops = {
        .read_emulated       = emulator_read_emulated,
        .write_emulated      = emulator_write_emulated,
        .cmpxchg_emulated    = emulator_cmpxchg_emulated,
+#ifdef CONFIG_X86_32
+       .cmpxchg8b_emulated  = emulator_cmpxchg8b_emulated,
+#endif
 };
 
 int emulate_instruction(struct kvm_vcpu *vcpu,
@@ -1021,6 +1122,8 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
        }
 
        if (r) {
+               if (kvm_mmu_unprotect_page_virt(vcpu, cr2))
+                       return EMULATE_DONE;
                if (!vcpu->mmio_needed) {
                        report_emulation_failure(&emulate_ctxt);
                        return EMULATE_FAIL;
@@ -1066,6 +1169,7 @@ void realmode_lmsw(struct kvm_vcpu *vcpu, unsigned long msw,
 
 unsigned long realmode_get_cr(struct kvm_vcpu *vcpu, int cr)
 {
+       kvm_arch_ops->decache_cr0_cr4_guest_bits(vcpu);
        switch (cr) {
        case 0:
                return vcpu->cr0;
@@ -1103,6 +1207,54 @@ void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long val,
        }
 }
 
+int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
+{
+       u64 data;
+
+       switch (msr) {
+       case 0xc0010010: /* SYSCFG */
+       case 0xc0010015: /* HWCR */
+       case MSR_IA32_PLATFORM_ID:
+       case MSR_IA32_P5_MC_ADDR:
+       case MSR_IA32_P5_MC_TYPE:
+       case MSR_IA32_MC0_CTL:
+       case MSR_IA32_MCG_STATUS:
+       case MSR_IA32_MCG_CAP:
+       case MSR_IA32_MC0_MISC:
+       case MSR_IA32_MC0_MISC+4:
+       case MSR_IA32_MC0_MISC+8:
+       case MSR_IA32_MC0_MISC+12:
+       case MSR_IA32_MC0_MISC+16:
+       case MSR_IA32_UCODE_REV:
+       case MSR_IA32_PERF_STATUS:
+               /* MTRR registers */
+       case 0xfe:
+       case 0x200 ... 0x2ff:
+               data = 0;
+               break;
+       case 0xcd: /* fsb frequency */
+               data = 3;
+               break;
+       case MSR_IA32_APICBASE:
+               data = vcpu->apic_base;
+               break;
+       case MSR_IA32_MISC_ENABLE:
+               data = vcpu->ia32_misc_enable_msr;
+               break;
+#ifdef CONFIG_X86_64
+       case MSR_EFER:
+               data = vcpu->shadow_efer;
+               break;
+#endif
+       default:
+               printk(KERN_ERR "kvm: unhandled rdmsr: 0x%x\n", msr);
+               return 1;
+       }
+       *pdata = data;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(kvm_get_msr_common);
+
 /*
  * Reads an msr value (of 'msr_index') into 'pdata'.
  * Returns 0 on success, non-0 otherwise.
@@ -1115,7 +1267,7 @@ static int get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
 
 #ifdef CONFIG_X86_64
 
-void set_efer(struct kvm_vcpu *vcpu, u64 efer)
+static void set_efer(struct kvm_vcpu *vcpu, u64 efer)
 {
        if (efer & EFER_RESERVED_BITS) {
                printk(KERN_DEBUG "set_efer: 0x%llx #GP, reserved bits\n",
@@ -1138,10 +1290,39 @@ void set_efer(struct kvm_vcpu *vcpu, u64 efer)
 
        vcpu->shadow_efer = efer;
 }
-EXPORT_SYMBOL_GPL(set_efer);
 
 #endif
 
+int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
+{
+       switch (msr) {
+#ifdef CONFIG_X86_64
+       case MSR_EFER:
+               set_efer(vcpu, data);
+               break;
+#endif
+       case MSR_IA32_MC0_STATUS:
+               printk(KERN_WARNING "%s: MSR_IA32_MC0_STATUS 0x%llx, nop\n",
+                      __FUNCTION__, data);
+               break;
+       case MSR_IA32_UCODE_REV:
+       case MSR_IA32_UCODE_WRITE:
+       case 0x200 ... 0x2ff: /* MTRRs */
+               break;
+       case MSR_IA32_APICBASE:
+               vcpu->apic_base = data;
+               break;
+       case MSR_IA32_MISC_ENABLE:
+               vcpu->ia32_misc_enable_msr = data;
+               break;
+       default:
+               printk(KERN_ERR "kvm: unhandled wrmsr: 0x%x\n", msr);
+               return 1;
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(kvm_set_msr_common);
+
 /*
  * Writes msr value into into the appropriate "register".
  * Returns 0 on success, non-0 otherwise.
@@ -1191,6 +1372,9 @@ static int kvm_dev_ioctl_run(struct kvm *kvm, struct kvm_run *kvm_run)
        if (!vcpu)
                return -ENOENT;
 
+       /* re-sync apic's tpr */
+       vcpu->cr8 = kvm_run->cr8;
+
        if (kvm_run->emulated) {
                kvm_arch_ops->skip_emulated_instruction(vcpu);
                kvm_run->emulated = 0;
@@ -1329,6 +1513,7 @@ static int kvm_dev_ioctl_get_sregs(struct kvm *kvm, struct kvm_sregs *sregs)
        sregs->gdt.limit = dt.limit;
        sregs->gdt.base = dt.base;
 
+       kvm_arch_ops->decache_cr0_cr4_guest_bits(vcpu);
        sregs->cr0 = vcpu->cr0;
        sregs->cr2 = vcpu->cr2;
        sregs->cr3 = vcpu->cr3;
@@ -1393,11 +1578,15 @@ static int kvm_dev_ioctl_set_sregs(struct kvm *kvm, struct kvm_sregs *sregs)
 #endif
        vcpu->apic_base = sregs->apic_base;
 
+       kvm_arch_ops->decache_cr0_cr4_guest_bits(vcpu);
+
        mmu_reset_needed |= vcpu->cr0 != sregs->cr0;
        kvm_arch_ops->set_cr0_no_modeswitch(vcpu, sregs->cr0);
 
        mmu_reset_needed |= vcpu->cr4 != sregs->cr4;
        kvm_arch_ops->set_cr4(vcpu, sregs->cr4);
+       if (!is_long_mode(vcpu) && is_pae(vcpu))
+               load_pdptrs(vcpu, vcpu->cr3);
 
        if (mmu_reset_needed)
                kvm_mmu_reset_context(vcpu);
@@ -1432,6 +1621,10 @@ static u32 msrs_to_save[] = {
 
 static unsigned num_msrs_to_save;
 
+static u32 emulated_msrs[] = {
+       MSR_IA32_MISC_ENABLE,
+};
+
 static __init void kvm_init_msr_list(void)
 {
        u32 dummy[2];
@@ -1600,6 +1793,7 @@ static long kvm_dev_ioctl(struct file *filp,
                          unsigned int ioctl, unsigned long arg)
 {
        struct kvm *kvm = filp->private_data;
+       void __user *argp = (void __user *)arg;
        int r = -EINVAL;
 
        switch (ioctl) {
@@ -1616,28 +1810,28 @@ static long kvm_dev_ioctl(struct file *filp,
                struct kvm_run kvm_run;
 
                r = -EFAULT;
-               if (copy_from_user(&kvm_run, (void *)arg, sizeof kvm_run))
+               if (copy_from_user(&kvm_run, argp, sizeof kvm_run))
                        goto out;
                r = kvm_dev_ioctl_run(kvm, &kvm_run);
-               if (r < 0)
+               if (r < 0 &&  r != -EINTR)
                        goto out;
-               r = -EFAULT;
-               if (copy_to_user((void *)arg, &kvm_run, sizeof kvm_run))
+               if (copy_to_user(argp, &kvm_run, sizeof kvm_run)) {
+                       r = -EFAULT;
                        goto out;
-               r = 0;
+               }
                break;
        }
        case KVM_GET_REGS: {
                struct kvm_regs kvm_regs;
 
                r = -EFAULT;
-               if (copy_from_user(&kvm_regs, (void *)arg, sizeof kvm_regs))
+               if (copy_from_user(&kvm_regs, argp, sizeof kvm_regs))
                        goto out;
                r = kvm_dev_ioctl_get_regs(kvm, &kvm_regs);
                if (r)
                        goto out;
                r = -EFAULT;
-               if (copy_to_user((void *)arg, &kvm_regs, sizeof kvm_regs))
+               if (copy_to_user(argp, &kvm_regs, sizeof kvm_regs))
                        goto out;
                r = 0;
                break;
@@ -1646,7 +1840,7 @@ static long kvm_dev_ioctl(struct file *filp,
                struct kvm_regs kvm_regs;
 
                r = -EFAULT;
-               if (copy_from_user(&kvm_regs, (void *)arg, sizeof kvm_regs))
+               if (copy_from_user(&kvm_regs, argp, sizeof kvm_regs))
                        goto out;
                r = kvm_dev_ioctl_set_regs(kvm, &kvm_regs);
                if (r)
@@ -1658,13 +1852,13 @@ static long kvm_dev_ioctl(struct file *filp,
                struct kvm_sregs kvm_sregs;
 
                r = -EFAULT;
-               if (copy_from_user(&kvm_sregs, (void *)arg, sizeof kvm_sregs))
+               if (copy_from_user(&kvm_sregs, argp, sizeof kvm_sregs))
                        goto out;
                r = kvm_dev_ioctl_get_sregs(kvm, &kvm_sregs);
                if (r)
                        goto out;
                r = -EFAULT;
-               if (copy_to_user((void *)arg, &kvm_sregs, sizeof kvm_sregs))
+               if (copy_to_user(argp, &kvm_sregs, sizeof kvm_sregs))
                        goto out;
                r = 0;
                break;
@@ -1673,7 +1867,7 @@ static long kvm_dev_ioctl(struct file *filp,
                struct kvm_sregs kvm_sregs;
 
                r = -EFAULT;
-               if (copy_from_user(&kvm_sregs, (void *)arg, sizeof kvm_sregs))
+               if (copy_from_user(&kvm_sregs, argp, sizeof kvm_sregs))
                        goto out;
                r = kvm_dev_ioctl_set_sregs(kvm, &kvm_sregs);
                if (r)
@@ -1685,13 +1879,13 @@ static long kvm_dev_ioctl(struct file *filp,
                struct kvm_translation tr;
 
                r = -EFAULT;
-               if (copy_from_user(&tr, (void *)arg, sizeof tr))
+               if (copy_from_user(&tr, argp, sizeof tr))
                        goto out;
                r = kvm_dev_ioctl_translate(kvm, &tr);
                if (r)
                        goto out;
                r = -EFAULT;
-               if (copy_to_user((void *)arg, &tr, sizeof tr))
+               if (copy_to_user(argp, &tr, sizeof tr))
                        goto out;
                r = 0;
                break;
@@ -1700,7 +1894,7 @@ static long kvm_dev_ioctl(struct file *filp,
                struct kvm_interrupt irq;
 
                r = -EFAULT;
-               if (copy_from_user(&irq, (void *)arg, sizeof irq))
+               if (copy_from_user(&irq, argp, sizeof irq))
                        goto out;
                r = kvm_dev_ioctl_interrupt(kvm, &irq);
                if (r)
@@ -1712,7 +1906,7 @@ static long kvm_dev_ioctl(struct file *filp,
                struct kvm_debug_guest dbg;
 
                r = -EFAULT;
-               if (copy_from_user(&dbg, (void *)arg, sizeof dbg))
+               if (copy_from_user(&dbg, argp, sizeof dbg))
                        goto out;
                r = kvm_dev_ioctl_debug_guest(kvm, &dbg);
                if (r)
@@ -1724,7 +1918,7 @@ static long kvm_dev_ioctl(struct file *filp,
                struct kvm_memory_region kvm_mem;
 
                r = -EFAULT;
-               if (copy_from_user(&kvm_mem, (void *)arg, sizeof kvm_mem))
+               if (copy_from_user(&kvm_mem, argp, sizeof kvm_mem))
                        goto out;
                r = kvm_dev_ioctl_set_memory_region(kvm, &kvm_mem);
                if (r)
@@ -1735,7 +1929,7 @@ static long kvm_dev_ioctl(struct file *filp,
                struct kvm_dirty_log log;
 
                r = -EFAULT;
-               if (copy_from_user(&log, (void *)arg, sizeof log))
+               if (copy_from_user(&log, argp, sizeof log))
                        goto out;
                r = kvm_dev_ioctl_get_dirty_log(kvm, &log);
                if (r)
@@ -1743,13 +1937,13 @@ static long kvm_dev_ioctl(struct file *filp,
                break;
        }
        case KVM_GET_MSRS:
-               r = msr_io(kvm, (void __user *)arg, get_msr, 1);
+               r = msr_io(kvm, argp, get_msr, 1);
                break;
        case KVM_SET_MSRS:
-               r = msr_io(kvm, (void __user *)arg, do_set_msr, 0);
+               r = msr_io(kvm, argp, do_set_msr, 0);
                break;
        case KVM_GET_MSR_INDEX_LIST: {
-               struct kvm_msr_list __user *user_msr_list = (void __user *)arg;
+               struct kvm_msr_list __user *user_msr_list = argp;
                struct kvm_msr_list msr_list;
                unsigned n;
 
@@ -1757,7 +1951,7 @@ static long kvm_dev_ioctl(struct file *filp,
                if (copy_from_user(&msr_list, user_msr_list, sizeof msr_list))
                        goto out;
                n = msr_list.nmsrs;
-               msr_list.nmsrs = num_msrs_to_save;
+               msr_list.nmsrs = num_msrs_to_save + ARRAY_SIZE(emulated_msrs);
                if (copy_to_user(user_msr_list, &msr_list, sizeof msr_list))
                        goto out;
                r = -E2BIG;
@@ -1767,7 +1961,13 @@ static long kvm_dev_ioctl(struct file *filp,
                if (copy_to_user(user_msr_list->indices, &msrs_to_save,
                                 num_msrs_to_save * sizeof(u32)))
                        goto out;
+               if (copy_to_user(user_msr_list->indices
+                                + num_msrs_to_save * sizeof(u32),
+                                &emulated_msrs,
+                                ARRAY_SIZE(emulated_msrs) * sizeof(u32)))
+                       goto out;
                r = 0;
+               break;
        }
        default:
                ;
@@ -1830,7 +2030,7 @@ static int kvm_reboot(struct notifier_block *notifier, unsigned long val,
                 * in vmx root mode.
                 */
                printk(KERN_INFO "kvm: exiting hardware virtualization\n");
-               on_each_cpu(kvm_arch_ops->hardware_disable, 0, 0, 1);
+               on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1);
        }
        return NOTIFY_OK;
 }
@@ -1840,11 +2040,69 @@ static struct notifier_block kvm_reboot_notifier = {
        .priority = 0,
 };
 
+/*
+ * Make sure that a cpu that is being hot-unplugged does not have any vcpus
+ * cached on it.
+ */
+static void decache_vcpus_on_cpu(int cpu)
+{
+       struct kvm *vm;
+       struct kvm_vcpu *vcpu;
+       int i;
+
+       spin_lock(&kvm_lock);
+       list_for_each_entry(vm, &vm_list, vm_list)
+               for (i = 0; i < KVM_MAX_VCPUS; ++i) {
+                       vcpu = &vm->vcpus[i];
+                       /*
+                        * If the vcpu is locked, then it is running on some
+                        * other cpu and therefore it is not cached on the
+                        * cpu in question.
+                        *
+                        * If it's not locked, check the last cpu it executed
+                        * on.
+                        */
+                       if (mutex_trylock(&vcpu->mutex)) {
+                               if (vcpu->cpu == cpu) {
+                                       kvm_arch_ops->vcpu_decache(vcpu);
+                                       vcpu->cpu = -1;
+                               }
+                               mutex_unlock(&vcpu->mutex);
+                       }
+               }
+       spin_unlock(&kvm_lock);
+}
+
+static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val,
+                          void *v)
+{
+       int cpu = (long)v;
+
+       switch (val) {
+       case CPU_DEAD:
+       case CPU_UP_CANCELED:
+               decache_vcpus_on_cpu(cpu);
+               smp_call_function_single(cpu, kvm_arch_ops->hardware_disable,
+                                        NULL, 0, 1);
+               break;
+       case CPU_UP_PREPARE:
+               smp_call_function_single(cpu, kvm_arch_ops->hardware_enable,
+                                        NULL, 0, 1);
+               break;
+       }
+       return NOTIFY_OK;
+}
+
+static struct notifier_block kvm_cpu_notifier = {
+       .notifier_call = kvm_cpu_hotplug,
+       .priority = 20, /* must be > scheduler priority */
+};
+
 static __init void kvm_init_debug(void)
 {
        struct kvm_stats_debugfs_item *p;
 
-       debugfs_dir = debugfs_create_dir("kvm", 0);
+       debugfs_dir = debugfs_create_dir("kvm", NULL);
        for (p = debugfs_entries; p->name; ++p)
                p->dentry = debugfs_create_u32(p->name, 0444, debugfs_dir,
                                               p->data);
@@ -1865,22 +2123,30 @@ int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module)
 {
        int r;
 
-       kvm_arch_ops = ops;
+       if (kvm_arch_ops) {
+               printk(KERN_ERR "kvm: already loaded the other module\n");
+               return -EEXIST;
+       }
 
-       if (!kvm_arch_ops->cpu_has_kvm_support()) {
+       if (!ops->cpu_has_kvm_support()) {
                printk(KERN_ERR "kvm: no hardware support\n");
                return -EOPNOTSUPP;
        }
-       if (kvm_arch_ops->disabled_by_bios()) {
+       if (ops->disabled_by_bios()) {
                printk(KERN_ERR "kvm: disabled by bios\n");
                return -EOPNOTSUPP;
        }
 
+       kvm_arch_ops = ops;
+
        r = kvm_arch_ops->hardware_setup();
        if (r < 0)
            return r;
 
-       on_each_cpu(kvm_arch_ops->hardware_enable, 0, 0, 1);
+       on_each_cpu(kvm_arch_ops->hardware_enable, NULL, 0, 1);
+       r = register_cpu_notifier(&kvm_cpu_notifier);
+       if (r)
+               goto out_free_1;
        register_reboot_notifier(&kvm_reboot_notifier);
 
        kvm_chardev_ops.owner = module;
@@ -1895,7 +2161,9 @@ int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module)
 
 out_free:
        unregister_reboot_notifier(&kvm_reboot_notifier);
-       on_each_cpu(kvm_arch_ops->hardware_disable, 0, 0, 1);
+       unregister_cpu_notifier(&kvm_cpu_notifier);
+out_free_1:
+       on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1);
        kvm_arch_ops->hardware_unsetup();
        return r;
 }
@@ -1905,8 +2173,9 @@ void kvm_exit_arch(void)
        misc_deregister(&kvm_dev);
 
        unregister_reboot_notifier(&kvm_reboot_notifier);
-       on_each_cpu(kvm_arch_ops->hardware_disable, 0, 0, 1);
+       on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1);
        kvm_arch_ops->hardware_unsetup();
+       kvm_arch_ops = NULL;
 }
 
 static __init int kvm_init(void)