Commit 0fb97abe authored by Jens Freimann's avatar Jens Freimann Committed by Christian Borntraeger

KVM: s390: refactor interrupt delivery code

Move delivery code for cpu-local interrupt from the huge do_deliver_interrupt()
to smaller functions which handle one type of interrupt.
Signed-off-by: default avatarJens Freimann <jfrei@linux.vnet.ibm.com>
Reviewed-by: default avatarDavid Hildenbrand <dahi@linux.vnet.ibm.com>
Reviewed-by: default avatarCornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: default avatarChristian Borntraeger <borntraeger@de.ibm.com>
parent 60f90a14
...@@ -30,8 +30,6 @@ ...@@ -30,8 +30,6 @@
#define PFAULT_DONE 0x0680 #define PFAULT_DONE 0x0680
#define VIRTIO_PARAM 0x0d00 #define VIRTIO_PARAM 0x0d00
static int __must_check deliver_ckc_interrupt(struct kvm_vcpu *vcpu);
static int is_ioint(u64 type) static int is_ioint(u64 type)
{ {
return ((type & 0xfffe0000u) != 0xfffe0000u); return ((type & 0xfffe0000u) != 0xfffe0000u);
...@@ -228,12 +226,183 @@ static u16 get_ilc(struct kvm_vcpu *vcpu) ...@@ -228,12 +226,183 @@ static u16 get_ilc(struct kvm_vcpu *vcpu)
} }
} }
static int __must_check __deliver_prog_irq(struct kvm_vcpu *vcpu, static int __must_check __deliver_cpu_timer(struct kvm_vcpu *vcpu)
struct kvm_s390_pgm_info *pgm_info)
{ {
int rc;
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_INT_CPU_TIMER,
0, 0);
rc = put_guest_lc(vcpu, EXT_IRQ_CPU_TIMER,
(u16 *)__LC_EXT_INT_CODE);
rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
&vcpu->arch.sie_block->gpsw, sizeof(psw_t));
rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
&vcpu->arch.sie_block->gpsw, sizeof(psw_t));
return rc;
}
static int __must_check __deliver_ckc(struct kvm_vcpu *vcpu)
{
int rc;
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_INT_CLOCK_COMP,
0, 0);
rc = put_guest_lc(vcpu, EXT_IRQ_CLK_COMP,
(u16 __user *)__LC_EXT_INT_CODE);
rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
&vcpu->arch.sie_block->gpsw, sizeof(psw_t));
rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
&vcpu->arch.sie_block->gpsw, sizeof(psw_t));
return rc;
}
static int __must_check __deliver_pfault_init(struct kvm_vcpu *vcpu,
struct kvm_s390_interrupt_info *inti)
{
struct kvm_s390_ext_info *ext = &inti->ext;
int rc;
VCPU_EVENT(vcpu, 4, "interrupt: pfault init parm:%x,parm64:%llx",
0, ext->ext_params2);
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id,
KVM_S390_INT_PFAULT_INIT,
0, ext->ext_params2);
rc = put_guest_lc(vcpu, EXT_IRQ_CP_SERVICE, (u16 *) __LC_EXT_INT_CODE);
rc |= put_guest_lc(vcpu, PFAULT_INIT, (u16 *) __LC_EXT_CPU_ADDR);
rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
&vcpu->arch.sie_block->gpsw, sizeof(psw_t));
rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
&vcpu->arch.sie_block->gpsw, sizeof(psw_t));
rc |= put_guest_lc(vcpu, ext->ext_params2, (u64 *) __LC_EXT_PARAMS2);
return rc;
}
static int __must_check __deliver_machine_check(struct kvm_vcpu *vcpu,
struct kvm_s390_interrupt_info *inti)
{
struct kvm_s390_mchk_info *mchk = &inti->mchk;
int rc;
VCPU_EVENT(vcpu, 4, "interrupt: machine check mcic=%llx",
mchk->mcic);
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_MCHK,
mchk->cr14, mchk->mcic);
rc = kvm_s390_vcpu_store_status(vcpu, KVM_S390_STORE_STATUS_PREFIXED);
rc |= put_guest_lc(vcpu, mchk->mcic,
(u64 __user *) __LC_MCCK_CODE);
rc |= put_guest_lc(vcpu, mchk->failing_storage_address,
(u64 __user *) __LC_MCCK_FAIL_STOR_ADDR);
rc |= write_guest_lc(vcpu, __LC_PSW_SAVE_AREA,
&mchk->fixed_logout, sizeof(mchk->fixed_logout));
rc |= write_guest_lc(vcpu, __LC_MCK_OLD_PSW,
&vcpu->arch.sie_block->gpsw, sizeof(psw_t));
rc |= read_guest_lc(vcpu, __LC_MCK_NEW_PSW,
&vcpu->arch.sie_block->gpsw, sizeof(psw_t));
return rc;
}
static int __must_check __deliver_restart(struct kvm_vcpu *vcpu)
{
int rc;
VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu restart");
vcpu->stat.deliver_restart_signal++;
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_RESTART, 0, 0);
rc = write_guest_lc(vcpu,
offsetof(struct _lowcore, restart_old_psw),
&vcpu->arch.sie_block->gpsw, sizeof(psw_t));
rc |= read_guest_lc(vcpu, offsetof(struct _lowcore, restart_psw),
&vcpu->arch.sie_block->gpsw, sizeof(psw_t));
return rc;
}
static int __must_check __deliver_stop(struct kvm_vcpu *vcpu)
{
VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu stop");
vcpu->stat.deliver_stop_signal++;
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_SIGP_STOP,
0, 0);
__set_cpuflag(vcpu, CPUSTAT_STOP_INT);
return 0;
}
static int __must_check __deliver_set_prefix(struct kvm_vcpu *vcpu,
struct kvm_s390_interrupt_info *inti)
{
struct kvm_s390_prefix_info *prefix = &inti->prefix;
VCPU_EVENT(vcpu, 4, "interrupt: set prefix to %x", prefix->address);
vcpu->stat.deliver_prefix_signal++;
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id,
KVM_S390_SIGP_SET_PREFIX,
prefix->address, 0);
kvm_s390_set_prefix(vcpu, prefix->address);
return 0;
}
static int __must_check __deliver_emergency_signal(struct kvm_vcpu *vcpu,
struct kvm_s390_interrupt_info *inti)
{
struct kvm_s390_emerg_info *emerg = &inti->emerg;
int rc;
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);
rc = put_guest_lc(vcpu, EXT_IRQ_EMERGENCY_SIG,
(u16 *)__LC_EXT_INT_CODE);
rc |= put_guest_lc(vcpu, emerg->code, (u16 *)__LC_EXT_CPU_ADDR);
rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
&vcpu->arch.sie_block->gpsw, sizeof(psw_t));
rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
&vcpu->arch.sie_block->gpsw, sizeof(psw_t));
return rc;
}
static int __must_check __deliver_external_call(struct kvm_vcpu *vcpu,
struct kvm_s390_interrupt_info *inti)
{
struct kvm_s390_extcall_info *extcall = &inti->extcall;
int rc;
VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp ext call");
vcpu->stat.deliver_external_call++;
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id,
KVM_S390_INT_EXTERNAL_CALL,
extcall->code, 0);
rc = put_guest_lc(vcpu, EXT_IRQ_EXTERNAL_CALL,
(u16 *)__LC_EXT_INT_CODE);
rc |= put_guest_lc(vcpu, extcall->code, (u16 *)__LC_EXT_CPU_ADDR);
rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
&vcpu->arch.sie_block->gpsw, sizeof(psw_t));
rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, &vcpu->arch.sie_block->gpsw,
sizeof(psw_t));
return rc;
}
static int __must_check __deliver_prog(struct kvm_vcpu *vcpu,
struct kvm_s390_interrupt_info *inti)
{
struct kvm_s390_pgm_info *pgm_info = &inti->pgm;
int rc = 0; int rc = 0;
u16 ilc = get_ilc(vcpu); u16 ilc = get_ilc(vcpu);
VCPU_EVENT(vcpu, 4, "interrupt: pgm check code:%x, ilc:%x",
pgm_info->code, ilc);
vcpu->stat.deliver_program_int++;
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_PROGRAM_INT,
pgm_info->code, 0);
switch (pgm_info->code & ~PGM_PER) { switch (pgm_info->code & ~PGM_PER) {
case PGM_AFX_TRANSLATION: case PGM_AFX_TRANSLATION:
case PGM_ASX_TRANSLATION: case PGM_ASX_TRANSLATION:
...@@ -306,186 +475,88 @@ static int __must_check __deliver_prog_irq(struct kvm_vcpu *vcpu, ...@@ -306,186 +475,88 @@ static int __must_check __deliver_prog_irq(struct kvm_vcpu *vcpu,
&vcpu->arch.sie_block->gpsw, sizeof(psw_t)); &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
rc |= read_guest_lc(vcpu, __LC_PGM_NEW_PSW, rc |= read_guest_lc(vcpu, __LC_PGM_NEW_PSW,
&vcpu->arch.sie_block->gpsw, sizeof(psw_t)); &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
return rc; return rc;
} }
static int __must_check __do_deliver_interrupt(struct kvm_vcpu *vcpu, static int __must_check __deliver_service(struct kvm_vcpu *vcpu,
struct kvm_s390_interrupt_info *inti) struct kvm_s390_interrupt_info *inti)
{ {
const unsigned short table[] = { 2, 4, 4, 6 }; int rc;
int rc = 0;
switch (inti->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);
rc = put_guest_lc(vcpu, 0x1201, (u16 *)__LC_EXT_INT_CODE);
rc |= put_guest_lc(vcpu, inti->emerg.code,
(u16 *)__LC_EXT_CPU_ADDR);
rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
&vcpu->arch.sie_block->gpsw, sizeof(psw_t));
rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
&vcpu->arch.sie_block->gpsw, sizeof(psw_t));
break;
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);
rc = put_guest_lc(vcpu, 0x1202, (u16 *)__LC_EXT_INT_CODE);
rc |= put_guest_lc(vcpu, inti->extcall.code,
(u16 *)__LC_EXT_CPU_ADDR);
rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
&vcpu->arch.sie_block->gpsw,
sizeof(psw_t));
rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
&vcpu->arch.sie_block->gpsw,
sizeof(psw_t));
break;
case KVM_S390_INT_CLOCK_COMP:
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
0, 0);
rc = deliver_ckc_interrupt(vcpu);
break;
case KVM_S390_INT_CPU_TIMER:
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
0, 0);
rc = put_guest_lc(vcpu, EXT_IRQ_CPU_TIMER,
(u16 *)__LC_EXT_INT_CODE);
rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
&vcpu->arch.sie_block->gpsw,
sizeof(psw_t));
rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
&vcpu->arch.sie_block->gpsw, sizeof(psw_t));
break;
case KVM_S390_INT_SERVICE:
VCPU_EVENT(vcpu, 4, "interrupt: sclp parm:%x", VCPU_EVENT(vcpu, 4, "interrupt: sclp parm:%x",
inti->ext.ext_params); inti->ext.ext_params);
vcpu->stat.deliver_service_signal++; vcpu->stat.deliver_service_signal++;
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);
rc = put_guest_lc(vcpu, 0x2401, (u16 *)__LC_EXT_INT_CODE);
rc = put_guest_lc(vcpu, EXT_IRQ_SERVICE_SIG, (u16 *)__LC_EXT_INT_CODE);
rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
&vcpu->arch.sie_block->gpsw, &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
sizeof(psw_t));
rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
&vcpu->arch.sie_block->gpsw, sizeof(psw_t)); &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
rc |= put_guest_lc(vcpu, inti->ext.ext_params, rc |= put_guest_lc(vcpu, inti->ext.ext_params,
(u32 *)__LC_EXT_PARAMS); (u32 *)__LC_EXT_PARAMS);
break; return rc;
case KVM_S390_INT_PFAULT_INIT: }
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, 0,
inti->ext.ext_params2); static int __must_check __deliver_pfault_done(struct kvm_vcpu *vcpu,
rc = put_guest_lc(vcpu, EXT_IRQ_CP_SERVICE, struct kvm_s390_interrupt_info *inti)
(u16 *) __LC_EXT_INT_CODE); {
rc |= put_guest_lc(vcpu, PFAULT_INIT, (u16 *) __LC_EXT_CPU_ADDR); int rc;
rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
&vcpu->arch.sie_block->gpsw, sizeof(psw_t)); trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id,
rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, KVM_S390_INT_PFAULT_DONE, 0,
&vcpu->arch.sie_block->gpsw, sizeof(psw_t));
rc |= put_guest_lc(vcpu, inti->ext.ext_params2,
(u64 *) __LC_EXT_PARAMS2);
break;
case KVM_S390_INT_PFAULT_DONE:
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, 0,
inti->ext.ext_params2); inti->ext.ext_params2);
rc = put_guest_lc(vcpu, 0x2603, (u16 *)__LC_EXT_INT_CODE);
rc = put_guest_lc(vcpu, EXT_IRQ_CP_SERVICE, (u16 *)__LC_EXT_INT_CODE);
rc |= put_guest_lc(vcpu, PFAULT_DONE, (u16 *)__LC_EXT_CPU_ADDR); rc |= put_guest_lc(vcpu, PFAULT_DONE, (u16 *)__LC_EXT_CPU_ADDR);
rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
&vcpu->arch.sie_block->gpsw, &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
sizeof(psw_t));
rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
&vcpu->arch.sie_block->gpsw, sizeof(psw_t)); &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
rc |= put_guest_lc(vcpu, inti->ext.ext_params2, rc |= put_guest_lc(vcpu, inti->ext.ext_params2,
(u64 *)__LC_EXT_PARAMS2); (u64 *)__LC_EXT_PARAMS2);
break; return rc;
case KVM_S390_INT_VIRTIO: }
static int __must_check __deliver_virtio(struct kvm_vcpu *vcpu,
struct kvm_s390_interrupt_info *inti)
{
int rc;
VCPU_EVENT(vcpu, 4, "interrupt: virtio parm:%x,parm64:%llx", VCPU_EVENT(vcpu, 4, "interrupt: virtio parm:%x,parm64:%llx",
inti->ext.ext_params, inti->ext.ext_params2); inti->ext.ext_params, inti->ext.ext_params2);
vcpu->stat.deliver_virtio_interrupt++; vcpu->stat.deliver_virtio_interrupt++;
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
inti->ext.ext_params, inti->ext.ext_params,
inti->ext.ext_params2); inti->ext.ext_params2);
rc = put_guest_lc(vcpu, 0x2603, (u16 *)__LC_EXT_INT_CODE);
rc = put_guest_lc(vcpu, EXT_IRQ_CP_SERVICE, (u16 *)__LC_EXT_INT_CODE);
rc |= put_guest_lc(vcpu, VIRTIO_PARAM, (u16 *)__LC_EXT_CPU_ADDR); rc |= put_guest_lc(vcpu, VIRTIO_PARAM, (u16 *)__LC_EXT_CPU_ADDR);
rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
&vcpu->arch.sie_block->gpsw, &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
sizeof(psw_t));
rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
&vcpu->arch.sie_block->gpsw, sizeof(psw_t)); &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
rc |= put_guest_lc(vcpu, inti->ext.ext_params, rc |= put_guest_lc(vcpu, inti->ext.ext_params,
(u32 *)__LC_EXT_PARAMS); (u32 *)__LC_EXT_PARAMS);
rc |= put_guest_lc(vcpu, inti->ext.ext_params2, rc |= put_guest_lc(vcpu, inti->ext.ext_params2,
(u64 *)__LC_EXT_PARAMS2); (u64 *)__LC_EXT_PARAMS2);
break; return rc;
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,
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);
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);
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,
0, 0);
rc = write_guest_lc(vcpu,
offsetof(struct _lowcore, restart_old_psw),
&vcpu->arch.sie_block->gpsw, sizeof(psw_t));
rc |= read_guest_lc(vcpu, offsetof(struct _lowcore, restart_psw),
&vcpu->arch.sie_block->gpsw,
sizeof(psw_t));
break;
case KVM_S390_PROGRAM_INT:
VCPU_EVENT(vcpu, 4, "interrupt: pgm check code:%x, ilc:%x",
inti->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 = __deliver_prog_irq(vcpu, &inti->pgm);
break;
case KVM_S390_MCHK: static int __must_check __deliver_io(struct kvm_vcpu *vcpu,
VCPU_EVENT(vcpu, 4, "interrupt: machine check mcic=%llx", struct kvm_s390_interrupt_info *inti)
inti->mchk.mcic); {
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, int rc;
inti->mchk.cr14,
inti->mchk.mcic);
rc = kvm_s390_vcpu_store_status(vcpu,
KVM_S390_STORE_STATUS_PREFIXED);
rc |= put_guest_lc(vcpu, inti->mchk.mcic, (u64 *)__LC_MCCK_CODE);
rc |= write_guest_lc(vcpu, __LC_MCK_OLD_PSW,
&vcpu->arch.sie_block->gpsw,
sizeof(psw_t));
rc |= read_guest_lc(vcpu, __LC_MCK_NEW_PSW,
&vcpu->arch.sie_block->gpsw, sizeof(psw_t));
break;
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); VCPU_EVENT(vcpu, 4, "interrupt: I/O %llx", inti->type);
vcpu->stat.deliver_io_int++; vcpu->stat.deliver_io_int++;
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
param0, param1); ((__u32)inti->io.subchannel_id << 16) |
inti->io.subchannel_nr,
((__u64)inti->io.io_int_parm << 32) |
inti->io.io_int_word);
rc = put_guest_lc(vcpu, inti->io.subchannel_id, rc = put_guest_lc(vcpu, inti->io.subchannel_id,
(u16 *)__LC_SUBCHANNEL_ID); (u16 *)__LC_SUBCHANNEL_ID);
rc |= put_guest_lc(vcpu, inti->io.subchannel_nr, rc |= put_guest_lc(vcpu, inti->io.subchannel_nr,
...@@ -495,30 +566,64 @@ static int __must_check __do_deliver_interrupt(struct kvm_vcpu *vcpu, ...@@ -495,30 +566,64 @@ static int __must_check __do_deliver_interrupt(struct kvm_vcpu *vcpu,
rc |= put_guest_lc(vcpu, inti->io.io_int_word, rc |= put_guest_lc(vcpu, inti->io.io_int_word,
(u32 *)__LC_IO_INT_WORD); (u32 *)__LC_IO_INT_WORD);
rc |= write_guest_lc(vcpu, __LC_IO_OLD_PSW, rc |= write_guest_lc(vcpu, __LC_IO_OLD_PSW,
&vcpu->arch.sie_block->gpsw, &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
sizeof(psw_t));
rc |= read_guest_lc(vcpu, __LC_IO_NEW_PSW, rc |= read_guest_lc(vcpu, __LC_IO_NEW_PSW,
&vcpu->arch.sie_block->gpsw, &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
sizeof(psw_t));
break;
}
default:
BUG();
}
return rc; return rc;
} }
static int __must_check deliver_ckc_interrupt(struct kvm_vcpu *vcpu) static int __must_check __do_deliver_interrupt(struct kvm_vcpu *vcpu,
struct kvm_s390_interrupt_info *inti)
{ {
int rc; int rc;
rc = put_guest_lc(vcpu, 0x1004, (u16 __user *)__LC_EXT_INT_CODE); switch (inti->type) {
rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, case KVM_S390_INT_EMERGENCY:
&vcpu->arch.sie_block->gpsw, sizeof(psw_t)); rc = __deliver_emergency_signal(vcpu, inti);
rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, break;
&vcpu->arch.sie_block->gpsw, case KVM_S390_INT_EXTERNAL_CALL:
sizeof(psw_t)); rc = __deliver_external_call(vcpu, inti);
break;
case KVM_S390_INT_CLOCK_COMP:
rc = __deliver_ckc(vcpu);
break;
case KVM_S390_INT_CPU_TIMER:
rc = __deliver_cpu_timer(vcpu);
break;
case KVM_S390_INT_SERVICE:
rc = __deliver_service(vcpu, inti);
break;
case KVM_S390_INT_PFAULT_INIT:
rc = __deliver_pfault_init(vcpu, inti);
break;
case KVM_S390_INT_PFAULT_DONE:
rc = __deliver_pfault_done(vcpu, inti);
break;
case KVM_S390_INT_VIRTIO:
rc = __deliver_virtio(vcpu, inti);
break;
case KVM_S390_SIGP_STOP:
rc = __deliver_stop(vcpu);
break;
case KVM_S390_SIGP_SET_PREFIX:
rc = __deliver_set_prefix(vcpu, inti);
break;
case KVM_S390_RESTART:
rc = __deliver_restart(vcpu);
break;
case KVM_S390_PROGRAM_INT:
rc = __deliver_prog(vcpu, inti);
break;
case KVM_S390_MCHK:
rc = __deliver_machine_check(vcpu, inti);
break;
case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
rc = __deliver_io(vcpu, inti);
break;
default:
BUG();
}
return rc; return rc;
} }
...@@ -691,7 +796,7 @@ int __must_check kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu) ...@@ -691,7 +796,7 @@ int __must_check kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
} }
if (!rc && kvm_cpu_has_pending_timer(vcpu)) if (!rc && kvm_cpu_has_pending_timer(vcpu))
rc = deliver_ckc_interrupt(vcpu); rc = __deliver_ckc(vcpu);
if (!rc && atomic_read(&fi->active)) { if (!rc && atomic_read(&fi->active)) {
do { do {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment