mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-07 09:43:56 -06:00
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
44 changed files with 361 additions and 163 deletions
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue