KVM: powerpc: fix init/exit annotation
[safe/jmp/linux-2.6] / arch / powerpc / kvm / powerpc.c
index fda9baa..9b8683f 100644 (file)
 #include <linux/kvm_host.h>
 #include <linux/module.h>
 #include <linux/vmalloc.h>
+#include <linux/hrtimer.h>
 #include <linux/fs.h>
+#include <linux/slab.h>
 #include <asm/cputable.h>
 #include <asm/uaccess.h>
 #include <asm/kvm_ppc.h>
 #include <asm/tlbflush.h>
+#include "timing.h"
+#include "../mm/mmu_decl.h"
 
+#define CREATE_TRACE_POINTS
+#include "trace.h"
 
 gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn)
 {
        return gfn;
 }
 
-int kvm_cpu_has_interrupt(struct kvm_vcpu *v)
-{
-       return !!(v->arch.pending_exceptions);
-}
-
 int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
 {
-       return !(v->arch.msr & MSR_WE);
+       return !(v->arch.msr & MSR_WE) || !!(v->arch.pending_exceptions);
 }
 
 
@@ -69,7 +70,7 @@ int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu)
        case EMULATE_FAIL:
                /* XXX Deliver Program interrupt to guest. */
                printk(KERN_EMERG "%s: emulation failed (%08x)\n", __func__,
-                      vcpu->arch.last_inst);
+                      kvmppc_get_last_inst(vcpu));
                r = RESUME_HOST;
                break;
        default:
@@ -79,8 +80,9 @@ int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu)
        return r;
 }
 
-void kvm_arch_hardware_enable(void *garbage)
+int kvm_arch_hardware_enable(void *garbage)
 {
+       return 0;
 }
 
 void kvm_arch_hardware_disable(void *garbage)
@@ -98,14 +100,7 @@ void kvm_arch_hardware_unsetup(void)
 
 void kvm_arch_check_processor_compat(void *rtn)
 {
-       int r;
-
-       if (strcmp(cur_cpu_spec->platform, "ppc440") == 0)
-               r = 0;
-       else
-               r = -ENOTSUPP;
-
-       *(int *)rtn = r;
+       *(int *)rtn = kvmppc_core_check_processor_compat();
 }
 
 struct kvm *kvm_arch_create_vm(void)
@@ -122,19 +117,28 @@ struct kvm *kvm_arch_create_vm(void)
 static void kvmppc_free_vcpus(struct kvm *kvm)
 {
        unsigned int i;
+       struct kvm_vcpu *vcpu;
 
-       for (i = 0; i < KVM_MAX_VCPUS; ++i) {
-               if (kvm->vcpus[i]) {
-                       kvm_arch_vcpu_free(kvm->vcpus[i]);
-                       kvm->vcpus[i] = NULL;
-               }
-       }
+       kvm_for_each_vcpu(i, vcpu, kvm)
+               kvm_arch_vcpu_free(vcpu);
+
+       mutex_lock(&kvm->lock);
+       for (i = 0; i < atomic_read(&kvm->online_vcpus); i++)
+               kvm->vcpus[i] = NULL;
+
+       atomic_set(&kvm->online_vcpus, 0);
+       mutex_unlock(&kvm->lock);
+}
+
+void kvm_arch_sync_events(struct kvm *kvm)
+{
 }
 
 void kvm_arch_destroy_vm(struct kvm *kvm)
 {
        kvmppc_free_vcpus(kvm);
        kvm_free_physmem(kvm);
+       cleanup_srcu_struct(&kvm->srcu);
        kfree(kvm);
 }
 
