|
@@ -28,7 +28,7 @@
|
|
#define IOINT_AI_MASK 0x04000000
|
|
#define IOINT_AI_MASK 0x04000000
|
|
#define PFAULT_INIT 0x0600
|
|
#define PFAULT_INIT 0x0600
|
|
|
|
|
|
-static void deliver_ckc_interrupt(struct kvm_vcpu *vcpu);
|
|
|
|
|
|
+static int deliver_ckc_interrupt(struct kvm_vcpu *vcpu);
|
|
|
|
|
|
static int is_ioint(u64 type)
|
|
static int is_ioint(u64 type)
|
|
{
|
|
{
|
|
@@ -307,7 +307,7 @@ static int __deliver_prog_irq(struct kvm_vcpu *vcpu,
|
|
return rc;
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
|
|
-static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
|
|
|
|
|
|
+static int __do_deliver_interrupt(struct kvm_vcpu *vcpu,
|
|
struct kvm_s390_interrupt_info *inti)
|
|
struct kvm_s390_interrupt_info *inti)
|
|
{
|
|
{
|
|
const unsigned short table[] = { 2, 4, 4, 6 };
|
|
const unsigned short table[] = { 2, 4, 4, 6 };
|
|
@@ -345,7 +345,7 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
|
|
case KVM_S390_INT_CLOCK_COMP:
|
|
case KVM_S390_INT_CLOCK_COMP:
|
|
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
|
|
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
|
|
inti->ext.ext_params, 0);
|
|
inti->ext.ext_params, 0);
|
|
- deliver_ckc_interrupt(vcpu);
|
|
|
|
|
|
+ rc = deliver_ckc_interrupt(vcpu);
|
|
break;
|
|
break;
|
|
case KVM_S390_INT_CPU_TIMER:
|
|
case KVM_S390_INT_CPU_TIMER:
|
|
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
|
|
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
|
|
@@ -504,14 +504,11 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
|
|
default:
|
|
default:
|
|
BUG();
|
|
BUG();
|
|
}
|
|
}
|
|
- if (rc) {
|
|
|
|
- printk("kvm: The guest lowcore is not mapped during interrupt "
|
|
|
|
- "delivery, killing userspace\n");
|
|
|
|
- do_exit(SIGKILL);
|
|
|
|
- }
|
|
|
|
|
|
+
|
|
|
|
+ return rc;
|
|
}
|
|
}
|
|
|
|
|
|
-static void deliver_ckc_interrupt(struct kvm_vcpu *vcpu)
|
|
|
|
|
|
+static int deliver_ckc_interrupt(struct kvm_vcpu *vcpu)
|
|
{
|
|
{
|
|
int rc;
|
|
int rc;
|
|
|
|
|
|
@@ -521,11 +518,7 @@ static void deliver_ckc_interrupt(struct kvm_vcpu *vcpu)
|
|
rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
|
|
rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
|
|
&vcpu->arch.sie_block->gpsw,
|
|
&vcpu->arch.sie_block->gpsw,
|
|
sizeof(psw_t));
|
|
sizeof(psw_t));
|
|
- if (rc) {
|
|
|
|
- printk("kvm: The guest lowcore is not mapped during interrupt "
|
|
|
|
- "delivery, killing userspace\n");
|
|
|
|
- do_exit(SIGKILL);
|
|
|
|
- }
|
|
|
|
|
|
+ return rc;
|
|
}
|
|
}
|
|
|
|
|
|
/* Check whether SIGP interpretation facility has an external call pending */
|
|
/* Check whether SIGP interpretation facility has an external call pending */
|
|
@@ -664,12 +657,13 @@ void kvm_s390_clear_local_irqs(struct kvm_vcpu *vcpu)
|
|
&vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].ctrl);
|
|
&vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].ctrl);
|
|
}
|
|
}
|
|
|
|
|
|
-void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
|
|
|
|
|
|
+int kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
|
|
{
|
|
{
|
|
struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
|
|
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_float_interrupt *fi = vcpu->arch.local_int.float_int;
|
|
struct kvm_s390_interrupt_info *n, *inti = NULL;
|
|
struct kvm_s390_interrupt_info *n, *inti = NULL;
|
|
int deliver;
|
|
int deliver;
|
|
|
|
+ int rc = 0;
|
|
|
|
|
|
__reset_intercept_indicators(vcpu);
|
|
__reset_intercept_indicators(vcpu);
|
|
if (atomic_read(&li->active)) {
|
|
if (atomic_read(&li->active)) {
|
|
@@ -688,16 +682,16 @@ void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
|
|
atomic_set(&li->active, 0);
|
|
atomic_set(&li->active, 0);
|
|
spin_unlock(&li->lock);
|
|
spin_unlock(&li->lock);
|
|
if (deliver) {
|
|
if (deliver) {
|
|
- __do_deliver_interrupt(vcpu, inti);
|
|
|
|
|
|
+ rc = __do_deliver_interrupt(vcpu, inti);
|
|
kfree(inti);
|
|
kfree(inti);
|
|
}
|
|
}
|
|
- } while (deliver);
|
|
|
|
|
|
+ } while (!rc && deliver);
|
|
}
|
|
}
|
|
|
|
|
|
- if (kvm_cpu_has_pending_timer(vcpu))
|
|
|
|
- deliver_ckc_interrupt(vcpu);
|
|
|
|
|
|
+ if (!rc && kvm_cpu_has_pending_timer(vcpu))
|
|
|
|
+ rc = deliver_ckc_interrupt(vcpu);
|
|
|
|
|
|
- if (atomic_read(&fi->active)) {
|
|
|
|
|
|
+ if (!rc && atomic_read(&fi->active)) {
|
|
do {
|
|
do {
|
|
deliver = 0;
|
|
deliver = 0;
|
|
spin_lock(&fi->lock);
|
|
spin_lock(&fi->lock);
|
|
@@ -714,11 +708,13 @@ void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
|
|
atomic_set(&fi->active, 0);
|
|
atomic_set(&fi->active, 0);
|
|
spin_unlock(&fi->lock);
|
|
spin_unlock(&fi->lock);
|
|
if (deliver) {
|
|
if (deliver) {
|
|
- __do_deliver_interrupt(vcpu, inti);
|
|
|
|
|
|
+ rc = __do_deliver_interrupt(vcpu, inti);
|
|
kfree(inti);
|
|
kfree(inti);
|
|
}
|
|
}
|
|
- } while (deliver);
|
|
|
|
|
|
+ } while (!rc && deliver);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ return rc;
|
|
}
|
|
}
|
|
|
|
|
|
int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code)
|
|
int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code)
|