KVM: s390: Fix program check on interrupt delivery handling
[linux-2.6-block.git] / arch / s390 / kvm / interrupt.c
index 84a7fed4cd4e1462199cf68733db2196dbc2df69..2960702b48246488087546669b1459524ead2958 100644 (file)
@@ -13,6 +13,7 @@
 #include <asm/lowcore.h>
 #include <asm/uaccess.h>
 #include <linux/kvm_host.h>
+#include <linux/signal.h>
 #include "kvm-s390.h"
 #include "gaccess.h"
 
@@ -31,7 +32,7 @@ static int psw_interrupts_disabled(struct kvm_vcpu *vcpu)
 }
 
 static int __interrupt_is_deliverable(struct kvm_vcpu *vcpu,
-                                     struct interrupt_info *inti)
+                                     struct kvm_s390_interrupt_info *inti)
 {
        switch (inti->type) {
        case KVM_S390_INT_EMERGENCY:
@@ -91,7 +92,7 @@ static void __set_cpuflag(struct kvm_vcpu *vcpu, u32 flag)
 }
 
 static void __set_intercept_indicator(struct kvm_vcpu *vcpu,
-                                     struct interrupt_info *inti)
+                                     struct kvm_s390_interrupt_info *inti)
 {
        switch (inti->type) {
        case KVM_S390_INT_EMERGENCY:
@@ -111,7 +112,7 @@ static void __set_intercept_indicator(struct kvm_vcpu *vcpu,
 }
 
 static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
-                                  struct interrupt_info *inti)
+                                  struct kvm_s390_interrupt_info *inti)
 {
        const unsigned short table[] = { 2, 4, 4, 6 };
        int rc, exception = 0;
@@ -246,15 +247,10 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
        default:
                BUG();
        }
-
        if (exception) {
-               VCPU_EVENT(vcpu, 1, "%s", "program exception while delivering"
-                          " interrupt");
-               kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
-               if (inti->type == KVM_S390_PROGRAM_INT) {
-                       printk(KERN_WARNING "kvm: recursive program check\n");
-                       BUG();
-               }
+               printk("kvm: The guest lowcore is not mapped during interrupt "
+                       "delivery, killing userspace\n");
+               do_exit(SIGKILL);
        }
 }
 
@@ -277,22 +273,19 @@ static int __try_deliver_ckc_interrupt(struct kvm_vcpu *vcpu)
                __LC_EXT_NEW_PSW, sizeof(psw_t));
        if (rc == -EFAULT)
                exception = 1;
-
        if (exception) {
-               VCPU_EVENT(vcpu, 1, "%s", "program exception while delivering" \
-                          " ckc interrupt");
-               kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
-               return 0;
+               printk("kvm: The guest lowcore is not mapped during interrupt "
+                       "delivery, killing userspace\n");
+               do_exit(SIGKILL);
        }
-
        return 1;
 }
 
 int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu)
 {
-       struct local_interrupt *li = &vcpu->arch.local_int;
-       struct float_interrupt *fi = vcpu->arch.local_int.float_int;
-       struct interrupt_info  *inti;
+       struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
+       struct kvm_s390_float_interrupt *fi = vcpu->arch.local_int.float_int;
+       struct kvm_s390_interrupt_info  *inti;
        int rc = 0;
 
        if (atomic_read(&li->active)) {
@@ -408,9 +401,9 @@ void kvm_s390_idle_wakeup(unsigned long data)
 
 void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
 {
-       struct local_interrupt *li = &vcpu->arch.local_int;
-       struct float_interrupt *fi = vcpu->arch.local_int.float_int;
-       struct interrupt_info  *n, *inti = NULL;
+       struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
+       struct kvm_s390_float_interrupt *fi = vcpu->arch.local_int.float_int;
+       struct kvm_s390_interrupt_info  *n, *inti = NULL;
        int deliver;
 
        __reset_intercept_indicators(vcpu);
@@ -465,8 +458,8 @@ void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
 
 int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code)
 {
-       struct local_interrupt *li = &vcpu->arch.local_int;
-       struct interrupt_info *inti;
+       struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
+       struct kvm_s390_interrupt_info *inti;
 
        inti = kzalloc(sizeof(*inti), GFP_KERNEL);
        if (!inti)
@@ -487,9 +480,9 @@ int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code)
 int kvm_s390_inject_vm(struct kvm *kvm,
                       struct kvm_s390_interrupt *s390int)
 {
-       struct local_interrupt *li;
-       struct float_interrupt *fi;
-       struct interrupt_info *inti;
+       struct kvm_s390_local_interrupt *li;
+       struct kvm_s390_float_interrupt *fi;
+       struct kvm_s390_interrupt_info *inti;
        int sigcpu;
 
        inti = kzalloc(sizeof(*inti), GFP_KERNEL);
@@ -544,8 +537,8 @@ int kvm_s390_inject_vm(struct kvm *kvm,
 int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
                         struct kvm_s390_interrupt *s390int)
 {
-       struct local_interrupt *li;
-       struct interrupt_info *inti;
+       struct kvm_s390_local_interrupt *li;
+       struct kvm_s390_interrupt_info *inti;
 
        inti = kzalloc(sizeof(*inti), GFP_KERNEL);
        if (!inti)