@@ -143,7 +147,11 @@ int kvm_dev_ioctl_check_extension(long ext)
        int r;
 
        switch (ext) {
-       case KVM_CAP_USER_MEMORY:
+       case KVM_CAP_PPC_SEGSTATE:
+       case KVM_CAP_PPC_PAIRED_SINGLES:
+       case KVM_CAP_PPC_UNSET_IRQ:
+       case KVM_CAP_ENABLE_CAP:
+       case KVM_CAP_PPC_OSI:
                r = 1;
                break;
        case KVM_CAP_COALESCED_MMIO:
@@ -163,14 +171,24 @@ long kvm_arch_dev_ioctl(struct file *filp,
        return -EINVAL;
 }
 
-int kvm_arch_set_memory_region(struct kvm *kvm,
-                               struct kvm_userspace_memory_region *mem,
-                               struct kvm_memory_slot old,
-                               int user_alloc)
+int kvm_arch_prepare_memory_region(struct kvm *kvm,
+                                   struct kvm_memory_slot *memslot,
+                                   struct kvm_memory_slot old,
+                                   struct kvm_userspace_memory_region *mem,
+                                   int user_alloc)
 {
        return 0;
 }
 
+void kvm_arch_commit_memory_region(struct kvm *kvm,
+               struct kvm_userspace_memory_region *mem,
+               struct kvm_memory_slot old,
+               int user_alloc)
+{
+       return;
+}
+
+
 void kvm_arch_flush_shadow(struct kvm *kvm)
 {
 }
@@ -178,30 +196,20 @@ void kvm_arch_flush_shadow(struct kvm *kvm)
 struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
 {
        struct kvm_vcpu *vcpu;
-       int err;
-
-       vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);
-       if (!vcpu) {
-               err = -ENOMEM;
-               goto out;
-       }
-
-       err = kvm_vcpu_init(vcpu, kvm, id);
-       if (err)
-               goto free_vcpu;
-
+       vcpu = kvmppc_core_vcpu_create(kvm, id);
+       if (!IS_ERR(vcpu))
+               kvmppc_create_vcpu_debugfs(vcpu, id);
        return vcpu;
-
-free_vcpu:
-       kmem_cache_free(kvm_vcpu_cache, vcpu);
-out:
-       return ERR_PTR(err);
 }
 
 void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
 {
-       kvm_vcpu_uninit(vcpu);
-       kmem_cache_free(kvm_vcpu_cache, vcpu);
+       /* Make sure we're not using the vcpu anymore */
+       hrtimer_cancel(&vcpu->arch.dec_timer);
+       tasklet_kill(&vcpu->arch.tasklet);
+
+       kvmppc_remove_vcpu_debugfs(vcpu);
+       kvmppc_core_vcpu_free(vcpu);
 }
 
 void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
@@ -211,16 +219,14 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
 
 int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
 {
-       unsigned int priority = exception_priority[BOOKE_INTERRUPT_DECREMENTER];
-
-       return test_bit(priority, &vcpu->arch.pending_exceptions);
+       return kvmppc_core_pending_dec(vcpu);
 }
 
 static void kvmppc_decrementer_func(unsigned long data)
 {
        struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data;
 
-       kvmppc_queue_exception(vcpu, BOOKE_INTERRUPT_DECREMENTER);
+       kvmppc_core_queue_dec(vcpu);
 
        if (waitqueue_active(&vcpu->wq)) {
                wake_up_interruptible(&vcpu->wq);
@@ -228,160 +234,119 @@ static void kvmppc_decrementer_func(unsigned long data)
        }
 }
 
-int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
+/*
+ * low level hrtimer wake routine. Because this runs in hardirq context
+ * we schedule a tasklet to do the real work.
+ */
+enum hrtimer_restart kvmppc_decrementer_wakeup(struct hrtimer *timer)
 {
-       setup_timer(&vcpu->arch.dec_timer, kvmppc_decrementer_func,
-                   (unsigned long)vcpu);
-
-       return 0;
-}
+       struct kvm_vcpu *vcpu;
 
-void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
-{
-       kvmppc_core_destroy_mmu(vcpu);
-}
+       vcpu = container_of(timer, struct kvm_vcpu, arch.dec_timer);
+       tasklet_schedule(&vcpu->arch.tasklet);
 
-/* Note: clearing MSR[DE] just means that the debug interrupt will not be
- * delivered *immediately*. Instead, it simply sets the appropriate DBSR bits.
- * If those DBSR bits are still set when MSR[DE] is re-enabled, the interrupt
- * will be delivered as an "imprecise debug event" (which is indicated by
- * DBSR[IDE].
- */
-static void kvmppc_disable_debug_interrupts(void)
-{
-       mtmsr(mfmsr() & ~MSR_DE);
+       return HRTIMER_NORESTART;
 }
 
