Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[sfrench/cifs-2.6.git] / arch / mips / kvm / mips.c
index 2416fa40b6875cba7a36db29b27e6eaa25e1ed5f..521bd5891e846da643ae03c4afa7cd17f9658951 100644 (file)
@@ -67,6 +67,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
        VCPU_STAT("vz_ghfc", vz_ghfc_exits),
        VCPU_STAT("vz_gpa", vz_gpa_exits),
        VCPU_STAT("vz_resvd", vz_resvd_exits),
+       VCPU_STAT("vz_cpucfg", vz_cpucfg_exits),
 #endif
        VCPU_STAT("halt_successful_poll", halt_successful_poll),
        VCPU_STAT("halt_attempted_poll", halt_attempted_poll),
@@ -129,6 +130,8 @@ int kvm_arch_check_processor_compat(void *opaque)
        return 0;
 }
 
+extern void kvm_init_loongson_ipi(struct kvm *kvm);
+
 int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 {
        switch (type) {
@@ -148,6 +151,10 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
        if (!kvm->arch.gpa_mm.pgd)
                return -ENOMEM;
 
+#ifdef CONFIG_CPU_LOONGSON64
+       kvm_init_loongson_ipi(kvm);
+#endif
+
        return 0;
 }
 
@@ -490,7 +497,10 @@ int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu,
        int intr = (int)irq->irq;
        struct kvm_vcpu *dvcpu = NULL;
 
-       if (intr == 3 || intr == -3 || intr == 4 || intr == -4)
+       if (intr == kvm_priority_to_irq[MIPS_EXC_INT_IPI_1] ||
+           intr == kvm_priority_to_irq[MIPS_EXC_INT_IPI_2] ||
+           intr == (-kvm_priority_to_irq[MIPS_EXC_INT_IPI_1]) ||
+           intr == (-kvm_priority_to_irq[MIPS_EXC_INT_IPI_2]))
                kvm_debug("%s: CPU: %d, INTR: %d\n", __func__, irq->cpu,
                          (int)intr);
 
@@ -499,10 +509,10 @@ int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu,
        else
                dvcpu = vcpu->kvm->vcpus[irq->cpu];
 
-       if (intr == 2 || intr == 3 || intr == 4) {
+       if (intr == 2 || intr == 3 || intr == 4 || intr == 6) {
                kvm_mips_callbacks->queue_io_int(dvcpu, irq);
 
-       } else if (intr == -2 || intr == -3 || intr == -4) {
+       } else if (intr == -2 || intr == -3 || intr == -4 || intr == -6) {
                kvm_mips_callbacks->dequeue_io_int(dvcpu, irq);
        } else {
                kvm_err("%s: invalid interrupt ioctl (%d:%d)\n", __func__,
@@ -1620,6 +1630,34 @@ static struct notifier_block kvm_mips_csr_die_notifier = {
        .notifier_call = kvm_mips_csr_die_notify,
 };
 
+static u32 kvm_default_priority_to_irq[MIPS_EXC_MAX] = {
+       [MIPS_EXC_INT_TIMER] = C_IRQ5,
+       [MIPS_EXC_INT_IO_1]  = C_IRQ0,
+       [MIPS_EXC_INT_IPI_1] = C_IRQ1,
+       [MIPS_EXC_INT_IPI_2] = C_IRQ2,
+};
+
+static u32 kvm_loongson3_priority_to_irq[MIPS_EXC_MAX] = {
+       [MIPS_EXC_INT_TIMER] = C_IRQ5,
+       [MIPS_EXC_INT_IO_1]  = C_IRQ0,
+       [MIPS_EXC_INT_IO_2]  = C_IRQ1,
+       [MIPS_EXC_INT_IPI_1] = C_IRQ4,
+};
+
+u32 *kvm_priority_to_irq = kvm_default_priority_to_irq;
+
+u32 kvm_irq_to_priority(u32 irq)
+{
+       int i;
+
+       for (i = MIPS_EXC_INT_TIMER; i < MIPS_EXC_MAX; i++) {
+               if (kvm_priority_to_irq[i] == (1 << (irq + 8)))
+                       return i;
+       }
+
+       return MIPS_EXC_MAX;
+}
+
 static int __init kvm_mips_init(void)
 {
        int ret;
@@ -1638,6 +1676,9 @@ static int __init kvm_mips_init(void)
        if (ret)
                return ret;
 
+       if (boot_cpu_type() == CPU_LOONGSON64)
+               kvm_priority_to_irq = kvm_loongson3_priority_to_irq;
+
        register_die_notifier(&kvm_mips_csr_die_notifier);
 
        return 0;