mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-07-26 20:03:54 -06:00

As HW virtualization requires specific support to handle breakpoints lets push out special casing out of the core gdbstub code and into AccelOpsClass. This will make it easier to add other accelerator support and reduces some of the stub shenanigans. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Mads Ynddal <mads@ynddal.dk> Message-Id: <20220929114231.583801-45-alex.bennee@linaro.org>
120 lines
3.1 KiB
C
120 lines
3.1 KiB
C
/*
|
|
* QEMU KVM support
|
|
*
|
|
* Copyright IBM, Corp. 2008
|
|
* Red Hat, Inc. 2008
|
|
*
|
|
* Authors:
|
|
* Anthony Liguori <aliguori@us.ibm.com>
|
|
* Glauber Costa <gcosta@redhat.com>
|
|
*
|
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
|
* See the COPYING file in the top-level directory.
|
|
*
|
|
*/
|
|
|
|
#include "qemu/osdep.h"
|
|
#include "qemu/error-report.h"
|
|
#include "qemu/main-loop.h"
|
|
#include "sysemu/kvm.h"
|
|
#include "sysemu/kvm_int.h"
|
|
#include "sysemu/runstate.h"
|
|
#include "sysemu/cpus.h"
|
|
#include "qemu/guest-random.h"
|
|
#include "qapi/error.h"
|
|
|
|
#include <linux/kvm.h>
|
|
#include "kvm-cpus.h"
|
|
|
|
static void *kvm_vcpu_thread_fn(void *arg)
|
|
{
|
|
CPUState *cpu = arg;
|
|
int r;
|
|
|
|
rcu_register_thread();
|
|
|
|
qemu_mutex_lock_iothread();
|
|
qemu_thread_get_self(cpu->thread);
|
|
cpu->thread_id = qemu_get_thread_id();
|
|
cpu->can_do_io = 1;
|
|
current_cpu = cpu;
|
|
|
|
r = kvm_init_vcpu(cpu, &error_fatal);
|
|
kvm_init_cpu_signals(cpu);
|
|
|
|
/* signal CPU creation */
|
|
cpu_thread_signal_created(cpu);
|
|
qemu_guest_random_seed_thread_part2(cpu->random_seed);
|
|
|
|
do {
|
|
if (cpu_can_run(cpu)) {
|
|
r = kvm_cpu_exec(cpu);
|
|
if (r == EXCP_DEBUG) {
|
|
cpu_handle_guest_debug(cpu);
|
|
}
|
|
}
|
|
qemu_wait_io_event(cpu);
|
|
} while (!cpu->unplug || cpu_can_run(cpu));
|
|
|
|
kvm_destroy_vcpu(cpu);
|
|
cpu_thread_signal_destroyed(cpu);
|
|
qemu_mutex_unlock_iothread();
|
|
rcu_unregister_thread();
|
|
return NULL;
|
|
}
|
|
|
|
static void kvm_start_vcpu_thread(CPUState *cpu)
|
|
{
|
|
char thread_name[VCPU_THREAD_NAME_SIZE];
|
|
|
|
cpu->thread = g_malloc0(sizeof(QemuThread));
|
|
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
|
|
qemu_cond_init(cpu->halt_cond);
|
|
snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/KVM",
|
|
cpu->cpu_index);
|
|
qemu_thread_create(cpu->thread, thread_name, kvm_vcpu_thread_fn,
|
|
cpu, QEMU_THREAD_JOINABLE);
|
|
}
|
|
|
|
static bool kvm_vcpu_thread_is_idle(CPUState *cpu)
|
|
{
|
|
return !kvm_halt_in_kernel();
|
|
}
|
|
|
|
static bool kvm_cpus_are_resettable(void)
|
|
{
|
|
return !kvm_enabled() || kvm_cpu_check_are_resettable();
|
|
}
|
|
|
|
static void kvm_accel_ops_class_init(ObjectClass *oc, void *data)
|
|
{
|
|
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
|
|
|
|
ops->create_vcpu_thread = kvm_start_vcpu_thread;
|
|
ops->cpu_thread_is_idle = kvm_vcpu_thread_is_idle;
|
|
ops->cpus_are_resettable = kvm_cpus_are_resettable;
|
|
ops->synchronize_post_reset = kvm_cpu_synchronize_post_reset;
|
|
ops->synchronize_post_init = kvm_cpu_synchronize_post_init;
|
|
ops->synchronize_state = kvm_cpu_synchronize_state;
|
|
ops->synchronize_pre_loadvm = kvm_cpu_synchronize_pre_loadvm;
|
|
|
|
#ifdef KVM_CAP_SET_GUEST_DEBUG
|
|
ops->insert_breakpoint = kvm_insert_breakpoint;
|
|
ops->remove_breakpoint = kvm_remove_breakpoint;
|
|
ops->remove_all_breakpoints = kvm_remove_all_breakpoints;
|
|
#endif
|
|
}
|
|
|
|
static const TypeInfo kvm_accel_ops_type = {
|
|
.name = ACCEL_OPS_NAME("kvm"),
|
|
|
|
.parent = TYPE_ACCEL_OPS,
|
|
.class_init = kvm_accel_ops_class_init,
|
|
.abstract = true,
|
|
};
|
|
|
|
static void kvm_accel_ops_register_types(void)
|
|
{
|
|
type_register_static(&kvm_accel_ops_type);
|
|
}
|
|
type_init(kvm_accel_ops_register_types);
|