KVM: s390: Fix program check on interrupt delivery handling

The current interrupt handling on s390 misbehaves on an error case. On s390
each cpu has the prefix area (lowcore) for interrupt delivery. This memory
must always be available. If we fail to access the prefix area for a guest
on interrupt delivery the configuration is completely unusable. There is no
point in sending another program interrupt to an inaccessible lowcore.
Furthermore, we should not bug the host kernel, because this can be triggered
by userspace. I think the guest kernel itself can not trigger the problem, as
SET PREFIX and SIGNAL PROCESSOR SET PREFIX both check that the memory is
available and sane. As this is a userspace bug (e.g. setting the wrong guest
offset, unmapping guest memory) we should kill the userspace process instead
of BUGing the host kernel.
In the long term we probably should notify the userspace process about this
problem.

Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Avi Kivity <avi@qumranet.com>

authored by

Christian Borntraeger and committed by
Avi Kivity
3cd61299 0096369d

+7 -14
+7 -14
arch/s390/kvm/interrupt.c
··· 13 #include <asm/lowcore.h> 14 #include <asm/uaccess.h> 15 #include <linux/kvm_host.h> 16 #include "kvm-s390.h" 17 #include "gaccess.h" 18 ··· 247 default: 248 BUG(); 249 } 250 - 251 if (exception) { 252 - VCPU_EVENT(vcpu, 1, "%s", "program exception while delivering" 253 - " interrupt"); 254 - kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); 255 - if (inti->type == KVM_S390_PROGRAM_INT) { 256 - printk(KERN_WARNING "kvm: recursive program check\n"); 257 - BUG(); 258 - } 259 } 260 } 261 ··· 273 __LC_EXT_NEW_PSW, sizeof(psw_t)); 274 if (rc == -EFAULT) 275 exception = 1; 276 - 277 if (exception) { 278 - VCPU_EVENT(vcpu, 1, "%s", "program exception while delivering" \ 279 - " ckc interrupt"); 280 - kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); 281 - return 0; 282 } 283 - 284 return 1; 285 } 286
··· 13 #include <asm/lowcore.h> 14 #include <asm/uaccess.h> 15 #include <linux/kvm_host.h> 16 + #include <linux/signal.h> 17 #include "kvm-s390.h" 18 #include "gaccess.h" 19 ··· 246 default: 247 BUG(); 248 } 249 if (exception) { 250 + printk("kvm: The guest lowcore is not mapped during interrupt " 251 + "delivery, killing userspace\n"); 252 + do_exit(SIGKILL); 253 } 254 } 255 ··· 277 __LC_EXT_NEW_PSW, sizeof(psw_t)); 278 if (rc == -EFAULT) 279 exception = 1; 280 if (exception) { 281 + printk("kvm: The guest lowcore is not mapped during interrupt " 282 + "delivery, killing userspace\n"); 283 + do_exit(SIGKILL); 284 } 285 return 1; 286 } 287