-static void kvmppc_restore_host_debug_state(struct kvm_vcpu *vcpu)
+int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 {
-       kvmppc_disable_debug_interrupts();
+       hrtimer_init(&vcpu->arch.dec_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
+       tasklet_init(&vcpu->arch.tasklet, kvmppc_decrementer_func, (ulong)vcpu);
+       vcpu->arch.dec_timer.function = kvmppc_decrementer_wakeup;
 
-       mtspr(SPRN_IAC1, vcpu->arch.host_iac[0]);
-       mtspr(SPRN_IAC2, vcpu->arch.host_iac[1]);
-       mtspr(SPRN_IAC3, vcpu->arch.host_iac[2]);
-       mtspr(SPRN_IAC4, vcpu->arch.host_iac[3]);
-       mtspr(SPRN_DBCR1, vcpu->arch.host_dbcr1);
-       mtspr(SPRN_DBCR2, vcpu->arch.host_dbcr2);
-       mtspr(SPRN_DBCR0, vcpu->arch.host_dbcr0);
-       mtmsr(vcpu->arch.host_msr);
+       return 0;
 }
 
-static void kvmppc_load_guest_debug_registers(struct kvm_vcpu *vcpu)
+void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
 {
-       struct kvm_guest_debug *dbg = &vcpu->guest_debug;
-       u32 dbcr0 = 0;
-
-       vcpu->arch.host_msr = mfmsr();
-       kvmppc_disable_debug_interrupts();
-
-       /* Save host debug register state. */
-       vcpu->arch.host_iac[0] = mfspr(SPRN_IAC1);
-       vcpu->arch.host_iac[1] = mfspr(SPRN_IAC2);
-       vcpu->arch.host_iac[2] = mfspr(SPRN_IAC3);
-       vcpu->arch.host_iac[3] = mfspr(SPRN_IAC4);
-       vcpu->arch.host_dbcr0 = mfspr(SPRN_DBCR0);
-       vcpu->arch.host_dbcr1 = mfspr(SPRN_DBCR1);
-       vcpu->arch.host_dbcr2 = mfspr(SPRN_DBCR2);
-
-       /* set registers up for guest */
-
-       if (dbg->bp[0]) {
-               mtspr(SPRN_IAC1, dbg->bp[0]);
-               dbcr0 |= DBCR0_IAC1 | DBCR0_IDM;
-       }
-       if (dbg->bp[1]) {
-               mtspr(SPRN_IAC2, dbg->bp[1]);
-               dbcr0 |= DBCR0_IAC2 | DBCR0_IDM;
-       }
-       if (dbg->bp[2]) {
-               mtspr(SPRN_IAC3, dbg->bp[2]);
-               dbcr0 |= DBCR0_IAC3 | DBCR0_IDM;
-       }
-       if (dbg->bp[3]) {
-               mtspr(SPRN_IAC4, dbg->bp[3]);
-               dbcr0 |= DBCR0_IAC4 | DBCR0_IDM;
-       }
-
-       mtspr(SPRN_DBCR0, dbcr0);
-       mtspr(SPRN_DBCR1, 0);
-       mtspr(SPRN_DBCR2, 0);
+       kvmppc_mmu_destroy(vcpu);
 }
 
 void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
-       int i;
-
-       if (vcpu->guest_debug.enabled)
-               kvmppc_load_guest_debug_registers(vcpu);
-
-       /* Mark every guest entry in the shadow TLB entry modified, so that they
-        * will all be reloaded on the next vcpu run (instead of being
-        * demand-faulted). */
-       for (i = 0; i <= tlb_44x_hwater; i++)
-               kvmppc_tlbe_set_modified(vcpu, i);
+       kvmppc_core_vcpu_load(vcpu, cpu);
 }
 
 void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 {
-       if (vcpu->guest_debug.enabled)
-               kvmppc_restore_host_debug_state(vcpu);
-
-       /* Don't leave guest TLB entries resident when being de-scheduled. */
-       /* XXX It would be nice to differentiate between heavyweight exit and
-        * sched_out here, since we could avoid the TLB flush for heavyweight
-        * exits. */
-       _tlbia();
+       kvmppc_core_vcpu_put(vcpu);
 }
 
