From nobody Tue Oct 28 01:48:52 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 151621151974456.03239428431323; Wed, 17 Jan 2018 09:51:59 -0800 (PST) Received: from localhost ([::1]:51239 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ebrsU-0000xU-Js for importer@patchew.org; Wed, 17 Jan 2018 12:51:58 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46875) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ebriZ-0000F3-VX for qemu-devel@nongnu.org; Wed, 17 Jan 2018 12:41:46 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ebriW-00084h-O4 for qemu-devel@nongnu.org; Wed, 17 Jan 2018 12:41:44 -0500 Received: from mx1.redhat.com ([209.132.183.28]:35096) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ebriW-00083o-FB; Wed, 17 Jan 2018 12:41:40 -0500 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 398A74D2D1; Wed, 17 Jan 2018 17:41:39 +0000 (UTC) Received: from t460s.redhat.com (ovpn-117-185.ams2.redhat.com [10.36.117.185]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6FAEC62462; Wed, 17 Jan 2018 17:41:28 +0000 (UTC) From: David Hildenbrand To: qemu-s390x@nongnu.org, qemu-devel@nongnu.org Date: Wed, 17 Jan 2018 18:40:37 +0100 Message-Id: <20180117174047.6382-9-david@redhat.com> In-Reply-To: <20180117174047.6382-1-david@redhat.com> References: <20180117174047.6382-1-david@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Wed, 17 Jan 2018 17:41:39 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v2 08/18] s390x/flic: make floating interrupts on TCG actually floating X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Thomas Huth , David Hildenbrand , Cornelia Huck , Alexander Graf , Christian Borntraeger , Richard Henderson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Move floating interrupt handling into the flic. Floating interrupts will now be considered by all CPUs, not just CPU #0. While at it, convert I/O interrupts to use a list and make sure we properly consider I/O sub-classes in s390_cpu_has_io_int(). Signed-off-by: David Hildenbrand --- hw/intc/s390_flic.c | 144 +++++++++++++++++++++++++++++++++++++++= +--- include/hw/s390x/s390_flic.h | 41 ++++++++++++ target/s390x/cpu.c | 8 --- target/s390x/cpu.h | 22 ------- target/s390x/excp_helper.c | 97 ++++++++++------------------- target/s390x/interrupt.c | 52 ++-------------- 6 files changed, 212 insertions(+), 152 deletions(-) diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c index d6ed1d7380..928bdc3037 100644 --- a/hw/intc/s390_flic.c +++ b/hw/intc/s390_flic.c @@ -128,40 +128,153 @@ static int qemu_s390_inject_airq(S390FLICState *fs, = uint8_t type, return 0; } =20 +static void qemu_s390_flic_notify(uint32_t type) +{ + CPUState *cs; + + /* + * We have to make all CPUs see CPU_INTERRUPT_HARD, so they might + * consider it. TODO: don't kick/wakeup all VCPUs but try to be + * smarter (using the interrupt type). + */ + CPU_FOREACH(cs) { + cpu_interrupt(cs, CPU_INTERRUPT_HARD); + } +} + +uint32_t qemu_s390_flic_dequeue_service(QEMUS390FLICState *flic) +{ + uint32_t tmp; + + g_assert(qemu_mutex_iothread_locked()); + g_assert(flic->pending & FLIC_PENDING_SERVICE); + tmp =3D flic->service_param; + flic->service_param =3D 0; + flic->pending &=3D ~FLIC_PENDING_SERVICE; + + return tmp; +} + +/* caller has to free the returned object */ +QEMUS390FlicIO *qemu_s390_flic_dequeue_io(QEMUS390FLICState *flic, uint64_= t cr6) +{ + QEMUS390FlicIO *io; + uint8_t isc; + + g_assert(qemu_mutex_iothread_locked()); + if (!(flic->pending & CR6_TO_PENDING_IO(cr6))) { + return NULL; + } + + for (isc =3D 0; isc < 8; isc++) { + if (QLIST_EMPTY(&flic->io[isc]) || !(cr6 & ISC_TO_ISC_BITS(isc))) { + continue; + } + io =3D QLIST_FIRST(&flic->io[isc]); + QLIST_REMOVE(io, next); + + /* update our indicator bit */ + if (QLIST_EMPTY(&flic->io[isc])) { + flic->pending &=3D ~ISC_TO_PENDING_IO(isc); + } + return io; + } + + return NULL; +} + +void qemu_s390_flic_dequeue_crw_mchk(QEMUS390FLICState *flic) +{ + g_assert(qemu_mutex_iothread_locked()); + g_assert(flic->pending & FLIC_PENDING_MCHK_CR); + flic->pending &=3D ~FLIC_PENDING_MCHK_CR; +} + static void qemu_s390_inject_service(S390FLICState *fs, uint32_t parm) { + QEMUS390FLICState *flic =3D QEMU_S390_FLIC(fs); =20 - S390CPU *dummy_cpu =3D s390_cpu_addr2state(0); + g_assert(qemu_mutex_iothread_locked()); + /* multiplexing is good enough for sclp - kvm does it internally as we= ll */ + flic->service_param |=3D parm; + flic->pending |=3D FLIC_PENDING_SERVICE; =20 - /* FIXME: don't inject into dummy CPU */ - cpu_inject_service(dummy_cpu, parm); + qemu_s390_flic_notify(FLIC_PENDING_SERVICE); } =20 static void qemu_s390_inject_io(S390FLICState *fs, uint16_t subchannel_id, uint16_t subchannel_nr, uint32_t io_int_pa= rm, uint32_t io_int_word) { - S390CPU *dummy_cpu =3D s390_cpu_addr2state(0); + const uint8_t isc =3D IO_INT_WORD_ISC(io_int_word); + QEMUS390FLICState *flic =3D QEMU_S390_FLIC(fs); + QEMUS390FlicIO *io; =20 - /* FIXME: don't inject into dummy CPU */ - cpu_inject_io(dummy_cpu, subchannel_id, subchannel_nr, io_int_parm, - io_int_word); + g_assert(qemu_mutex_iothread_locked()); + io =3D g_new0(QEMUS390FlicIO, 1); + io->id =3D subchannel_id; + io->nr =3D subchannel_nr; + io->parm =3D io_int_parm; + io->word =3D io_int_word; + + QLIST_INSERT_HEAD(&flic->io[isc], io, next); + flic->pending |=3D ISC_TO_PENDING_IO(isc); + + qemu_s390_flic_notify(ISC_TO_PENDING_IO(isc)); } =20 static void qemu_s390_inject_crw_mchk(S390FLICState *fs) { - S390CPU *dummy_cpu =3D s390_cpu_addr2state(0); + QEMUS390FLICState *flic =3D QEMU_S390_FLIC(fs); + + g_assert(qemu_mutex_iothread_locked()); + flic->pending |=3D FLIC_PENDING_MCHK_CR; + + qemu_s390_flic_notify(FLIC_PENDING_MCHK_CR); +} + +bool qemu_s390_flic_has_service(QEMUS390FLICState *flic) +{ + /* called without lock via cc->has_work, will be validated under lock = */ + return !!(flic->pending & FLIC_PENDING_SERVICE); +} + +bool qemu_s390_flic_has_io(QEMUS390FLICState *flic, uint64_t cr6) +{ + /* called without lock via cc->has_work, will be validated under lock = */ + return !!(flic->pending & CR6_TO_PENDING_IO(cr6)); +} + +bool qemu_s390_flic_has_crw_mchk(QEMUS390FLICState *flic) +{ + /* called without lock via cc->has_work, will be validated under lock = */ + return !!(flic->pending & FLIC_PENDING_MCHK_CR); +} =20 - /* FIXME: don't inject into dummy CPU */ - cpu_inject_crw_mchk(dummy_cpu); +bool qemu_s390_flic_has_any(QEMUS390FLICState *flic) +{ + g_assert(qemu_mutex_iothread_locked()); + return !!flic->pending; } =20 static void qemu_s390_flic_reset(DeviceState *dev) { QEMUS390FLICState *flic =3D QEMU_S390_FLIC(dev); + QEMUS390FlicIO *cur, *next; + int isc; =20 + g_assert(qemu_mutex_iothread_locked()); flic->simm =3D 0; flic->nimm =3D 0; + flic->pending =3D 0; + + /* remove all pending io interrupts */ + for (isc =3D 0; isc < 8; isc++) { + QLIST_FOREACH_SAFE(cur, &flic->io[isc], next, next) { + QLIST_REMOVE(cur, next); + g_free(cur); + } + } } =20 bool ais_needed(void *opaque) @@ -183,6 +296,16 @@ static const VMStateDescription qemu_s390_flic_vmstate= =3D { } }; =20 +static void qemu_s390_flic_instance_init(Object *obj) +{ + QEMUS390FLICState *flic =3D QEMU_S390_FLIC(obj); + int isc; + + for (isc =3D 0; isc < 8; isc++) { + QLIST_INIT(&flic->io[isc]); + } +} + static void qemu_s390_flic_class_init(ObjectClass *oc, void *data) { DeviceClass *dc =3D DEVICE_CLASS(oc); @@ -234,6 +357,7 @@ static const TypeInfo qemu_s390_flic_info =3D { .name =3D TYPE_QEMU_S390_FLIC, .parent =3D TYPE_S390_FLIC_COMMON, .instance_size =3D sizeof(QEMUS390FLICState), + .instance_init =3D qemu_s390_flic_instance_init, .class_init =3D qemu_s390_flic_class_init, }; =20 diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h index d0538134b7..566d153371 100644 --- a/include/hw/s390x/s390_flic.h +++ b/include/hw/s390x/s390_flic.h @@ -16,6 +16,7 @@ #include "hw/sysbus.h" #include "hw/s390x/adapter.h" #include "hw/virtio/virtio.h" +#include "qemu/queue.h" =20 /* * Reserve enough gsis to accommodate all virtio devices. @@ -85,12 +86,52 @@ typedef struct S390FLICStateClass { #define SIC_IRQ_MODE_SINGLE 1 #define AIS_MODE_MASK(isc) (0x80 >> isc) =20 +#define ISC_TO_PENDING_IO(_isc) (0x80 >> (_isc)) +#define CR6_TO_PENDING_IO(_cr6) (((_cr6) >> 24) & 0xff) + +/* organize the ISC bits so that the macros above work */ +#define FLIC_PENDING_IO_ISC7 (1 << 0) +#define FLIC_PENDING_IO_ISC6 (1 << 1) +#define FLIC_PENDING_IO_ISC5 (1 << 2) +#define FLIC_PENDING_IO_ISC4 (1 << 3) +#define FLIC_PENDING_IO_ISC3 (1 << 4) +#define FLIC_PENDING_IO_ISC2 (1 << 5) +#define FLIC_PENDING_IO_ISC1 (1 << 6) +#define FLIC_PENDING_IO_ISC0 (1 << 7) +#define FLIC_PENDING_SERVICE (1 << 8) +#define FLIC_PENDING_MCHK_CR (1 << 9) + +#define FLIC_PENDING_IO (FLIC_PENDING_IO_ISC0 | FLIC_PENDING_IO_ISC1 | \ + FLIC_PENDING_IO_ISC2 | FLIC_PENDING_IO_ISC3 | \ + FLIC_PENDING_IO_ISC4 | FLIC_PENDING_IO_ISC5 | \ + FLIC_PENDING_IO_ISC6 | FLIC_PENDING_IO_ISC7) + +typedef struct QEMUS390FlicIO { + uint16_t id; + uint16_t nr; + uint32_t parm; + uint32_t word; + QLIST_ENTRY(QEMUS390FlicIO) next; +} QEMUS390FlicIO; + typedef struct QEMUS390FLICState { S390FLICState parent_obj; + uint32_t pending; + uint32_t service_param; uint8_t simm; uint8_t nimm; + QLIST_HEAD(, QEMUS390FlicIO) io[8]; } QEMUS390FLICState; =20 +uint32_t qemu_s390_flic_dequeue_service(QEMUS390FLICState *flic); +QEMUS390FlicIO *qemu_s390_flic_dequeue_io(QEMUS390FLICState *flic, + uint64_t cr6); +void qemu_s390_flic_dequeue_crw_mchk(QEMUS390FLICState *flic); +bool qemu_s390_flic_has_service(QEMUS390FLICState *flic); +bool qemu_s390_flic_has_io(QEMUS390FLICState *fs, uint64_t cr6); +bool qemu_s390_flic_has_crw_mchk(QEMUS390FLICState *flic); +bool qemu_s390_flic_has_any(QEMUS390FLICState *flic); + void s390_flic_init(void); =20 S390FLICState *s390_get_flic(void); diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c index bb4fc0f879..1de7cc6c56 100644 --- a/target/s390x/cpu.c +++ b/target/s390x/cpu.c @@ -99,7 +99,6 @@ static void s390_cpu_initial_reset(CPUState *s) { S390CPU *cpu =3D S390_CPU(s); CPUS390XState *env =3D &cpu->env; - int i; =20 s390_cpu_reset(s); /* initial reset does not clear everything! */ @@ -115,9 +114,6 @@ static void s390_cpu_initial_reset(CPUState *s) env->gbea =3D 1; =20 env->pfault_token =3D -1UL; - for (i =3D 0; i < ARRAY_SIZE(env->io_index); i++) { - env->io_index[i] =3D -1; - } =20 /* tininess for underflow is detected before rounding */ set_float_detect_tininess(float_tininess_before_rounding, @@ -135,7 +131,6 @@ static void s390_cpu_full_reset(CPUState *s) S390CPU *cpu =3D S390_CPU(s); S390CPUClass *scc =3D S390_CPU_GET_CLASS(cpu); CPUS390XState *env =3D &cpu->env; - int i; =20 scc->parent_reset(s); cpu->env.sigp_order =3D 0; @@ -151,9 +146,6 @@ static void s390_cpu_full_reset(CPUState *s) env->gbea =3D 1; =20 env->pfault_token =3D -1UL; - for (i =3D 0; i < ARRAY_SIZE(env->io_index); i++) { - env->io_index[i] =3D -1; - } =20 /* tininess for underflow is detected before rounding */ set_float_detect_tininess(float_tininess_before_rounding, diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h index 9df851b1e8..2a37ef5050 100644 --- a/target/s390x/cpu.h +++ b/target/s390x/cpu.h @@ -53,8 +53,6 @@ =20 #define MMU_USER_IDX 0 =20 -#define MAX_IO_QUEUE 16 - #define S390_MAX_CPUS 248 =20 typedef struct PSW { @@ -62,13 +60,6 @@ typedef struct PSW { uint64_t addr; } PSW; =20 -typedef struct IOIntQueue { - uint16_t id; - uint16_t nr; - uint32_t parm; - uint32_t word; -} IOIntQueue; - struct CPUS390XState { uint64_t regs[16]; /* GP registers */ /* @@ -113,13 +104,9 @@ struct CPUS390XState { =20 uint64_t cregs[16]; /* control registers */ =20 - IOIntQueue io_queue[MAX_IO_QUEUE][8]; - int pending_int; - uint32_t service_param; uint16_t external_call_addr; DECLARE_BITMAP(emergency_signals, S390_MAX_CPUS); - int io_index[8]; =20 uint64_t ckc; uint64_t cputm; @@ -398,9 +385,6 @@ static inline void cpu_get_tb_cpu_state(CPUS390XState* = env, target_ulong *pc, #define EXCP_IO 7 /* I/O interrupt */ #define EXCP_MCHK 8 /* machine check */ =20 -#define INTERRUPT_IO (1 << 0) -#define INTERRUPT_MCHK (1 << 1) -#define INTERRUPT_EXT_SERVICE (1 << 2) #define INTERRUPT_EXT_CPU_TIMER (1 << 3) #define INTERRUPT_EXT_CLOCK_COMPARATOR (1 << 4) #define INTERRUPT_EXTERNAL_CALL (1 << 5) @@ -740,12 +724,6 @@ 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); =20 /* mmu_helper.c */ int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, uint8_t ar, void *host= buf, diff --git a/target/s390x/excp_helper.c b/target/s390x/excp_helper.c index eeffb49f63..24dfd0333b 100644 --- a/target/s390x/excp_helper.c +++ b/target/s390x/excp_helper.c @@ -29,6 +29,7 @@ #include "exec/address-spaces.h" #ifndef CONFIG_USER_ONLY #include "sysemu/sysemu.h" +#include "hw/s390x/s390_flic.h" #endif =20 /* #define DEBUG_S390 */ @@ -237,6 +238,7 @@ static void do_svc_interrupt(CPUS390XState *env) =20 static void do_ext_interrupt(CPUS390XState *env) { + QEMUS390FLICState *flic =3D QEMU_S390_FLIC(s390_get_flic()); S390CPU *cpu =3D s390_env_get_cpu(env); uint64_t mask, addr; uint16_t cpu_addr; @@ -273,17 +275,14 @@ static void do_ext_interrupt(CPUS390XState *env) lowcore->ext_int_code =3D cpu_to_be16(EXT_CPU_TIMER); lowcore->cpu_addr =3D 0; env->pending_int &=3D ~INTERRUPT_EXT_CPU_TIMER; - } else if ((env->pending_int & INTERRUPT_EXT_SERVICE) && + } else if (qemu_s390_flic_has_service(flic) && (env->cregs[0] & CR0_SERVICE_SC)) { - /* - * FIXME: floating IRQs should be considered by all CPUs and - * shuld not get cleared by CPU reset. - */ + uint32_t param; + + param =3D qemu_s390_flic_dequeue_service(flic); lowcore->ext_int_code =3D cpu_to_be16(EXT_SERVICE); - lowcore->ext_params =3D cpu_to_be32(env->service_param); + lowcore->ext_params =3D cpu_to_be32(param); lowcore->cpu_addr =3D 0; - env->service_param =3D 0; - env->pending_int &=3D ~INTERRUPT_EXT_SERVICE; } else { g_assert_not_reached(); } @@ -303,71 +302,37 @@ static void do_ext_interrupt(CPUS390XState *env) =20 static void do_io_interrupt(CPUS390XState *env) { - S390CPU *cpu =3D s390_env_get_cpu(env); + QEMUS390FLICState *flic =3D QEMU_S390_FLIC(s390_get_flic()); + uint64_t mask, addr; + QEMUS390FlicIO *io; LowCore *lowcore; - IOIntQueue *q; - uint8_t isc; - int disable =3D 1; - int found =3D 0; - - if (!(env->psw.mask & PSW_MASK_IO)) { - cpu_abort(CPU(cpu), "I/O int w/o I/O mask\n"); - } - - for (isc =3D 0; isc < ARRAY_SIZE(env->io_index); isc++) { - uint64_t isc_bits; - - if (env->io_index[isc] < 0) { - continue; - } - if (env->io_index[isc] >=3D MAX_IO_QUEUE) { - cpu_abort(CPU(cpu), "I/O queue overrun for isc %d: %d\n", - isc, env->io_index[isc]); - } - - q =3D &env->io_queue[env->io_index[isc]][isc]; - isc_bits =3D ISC_TO_ISC_BITS(IO_INT_WORD_ISC(q->word)); - if (!(env->cregs[6] & isc_bits)) { - disable =3D 0; - continue; - } - if (!found) { - uint64_t mask, addr; =20 - found =3D 1; - lowcore =3D cpu_map_lowcore(env); + g_assert(env->psw.mask & PSW_MASK_IO); + io =3D qemu_s390_flic_dequeue_io(flic, env->cregs[6]); + g_assert(io); =20 - lowcore->subchannel_id =3D cpu_to_be16(q->id); - lowcore->subchannel_nr =3D cpu_to_be16(q->nr); - lowcore->io_int_parm =3D cpu_to_be32(q->parm); - lowcore->io_int_word =3D cpu_to_be32(q->word); - lowcore->io_old_psw.mask =3D cpu_to_be64(get_psw_mask(env)); - lowcore->io_old_psw.addr =3D cpu_to_be64(env->psw.addr); - mask =3D be64_to_cpu(lowcore->io_new_psw.mask); - addr =3D be64_to_cpu(lowcore->io_new_psw.addr); - - cpu_unmap_lowcore(lowcore); - - env->io_index[isc]--; + lowcore =3D cpu_map_lowcore(env); =20 - DPRINTF("%s: %" PRIx64 " %" PRIx64 "\n", __func__, - env->psw.mask, env->psw.addr); - load_psw(env, mask, addr); - } - if (env->io_index[isc] >=3D 0) { - disable =3D 0; - } - continue; - } + lowcore->subchannel_id =3D cpu_to_be16(io->id); + lowcore->subchannel_nr =3D cpu_to_be16(io->nr); + lowcore->io_int_parm =3D cpu_to_be32(io->parm); + lowcore->io_int_word =3D cpu_to_be32(io->word); + lowcore->io_old_psw.mask =3D cpu_to_be64(get_psw_mask(env)); + lowcore->io_old_psw.addr =3D cpu_to_be64(env->psw.addr); + mask =3D be64_to_cpu(lowcore->io_new_psw.mask); + addr =3D be64_to_cpu(lowcore->io_new_psw.addr); =20 - if (disable) { - env->pending_int &=3D ~INTERRUPT_IO; - } + cpu_unmap_lowcore(lowcore); + g_free(io); =20 + DPRINTF("%s: %" PRIx64 " %" PRIx64 "\n", __func__, env->psw.mask, + env->psw.addr); + load_psw(env, mask, addr); } =20 static void do_mchk_interrupt(CPUS390XState *env) { + QEMUS390FLICState *flic =3D QEMU_S390_FLIC(s390_get_flic()); uint64_t mask, addr; LowCore *lowcore; int i; @@ -376,8 +341,7 @@ static void do_mchk_interrupt(CPUS390XState *env) g_assert(env->psw.mask & PSW_MASK_MCHECK); g_assert(env->cregs[14] & CR0_SERVICE_SC); =20 - g_assert(env->pending_int & INTERRUPT_MCHK); - env->pending_int &=3D ~INTERRUPT_MCHK; + qemu_s390_flic_dequeue_crw_mchk(flic); =20 lowcore =3D cpu_map_lowcore(env); =20 @@ -412,6 +376,7 @@ static void do_mchk_interrupt(CPUS390XState *env) =20 void s390_cpu_do_interrupt(CPUState *cs) { + QEMUS390FLICState *flic =3D QEMU_S390_FLIC(s390_get_flic()); S390CPU *cpu =3D S390_CPU(cs); CPUS390XState *env =3D &cpu->env; bool stopped =3D false; @@ -474,7 +439,7 @@ try_deliver: cs->exception_index =3D -1; =20 /* we might still have pending interrupts, but not deliverable */ - if (!env->pending_int) { + if (!env->pending_int && !qemu_s390_flic_has_any(flic)) { cs->interrupt_request &=3D ~CPU_INTERRUPT_HARD; } =20 diff --git a/target/s390x/interrupt.c b/target/s390x/interrupt.c index 8229572f7d..61691aa3a4 100644 --- a/target/s390x/interrupt.c +++ b/target/s390x/interrupt.c @@ -58,17 +58,6 @@ void s390_program_interrupt(CPUS390XState *env, uint32_t= code, int ilen, } =20 #if !defined(CONFIG_USER_ONLY) -void cpu_inject_service(S390CPU *cpu, uint32_t param) -{ - CPUS390XState *env =3D &cpu->env; - - /* multiplexing is good enough for sclp - kvm does it internally as we= ll*/ - env->service_param |=3D param; - - env->pending_int |=3D INTERRUPT_EXT_SERVICE; - cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD); -} - void cpu_inject_clock_comparator(S390CPU *cpu) { CPUS390XState *env =3D &cpu->env; @@ -137,38 +126,6 @@ void cpu_inject_stop(S390CPU *cpu) cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD); } =20 -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 =3D &cpu->env; - int isc =3D IO_INT_WORD_ISC(io_int_word); - - if (env->io_index[isc] =3D=3D MAX_IO_QUEUE - 1) { - /* ugh - can't queue anymore. Let's drop. */ - return; - } - - env->io_index[isc]++; - assert(env->io_index[isc] < MAX_IO_QUEUE); - - env->io_queue[env->io_index[isc]][isc].id =3D subchannel_id; - env->io_queue[env->io_index[isc]][isc].nr =3D subchannel_number; - env->io_queue[env->io_index[isc]][isc].parm =3D io_int_parm; - env->io_queue[env->io_index[isc]][isc].word =3D io_int_word; - - env->pending_int |=3D INTERRUPT_IO; - cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD); -} - -void cpu_inject_crw_mchk(S390CPU *cpu) -{ - CPUS390XState *env =3D &cpu->env; - - env->pending_int |=3D INTERRUPT_MCHK; - cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD); -} - /* * All of the following interrupts are floating, i.e. not per-vcpu. * We just need a dummy cpustate in order to be able to inject in the @@ -201,6 +158,7 @@ void s390_crw_mchk(void) =20 bool s390_cpu_has_mcck_int(S390CPU *cpu) { + QEMUS390FLICState *flic =3D QEMU_S390_FLIC(s390_get_flic()); CPUS390XState *env =3D &cpu->env; =20 if (!(env->psw.mask & PSW_MASK_MCHECK)) { @@ -208,7 +166,7 @@ bool s390_cpu_has_mcck_int(S390CPU *cpu) } =20 /* for now we only support channel report machine checks (floating) */ - if ((env->pending_int & INTERRUPT_MCHK) && + if (qemu_s390_flic_has_crw_mchk(flic) && (env->cregs[14] & CR14_CHANNEL_REPORT_SC)) { return true; } @@ -218,6 +176,7 @@ bool s390_cpu_has_mcck_int(S390CPU *cpu) =20 bool s390_cpu_has_ext_int(S390CPU *cpu) { + QEMUS390FLICState *flic =3D QEMU_S390_FLIC(s390_get_flic()); CPUS390XState *env =3D &cpu->env; =20 if (!(env->psw.mask & PSW_MASK_EXT)) { @@ -249,7 +208,7 @@ bool s390_cpu_has_ext_int(S390CPU *cpu) return true; } =20 - if ((env->pending_int & INTERRUPT_EXT_SERVICE) && + if (qemu_s390_flic_has_service(flic) && (env->cregs[0] & CR0_SERVICE_SC)) { return true; } @@ -259,13 +218,14 @@ bool s390_cpu_has_ext_int(S390CPU *cpu) =20 bool s390_cpu_has_io_int(S390CPU *cpu) { + QEMUS390FLICState *flic =3D QEMU_S390_FLIC(s390_get_flic()); CPUS390XState *env =3D &cpu->env; =20 if (!(env->psw.mask & PSW_MASK_IO)) { return false; } =20 - return env->pending_int & INTERRUPT_IO; + return qemu_s390_flic_has_io(flic, env->cregs[6]); } =20 bool s390_cpu_has_restart_int(S390CPU *cpu) --=20 2.14.3