@@ -16,6 +16,7 @@
#include <linux/hrtimer.h>
#include <linux/interrupt.h>
#include <linux/kvm_host.h>
+#include <linux/kvm.h>
#include <asm/debug.h>
#include <asm/cpu.h>
@@ -162,18 +163,6 @@ struct kvm_vcpu_stat {
u32 diagnose_9c;
};
-struct kvm_s390_io_info {
- __u16 subchannel_id; /* 0x0b8 */
- __u16 subchannel_nr; /* 0x0ba */
- __u32 io_int_parm; /* 0x0bc */
- __u32 io_int_word; /* 0x0c0 */
-};
-
-struct kvm_s390_ext_info {
- __u32 ext_params;
- __u64 ext_params2;
-};
-
#define PGM_OPERATION 0x01
#define PGM_PRIVILEGED_OP 0x02
#define PGM_EXECUTE 0x03
@@ -182,39 +171,9 @@ struct kvm_s390_ext_info {
#define PGM_SPECIFICATION 0x06
#define PGM_DATA 0x07
-struct kvm_s390_pgm_info {
- __u16 code;
-};
-
-struct kvm_s390_prefix_info {
- __u32 address;
-};
-
-struct kvm_s390_extcall_info {
- __u16 code;
-};
-
-struct kvm_s390_emerg_info {
- __u16 code;
-};
-
-struct kvm_s390_mchk_info {
- __u64 cr14;
- __u64 mcic;
-};
-
struct kvm_s390_interrupt_info {
struct list_head list;
- u64 type;
- union {
- struct kvm_s390_io_info io;
- struct kvm_s390_ext_info ext;
- struct kvm_s390_pgm_info pgm;
- struct kvm_s390_emerg_info emerg;
- struct kvm_s390_extcall_info extcall;
- struct kvm_s390_prefix_info prefix;
- struct kvm_s390_mchk_info mchk;
- };
+ struct kvm_s390_irq irq;
};
/* for local_interrupt.action_flags */
@@ -65,7 +65,7 @@ static u64 int_word_to_isc_bits(u32 int_word)
static int __interrupt_is_deliverable(struct kvm_vcpu *vcpu,
struct kvm_s390_interrupt_info *inti)
{
- switch (inti->type) {
+ switch (inti->irq.type) {
case KVM_S390_INT_EXTERNAL_CALL:
if (psw_extint_disabled(vcpu))
return 0;
@@ -97,19 +97,19 @@ static int __interrupt_is_deliverable(struct kvm_vcpu *vcpu,
case KVM_S390_MCHK:
if (psw_mchk_disabled(vcpu))
return 0;
- if (vcpu->arch.sie_block->gcr[14] & inti->mchk.cr14)
+ if (vcpu->arch.sie_block->gcr[14] & inti->irq.mchk.cr14)
return 1;
return 0;
case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
if (psw_ioint_disabled(vcpu))
return 0;
if (vcpu->arch.sie_block->gcr[6] &
- int_word_to_isc_bits(inti->io.io_int_word))
+ int_word_to_isc_bits(inti->irq.io.io_int_word))
return 1;
return 0;
default:
printk(KERN_WARNING "illegal interrupt type %llx\n",
- inti->type);
+ inti->irq.type);
BUG();
}
return 0;
@@ -146,7 +146,7 @@ static void __set_cpuflag(struct kvm_vcpu *vcpu, u32 flag)
static void __set_intercept_indicator(struct kvm_vcpu *vcpu,
struct kvm_s390_interrupt_info *inti)
{
- switch (inti->type) {
+ switch (inti->irq.type) {
case KVM_S390_INT_EXTERNAL_CALL:
case KVM_S390_INT_EMERGENCY:
case KVM_S390_INT_SERVICE:
@@ -182,14 +182,14 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
const unsigned short table[] = { 2, 4, 4, 6 };
int rc = 0;
- switch (inti->type) {
+ switch (inti->irq.type) {
case KVM_S390_INT_EMERGENCY:
VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp emerg");
vcpu->stat.deliver_emergency_signal++;
- trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
- inti->emerg.code, 0);
+ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->irq.type,
+ inti->irq.emerg.code, 0);
rc = put_guest(vcpu, 0x1201, (u16 __user *)__LC_EXT_INT_CODE);
- rc |= put_guest(vcpu, inti->emerg.code,
+ rc |= put_guest(vcpu, inti->irq.emerg.code,
(u16 __user *)__LC_EXT_CPU_ADDR);
rc |= copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
&vcpu->arch.sie_block->gpsw, sizeof(psw_t));
@@ -199,10 +199,10 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
case KVM_S390_INT_EXTERNAL_CALL:
VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp ext call");
vcpu->stat.deliver_external_call++;
- trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
- inti->extcall.code, 0);
+ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->irq.type,
+ inti->irq.extcall.code, 0);
rc = put_guest(vcpu, 0x1202, (u16 __user *)__LC_EXT_INT_CODE);
- rc |= put_guest(vcpu, inti->extcall.code,
+ rc |= put_guest(vcpu, inti->irq.extcall.code,
(u16 __user *)__LC_EXT_CPU_ADDR);
rc |= copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
&vcpu->arch.sie_block->gpsw, sizeof(psw_t));
@@ -211,57 +211,57 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
break;
case KVM_S390_INT_SERVICE:
VCPU_EVENT(vcpu, 4, "interrupt: sclp parm:%x",
- inti->ext.ext_params);
+ inti->irq.ext.ext_params);
vcpu->stat.deliver_service_signal++;
- trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
- inti->ext.ext_params, 0);
+ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->irq.type,
+ inti->irq.ext.ext_params, 0);
rc = put_guest(vcpu, 0x2401, (u16 __user *)__LC_EXT_INT_CODE);
rc |= copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
&vcpu->arch.sie_block->gpsw, sizeof(psw_t));
rc |= copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
__LC_EXT_NEW_PSW, sizeof(psw_t));
- rc |= put_guest(vcpu, inti->ext.ext_params,
+ rc |= put_guest(vcpu, inti->irq.ext.ext_params,
(u32 __user *)__LC_EXT_PARAMS);
break;
case KVM_S390_INT_VIRTIO:
VCPU_EVENT(vcpu, 4, "interrupt: virtio parm:%x,parm64:%llx",
- inti->ext.ext_params, inti->ext.ext_params2);
+ inti->irq.ext.ext_params, inti->irq.ext.ext_params2);
vcpu->stat.deliver_virtio_interrupt++;
- trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
- inti->ext.ext_params,
- inti->ext.ext_params2);
+ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->irq.type,
+ inti->irq.ext.ext_params,
+ inti->irq.ext.ext_params2);
rc = put_guest(vcpu, 0x2603, (u16 __user *)__LC_EXT_INT_CODE);
rc |= put_guest(vcpu, 0x0d00, (u16 __user *)__LC_EXT_CPU_ADDR);
rc |= copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
&vcpu->arch.sie_block->gpsw, sizeof(psw_t));
rc |= copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
__LC_EXT_NEW_PSW, sizeof(psw_t));
- rc |= put_guest(vcpu, inti->ext.ext_params,
+ rc |= put_guest(vcpu, inti->irq.ext.ext_params,
(u32 __user *)__LC_EXT_PARAMS);
- rc |= put_guest(vcpu, inti->ext.ext_params2,
+ rc |= put_guest(vcpu, inti->irq.ext.ext_params2,
(u64 __user *)__LC_EXT_PARAMS2);
break;
case KVM_S390_SIGP_STOP:
VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu stop");
vcpu->stat.deliver_stop_signal++;
- trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
+ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->irq.type,
0, 0);
__set_intercept_indicator(vcpu, inti);
break;
case KVM_S390_SIGP_SET_PREFIX:
VCPU_EVENT(vcpu, 4, "interrupt: set prefix to %x",
- inti->prefix.address);
+ inti->irq.prefix.address);
vcpu->stat.deliver_prefix_signal++;
- trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
- inti->prefix.address, 0);
- kvm_s390_set_prefix(vcpu, inti->prefix.address);
+ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->irq.type,
+ inti->irq.prefix.address, 0);
+ kvm_s390_set_prefix(vcpu, inti->irq.prefix.address);
break;
case KVM_S390_RESTART:
VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu restart");
vcpu->stat.deliver_restart_signal++;
- trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
+ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->irq.type,
0, 0);
rc = copy_to_guest(vcpu,
offsetof(struct _lowcore, restart_old_psw),
@@ -273,12 +273,12 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
break;
case KVM_S390_PROGRAM_INT:
VCPU_EVENT(vcpu, 4, "interrupt: pgm check code:%x, ilc:%x",
- inti->pgm.code,
+ inti->irq.pgm.code,
table[vcpu->arch.sie_block->ipa >> 14]);
vcpu->stat.deliver_program_int++;
- trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
- inti->pgm.code, 0);
- rc = put_guest(vcpu, inti->pgm.code, (u16 __user *)__LC_PGM_INT_CODE);
+ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->irq.type,
+ inti->irq.pgm.code, 0);
+ rc = put_guest(vcpu, inti->irq.pgm.code, (u16 __user *)__LC_PGM_INT_CODE);
rc |= put_guest(vcpu, table[vcpu->arch.sie_block->ipa >> 14],
(u16 __user *)__LC_PGM_ILC);
rc |= copy_to_guest(vcpu, __LC_PGM_OLD_PSW,
@@ -289,13 +289,13 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
case KVM_S390_MCHK:
VCPU_EVENT(vcpu, 4, "interrupt: machine check mcic=%llx",
- inti->mchk.mcic);
- trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
- inti->mchk.cr14,
- inti->mchk.mcic);
+ inti->irq.mchk.mcic);
+ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->irq.type,
+ inti->irq.mchk.cr14,
+ inti->irq.mchk.mcic);
rc = kvm_s390_vcpu_store_status(vcpu,
KVM_S390_STORE_STATUS_PREFIXED);
- rc |= put_guest(vcpu, inti->mchk.mcic, (u64 __user *) __LC_MCCK_CODE);
+ rc |= put_guest(vcpu, inti->irq.mchk.mcic, (u64 __user *) __LC_MCCK_CODE);
rc |= copy_to_guest(vcpu, __LC_MCK_OLD_PSW,
&vcpu->arch.sie_block->gpsw, sizeof(psw_t));
rc |= copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
@@ -304,21 +304,21 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
{
- __u32 param0 = ((__u32)inti->io.subchannel_id << 16) |
- inti->io.subchannel_nr;
- __u64 param1 = ((__u64)inti->io.io_int_parm << 32) |
- inti->io.io_int_word;
- VCPU_EVENT(vcpu, 4, "interrupt: I/O %llx", inti->type);
+ __u32 param0 = ((__u32)inti->irq.io.subchannel_id << 16) |
+ inti->irq.io.subchannel_nr;
+ __u64 param1 = ((__u64)inti->irq.io.io_int_parm << 32) |
+ inti->irq.io.io_int_word;
+ VCPU_EVENT(vcpu, 4, "interrupt: I/O %llx", inti->irq.type);
vcpu->stat.deliver_io_int++;
- trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
+ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->irq.type,
param0, param1);
- rc = put_guest(vcpu, inti->io.subchannel_id,
+ rc = put_guest(vcpu, inti->irq.io.subchannel_id,
(u16 __user *) __LC_SUBCHANNEL_ID);
- rc |= put_guest(vcpu, inti->io.subchannel_nr,
+ rc |= put_guest(vcpu, inti->irq.io.subchannel_nr,
(u16 __user *) __LC_SUBCHANNEL_NR);
- rc |= put_guest(vcpu, inti->io.io_int_parm,
+ rc |= put_guest(vcpu, inti->irq.io.io_int_parm,
(u32 __user *) __LC_IO_INT_PARM);
- rc |= put_guest(vcpu, inti->io.io_int_word,
+ rc |= put_guest(vcpu, inti->irq.io.io_int_word,
(u32 __user *) __LC_IO_INT_WORD);
rc |= copy_to_guest(vcpu, __LC_IO_OLD_PSW,
&vcpu->arch.sie_block->gpsw, sizeof(psw_t));
@@ -554,7 +554,7 @@ void kvm_s390_deliver_pending_machine_checks(struct kvm_vcpu *vcpu)
deliver = 0;
spin_lock_bh(&li->lock);
list_for_each_entry_safe(inti, n, &li->list, list) {
- if ((inti->type == KVM_S390_MCHK) &&
+ if ((inti->irq.type == KVM_S390_MCHK) &&
__interrupt_is_deliverable(vcpu, inti)) {
list_del(&inti->list);
deliver = 1;
@@ -577,7 +577,7 @@ void kvm_s390_deliver_pending_machine_checks(struct kvm_vcpu *vcpu)
deliver = 0;
spin_lock(&fi->lock);
list_for_each_entry_safe(inti, n, &fi->list, list) {
- if ((inti->type == KVM_S390_MCHK) &&
+ if ((inti->irq.type == KVM_S390_MCHK) &&
__interrupt_is_deliverable(vcpu, inti)) {
list_del(&inti->list);
deliver = 1;
@@ -605,11 +605,11 @@ int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code)
if (!inti)
return -ENOMEM;
- inti->type = KVM_S390_PROGRAM_INT;
- inti->pgm.code = code;
+ inti->irq.type = KVM_S390_PROGRAM_INT;
+ inti->irq.pgm.code = code;
VCPU_EVENT(vcpu, 3, "inject: program check %d (from kernel)", code);
- trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, inti->type, code, 0, 1);
+ trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, inti->irq.type, code, 0, 1);
spin_lock_bh(&li->lock);
list_add(&inti->list, &li->list);
atomic_set(&li->active, 1);
@@ -631,17 +631,17 @@ struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm,
spin_lock(&fi->lock);
inti = NULL;
list_for_each_entry(iter, &fi->list, list) {
- if (!is_ioint(iter->type))
+ if (!is_ioint(iter->irq.type))
continue;
if (cr6 &&
- ((cr6 & int_word_to_isc_bits(iter->io.io_int_word)) == 0))
+ ((cr6 & int_word_to_isc_bits(iter->irq.io.io_int_word)) == 0))
continue;
if (schid) {
if (((schid & 0x00000000ffff0000) >> 16) !=
- iter->io.subchannel_id)
+ iter->irq.io.subchannel_id)
continue;
if ((schid & 0x000000000000ffff) !=
- iter->io.subchannel_nr)
+ iter->irq.io.subchannel_nr)
continue;
}
inti = iter;
@@ -662,72 +662,69 @@ int kvm_s390_inject_vm(struct kvm *kvm,
struct kvm_s390_local_interrupt *li;
struct kvm_s390_float_interrupt *fi;
struct kvm_s390_interrupt_info *inti, *iter;
+ struct kvm_s390_irq *irq;
int sigcpu;
inti = kzalloc(sizeof(*inti), GFP_KERNEL);
if (!inti)
return -ENOMEM;
- switch (s390int->type) {
+ irq = &inti->irq;
+
+ irq->type = s390int->type;
+ switch (irq->type) {
case KVM_S390_INT_VIRTIO:
VM_EVENT(kvm, 5, "inject: virtio parm:%x,parm64:%llx",
s390int->parm, s390int->parm64);
- inti->type = s390int->type;
- inti->ext.ext_params = s390int->parm;
- inti->ext.ext_params2 = s390int->parm64;
+ irq->ext.ext_params = s390int->parm;
+ irq->ext.ext_params2 = s390int->parm64;
break;
case KVM_S390_INT_SERVICE:
VM_EVENT(kvm, 5, "inject: sclp parm:%x", s390int->parm);
- inti->type = s390int->type;
- inti->ext.ext_params = s390int->parm;
+ irq->ext.ext_params = s390int->parm;
break;
- case KVM_S390_PROGRAM_INT:
- case KVM_S390_SIGP_STOP:
- case KVM_S390_INT_EXTERNAL_CALL:
- case KVM_S390_INT_EMERGENCY:
- kfree(inti);
- return -EINVAL;
case KVM_S390_MCHK:
VM_EVENT(kvm, 5, "inject: machine check parm64:%llx",
s390int->parm64);
- inti->type = s390int->type;
- inti->mchk.cr14 = s390int->parm; /* upper bits are not used */
- inti->mchk.mcic = s390int->parm64;
+ irq->mchk.cr14 = s390int->parm; /* upper bits are not used */
+ irq->mchk.mcic = s390int->parm64;
break;
case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
- if (s390int->type & IOINT_AI_MASK)
+ if (irq->type & IOINT_AI_MASK)
VM_EVENT(kvm, 5, "%s", "inject: I/O (AI)");
else
VM_EVENT(kvm, 5, "inject: I/O css %x ss %x schid %04x",
s390int->type & IOINT_CSSID_MASK,
s390int->type & IOINT_SSID_MASK,
s390int->type & IOINT_SCHID_MASK);
- inti->type = s390int->type;
- inti->io.subchannel_id = s390int->parm >> 16;
- inti->io.subchannel_nr = s390int->parm & 0x0000ffffu;
- inti->io.io_int_parm = s390int->parm64 >> 32;
- inti->io.io_int_word = s390int->parm64 & 0x00000000ffffffffull;
+ irq->io.subchannel_id = s390int->parm >> 16;
+ irq->io.subchannel_nr = s390int->parm & 0x0000ffffu;
+ irq->io.io_int_parm = s390int->parm64 >> 32;
+ irq->io.io_int_word = s390int->parm64 & 0x00000000ffffffffull;
break;
+ case KVM_S390_PROGRAM_INT:
+ case KVM_S390_SIGP_STOP:
+ case KVM_S390_INT_EXTERNAL_CALL:
+ case KVM_S390_INT_EMERGENCY:
default:
kfree(inti);
return -EINVAL;
}
- trace_kvm_s390_inject_vm(s390int->type, s390int->parm, s390int->parm64,
- 2);
+ trace_kvm_s390_inject_vm(s390int->type, s390int->parm, s390int->parm64, 2);
mutex_lock(&kvm->lock);
fi = &kvm->arch.float_int;
spin_lock(&fi->lock);
- if (!is_ioint(inti->type))
+ if (!is_ioint(inti->irq.type))
list_add_tail(&inti->list, &fi->list);
else {
- u64 isc_bits = int_word_to_isc_bits(inti->io.io_int_word);
+ u64 isc_bits = int_word_to_isc_bits(inti->irq.io.io_int_word);
/* Keep I/O interrupts sorted in isc order. */
list_for_each_entry(iter, &fi->list, list) {
- if (!is_ioint(iter->type))
+ if (!is_ioint(iter->irq.type))
continue;
- if (int_word_to_isc_bits(iter->io.io_int_word)
+ if (int_word_to_isc_bits(iter->irq.io.io_int_word)
<= isc_bits)
continue;
break;
@@ -770,21 +767,21 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
kfree(inti);
return -EINVAL;
}
- inti->type = s390int->type;
- inti->pgm.code = s390int->parm;
+ inti->irq.type = s390int->type;
+ inti->irq.pgm.code = s390int->parm;
VCPU_EVENT(vcpu, 3, "inject: program check %d (from user)",
s390int->parm);
break;
case KVM_S390_SIGP_SET_PREFIX:
- inti->prefix.address = s390int->parm;
- inti->type = s390int->type;
+ inti->irq.prefix.address = s390int->parm;
+ inti->irq.type = s390int->type;
VCPU_EVENT(vcpu, 3, "inject: set prefix to %x (from user)",
s390int->parm);
break;
case KVM_S390_SIGP_STOP:
case KVM_S390_RESTART:
VCPU_EVENT(vcpu, 3, "inject: type %x", s390int->type);
- inti->type = s390int->type;
+ inti->irq.type = s390int->type;
break;
case KVM_S390_INT_EXTERNAL_CALL:
if (s390int->parm & 0xffff0000) {
@@ -793,8 +790,8 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
}
VCPU_EVENT(vcpu, 3, "inject: external call source-cpu:%u",
s390int->parm);
- inti->type = s390int->type;
- inti->extcall.code = s390int->parm;
+ inti->irq.type = s390int->type;
+ inti->irq.extcall.code = s390int->parm;
break;
case KVM_S390_INT_EMERGENCY:
if (s390int->parm & 0xffff0000) {
@@ -802,14 +799,14 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
return -EINVAL;
}
VCPU_EVENT(vcpu, 3, "inject: emergency %u\n", s390int->parm);
- inti->type = s390int->type;
- inti->emerg.code = s390int->parm;
+ inti->irq.type = s390int->type;
+ inti->irq.emerg.code = s390int->parm;
break;
case KVM_S390_MCHK:
VCPU_EVENT(vcpu, 5, "inject: machine check parm64:%llx",
s390int->parm64);
- inti->type = s390int->type;
- inti->mchk.mcic = s390int->parm64;
+ inti->irq.type = s390int->type;
+ inti->irq.mchk.mcic = s390int->parm64;
break;
case KVM_S390_INT_VIRTIO:
case KVM_S390_INT_SERVICE:
@@ -824,12 +821,12 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
mutex_lock(&vcpu->kvm->lock);
li = &vcpu->arch.local_int;
spin_lock_bh(&li->lock);
- if (inti->type == KVM_S390_PROGRAM_INT)
+ if (inti->irq.type == KVM_S390_PROGRAM_INT)
list_add(&inti->list, &li->list);
else
list_add_tail(&inti->list, &li->list);
atomic_set(&li->active, 1);
- if (inti->type == KVM_S390_SIGP_STOP)
+ if (inti->irq.type == KVM_S390_SIGP_STOP)
li->action_bits |= ACTION_STOP_ON_STOP;
atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
if (waitqueue_active(&vcpu->wq))
@@ -146,19 +146,19 @@ static int handle_tpi(struct kvm_vcpu *vcpu)
* Store the two-word I/O interruption code into the
* provided area.
*/
- if (put_guest(vcpu, inti->io.subchannel_id, (u16 __user *)addr)
- || put_guest(vcpu, inti->io.subchannel_nr, (u16 __user *)(addr + 2))
- || put_guest(vcpu, inti->io.io_int_parm, (u32 __user *)(addr + 4)))
+ if (put_guest(vcpu, inti->irq.io.subchannel_id, (u16 __user *)addr)
+ || put_guest(vcpu, inti->irq.io.subchannel_nr, (u16 __user *)(addr + 2))
+ || put_guest(vcpu, inti->irq.io.io_int_parm, (u32 __user *)(addr + 4)))
return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
} else {
/*
* Store the three-word I/O interruption code into
* the appropriate lowcore area.
*/
- put_guest(vcpu, inti->io.subchannel_id, (u16 __user *) __LC_SUBCHANNEL_ID);
- put_guest(vcpu, inti->io.subchannel_nr, (u16 __user *) __LC_SUBCHANNEL_NR);
- put_guest(vcpu, inti->io.io_int_parm, (u32 __user *) __LC_IO_INT_PARM);
- put_guest(vcpu, inti->io.io_int_word, (u32 __user *) __LC_IO_INT_WORD);
+ put_guest(vcpu, inti->irq.io.subchannel_id, (u16 __user *) __LC_SUBCHANNEL_ID);
+ put_guest(vcpu, inti->irq.io.subchannel_nr, (u16 __user *) __LC_SUBCHANNEL_NR);
+ put_guest(vcpu, inti->irq.io.io_int_parm, (u32 __user *) __LC_IO_INT_PARM);
+ put_guest(vcpu, inti->irq.io.io_int_word, (u32 __user *) __LC_IO_INT_WORD);
}
kfree(inti);
no_interrupt:
@@ -186,10 +186,10 @@ static int handle_tsch(struct kvm_vcpu *vcpu)
vcpu->run->exit_reason = KVM_EXIT_S390_TSCH;
vcpu->run->s390_tsch.dequeued = !!inti;
if (inti) {
- vcpu->run->s390_tsch.subchannel_id = inti->io.subchannel_id;
- vcpu->run->s390_tsch.subchannel_nr = inti->io.subchannel_nr;
- vcpu->run->s390_tsch.io_int_parm = inti->io.io_int_parm;
- vcpu->run->s390_tsch.io_int_word = inti->io.io_int_word;
+ vcpu->run->s390_tsch.subchannel_id = inti->irq.io.subchannel_id;
+ vcpu->run->s390_tsch.subchannel_nr = inti->irq.io.subchannel_nr;
+ vcpu->run->s390_tsch.io_int_parm = inti->irq.io.io_int_parm;
+ vcpu->run->s390_tsch.io_int_word = inti->irq.io.io_int_word;
}
vcpu->run->s390_tsch.ipb = vcpu->arch.sie_block->ipb;
kfree(inti);
@@ -65,8 +65,8 @@ static int __sigp_emergency(struct kvm_vcpu *vcpu, u16 cpu_addr)
if (!inti)
return -ENOMEM;
- inti->type = KVM_S390_INT_EMERGENCY;
- inti->emerg.code = vcpu->vcpu_id;
+ inti->irq.type = KVM_S390_INT_EMERGENCY;
+ inti->irq.emerg.code = vcpu->vcpu_id;
spin_lock(&fi->lock);
li = fi->local_int[cpu_addr];
@@ -103,8 +103,8 @@ static int __sigp_external_call(struct kvm_vcpu *vcpu, u16 cpu_addr)
if (!inti)
return -ENOMEM;
- inti->type = KVM_S390_INT_EXTERNAL_CALL;
- inti->extcall.code = vcpu->vcpu_id;
+ inti->irq.type = KVM_S390_INT_EXTERNAL_CALL;
+ inti->irq.extcall.code = vcpu->vcpu_id;
spin_lock(&fi->lock);
li = fi->local_int[cpu_addr];
@@ -134,7 +134,7 @@ static int __inject_sigp_stop(struct kvm_s390_local_interrupt *li, int action)
inti = kzalloc(sizeof(*inti), GFP_ATOMIC);
if (!inti)
return -ENOMEM;
- inti->type = KVM_S390_SIGP_STOP;
+ inti->irq.type = KVM_S390_SIGP_STOP;
spin_lock_bh(&li->lock);
if ((atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) {
@@ -245,8 +245,8 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,
goto out_li;
}
- inti->type = KVM_S390_SIGP_SET_PREFIX;
- inti->prefix.address = address;
+ inti->irq.type = KVM_S390_SIGP_SET_PREFIX;
+ inti->irq.prefix.address = address;
list_add_tail(&inti->list, &li->list);
atomic_set(&li->active, 1);
@@ -434,6 +434,68 @@ struct kvm_s390_interrupt {
__u64 parm64;
};
+struct kvm_s390_io_info {
+ __u16 subchannel_id;
+ __u16 subchannel_nr;
+ __u32 io_int_parm;
+ __u32 io_int_word;
+};
+
+struct kvm_s390_ext_info {
+ __u32 ext_params;
+ __u64 ext_params2;
+};
+
+struct kvm_s390_pgm_info {
+ __u64 trans_exc_code;
+ __u64 mon_code;
+ __u64 per_address;
+ __u32 data_exc_code;
+ __u16 code;
+ __u16 mon_class_nr;
+ __u8 per_code;
+ __u8 per_atmid;
+ __u8 exc_access_id;
+ __u8 per_access_id;
+ __u8 op_access_id;
+ __u8 pad[3];
+};
+
+struct kvm_s390_prefix_info {
+ __u32 address;
+};
+
+struct kvm_s390_extcall_info {
+ __u16 code;
+};
+
+struct kvm_s390_emerg_info {
+ __u16 code;
+};
+
+struct kvm_s390_mchk_info {
+ __u64 cr14;
+ __u64 mcic;
+ __u64 failing_storage_address;
+ __u32 ext_damage_code;
+ __u32 pad;
+ __u8 fixed_logout[16];
+};
+
+struct kvm_s390_irq {
+ __u64 type;
+ union {
+ struct kvm_s390_io_info io;
+ struct kvm_s390_ext_info ext;
+ struct kvm_s390_pgm_info pgm;
+ struct kvm_s390_emerg_info emerg;
+ struct kvm_s390_extcall_info extcall;
+ struct kvm_s390_prefix_info prefix;
+ struct kvm_s390_mchk_info mchk;
+ };
+ char reserved[64];
+};
+
/* for KVM_SET_GUEST_DEBUG */
#define KVM_GUESTDBG_ENABLE 0x00000001
With the currently available struct kvm_s390_interrupt it is not possible to inject all kinds of interrupts as defined in the z/Architecture. Add interruption parameters to the structures to make sure we can inject all kinds of interrupts and move it to kvm.h Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com> --- arch/s390/include/asm/kvm_host.h | 45 +--------- arch/s390/kvm/interrupt.c | 189 +++++++++++++++++++-------------------- arch/s390/kvm/priv.c | 22 ++--- arch/s390/kvm/sigp.c | 14 +-- include/uapi/linux/kvm.h | 62 +++++++++++++ 5 files changed, 175 insertions(+), 157 deletions(-)