Commit 631b5966 authored by David Hildenbrand's avatar David Hildenbrand Committed by Cornelia Huck
Browse files

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: default avatarDavid Hildenbrand <david@redhat.com>
Message-Id: <20180129125623.21729-12-david@redhat.com>
Signed-off-by: default avatarCornelia Huck <cohuck@redhat.com>
parent 6e0d8175
Loading
Loading
Loading
Loading
+29 −2
Original line number Diff line number Diff line
@@ -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);
    }
}
+4 −0
Original line number Diff line number Diff line
@@ -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 */
+0 −5
Original line number Diff line number Diff line
@@ -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,