diff options
author | David Hildenbrand <david@redhat.com> | 2018-01-29 13:56:16 +0100 |
---|---|---|
committer | Cornelia Huck <cohuck@redhat.com> | 2018-02-09 09:37:13 +0100 |
commit | 631b59664c9d8472d64c9c9c14b709dd40f07b16 (patch) | |
tree | 96023ad9d280f23c125266bb30bb5c48d7d0091f /hw | |
parent | 6e0d8175d63afba248f7da09047d0fcedd1e953d (diff) | |
download | qemu-631b59664c9d8472d64c9c9c14b709dd40f07b16.zip qemu-631b59664c9d8472d64c9c9c14b709dd40f07b16.tar.gz qemu-631b59664c9d8472d64c9c9c14b709dd40f07b16.tar.bz2 |
s390x/flic: optimize CPU wakeup for TCG
Kicking all CPUs on every floating interrupt is far from efficient.
Let's optimize it at least a little bit.
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20180129125623.21729-12-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/intc/s390_flic.c | 31 |
1 files changed, 29 insertions, 2 deletions
diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c index cb216de..5febde2 100644 --- a/hw/intc/s390_flic.c +++ b/hw/intc/s390_flic.c @@ -161,10 +161,37 @@ static void qemu_s390_flic_notify(uint32_t type) /* * 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). + * consider it. We will kick all running CPUs and only relevant + * sleeping ones. */ CPU_FOREACH(cs) { + S390CPU *cpu = S390_CPU(cs); + + cs->interrupt_request |= CPU_INTERRUPT_HARD; + + /* ignore CPUs that are not sleeping */ + if (s390_cpu_get_state(cpu) != CPU_STATE_OPERATING && + s390_cpu_get_state(cpu) != CPU_STATE_LOAD) { + continue; + } + + /* we always kick running CPUs for now, this is tricky */ + if (cs->halted) { + /* don't check for subclasses, CPUs double check when waking up */ + if (type & FLIC_PENDING_SERVICE) { + if (!(cpu->env.psw.mask & PSW_MASK_EXT)) { + continue; + } + } else if (type & FLIC_PENDING_IO) { + if (!(cpu->env.psw.mask & PSW_MASK_IO)) { + continue; + } + } else if (type & FLIC_PENDING_MCHK_CR) { + if (!(cpu->env.psw.mask & PSW_MASK_MCHECK)) { + continue; + } + } + } cpu_interrupt(cs, CPU_INTERRUPT_HARD); } } |