kvm: First step to push iothread lock out of inner run loop

This opens the path to get rid of the iothread lock on vmexits in KVM
mode. On x86, the in-kernel irqchips has to be used because we otherwise
need to synchronize APIC and other per-cpu state accesses that could be
changed concurrently.

Regarding pre/post-run callbacks, s390x and ARM should be fine without
specific locking as the callbacks are empty. MIPS and POWER require
locking for the pre-run callback.

For the handle_exit callback, it is non-empty in x86, POWER and s390.
Some POWER cases could do without the locking, but it is left in
place for now.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <1434646046-27150-7-git-send-email-pbonzini@redhat.com>
This commit is contained in:
Jan Kiszka 2015-06-18 18:47:23 +02:00 committed by Paolo Bonzini
parent 4840f10eff
commit 4b8523ee89
5 changed files with 46 additions and 2 deletions

View file

@ -1755,6 +1755,8 @@ int kvm_cpu_exec(CPUState *cpu)
return EXCP_HLT;
}
qemu_mutex_unlock_iothread();
do {
MemTxAttrs attrs;
@ -1773,11 +1775,9 @@ int kvm_cpu_exec(CPUState *cpu)
*/
qemu_cpu_kick_self();
}
qemu_mutex_unlock_iothread();
run_ret = kvm_vcpu_ioctl(cpu, KVM_RUN, 0);
qemu_mutex_lock_iothread();
attrs = kvm_arch_post_run(cpu, run);
if (run_ret < 0) {
@ -1804,20 +1804,24 @@ int kvm_cpu_exec(CPUState *cpu)
switch (run->exit_reason) {
case KVM_EXIT_IO:
DPRINTF("handle_io\n");
qemu_mutex_lock_iothread();
kvm_handle_io(run->io.port, attrs,
(uint8_t *)run + run->io.data_offset,
run->io.direction,
run->io.size,
run->io.count);
qemu_mutex_unlock_iothread();
ret = 0;
break;
case KVM_EXIT_MMIO:
DPRINTF("handle_mmio\n");
qemu_mutex_lock_iothread();
address_space_rw(&address_space_memory,
run->mmio.phys_addr, attrs,
run->mmio.data,
run->mmio.len,
run->mmio.is_write);
qemu_mutex_unlock_iothread();
ret = 0;
break;
case KVM_EXIT_IRQ_WINDOW_OPEN:
@ -1860,6 +1864,8 @@ int kvm_cpu_exec(CPUState *cpu)
}
} while (ret == 0);
qemu_mutex_lock_iothread();
if (ret < 0) {
cpu_dump_state(cpu, stderr, fprintf, CPU_DUMP_CODE);
vm_stop(RUN_STATE_INTERNAL_ERROR);