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 | |
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>
-rw-r--r-- | hw/intc/s390_flic.c | 31 | ||||
-rw-r--r-- | target/s390x/cpu.h | 4 | ||||
-rw-r--r-- | target/s390x/internal.h | 5 |
3 files changed, 33 insertions, 7 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); } } diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h index ba6cf0c..76c31d9 100644 --- a/target/s390x/cpu.h +++ b/target/s390x/cpu.h @@ -692,6 +692,10 @@ static inline unsigned int s390_cpu_set_state(uint8_t cpu_state, S390CPU *cpu) return 0; } #endif /* CONFIG_USER_ONLY */ +static inline uint8_t s390_cpu_get_state(S390CPU *cpu) +{ + return cpu->env.cpu_state; +} /* cpu_models.c */ diff --git a/target/s390x/internal.h b/target/s390x/internal.h index fea165f..d911e84 100644 --- a/target/s390x/internal.h +++ b/target/s390x/internal.h @@ -278,11 +278,6 @@ static inline void s390_do_cpu_full_reset(CPUState *cs, run_on_cpu_data arg) cpu_reset(cs); } -static inline uint8_t s390_cpu_get_state(S390CPU *cpu) -{ - return cpu->env.cpu_state; -} - /* arch_dump.c */ int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, |