accel: replace struct CpusAccel with AccelOpsClass
This will allow us to centralize the registration of the cpus.c module accelerator operations (in accel/accel-softmmu.c), and trigger it automatically using object hierarchy lookup from the new accel_init_interfaces() initialization step, depending just on which accelerators are available in the code. Rename all tcg-cpus.c, kvm-cpus.c, etc to tcg-accel-ops.c, kvm-accel-ops.c, etc, matching the object type names. Signed-off-by: Claudio Fontana <cfontana@suse.de> Message-Id: <20210204163931.7358-18-cfontana@suse.de> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
940e43aa30
commit
b86f59c715
@ -439,7 +439,8 @@ M: Richard Henderson <richard.henderson@linaro.org>
|
||||
R: Paolo Bonzini <pbonzini@redhat.com>
|
||||
S: Maintained
|
||||
F: include/qemu/accel.h
|
||||
F: accel/accel.c
|
||||
F: include/sysemu/accel-ops.h
|
||||
F: accel/accel-*.c
|
||||
F: accel/Makefile.objs
|
||||
F: accel/stubs/Makefile.objs
|
||||
|
||||
|
@ -26,6 +26,10 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/accel.h"
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
#include "accel-softmmu.h"
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
||||
static const TypeInfo accel_type = {
|
||||
.name = TYPE_ACCEL,
|
||||
.parent = TYPE_OBJECT,
|
||||
@ -42,6 +46,13 @@ AccelClass *accel_find(const char *opt_name)
|
||||
return ac;
|
||||
}
|
||||
|
||||
void accel_init_interfaces(AccelClass *ac)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
accel_init_ops_interfaces(ac);
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
}
|
||||
|
||||
static void register_accel_types(void)
|
||||
{
|
||||
type_register_static(&accel_type);
|
||||
|
@ -26,9 +26,9 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/accel.h"
|
||||
#include "hw/boards.h"
|
||||
#include "sysemu/arch_init.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qom/object.h"
|
||||
#include "sysemu/cpus.h"
|
||||
|
||||
#include "accel-softmmu.h"
|
||||
|
||||
int accel_init_machine(AccelState *accel, MachineState *ms)
|
||||
{
|
||||
@ -60,3 +60,41 @@ void accel_setup_post(MachineState *ms)
|
||||
acc->setup_post(ms, accel);
|
||||
}
|
||||
}
|
||||
|
||||
/* initialize the arch-independent accel operation interfaces */
|
||||
void accel_init_ops_interfaces(AccelClass *ac)
|
||||
{
|
||||
const char *ac_name;
|
||||
char *ops_name;
|
||||
AccelOpsClass *ops;
|
||||
|
||||
ac_name = object_class_get_name(OBJECT_CLASS(ac));
|
||||
g_assert(ac_name != NULL);
|
||||
|
||||
ops_name = g_strdup_printf("%s" ACCEL_OPS_SUFFIX, ac_name);
|
||||
ops = ACCEL_OPS_CLASS(object_class_by_name(ops_name));
|
||||
g_free(ops_name);
|
||||
|
||||
/*
|
||||
* all accelerators need to define ops, providing at least a mandatory
|
||||
* non-NULL create_vcpu_thread operation.
|
||||
*/
|
||||
g_assert(ops != NULL);
|
||||
if (ops->ops_init) {
|
||||
ops->ops_init(ops);
|
||||
}
|
||||
cpus_register_accel(ops);
|
||||
}
|
||||
|
||||
static const TypeInfo accel_ops_type_info = {
|
||||
.name = TYPE_ACCEL_OPS,
|
||||
.parent = TYPE_OBJECT,
|
||||
.abstract = true,
|
||||
.class_size = sizeof(AccelOpsClass),
|
||||
};
|
||||
|
||||
static void accel_softmmu_register_types(void)
|
||||
{
|
||||
type_register_static(&accel_ops_type_info);
|
||||
}
|
||||
type_init(accel_softmmu_register_types);
|
||||
|
15
accel/accel-softmmu.h
Normal file
15
accel/accel-softmmu.h
Normal file
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* QEMU System Emulation accel internal functions
|
||||
*
|
||||
* Copyright 2021 SUSE LLC
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef ACCEL_SOFTMMU_H
|
||||
#define ACCEL_SOFTMMU_H
|
||||
|
||||
void accel_init_ops_interfaces(AccelClass *ac);
|
||||
|
||||
#endif /* ACCEL_SOFTMMU_H */
|
@ -74,11 +74,27 @@ static void kvm_start_vcpu_thread(CPUState *cpu)
|
||||
cpu, QEMU_THREAD_JOINABLE);
|
||||
}
|
||||
|
||||
const CpusAccel kvm_cpus = {
|
||||
.create_vcpu_thread = kvm_start_vcpu_thread,
|
||||
static void kvm_accel_ops_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
|
||||
|
||||
.synchronize_post_reset = kvm_cpu_synchronize_post_reset,
|
||||
.synchronize_post_init = kvm_cpu_synchronize_post_init,
|
||||
.synchronize_state = kvm_cpu_synchronize_state,
|
||||
.synchronize_pre_loadvm = kvm_cpu_synchronize_pre_loadvm,
|
||||
ops->create_vcpu_thread = kvm_start_vcpu_thread;
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
@ -2256,8 +2256,6 @@ static int kvm_init(MachineState *ms)
|
||||
ret = ram_block_discard_disable(true);
|
||||
assert(!ret);
|
||||
}
|
||||
|
||||
cpus_register_accel(&kvm_cpus);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
|
@ -12,8 +12,6 @@
|
||||
|
||||
#include "sysemu/cpus.h"
|
||||
|
||||
extern const CpusAccel kvm_cpus;
|
||||
|
||||
int kvm_init_vcpu(CPUState *cpu, Error **errp);
|
||||
int kvm_cpu_exec(CPUState *cpu);
|
||||
void kvm_destroy_vcpu(CPUState *cpu);
|
||||
|
@ -1,7 +1,7 @@
|
||||
kvm_ss = ss.source_set()
|
||||
kvm_ss.add(files(
|
||||
'kvm-all.c',
|
||||
'kvm-cpus.c',
|
||||
'kvm-accel-ops.c',
|
||||
))
|
||||
kvm_ss.add(when: 'CONFIG_SEV', if_false: files('sev-stub.c'))
|
||||
|
||||
|
@ -25,14 +25,8 @@
|
||||
#include "qemu/main-loop.h"
|
||||
#include "hw/core/cpu.h"
|
||||
|
||||
const CpusAccel qtest_cpus = {
|
||||
.create_vcpu_thread = dummy_start_vcpu_thread,
|
||||
.get_virtual_clock = qtest_get_virtual_clock,
|
||||
};
|
||||
|
||||
static int qtest_init_accel(MachineState *ms)
|
||||
{
|
||||
cpus_register_accel(&qtest_cpus);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -52,9 +46,26 @@ static const TypeInfo qtest_accel_type = {
|
||||
.class_init = qtest_accel_class_init,
|
||||
};
|
||||
|
||||
static void qtest_accel_ops_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
|
||||
|
||||
ops->create_vcpu_thread = dummy_start_vcpu_thread;
|
||||
ops->get_virtual_clock = qtest_get_virtual_clock;
|
||||
};
|
||||
|
||||
static const TypeInfo qtest_accel_ops_type = {
|
||||
.name = ACCEL_OPS_NAME("qtest"),
|
||||
|
||||
.parent = TYPE_ACCEL_OPS,
|
||||
.class_init = qtest_accel_ops_class_init,
|
||||
.abstract = true,
|
||||
};
|
||||
|
||||
static void qtest_type_init(void)
|
||||
{
|
||||
type_register_static(&qtest_accel_type);
|
||||
type_register_static(&qtest_accel_ops_type);
|
||||
}
|
||||
|
||||
type_init(qtest_type_init);
|
||||
|
@ -15,8 +15,8 @@ specific_ss.add_all(when: 'CONFIG_TCG', if_true: tcg_ss)
|
||||
|
||||
specific_ss.add(when: ['CONFIG_SOFTMMU', 'CONFIG_TCG'], if_true: files(
|
||||
'cputlb.c',
|
||||
'tcg-cpus.c',
|
||||
'tcg-cpus-mttcg.c',
|
||||
'tcg-cpus-icount.c',
|
||||
'tcg-cpus-rr.c'
|
||||
'tcg-accel-ops.c',
|
||||
'tcg-accel-ops-mttcg.c',
|
||||
'tcg-accel-ops-icount.c',
|
||||
'tcg-accel-ops-rr.c'
|
||||
))
|
||||
|
@ -32,9 +32,9 @@
|
||||
#include "exec/exec-all.h"
|
||||
#include "hw/boards.h"
|
||||
|
||||
#include "tcg-cpus.h"
|
||||
#include "tcg-cpus-icount.h"
|
||||
#include "tcg-cpus-rr.h"
|
||||
#include "tcg-accel-ops.h"
|
||||
#include "tcg-accel-ops-icount.h"
|
||||
#include "tcg-accel-ops-rr.h"
|
||||
|
||||
static int64_t icount_get_limit(void)
|
||||
{
|
||||
@ -93,7 +93,7 @@ void icount_prepare_for_run(CPUState *cpu)
|
||||
/*
|
||||
* These should always be cleared by icount_process_data after
|
||||
* each vCPU execution. However u16.high can be raised
|
||||
* asynchronously by cpu_exit/cpu_interrupt/tcg_cpus_handle_interrupt
|
||||
* asynchronously by cpu_exit/cpu_interrupt/tcg_handle_interrupt
|
||||
*/
|
||||
g_assert(cpu_neg(cpu)->icount_decr.u16.low == 0);
|
||||
g_assert(cpu->icount_extra == 0);
|
||||
@ -125,23 +125,14 @@ void icount_process_data(CPUState *cpu)
|
||||
replay_mutex_unlock();
|
||||
}
|
||||
|
||||
static void icount_handle_interrupt(CPUState *cpu, int mask)
|
||||
void icount_handle_interrupt(CPUState *cpu, int mask)
|
||||
{
|
||||
int old_mask = cpu->interrupt_request;
|
||||
|
||||
tcg_cpus_handle_interrupt(cpu, mask);
|
||||
tcg_handle_interrupt(cpu, mask);
|
||||
if (qemu_cpu_is_self(cpu) &&
|
||||
!cpu->can_do_io
|
||||
&& (mask & ~old_mask) != 0) {
|
||||
cpu_abort(cpu, "Raised interrupt while not in I/O function");
|
||||
}
|
||||
}
|
||||
|
||||
const CpusAccel tcg_cpus_icount = {
|
||||
.create_vcpu_thread = rr_start_vcpu_thread,
|
||||
.kick_vcpu_thread = rr_kick_vcpu_thread,
|
||||
|
||||
.handle_interrupt = icount_handle_interrupt,
|
||||
.get_virtual_clock = icount_get,
|
||||
.get_elapsed_ticks = icount_get,
|
||||
};
|
@ -14,4 +14,6 @@ void icount_handle_deadline(void);
|
||||
void icount_prepare_for_run(CPUState *cpu);
|
||||
void icount_process_data(CPUState *cpu);
|
||||
|
||||
void icount_handle_interrupt(CPUState *cpu, int mask);
|
||||
|
||||
#endif /* TCG_CPUS_ICOUNT_H */
|
@ -32,7 +32,8 @@
|
||||
#include "exec/exec-all.h"
|
||||
#include "hw/boards.h"
|
||||
|
||||
#include "tcg-cpus.h"
|
||||
#include "tcg-accel-ops.h"
|
||||
#include "tcg-accel-ops-mttcg.h"
|
||||
|
||||
/*
|
||||
* In the multi-threaded case each vCPU has its own thread. The TLS
|
||||
@ -103,12 +104,12 @@ static void *mttcg_cpu_thread_fn(void *arg)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void mttcg_kick_vcpu_thread(CPUState *cpu)
|
||||
void mttcg_kick_vcpu_thread(CPUState *cpu)
|
||||
{
|
||||
cpu_exit(cpu);
|
||||
}
|
||||
|
||||
static void mttcg_start_vcpu_thread(CPUState *cpu)
|
||||
void mttcg_start_vcpu_thread(CPUState *cpu)
|
||||
{
|
||||
char thread_name[VCPU_THREAD_NAME_SIZE];
|
||||
|
||||
@ -131,10 +132,3 @@ static void mttcg_start_vcpu_thread(CPUState *cpu)
|
||||
cpu->hThread = qemu_thread_get_handle(cpu->thread);
|
||||
#endif
|
||||
}
|
||||
|
||||
const CpusAccel tcg_cpus_mttcg = {
|
||||
.create_vcpu_thread = mttcg_start_vcpu_thread,
|
||||
.kick_vcpu_thread = mttcg_kick_vcpu_thread,
|
||||
|
||||
.handle_interrupt = tcg_cpus_handle_interrupt,
|
||||
};
|
19
accel/tcg/tcg-accel-ops-mttcg.h
Normal file
19
accel/tcg/tcg-accel-ops-mttcg.h
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* QEMU TCG Multi Threaded vCPUs implementation
|
||||
*
|
||||
* Copyright 2021 SUSE LLC
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef TCG_CPUS_MTTCG_H
|
||||
#define TCG_CPUS_MTTCG_H
|
||||
|
||||
/* kick MTTCG vCPU thread */
|
||||
void mttcg_kick_vcpu_thread(CPUState *cpu);
|
||||
|
||||
/* start an mttcg vCPU thread */
|
||||
void mttcg_start_vcpu_thread(CPUState *cpu);
|
||||
|
||||
#endif /* TCG_CPUS_MTTCG_H */
|
@ -32,9 +32,9 @@
|
||||
#include "exec/exec-all.h"
|
||||
#include "hw/boards.h"
|
||||
|
||||
#include "tcg-cpus.h"
|
||||
#include "tcg-cpus-rr.h"
|
||||
#include "tcg-cpus-icount.h"
|
||||
#include "tcg-accel-ops.h"
|
||||
#include "tcg-accel-ops-rr.h"
|
||||
#include "tcg-accel-ops-icount.h"
|
||||
|
||||
/* Kick all RR vCPUs */
|
||||
void rr_kick_vcpu_thread(CPUState *unused)
|
||||
@ -296,10 +296,3 @@ void rr_start_vcpu_thread(CPUState *cpu)
|
||||
cpu->created = true;
|
||||
}
|
||||
}
|
||||
|
||||
const CpusAccel tcg_cpus_rr = {
|
||||
.create_vcpu_thread = rr_start_vcpu_thread,
|
||||
.kick_vcpu_thread = rr_kick_vcpu_thread,
|
||||
|
||||
.handle_interrupt = tcg_cpus_handle_interrupt,
|
||||
};
|
@ -34,7 +34,10 @@
|
||||
#include "exec/exec-all.h"
|
||||
#include "hw/boards.h"
|
||||
|
||||
#include "tcg-cpus.h"
|
||||
#include "tcg-accel-ops.h"
|
||||
#include "tcg-accel-ops-mttcg.h"
|
||||
#include "tcg-accel-ops-rr.h"
|
||||
#include "tcg-accel-ops-icount.h"
|
||||
|
||||
/* common functionality among all TCG variants */
|
||||
|
||||
@ -64,7 +67,7 @@ int tcg_cpus_exec(CPUState *cpu)
|
||||
}
|
||||
|
||||
/* mask must never be zero, except for A20 change call */
|
||||
void tcg_cpus_handle_interrupt(CPUState *cpu, int mask)
|
||||
void tcg_handle_interrupt(CPUState *cpu, int mask)
|
||||
{
|
||||
g_assert(qemu_mutex_iothread_locked());
|
||||
|
||||
@ -80,3 +83,43 @@ void tcg_cpus_handle_interrupt(CPUState *cpu, int mask)
|
||||
qatomic_set(&cpu_neg(cpu)->icount_decr.u16.high, -1);
|
||||
}
|
||||
}
|
||||
|
||||
static void tcg_accel_ops_init(AccelOpsClass *ops)
|
||||
{
|
||||
if (qemu_tcg_mttcg_enabled()) {
|
||||
ops->create_vcpu_thread = mttcg_start_vcpu_thread;
|
||||
ops->kick_vcpu_thread = mttcg_kick_vcpu_thread;
|
||||
ops->handle_interrupt = tcg_handle_interrupt;
|
||||
} else if (icount_enabled()) {
|
||||
ops->create_vcpu_thread = rr_start_vcpu_thread;
|
||||
ops->kick_vcpu_thread = rr_kick_vcpu_thread;
|
||||
ops->handle_interrupt = icount_handle_interrupt;
|
||||
ops->get_virtual_clock = icount_get;
|
||||
ops->get_elapsed_ticks = icount_get;
|
||||
} else {
|
||||
ops->create_vcpu_thread = rr_start_vcpu_thread;
|
||||
ops->kick_vcpu_thread = rr_kick_vcpu_thread;
|
||||
ops->handle_interrupt = tcg_handle_interrupt;
|
||||
}
|
||||
}
|
||||
|
||||
static void tcg_accel_ops_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
|
||||
|
||||
ops->ops_init = tcg_accel_ops_init;
|
||||
}
|
||||
|
||||
static const TypeInfo tcg_accel_ops_type = {
|
||||
.name = ACCEL_OPS_NAME("tcg"),
|
||||
|
||||
.parent = TYPE_ACCEL_OPS,
|
||||
.class_init = tcg_accel_ops_class_init,
|
||||
.abstract = true,
|
||||
};
|
||||
|
||||
static void tcg_accel_ops_register_types(void)
|
||||
{
|
||||
type_register_static(&tcg_accel_ops_type);
|
||||
}
|
||||
type_init(tcg_accel_ops_register_types);
|
@ -14,12 +14,8 @@
|
||||
|
||||
#include "sysemu/cpus.h"
|
||||
|
||||
extern const CpusAccel tcg_cpus_mttcg;
|
||||
extern const CpusAccel tcg_cpus_icount;
|
||||
extern const CpusAccel tcg_cpus_rr;
|
||||
|
||||
void tcg_cpus_destroy(CPUState *cpu);
|
||||
int tcg_cpus_exec(CPUState *cpu);
|
||||
void tcg_cpus_handle_interrupt(CPUState *cpu, int mask);
|
||||
void tcg_handle_interrupt(CPUState *cpu, int mask);
|
||||
|
||||
#endif /* TCG_CPUS_H */
|
@ -33,10 +33,6 @@
|
||||
#include "qemu/accel.h"
|
||||
#include "qapi/qapi-builtin-visit.h"
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
#include "tcg-cpus.h"
|
||||
#endif /* CONFIG_USER_ONLY */
|
||||
|
||||
struct TCGState {
|
||||
AccelState parent_obj;
|
||||
|
||||
@ -124,14 +120,6 @@ static int tcg_init(MachineState *ms)
|
||||
*/
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
tcg_region_init();
|
||||
|
||||
if (mttcg_enabled) {
|
||||
cpus_register_accel(&tcg_cpus_mttcg);
|
||||
} else if (icount_enabled()) {
|
||||
cpus_register_accel(&tcg_cpus_icount);
|
||||
} else {
|
||||
cpus_register_accel(&tcg_cpus_rr);
|
||||
}
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
||||
return 0;
|
||||
|
@ -154,10 +154,6 @@ static void xen_setup_post(MachineState *ms, AccelState *accel)
|
||||
}
|
||||
}
|
||||
|
||||
const CpusAccel xen_cpus = {
|
||||
.create_vcpu_thread = dummy_start_vcpu_thread,
|
||||
};
|
||||
|
||||
static int xen_init(MachineState *ms)
|
||||
{
|
||||
MachineClass *mc = MACHINE_GET_CLASS(ms);
|
||||
@ -185,9 +181,6 @@ static int xen_init(MachineState *ms)
|
||||
* opt out of system RAM being allocated by generic code
|
||||
*/
|
||||
mc->default_ram_id = NULL;
|
||||
|
||||
cpus_register_accel(&xen_cpus);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -222,9 +215,24 @@ static const TypeInfo xen_accel_type = {
|
||||
.class_init = xen_accel_class_init,
|
||||
};
|
||||
|
||||
static void xen_accel_ops_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
|
||||
|
||||
ops->create_vcpu_thread = dummy_start_vcpu_thread;
|
||||
}
|
||||
|
||||
static const TypeInfo xen_accel_ops_type = {
|
||||
.name = ACCEL_OPS_NAME("xen"),
|
||||
|
||||
.parent = TYPE_ACCEL_OPS,
|
||||
.class_init = xen_accel_ops_class_init,
|
||||
.abstract = true,
|
||||
};
|
||||
|
||||
static void xen_type_init(void)
|
||||
{
|
||||
type_register_static(&xen_accel_type);
|
||||
type_register_static(&xen_accel_ops_type);
|
||||
}
|
||||
|
||||
type_init(xen_type_init);
|
||||
|
@ -909,13 +909,14 @@ int main(int argc, char **argv)
|
||||
#endif
|
||||
}
|
||||
|
||||
cpu_type = parse_cpu_option(cpu_model);
|
||||
/* init tcg before creating CPUs and to get qemu_host_page_size */
|
||||
{
|
||||
AccelClass *ac = ACCEL_GET_CLASS(current_accel());
|
||||
|
||||
ac->init_machine(NULL);
|
||||
accel_init_interfaces(ac);
|
||||
}
|
||||
cpu_type = parse_cpu_option(cpu_model);
|
||||
cpu = cpu_create(cpu_type);
|
||||
env = cpu->env_ptr;
|
||||
#if defined(TARGET_SPARC) || defined(TARGET_PPC)
|
||||
|
@ -69,6 +69,8 @@ typedef struct AccelClass {
|
||||
AccelClass *accel_find(const char *opt_name);
|
||||
AccelState *current_accel(void);
|
||||
|
||||
void accel_init_interfaces(AccelClass *ac);
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
int accel_init_machine(AccelState *accel, MachineState *ms);
|
||||
|
||||
|
45
include/sysemu/accel-ops.h
Normal file
45
include/sysemu/accel-ops.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Accelerator OPS, used for cpus.c module
|
||||
*
|
||||
* Copyright 2021 SUSE LLC
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef ACCEL_OPS_H
|
||||
#define ACCEL_OPS_H
|
||||
|
||||
#include "qom/object.h"
|
||||
|
||||
#define ACCEL_OPS_SUFFIX "-ops"
|
||||
#define TYPE_ACCEL_OPS "accel" ACCEL_OPS_SUFFIX
|
||||
#define ACCEL_OPS_NAME(name) (name "-" TYPE_ACCEL_OPS)
|
||||
|
||||
typedef struct AccelOpsClass AccelOpsClass;
|
||||
DECLARE_CLASS_CHECKERS(AccelOpsClass, ACCEL_OPS, TYPE_ACCEL_OPS)
|
||||
|
||||
/* cpus.c operations interface */
|
||||
struct AccelOpsClass {
|
||||
/*< private >*/
|
||||
ObjectClass parent_class;
|
||||
/*< public >*/
|
||||
|
||||
/* initialization function called when accel is chosen */
|
||||
void (*ops_init)(AccelOpsClass *ops);
|
||||
|
||||
void (*create_vcpu_thread)(CPUState *cpu); /* MANDATORY NON-NULL */
|
||||
void (*kick_vcpu_thread)(CPUState *cpu);
|
||||
|
||||
void (*synchronize_post_reset)(CPUState *cpu);
|
||||
void (*synchronize_post_init)(CPUState *cpu);
|
||||
void (*synchronize_state)(CPUState *cpu);
|
||||
void (*synchronize_pre_loadvm)(CPUState *cpu);
|
||||
|
||||
void (*handle_interrupt)(CPUState *cpu, int mask);
|
||||
|
||||
int64_t (*get_virtual_clock)(void);
|
||||
int64_t (*get_elapsed_ticks)(void);
|
||||
};
|
||||
|
||||
#endif /* ACCEL_OPS_H */
|
@ -2,30 +2,14 @@
|
||||
#define QEMU_CPUS_H
|
||||
|
||||
#include "qemu/timer.h"
|
||||
#include "sysemu/accel-ops.h"
|
||||
|
||||
/* cpus.c */
|
||||
/* register accel-specific operations */
|
||||
void cpus_register_accel(const AccelOpsClass *i);
|
||||
|
||||
/* CPU execution threads */
|
||||
/* accel/dummy-cpus.c */
|
||||
|
||||
typedef struct CpusAccel {
|
||||
void (*create_vcpu_thread)(CPUState *cpu); /* MANDATORY */
|
||||
void (*kick_vcpu_thread)(CPUState *cpu);
|
||||
|
||||
void (*synchronize_post_reset)(CPUState *cpu);
|
||||
void (*synchronize_post_init)(CPUState *cpu);
|
||||
void (*synchronize_state)(CPUState *cpu);
|
||||
void (*synchronize_pre_loadvm)(CPUState *cpu);
|
||||
|
||||
void (*handle_interrupt)(CPUState *cpu, int mask);
|
||||
|
||||
int64_t (*get_virtual_clock)(void);
|
||||
int64_t (*get_elapsed_ticks)(void);
|
||||
} CpusAccel;
|
||||
|
||||
/* register accel-specific cpus interface implementation */
|
||||
void cpus_register_accel(const CpusAccel *i);
|
||||
|
||||
/* Create a dummy vcpu for CpusAccel->create_vcpu_thread */
|
||||
/* Create a dummy vcpu for AccelOpsClass->create_vcpu_thread */
|
||||
void dummy_start_vcpu_thread(CPUState *);
|
||||
|
||||
/* interface available for cpus accelerator threads */
|
||||
|
@ -706,6 +706,7 @@ int main(int argc, char **argv, char **envp)
|
||||
AccelClass *ac = ACCEL_GET_CLASS(current_accel());
|
||||
|
||||
ac->init_machine(NULL);
|
||||
accel_init_interfaces(ac);
|
||||
}
|
||||
cpu = cpu_create(cpu_type);
|
||||
env = cpu->env_ptr;
|
||||
|
@ -128,7 +128,7 @@ void hw_error(const char *fmt, ...)
|
||||
/*
|
||||
* The chosen accelerator is supposed to register this.
|
||||
*/
|
||||
static const CpusAccel *cpus_accel;
|
||||
static const AccelOpsClass *cpus_accel;
|
||||
|
||||
void cpu_synchronize_all_states(void)
|
||||
{
|
||||
@ -594,11 +594,11 @@ void cpu_remove_sync(CPUState *cpu)
|
||||
qemu_mutex_lock_iothread();
|
||||
}
|
||||
|
||||
void cpus_register_accel(const CpusAccel *ca)
|
||||
void cpus_register_accel(const AccelOpsClass *ops)
|
||||
{
|
||||
assert(ca != NULL);
|
||||
assert(ca->create_vcpu_thread != NULL); /* mandatory */
|
||||
cpus_accel = ca;
|
||||
assert(ops != NULL);
|
||||
assert(ops->create_vcpu_thread != NULL); /* mandatory */
|
||||
cpus_accel = ops;
|
||||
}
|
||||
|
||||
void qemu_init_vcpu(CPUState *cpu)
|
||||
@ -618,7 +618,7 @@ void qemu_init_vcpu(CPUState *cpu)
|
||||
cpu_address_space_init(cpu, 0, "cpu-memory", cpu->memory);
|
||||
}
|
||||
|
||||
/* accelerators all implement the CpusAccel interface */
|
||||
/* accelerators all implement the AccelOpsClass */
|
||||
g_assert(cpus_accel != NULL && cpus_accel->create_vcpu_thread != NULL);
|
||||
cpus_accel->create_vcpu_thread(cpu);
|
||||
|
||||
|
@ -1726,7 +1726,8 @@ static bool object_create_early(const char *type, QemuOpts *opts)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Allocation of large amounts of memory may delay
|
||||
/*
|
||||
* Allocation of large amounts of memory may delay
|
||||
* chardev initialization for too long, and trigger timeouts
|
||||
* on software that waits for a monitor socket to be created
|
||||
* (e.g. libvirt).
|
||||
@ -3497,7 +3498,7 @@ void qemu_init(int argc, char **argv, char **envp)
|
||||
*
|
||||
* Machine compat properties: object_set_machine_compat_props().
|
||||
* Accelerator compat props: object_set_accelerator_compat_props(),
|
||||
* called from configure_accelerator().
|
||||
* called from do_configure_accelerator().
|
||||
*/
|
||||
|
||||
machine_class = MACHINE_GET_CLASS(current_machine);
|
||||
@ -3519,6 +3520,8 @@ void qemu_init(int argc, char **argv, char **envp)
|
||||
if (cpu_option) {
|
||||
current_machine->cpu_type = parse_cpu_option(cpu_option);
|
||||
}
|
||||
/* NB: for machine none cpu_type could STILL be NULL here! */
|
||||
accel_init_interfaces(ACCEL_GET_CLASS(current_machine->accelerator));
|
||||
|
||||
qemu_resolve_machine_memdev();
|
||||
parse_numa_opts(current_machine);
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include "sysemu/cpus.h"
|
||||
#include "qemu/guest-random.h"
|
||||
|
||||
#include "hax-cpus.h"
|
||||
#include "hax-accel-ops.h"
|
||||
|
||||
static void *hax_cpu_thread_fn(void *arg)
|
||||
{
|
||||
@ -74,12 +74,29 @@ static void hax_start_vcpu_thread(CPUState *cpu)
|
||||
#endif
|
||||
}
|
||||
|
||||
const CpusAccel hax_cpus = {
|
||||
.create_vcpu_thread = hax_start_vcpu_thread,
|
||||
.kick_vcpu_thread = hax_kick_vcpu_thread,
|
||||
static void hax_accel_ops_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
|
||||
|
||||
.synchronize_post_reset = hax_cpu_synchronize_post_reset,
|
||||
.synchronize_post_init = hax_cpu_synchronize_post_init,
|
||||
.synchronize_state = hax_cpu_synchronize_state,
|
||||
.synchronize_pre_loadvm = hax_cpu_synchronize_pre_loadvm,
|
||||
ops->create_vcpu_thread = hax_start_vcpu_thread;
|
||||
ops->kick_vcpu_thread = hax_kick_vcpu_thread;
|
||||
|
||||
ops->synchronize_post_reset = hax_cpu_synchronize_post_reset;
|
||||
ops->synchronize_post_init = hax_cpu_synchronize_post_init;
|
||||
ops->synchronize_state = hax_cpu_synchronize_state;
|
||||
ops->synchronize_pre_loadvm = hax_cpu_synchronize_pre_loadvm;
|
||||
}
|
||||
|
||||
static const TypeInfo hax_accel_ops_type = {
|
||||
.name = ACCEL_OPS_NAME("hax"),
|
||||
|
||||
.parent = TYPE_ACCEL_OPS,
|
||||
.class_init = hax_accel_ops_class_init,
|
||||
.abstract = true,
|
||||
};
|
||||
|
||||
static void hax_accel_ops_register_types(void)
|
||||
{
|
||||
type_register_static(&hax_accel_ops_type);
|
||||
}
|
||||
type_init(hax_accel_ops_register_types);
|
@ -12,8 +12,6 @@
|
||||
|
||||
#include "sysemu/cpus.h"
|
||||
|
||||
extern const CpusAccel hax_cpus;
|
||||
|
||||
#include "hax-interface.h"
|
||||
#include "hax-i386.h"
|
||||
|
@ -33,7 +33,7 @@
|
||||
#include "sysemu/runstate.h"
|
||||
#include "hw/boards.h"
|
||||
|
||||
#include "hax-cpus.h"
|
||||
#include "hax-accel-ops.h"
|
||||
|
||||
#define DEBUG_HAX 0
|
||||
|
||||
@ -364,9 +364,6 @@ static int hax_accel_init(MachineState *ms)
|
||||
!ret ? "working" : "not working",
|
||||
!ret ? "fast virt" : "emulation");
|
||||
}
|
||||
if (ret == 0) {
|
||||
cpus_register_accel(&hax_cpus);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include "exec/address-spaces.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
#include "hax-cpus.h"
|
||||
#include "hax-accel-ops.h"
|
||||
#include "qemu/queue.h"
|
||||
|
||||
#define DEBUG_HAX_MEM 0
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "sysemu/cpus.h"
|
||||
#include "hax-cpus.h"
|
||||
#include "hax-accel-ops.h"
|
||||
|
||||
hax_fd hax_mod_open(void)
|
||||
{
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "hax-cpus.h"
|
||||
#include "hax-accel-ops.h"
|
||||
|
||||
/*
|
||||
* return 0 when success, -1 when driver not loaded,
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include <winioctl.h>
|
||||
#include <windef.h>
|
||||
|
||||
#include "hax-cpus.h"
|
||||
#include "hax-accel-ops.h"
|
||||
|
||||
#define HAX_INVALID_FD INVALID_HANDLE_VALUE
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
i386_softmmu_ss.add(when: 'CONFIG_HAX', if_true: files(
|
||||
'hax-all.c',
|
||||
'hax-mem.c',
|
||||
'hax-cpus.c',
|
||||
'hax-accel-ops.c',
|
||||
))
|
||||
i386_softmmu_ss.add(when: ['CONFIG_HAX', 'CONFIG_POSIX'], if_true: files('hax-posix.c'))
|
||||
i386_softmmu_ss.add(when: ['CONFIG_HAX', 'CONFIG_WIN32'], if_true: files('hax-windows.c'))
|
||||
|
@ -55,7 +55,7 @@
|
||||
#include "target/i386/cpu.h"
|
||||
#include "qemu/guest-random.h"
|
||||
|
||||
#include "hvf-cpus.h"
|
||||
#include "hvf-accel-ops.h"
|
||||
|
||||
/*
|
||||
* The HVF-specific vCPU thread function. This one should only run when the host
|
||||
@ -121,11 +121,26 @@ static void hvf_start_vcpu_thread(CPUState *cpu)
|
||||
cpu, QEMU_THREAD_JOINABLE);
|
||||
}
|
||||
|
||||
const CpusAccel hvf_cpus = {
|
||||
.create_vcpu_thread = hvf_start_vcpu_thread,
|
||||
static void hvf_accel_ops_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
|
||||
|
||||
.synchronize_post_reset = hvf_cpu_synchronize_post_reset,
|
||||
.synchronize_post_init = hvf_cpu_synchronize_post_init,
|
||||
.synchronize_state = hvf_cpu_synchronize_state,
|
||||
.synchronize_pre_loadvm = hvf_cpu_synchronize_pre_loadvm,
|
||||
ops->create_vcpu_thread = hvf_start_vcpu_thread;
|
||||
|
||||
ops->synchronize_post_reset = hvf_cpu_synchronize_post_reset;
|
||||
ops->synchronize_post_init = hvf_cpu_synchronize_post_init;
|
||||
ops->synchronize_state = hvf_cpu_synchronize_state;
|
||||
ops->synchronize_pre_loadvm = hvf_cpu_synchronize_pre_loadvm;
|
||||
};
|
||||
static const TypeInfo hvf_accel_ops_type = {
|
||||
.name = ACCEL_OPS_NAME("hvf"),
|
||||
|
||||
.parent = TYPE_ACCEL_OPS,
|
||||
.class_init = hvf_accel_ops_class_init,
|
||||
.abstract = true,
|
||||
};
|
||||
static void hvf_accel_ops_register_types(void)
|
||||
{
|
||||
type_register_static(&hvf_accel_ops_type);
|
||||
}
|
||||
type_init(hvf_accel_ops_register_types);
|
@ -12,8 +12,6 @@
|
||||
|
||||
#include "sysemu/cpus.h"
|
||||
|
||||
extern const CpusAccel hvf_cpus;
|
||||
|
||||
int hvf_init_vcpu(CPUState *);
|
||||
int hvf_vcpu_exec(CPUState *);
|
||||
void hvf_cpu_synchronize_state(CPUState *);
|
@ -72,7 +72,7 @@
|
||||
#include "qemu/accel.h"
|
||||
#include "target/i386/cpu.h"
|
||||
|
||||
#include "hvf-cpus.h"
|
||||
#include "hvf-accel-ops.h"
|
||||
|
||||
HVFState *hvf_state;
|
||||
|
||||
@ -887,7 +887,6 @@ static int hvf_accel_init(MachineState *ms)
|
||||
|
||||
hvf_state = s;
|
||||
memory_listener_register(&hvf_memory_listener, &address_space_memory);
|
||||
cpus_register_accel(&hvf_cpus);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
i386_softmmu_ss.add(when: [hvf, 'CONFIG_HVF'], if_true: files(
|
||||
'hvf.c',
|
||||
'hvf-cpus.c',
|
||||
'hvf-accel-ops.c',
|
||||
'x86.c',
|
||||
'x86_cpuid.c',
|
||||
'x86_decode.c',
|
||||
|
@ -32,7 +32,7 @@
|
||||
#include <Hypervisor/hv.h>
|
||||
#include <Hypervisor/hv_vmx.h>
|
||||
|
||||
#include "hvf-cpus.h"
|
||||
#include "hvf-accel-ops.h"
|
||||
|
||||
void hvf_set_segment(struct CPUState *cpu, struct vmx_segment *vmx_seg,
|
||||
SegmentCache *qseg, bool is_tr)
|
||||
|
@ -1,5 +1,5 @@
|
||||
i386_softmmu_ss.add(when: 'CONFIG_WHPX', if_true: files(
|
||||
'whpx-all.c',
|
||||
'whpx-apic.c',
|
||||
'whpx-cpus.c',
|
||||
'whpx-accel-ops.c',
|
||||
))
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
#include "sysemu/whpx.h"
|
||||
#include "whpx-internal.h"
|
||||
#include "whpx-cpus.h"
|
||||
#include "whpx-accel-ops.h"
|
||||
|
||||
static void *whpx_cpu_thread_fn(void *arg)
|
||||
{
|
||||
@ -83,12 +83,29 @@ static void whpx_kick_vcpu_thread(CPUState *cpu)
|
||||
}
|
||||
}
|
||||
|
||||
const CpusAccel whpx_cpus = {
|
||||
.create_vcpu_thread = whpx_start_vcpu_thread,
|
||||
.kick_vcpu_thread = whpx_kick_vcpu_thread,
|
||||
static void whpx_accel_ops_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
|
||||
|
||||
.synchronize_post_reset = whpx_cpu_synchronize_post_reset,
|
||||
.synchronize_post_init = whpx_cpu_synchronize_post_init,
|
||||
.synchronize_state = whpx_cpu_synchronize_state,
|
||||
.synchronize_pre_loadvm = whpx_cpu_synchronize_pre_loadvm,
|
||||
ops->create_vcpu_thread = whpx_start_vcpu_thread;
|
||||
ops->kick_vcpu_thread = whpx_kick_vcpu_thread;
|
||||
|
||||
ops->synchronize_post_reset = whpx_cpu_synchronize_post_reset;
|
||||
ops->synchronize_post_init = whpx_cpu_synchronize_post_init;
|
||||
ops->synchronize_state = whpx_cpu_synchronize_state;
|
||||
ops->synchronize_pre_loadvm = whpx_cpu_synchronize_pre_loadvm;
|
||||
}
|
||||
|
||||
static const TypeInfo whpx_accel_ops_type = {
|
||||
.name = ACCEL_OPS_NAME("whpx"),
|
||||
|
||||
.parent = TYPE_ACCEL_OPS,
|
||||
.class_init = whpx_accel_ops_class_init,
|
||||
.abstract = true,
|
||||
};
|
||||
|
||||
static void whpx_accel_ops_register_types(void)
|
||||
{
|
||||
type_register_static(&whpx_accel_ops_type);
|
||||
}
|
||||
type_init(whpx_accel_ops_register_types);
|
@ -12,8 +12,6 @@
|
||||
|
||||
#include "sysemu/cpus.h"
|
||||
|
||||
extern const CpusAccel whpx_cpus;
|
||||
|
||||
int whpx_init_vcpu(CPUState *cpu);
|
||||
int whpx_vcpu_exec(CPUState *cpu);
|
||||
void whpx_destroy_vcpu(CPUState *cpu);
|
@ -28,8 +28,11 @@
|
||||
#include "migration/blocker.h"
|
||||
#include <winerror.h>
|
||||
|
||||
#include "whpx-cpus.h"
|
||||
#include "whpx-internal.h"
|
||||
#include "whpx-accel-ops.h"
|
||||
|
||||
#include <WinHvPlatform.h>
|
||||
#include <WinHvEmulation.h>
|
||||
|
||||
#define HYPERV_APIC_BUS_FREQUENCY (200000000ULL)
|
||||
|
||||
@ -1846,8 +1849,6 @@ static int whpx_accel_init(MachineState *ms)
|
||||
|
||||
whpx_memory_init();
|
||||
|
||||
cpus_register_accel(&whpx_cpus);
|
||||
|
||||
printf("Windows Hypervisor Platform accelerator is operational\n");
|
||||
return 0;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user