diff options
author | David Hildenbrand <david@redhat.com> | 2018-01-29 13:56:10 +0100 |
---|---|---|
committer | Cornelia Huck <cohuck@redhat.com> | 2018-02-09 09:37:13 +0100 |
commit | e6505d5395332d357ef663372f453381690cd2e0 (patch) | |
tree | 38d448f0482e3b9d17264789788fc6f5760bfd10 | |
parent | 520db63f3a50c6a5564dd2ce21912cfe011900a9 (diff) |
s390x/flic: factor out injection of floating interrupts
Let the flic device handle it internally. This will allow us to later
on store floating interrupts in the flic for the TCG case.
This now also simplifies kvm.c. All that's left is the fallback
interface for floating interrupts, which is now triggered directly via
the flic in case anything goes wrong.
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20180129125623.21729-6-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
-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 */ |