KVM: s390: Add clock comparator and CPU timer IRQ injection
Add an interface to inject clock comparator and CPU timer interrupts into the guest. This is needed for handling the external interrupt interception. Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com> Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com> Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
This commit is contained in:
parent
fcc9aec3de
commit
e029ae5b78
|
@ -2211,6 +2211,8 @@ KVM_S390_SIGP_STOP (vcpu) - sigp restart
|
||||||
KVM_S390_PROGRAM_INT (vcpu) - program check; code in parm
|
KVM_S390_PROGRAM_INT (vcpu) - program check; code in parm
|
||||||
KVM_S390_SIGP_SET_PREFIX (vcpu) - sigp set prefix; prefix address in parm
|
KVM_S390_SIGP_SET_PREFIX (vcpu) - sigp set prefix; prefix address in parm
|
||||||
KVM_S390_RESTART (vcpu) - restart
|
KVM_S390_RESTART (vcpu) - restart
|
||||||
|
KVM_S390_INT_CLOCK_COMP (vcpu) - clock comparator interrupt
|
||||||
|
KVM_S390_INT_CPU_TIMER (vcpu) - CPU timer interrupt
|
||||||
KVM_S390_INT_VIRTIO (vm) - virtio external interrupt; external interrupt
|
KVM_S390_INT_VIRTIO (vm) - virtio external interrupt; external interrupt
|
||||||
parameters in parm and parm64
|
parameters in parm and parm64
|
||||||
KVM_S390_INT_SERVICE (vm) - sclp external interrupt; sclp parameter in parm
|
KVM_S390_INT_SERVICE (vm) - sclp external interrupt; sclp parameter in parm
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
#define IOINT_CSSID_MASK 0x03fc0000
|
#define IOINT_CSSID_MASK 0x03fc0000
|
||||||
#define IOINT_AI_MASK 0x04000000
|
#define IOINT_AI_MASK 0x04000000
|
||||||
|
|
||||||
|
static void 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);
|
||||||
|
@ -89,6 +91,14 @@ static int __interrupt_is_deliverable(struct kvm_vcpu *vcpu,
|
||||||
if (vcpu->arch.sie_block->gcr[0] & 0x4000ul)
|
if (vcpu->arch.sie_block->gcr[0] & 0x4000ul)
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
|
case KVM_S390_INT_CLOCK_COMP:
|
||||||
|
return ckc_interrupts_enabled(vcpu);
|
||||||
|
case KVM_S390_INT_CPU_TIMER:
|
||||||
|
if (psw_extint_disabled(vcpu))
|
||||||
|
return 0;
|
||||||
|
if (vcpu->arch.sie_block->gcr[0] & 0x400ul)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
case KVM_S390_INT_SERVICE:
|
case KVM_S390_INT_SERVICE:
|
||||||
case KVM_S390_INT_PFAULT_INIT:
|
case KVM_S390_INT_PFAULT_INIT:
|
||||||
case KVM_S390_INT_PFAULT_DONE:
|
case KVM_S390_INT_PFAULT_DONE:
|
||||||
|
@ -166,6 +176,8 @@ static void __set_intercept_indicator(struct kvm_vcpu *vcpu,
|
||||||
case KVM_S390_INT_PFAULT_INIT:
|
case KVM_S390_INT_PFAULT_INIT:
|
||||||
case KVM_S390_INT_PFAULT_DONE:
|
case KVM_S390_INT_PFAULT_DONE:
|
||||||
case KVM_S390_INT_VIRTIO:
|
case KVM_S390_INT_VIRTIO:
|
||||||
|
case KVM_S390_INT_CLOCK_COMP:
|
||||||
|
case KVM_S390_INT_CPU_TIMER:
|
||||||
if (psw_extint_disabled(vcpu))
|
if (psw_extint_disabled(vcpu))
|
||||||
__set_cpuflag(vcpu, CPUSTAT_EXT_INT);
|
__set_cpuflag(vcpu, CPUSTAT_EXT_INT);
|
||||||
else
|
else
|
||||||
|
@ -326,6 +338,24 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
|
||||||
&vcpu->arch.sie_block->gpsw,
|
&vcpu->arch.sie_block->gpsw,
|
||||||
sizeof(psw_t));
|
sizeof(psw_t));
|
||||||
break;
|
break;
|
||||||
|
case KVM_S390_INT_CLOCK_COMP:
|
||||||
|
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
|
||||||
|
inti->ext.ext_params, 0);
|
||||||
|
deliver_ckc_interrupt(vcpu);
|
||||||
|
break;
|
||||||
|
case KVM_S390_INT_CPU_TIMER:
|
||||||
|
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
|
||||||
|
inti->ext.ext_params, 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));
|
||||||
|
rc |= put_guest_lc(vcpu, inti->ext.ext_params,
|
||||||
|
(u32 *)__LC_EXT_PARAMS);
|
||||||
|
break;
|
||||||
case KVM_S390_INT_SERVICE:
|
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);
|
||||||
|
@ -984,6 +1014,8 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
|
||||||
break;
|
break;
|
||||||
case KVM_S390_SIGP_STOP:
|
case KVM_S390_SIGP_STOP:
|
||||||
case KVM_S390_RESTART:
|
case KVM_S390_RESTART:
|
||||||
|
case KVM_S390_INT_CLOCK_COMP:
|
||||||
|
case KVM_S390_INT_CPU_TIMER:
|
||||||
VCPU_EVENT(vcpu, 3, "inject: type %x", s390int->type);
|
VCPU_EVENT(vcpu, 3, "inject: type %x", s390int->type);
|
||||||
inti->type = s390int->type;
|
inti->type = s390int->type;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -416,6 +416,8 @@ struct kvm_s390_psw {
|
||||||
#define KVM_S390_INT_PFAULT_INIT 0xfffe0004u
|
#define KVM_S390_INT_PFAULT_INIT 0xfffe0004u
|
||||||
#define KVM_S390_INT_PFAULT_DONE 0xfffe0005u
|
#define KVM_S390_INT_PFAULT_DONE 0xfffe0005u
|
||||||
#define KVM_S390_MCHK 0xfffe1000u
|
#define KVM_S390_MCHK 0xfffe1000u
|
||||||
|
#define KVM_S390_INT_CLOCK_COMP 0xffff1004u
|
||||||
|
#define KVM_S390_INT_CPU_TIMER 0xffff1005u
|
||||||
#define KVM_S390_INT_VIRTIO 0xffff2603u
|
#define KVM_S390_INT_VIRTIO 0xffff2603u
|
||||||
#define KVM_S390_INT_SERVICE 0xffff2401u
|
#define KVM_S390_INT_SERVICE 0xffff2401u
|
||||||
#define KVM_S390_INT_EMERGENCY 0xffff1201u
|
#define KVM_S390_INT_EMERGENCY 0xffff1201u
|
||||||
|
|
Loading…
Reference in New Issue