-int kvm_arch_vcpu_ioctl_debug_guest(struct kvm_vcpu *vcpu,
-                                    struct kvm_debug_guest *dbg)
+int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
+                                        struct kvm_guest_debug *dbg)
 {
-       int i;
-
-       vcpu->guest_debug.enabled = dbg->enabled;
-       if (vcpu->guest_debug.enabled) {
-               for (i=0; i < ARRAY_SIZE(vcpu->guest_debug.bp); i++) {
-                       if (dbg->breakpoints[i].enabled)
-                               vcpu->guest_debug.bp[i] = dbg->breakpoints[i].address;
-                       else
-                               vcpu->guest_debug.bp[i] = 0;
-               }
-       }
-
-       return 0;
+       return -EINVAL;
 }
 
 static void kvmppc_complete_dcr_load(struct kvm_vcpu *vcpu,
                                      struct kvm_run *run)
 {
-       u32 *gpr = &vcpu->arch.gpr[vcpu->arch.io_gpr];
-       *gpr = run->dcr.data;
+       kvmppc_set_gpr(vcpu, vcpu->arch.io_gpr, run->dcr.data);
 }
 
 static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu,
                                       struct kvm_run *run)
 {
-       u32 *gpr = &vcpu->arch.gpr[vcpu->arch.io_gpr];
+       u64 gpr;
 
-       if (run->mmio.len > sizeof(*gpr)) {
+       if (run->mmio.len > sizeof(gpr)) {
                printk(KERN_ERR "bad MMIO length: %d\n", run->mmio.len);
                return;
        }
 
        if (vcpu->arch.mmio_is_bigendian) {
                switch (run->mmio.len) {
-               case 4: *gpr = *(u32 *)run->mmio.data; break;
-               case 2: *gpr = *(u16 *)run->mmio.data; break;
-               case 1: *gpr = *(u8 *)run->mmio.data; break;
+               case 8: gpr = *(u64 *)run->mmio.data; break;
+               case 4: gpr = *(u32 *)run->mmio.data; break;
+               case 2: gpr = *(u16 *)run->mmio.data; break;
+               case 1: gpr = *(u8 *)run->mmio.data; break;
                }
        } else {
                /* Convert BE data from userland back to LE. */
                switch (run->mmio.len) {
-               case 4: *gpr = ld_le32((u32 *)run->mmio.data); break;
-               case 2: *gpr = ld_le16((u16 *)run->mmio.data); break;
-               case 1: *gpr = *(u8 *)run->mmio.data; break;
+               case 4: gpr = ld_le32((u32 *)run->mmio.data); break;
+               case 2: gpr = ld_le16((u16 *)run->mmio.data); break;
+               case 1: gpr = *(u8 *)run->mmio.data; break;
                }
        }
+
+       if (vcpu->arch.mmio_sign_extend) {
+               switch (run->mmio.len) {
+#ifdef CONFIG_PPC64
+               case 4:
+                       gpr = (s64)(s32)gpr;
+                       break;
+#endif
+               case 2:
+                       gpr = (s64)(s16)gpr;
+                       break;
+               case 1:
+                       gpr = (s64)(s8)gpr;
+                       break;
+               }
+       }
+
+       kvmppc_set_gpr(vcpu, vcpu->arch.io_gpr, gpr);
+
+       switch (vcpu->arch.io_gpr & KVM_REG_EXT_MASK) {
+       case KVM_REG_GPR:
+               kvmppc_set_gpr(vcpu, vcpu->arch.io_gpr, gpr);
+               break;
+       case KVM_REG_FPR:
+               vcpu->arch.fpr[vcpu->arch.io_gpr & KVM_REG_MASK] = gpr;
+               break;
+#ifdef CONFIG_PPC_BOOK3S
+       case KVM_REG_QPR:
+               vcpu->arch.qpr[vcpu->arch.io_gpr & KVM_REG_MASK] = gpr;
+               break;
+       case KVM_REG_FQPR:
+               vcpu->arch.fpr[vcpu->arch.io_gpr & KVM_REG_MASK] = gpr;
+               vcpu->arch.qpr[vcpu->arch.io_gpr & KVM_REG_MASK] = gpr;
+               break;
+#endif
+       default:
+               BUG();
+       }
 }
 
 int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
@@ -400,12 +365,25 @@ int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
        vcpu->arch.mmio_is_bigendian = is_bigendian;
        vcpu->mmio_needed = 1;
        vcpu->mmio_is_write = 0;
+       vcpu->arch.mmio_sign_extend = 0;
 
        return EMULATE_DO_MMIO;
 }
 
