diff options
-rw-r--r-- | hw/intc/s390_flic.c | 31 | ||||
-rw-r--r-- | hw/intc/s390_flic_kvm.c | 63 | ||||
-rw-r--r-- | include/hw/s390x/s390_flic.h | 5 | ||||
-rw-r--r-- | target/s390x/cpu.h | 7 | ||||
-rw-r--r-- | target/s390x/interrupt.c | 42 | ||||
-rw-r--r-- | target/s390x/kvm-stub.c | 13 | ||||
-rw-r--r-- | target/s390x/kvm.c | 68 | ||||
-rw-r--r-- | target/s390x/kvm_s390x.h | 10 |
8 files changed, 123 insertions, 116 deletions
diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c index ba1aa40eba..bdc8ec7607 100644 --- a/hw/intc/s390_flic.c +++ b/hw/intc/s390_flic.c @@ -127,6 +127,34 @@ static int qemu_s390_inject_airq(S390FLICState *fs, uint8_t type, return 0; } +static void qemu_s390_inject_service(S390FLICState *fs, uint32_t parm) +{ + + S390CPU *dummy_cpu = s390_cpu_addr2state(0); + + /* FIXME: don't inject into dummy CPU */ + cpu_inject_service(dummy_cpu, parm); +} + +static void qemu_s390_inject_io(S390FLICState *fs, uint16_t subchannel_id, + uint16_t subchannel_nr, uint32_t io_int_parm, + uint32_t io_int_word) +{ + S390CPU *dummy_cpu = s390_cpu_addr2state(0); + + /* FIXME: don't inject into dummy CPU */ + cpu_inject_io(dummy_cpu, subchannel_id, subchannel_nr, io_int_parm, + io_int_word); +} + +static void qemu_s390_inject_crw_mchk(S390FLICState *fs) +{ + S390CPU *dummy_cpu = s390_cpu_addr2state(0); + + /* FIXME: don't inject into dummy CPU */ + cpu_inject_crw_mchk(dummy_cpu); +} + static void qemu_s390_flic_reset(DeviceState *dev) { QEMUS390FLICState *flic = QEMU_S390_FLIC(dev); @@ -168,6 +196,9 @@ static void qemu_s390_flic_class_init(ObjectClass *oc, void *data) fsc->clear_io_irq = qemu_s390_clear_io_flic; fsc->modify_ais_mode = qemu_s390_modify_ais_mode; fsc->inject_airq = qemu_s390_inject_airq; + fsc->inject_service = qemu_s390_inject_service; + fsc->inject_io = qemu_s390_inject_io; + fsc->inject_crw_mchk = qemu_s390_inject_crw_mchk; } static Property s390_flic_common_properties[] = { diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c index 0cb5feab0c..d277ffdd2e 100644 --- a/hw/intc/s390_flic_kvm.c +++ b/hw/intc/s390_flic_kvm.c @@ -111,14 +111,64 @@ static int flic_enqueue_irqs(void *buf, uint64_t len, return rc ? -errno : 0; } -int kvm_s390_inject_flic(struct kvm_s390_irq *irq) +static void kvm_s390_inject_flic(S390FLICState *fs, struct kvm_s390_irq *irq) { - static KVMS390FLICState *flic; + static bool use_flic = true; + int r; + + if (use_flic) { + r = flic_enqueue_irqs(irq, sizeof(*irq), KVM_S390_FLIC(fs)); + if (r == -ENOSYS) { + use_flic = false; + } + if (!r) { + return; + } + } + /* fallback to legacy KVM IOCTL in case FLIC fails */ + kvm_s390_floating_interrupt_legacy(irq); +} + +static void kvm_s390_inject_service(S390FLICState *fs, uint32_t parm) +{ + struct kvm_s390_irq irq = { + .type = KVM_S390_INT_SERVICE, + .u.ext.ext_params = parm, + }; + + kvm_s390_inject_flic(fs, &irq); +} - if (unlikely(!flic)) { - flic = KVM_S390_FLIC(s390_get_flic()); +static void kvm_s390_inject_io(S390FLICState *fs, uint16_t subchannel_id, + uint16_t subchannel_nr, uint32_t io_int_parm, + uint32_t io_int_word) +{ + struct kvm_s390_irq irq = { + .u.io.subchannel_id = subchannel_id, + .u.io.subchannel_nr = subchannel_nr, + .u.io.io_int_parm = io_int_parm, + .u.io.io_int_word = io_int_word, + }; + + if (io_int_word & IO_INT_WORD_AI) { + irq.type = KVM_S390_INT_IO(1, 0, 0, 0); + } else { + irq.type = KVM_S390_INT_IO(0, (subchannel_id & 0xff00) >> 8, + (subchannel_id & 0x0006), + subchannel_nr); } - return flic_enqueue_irqs(irq, sizeof(*irq), flic); + kvm_s390_inject_flic(fs, &irq); +} + +static void kvm_s390_inject_crw_mchk(S390FLICState *fs) +{ + struct kvm_s390_irq irq = { + .type = KVM_S390_MCHK, + .u.mchk.cr14 = CR14_CHANNEL_REPORT_SC, + .u.mchk.mcic = s390_build_validity_mcic() | MCIC_SC_CP, + }; + + kvm_s390_inject_flic(fs, &irq); } static int kvm_s390_clear_io_flic(S390FLICState *fs, uint16_t subchannel_id, @@ -602,6 +652,9 @@ static void kvm_s390_flic_class_init(ObjectClass *oc, void *data) fsc->clear_io_irq = kvm_s390_clear_io_flic; fsc->modify_ais_mode = kvm_s390_modify_ais_mode; fsc->inject_airq = kvm_s390_inject_airq; + fsc->inject_service = kvm_s390_inject_service; + fsc->inject_io = kvm_s390_inject_io; + fsc->inject_crw_mchk = kvm_s390_inject_crw_mchk; } static const TypeInfo kvm_s390_flic_info = { diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h index 5b00e936fa..d0538134b7 100644 --- a/include/hw/s390x/s390_flic.h +++ b/include/hw/s390x/s390_flic.h @@ -66,6 +66,11 @@ typedef struct S390FLICStateClass { int (*modify_ais_mode)(S390FLICState *fs, uint8_t isc, uint16_t mode); int (*inject_airq)(S390FLICState *fs, uint8_t type, uint8_t isc, uint8_t flags); + void (*inject_service)(S390FLICState *fs, uint32_t parm); + void (*inject_io)(S390FLICState *fs, uint16_t subchannel_id, + uint16_t subchannel_nr, uint32_t io_int_parm, + uint32_t io_int_word); + void (*inject_crw_mchk)(S390FLICState *fs); } S390FLICStateClass; #define TYPE_KVM_S390_FLIC "s390-flic-kvm" diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h index f32a5ad6c9..9d3aa05a47 100644 --- a/target/s390x/cpu.h +++ b/target/s390x/cpu.h @@ -741,7 +741,12 @@ void s390_program_interrupt(CPUS390XState *env, uint32_t code, int ilen, uintptr_t ra); /* service interrupts are floating therefore we must not pass an cpustate */ void s390_sclp_extint(uint32_t parm); - +/* FIXME: remove once we have proper floating interrupts in TCG */ +void cpu_inject_service(S390CPU *cpu, uint32_t param); +void cpu_inject_crw_mchk(S390CPU *cpu); +void cpu_inject_io(S390CPU *cpu, uint16_t subchannel_id, + uint16_t subchannel_number, uint32_t io_int_parm, + uint32_t io_int_word); /* mmu_helper.c */ int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, uint8_t ar, void *hostbuf, diff --git a/target/s390x/interrupt.c b/target/s390x/interrupt.c index 380222b394..8229572f7d 100644 --- a/target/s390x/interrupt.c +++ b/target/s390x/interrupt.c @@ -15,6 +15,9 @@ #include "exec/exec-all.h" #include "sysemu/kvm.h" #include "hw/s390x/ioinst.h" +#if !defined(CONFIG_USER_ONLY) +#include "hw/s390x/s390_flic.h" +#endif /* Ensure to exit the TB after this call! */ void trigger_pgm_exception(CPUS390XState *env, uint32_t code, uint32_t ilen) @@ -55,7 +58,7 @@ void s390_program_interrupt(CPUS390XState *env, uint32_t code, int ilen, } #if !defined(CONFIG_USER_ONLY) -static void cpu_inject_service(S390CPU *cpu, uint32_t param) +void cpu_inject_service(S390CPU *cpu, uint32_t param) { CPUS390XState *env = &cpu->env; @@ -134,9 +137,9 @@ void cpu_inject_stop(S390CPU *cpu) cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD); } -static void cpu_inject_io(S390CPU *cpu, uint16_t subchannel_id, - uint16_t subchannel_number, - uint32_t io_int_parm, uint32_t io_int_word) +void cpu_inject_io(S390CPU *cpu, uint16_t subchannel_id, + uint16_t subchannel_number, uint32_t io_int_parm, + uint32_t io_int_word) { CPUS390XState *env = &cpu->env; int isc = IO_INT_WORD_ISC(io_int_word); @@ -158,7 +161,7 @@ static void cpu_inject_io(S390CPU *cpu, uint16_t subchannel_id, cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD); } -static void cpu_inject_crw_mchk(S390CPU *cpu) +void cpu_inject_crw_mchk(S390CPU *cpu) { CPUS390XState *env = &cpu->env; @@ -173,38 +176,27 @@ static void cpu_inject_crw_mchk(S390CPU *cpu) */ void s390_sclp_extint(uint32_t parm) { - if (kvm_enabled()) { - kvm_s390_service_interrupt(parm); - } else { - S390CPU *dummy_cpu = s390_cpu_addr2state(0); + S390FLICState *fs = s390_get_flic(); + S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs); - cpu_inject_service(dummy_cpu, parm); - } + fsc->inject_service(fs, parm); } void s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr, uint32_t io_int_parm, uint32_t io_int_word) { - if (kvm_enabled()) { - kvm_s390_io_interrupt(subchannel_id, subchannel_nr, io_int_parm, - io_int_word); - } else { - S390CPU *dummy_cpu = s390_cpu_addr2state(0); + S390FLICState *fs = s390_get_flic(); + S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs); - cpu_inject_io(dummy_cpu, subchannel_id, subchannel_nr, io_int_parm, - io_int_word); - } + fsc->inject_io(fs, subchannel_id, subchannel_nr, io_int_parm, io_int_word); } void s390_crw_mchk(void) { - if (kvm_enabled()) { - kvm_s390_crw_mchk(); - } else { - S390CPU *dummy_cpu = s390_cpu_addr2state(0); + S390FLICState *fs = s390_get_flic(); + S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs); - cpu_inject_crw_mchk(dummy_cpu); - } + fsc->inject_crw_mchk(fs); } bool s390_cpu_has_mcck_int(S390CPU *cpu) diff --git a/target/s390x/kvm-stub.c b/target/s390x/kvm-stub.c index 6bae3e99d3..8cdcf83845 100644 --- a/target/s390x/kvm-stub.c +++ b/target/s390x/kvm-stub.c @@ -12,10 +12,6 @@ #include "cpu.h" #include "kvm_s390x.h" -void kvm_s390_service_interrupt(uint32_t parm) -{ -} - void kvm_s390_access_exception(S390CPU *cpu, uint16_t code, uint64_t te_code) { } @@ -30,15 +26,6 @@ void kvm_s390_program_interrupt(S390CPU *cpu, uint16_t code) { } -void kvm_s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr, - uint32_t io_int_parm, uint32_t io_int_word) -{ -} - -void kvm_s390_crw_mchk(void) -{ -} - int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state) { return -ENOSYS; diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c index 8736001156..db5fe084ff 100644 --- a/target/s390x/kvm.c +++ b/target/s390x/kvm.c @@ -1034,7 +1034,7 @@ void kvm_s390_vcpu_interrupt(S390CPU *cpu, struct kvm_s390_irq *irq) inject_vcpu_irq_legacy(cs, irq); } -static void __kvm_s390_floating_interrupt(struct kvm_s390_irq *irq) +void kvm_s390_floating_interrupt_legacy(struct kvm_s390_irq *irq) { struct kvm_s390_interrupt kvmint = {}; int r; @@ -1052,33 +1052,6 @@ static void __kvm_s390_floating_interrupt(struct kvm_s390_irq *irq) } } -void kvm_s390_floating_interrupt(struct kvm_s390_irq *irq) -{ - static bool use_flic = true; - int r; - - if (use_flic) { - r = kvm_s390_inject_flic(irq); - if (r == -ENOSYS) { - use_flic = false; - } - if (!r) { - return; - } - } - __kvm_s390_floating_interrupt(irq); -} - -void kvm_s390_service_interrupt(uint32_t parm) -{ - struct kvm_s390_irq irq = { - .type = KVM_S390_INT_SERVICE, - .u.ext.ext_params = parm, - }; - - kvm_s390_floating_interrupt(&irq); -} - void kvm_s390_program_interrupt(S390CPU *cpu, uint16_t code) { struct kvm_s390_irq irq = { @@ -1690,10 +1663,10 @@ static int handle_tsch(S390CPU *cpu) * If an I/O interrupt had been dequeued, we have to reinject it. */ if (run->s390_tsch.dequeued) { - kvm_s390_io_interrupt(run->s390_tsch.subchannel_id, - run->s390_tsch.subchannel_nr, - run->s390_tsch.io_int_parm, - run->s390_tsch.io_int_word); + s390_io_interrupt(run->s390_tsch.subchannel_id, + run->s390_tsch.subchannel_nr, + run->s390_tsch.io_int_parm, + run->s390_tsch.io_int_word); } ret = 0; } @@ -1840,37 +1813,6 @@ bool kvm_arch_stop_on_emulation_error(CPUState *cpu) return true; } -void kvm_s390_io_interrupt(uint16_t subchannel_id, - uint16_t subchannel_nr, uint32_t io_int_parm, - uint32_t io_int_word) -{ - struct kvm_s390_irq irq = { - .u.io.subchannel_id = subchannel_id, - .u.io.subchannel_nr = subchannel_nr, - .u.io.io_int_parm = io_int_parm, - .u.io.io_int_word = io_int_word, - }; - - if (io_int_word & IO_INT_WORD_AI) { - irq.type = KVM_S390_INT_IO(1, 0, 0, 0); - } else { - irq.type = KVM_S390_INT_IO(0, (subchannel_id & 0xff00) >> 8, - (subchannel_id & 0x0006), - subchannel_nr); - } - kvm_s390_floating_interrupt(&irq); -} - -void kvm_s390_crw_mchk(void) -{ - struct kvm_s390_irq irq = { - .type = KVM_S390_MCHK, - .u.mchk.cr14 = CR14_CHANNEL_REPORT_SC, - .u.mchk.mcic = s390_build_validity_mcic() | MCIC_SC_CP, - }; - kvm_s390_floating_interrupt(&irq); -} - void kvm_s390_enable_css_support(S390CPU *cpu) { int r; diff --git a/target/s390x/kvm_s390x.h b/target/s390x/kvm_s390x.h index 79b35946f3..7a3b862eea 100644 --- a/target/s390x/kvm_s390x.h +++ b/target/s390x/kvm_s390x.h @@ -12,17 +12,12 @@ struct kvm_s390_irq; -void kvm_s390_floating_interrupt(struct kvm_s390_irq *irq); -void kvm_s390_service_interrupt(uint32_t parm); +void kvm_s390_floating_interrupt_legacy(struct kvm_s390_irq *irq); void kvm_s390_vcpu_interrupt(S390CPU *cpu, struct kvm_s390_irq *irq); void kvm_s390_access_exception(S390CPU *cpu, uint16_t code, uint64_t te_code); int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, uint8_t ar, void *hostbuf, int len, bool is_write); void kvm_s390_program_interrupt(S390CPU *cpu, uint16_t code); -void kvm_s390_io_interrupt(uint16_t subchannel_id, - uint16_t subchannel_nr, uint32_t io_int_parm, - uint32_t io_int_word); -void kvm_s390_crw_mchk(void); int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state); void kvm_s390_vcpu_interrupt_pre_save(S390CPU *cpu); int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu); @@ -44,7 +39,4 @@ void kvm_s390_crypto_reset(void); void kvm_s390_restart_interrupt(S390CPU *cpu); void kvm_s390_stop_interrupt(S390CPU *cpu); -/* implemented outside of target/s390x/ */ -int kvm_s390_inject_flic(struct kvm_s390_irq *irq); - #endif /* KVM_S390X_H */ |