+/* Same as above, but sign extends */
+int kvmppc_handle_loads(struct kvm_run *run, struct kvm_vcpu *vcpu,
+                        unsigned int rt, unsigned int bytes, int is_bigendian)
+{
+       int r;
+
+       r = kvmppc_handle_load(run, vcpu, rt, bytes, is_bigendian);
+       vcpu->arch.mmio_sign_extend = 1;
+
+       return r;
+}
+
 int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
-                        u32 val, unsigned int bytes, int is_bigendian)
+                        u64 val, unsigned int bytes, int is_bigendian)
 {
        void *data = run->mmio.data;
 
@@ -423,6 +401,7 @@ int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
        /* Store the value at the lowest bytes in 'data'. */
        if (is_bigendian) {
                switch (bytes) {
+               case 8: *(u64 *)data = val; break;
                case 4: *(u32 *)data = val; break;
                case 2: *(u16 *)data = val; break;
                case 1: *(u8  *)data = val; break;
@@ -457,9 +436,16 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
                if (!vcpu->arch.dcr_is_write)
                        kvmppc_complete_dcr_load(vcpu, run);
                vcpu->arch.dcr_needed = 0;
+       } else if (vcpu->arch.osi_needed) {
+               u64 *gprs = run->osi.gprs;
+               int i;
+
+               for (i = 0; i < 32; i++)
+                       kvmppc_set_gpr(vcpu, i, gprs[i]);
+               vcpu->arch.osi_needed = 0;
        }
 
-       kvmppc_check_and_deliver_interrupts(vcpu);
+       kvmppc_core_deliver_interrupts(vcpu);
 
        local_irq_disable();
        kvm_guest_enter();
@@ -477,7 +463,10 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
 
 int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq)
 {
-       kvmppc_queue_exception(vcpu, BOOKE_INTERRUPT_EXTERNAL);
+       if (irq->irq == KVM_INTERRUPT_UNSET)
+               kvmppc_core_dequeue_external(vcpu, irq);
+       else
+               kvmppc_core_queue_external(vcpu, irq);
 
        if (waitqueue_active(&vcpu->wq)) {
                wake_up_interruptible(&vcpu->wq);
@@ -487,6 +476,27 @@ int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq)
        return 0;
 }
 
+static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
+                                    struct kvm_enable_cap *cap)
+{
+       int r;
+
+       if (cap->flags)
+               return -EINVAL;
+
+       switch (cap->cap) {
+       case KVM_CAP_PPC_OSI:
+               r = 0;
+               vcpu->arch.osi_enabled = true;
+               break;
+       default:
+               r = -EINVAL;
+               break;
+       }
+
+       return r;
+}
+
 int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
                                     struct kvm_mp_state *mp_state)
 {
@@ -515,6 +525,15 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
                r = kvm_vcpu_ioctl_interrupt(vcpu, &irq);
                break;
        }
+       case KVM_ENABLE_CAP:
+       {
+               struct kvm_enable_cap cap;
+               r = -EFAULT;
+               if (copy_from_user(&cap, argp, sizeof(cap)))
+                       goto out;
+               r = kvm_vcpu_ioctl_enable_cap(vcpu, &cap);
+               break;
+       }
        default:
                r = -EINVAL;
        }
@@ -523,11 +542,6 @@ out:
        return r;
 }
 
-int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
-{
-       return -ENOTSUPP;
-}
-
 long kvm_arch_vm_ioctl(struct file *filp,
                        unsigned int ioctl, unsigned long arg)
 {
@@ -535,7 +549,7 @@ long kvm_arch_vm_ioctl(struct file *filp,
 
        switch (ioctl) {
        default:
-               r = -EINVAL;
+               r = -ENOTTY;
        }
 
        return r;