1802c4dafSPhilippe Mathieu-Daudé /*
2802c4dafSPhilippe Mathieu-Daudé * QEMU accel class, components common to system emulation and user mode
3802c4dafSPhilippe Mathieu-Daudé *
4802c4dafSPhilippe Mathieu-Daudé * Copyright (c) 2003-2008 Fabrice Bellard
5802c4dafSPhilippe Mathieu-Daudé * Copyright (c) 2014 Red Hat Inc.
6802c4dafSPhilippe Mathieu-Daudé *
7802c4dafSPhilippe Mathieu-Daudé * SPDX-License-Identifier: MIT
8802c4dafSPhilippe Mathieu-Daudé */
9802c4dafSPhilippe Mathieu-Daudé
10802c4dafSPhilippe Mathieu-Daudé #include "qemu/osdep.h"
11802c4dafSPhilippe Mathieu-Daudé #include "qemu/accel.h"
12802c4dafSPhilippe Mathieu-Daudé #include "qemu/target-info.h"
13*f7a7e7ddSPhilippe Mathieu-Daudé #include "accel/accel-ops.h"
14802c4dafSPhilippe Mathieu-Daudé #include "accel/accel-cpu.h"
15*f7a7e7ddSPhilippe Mathieu-Daudé #include "accel/accel-cpu-ops.h"
16802c4dafSPhilippe Mathieu-Daudé #include "accel-internal.h"
17802c4dafSPhilippe Mathieu-Daudé
18802c4dafSPhilippe Mathieu-Daudé /* Lookup AccelClass from opt_name. Returns NULL if not found */
accel_find(const char * opt_name)19802c4dafSPhilippe Mathieu-Daudé AccelClass *accel_find(const char *opt_name)
20802c4dafSPhilippe Mathieu-Daudé {
21802c4dafSPhilippe Mathieu-Daudé char *class_name = g_strdup_printf(ACCEL_CLASS_NAME("%s"), opt_name);
22802c4dafSPhilippe Mathieu-Daudé AccelClass *ac = ACCEL_CLASS(module_object_class_by_name(class_name));
23802c4dafSPhilippe Mathieu-Daudé g_free(class_name);
24802c4dafSPhilippe Mathieu-Daudé return ac;
25802c4dafSPhilippe Mathieu-Daudé }
26802c4dafSPhilippe Mathieu-Daudé
27802c4dafSPhilippe Mathieu-Daudé /* Return the name of the current accelerator */
current_accel_name(void)28802c4dafSPhilippe Mathieu-Daudé const char *current_accel_name(void)
29802c4dafSPhilippe Mathieu-Daudé {
30802c4dafSPhilippe Mathieu-Daudé AccelClass *ac = ACCEL_GET_CLASS(current_accel());
31802c4dafSPhilippe Mathieu-Daudé
32802c4dafSPhilippe Mathieu-Daudé return ac->name;
33802c4dafSPhilippe Mathieu-Daudé }
34802c4dafSPhilippe Mathieu-Daudé
accel_init_cpu_int_aux(ObjectClass * klass,void * opaque)35802c4dafSPhilippe Mathieu-Daudé static void accel_init_cpu_int_aux(ObjectClass *klass, void *opaque)
36802c4dafSPhilippe Mathieu-Daudé {
37802c4dafSPhilippe Mathieu-Daudé CPUClass *cc = CPU_CLASS(klass);
38802c4dafSPhilippe Mathieu-Daudé AccelCPUClass *accel_cpu = opaque;
39802c4dafSPhilippe Mathieu-Daudé
40802c4dafSPhilippe Mathieu-Daudé /*
41802c4dafSPhilippe Mathieu-Daudé * The first callback allows accel-cpu to run initializations
42802c4dafSPhilippe Mathieu-Daudé * for the CPU, customizing CPU behavior according to the accelerator.
43802c4dafSPhilippe Mathieu-Daudé *
44802c4dafSPhilippe Mathieu-Daudé * The second one allows the CPU to customize the accel-cpu
45802c4dafSPhilippe Mathieu-Daudé * behavior according to the CPU.
46802c4dafSPhilippe Mathieu-Daudé *
47802c4dafSPhilippe Mathieu-Daudé * The second is currently only used by TCG, to specialize the
48802c4dafSPhilippe Mathieu-Daudé * TCGCPUOps depending on the CPU type.
49802c4dafSPhilippe Mathieu-Daudé */
50802c4dafSPhilippe Mathieu-Daudé cc->accel_cpu = accel_cpu;
51802c4dafSPhilippe Mathieu-Daudé if (accel_cpu->cpu_class_init) {
52802c4dafSPhilippe Mathieu-Daudé accel_cpu->cpu_class_init(cc);
53802c4dafSPhilippe Mathieu-Daudé }
54802c4dafSPhilippe Mathieu-Daudé if (cc->init_accel_cpu) {
55802c4dafSPhilippe Mathieu-Daudé cc->init_accel_cpu(accel_cpu, cc);
56802c4dafSPhilippe Mathieu-Daudé }
57802c4dafSPhilippe Mathieu-Daudé }
58802c4dafSPhilippe Mathieu-Daudé
59802c4dafSPhilippe Mathieu-Daudé /* initialize the arch-specific accel CpuClass interfaces */
accel_init_cpu_interfaces(AccelClass * ac)60802c4dafSPhilippe Mathieu-Daudé static void accel_init_cpu_interfaces(AccelClass *ac)
61802c4dafSPhilippe Mathieu-Daudé {
62802c4dafSPhilippe Mathieu-Daudé const char *ac_name; /* AccelClass name */
63802c4dafSPhilippe Mathieu-Daudé char *acc_name; /* AccelCPUClass name */
64802c4dafSPhilippe Mathieu-Daudé ObjectClass *acc; /* AccelCPUClass */
65802c4dafSPhilippe Mathieu-Daudé const char *cpu_resolving_type = target_cpu_type();
66802c4dafSPhilippe Mathieu-Daudé
67802c4dafSPhilippe Mathieu-Daudé ac_name = object_class_get_name(OBJECT_CLASS(ac));
68802c4dafSPhilippe Mathieu-Daudé g_assert(ac_name != NULL);
69802c4dafSPhilippe Mathieu-Daudé
70802c4dafSPhilippe Mathieu-Daudé acc_name = g_strdup_printf("%s-%s", ac_name, cpu_resolving_type);
71802c4dafSPhilippe Mathieu-Daudé acc = object_class_by_name(acc_name);
72802c4dafSPhilippe Mathieu-Daudé g_free(acc_name);
73802c4dafSPhilippe Mathieu-Daudé
74802c4dafSPhilippe Mathieu-Daudé if (acc) {
75802c4dafSPhilippe Mathieu-Daudé object_class_foreach(accel_init_cpu_int_aux,
76802c4dafSPhilippe Mathieu-Daudé cpu_resolving_type, false, acc);
77802c4dafSPhilippe Mathieu-Daudé }
78802c4dafSPhilippe Mathieu-Daudé }
79802c4dafSPhilippe Mathieu-Daudé
accel_init_interfaces(AccelClass * ac)80802c4dafSPhilippe Mathieu-Daudé void accel_init_interfaces(AccelClass *ac)
81802c4dafSPhilippe Mathieu-Daudé {
82802c4dafSPhilippe Mathieu-Daudé accel_init_ops_interfaces(ac);
83802c4dafSPhilippe Mathieu-Daudé accel_init_cpu_interfaces(ac);
84802c4dafSPhilippe Mathieu-Daudé }
85802c4dafSPhilippe Mathieu-Daudé
accel_cpu_instance_init(CPUState * cpu)86802c4dafSPhilippe Mathieu-Daudé void accel_cpu_instance_init(CPUState *cpu)
87802c4dafSPhilippe Mathieu-Daudé {
88802c4dafSPhilippe Mathieu-Daudé if (cpu->cc->accel_cpu && cpu->cc->accel_cpu->cpu_instance_init) {
89802c4dafSPhilippe Mathieu-Daudé cpu->cc->accel_cpu->cpu_instance_init(cpu);
90802c4dafSPhilippe Mathieu-Daudé }
91802c4dafSPhilippe Mathieu-Daudé }
92802c4dafSPhilippe Mathieu-Daudé
accel_cpu_common_realize(CPUState * cpu,Error ** errp)93802c4dafSPhilippe Mathieu-Daudé bool accel_cpu_common_realize(CPUState *cpu, Error **errp)
94802c4dafSPhilippe Mathieu-Daudé {
95802c4dafSPhilippe Mathieu-Daudé AccelState *accel = current_accel();
96802c4dafSPhilippe Mathieu-Daudé AccelClass *acc = ACCEL_GET_CLASS(accel);
97802c4dafSPhilippe Mathieu-Daudé
98802c4dafSPhilippe Mathieu-Daudé /* target specific realization */
99802c4dafSPhilippe Mathieu-Daudé if (cpu->cc->accel_cpu
100802c4dafSPhilippe Mathieu-Daudé && cpu->cc->accel_cpu->cpu_target_realize
101802c4dafSPhilippe Mathieu-Daudé && !cpu->cc->accel_cpu->cpu_target_realize(cpu, errp)) {
102802c4dafSPhilippe Mathieu-Daudé return false;
103802c4dafSPhilippe Mathieu-Daudé }
104802c4dafSPhilippe Mathieu-Daudé
105802c4dafSPhilippe Mathieu-Daudé /* generic realization */
106802c4dafSPhilippe Mathieu-Daudé if (acc->cpu_common_realize && !acc->cpu_common_realize(cpu, errp)) {
107802c4dafSPhilippe Mathieu-Daudé return false;
108802c4dafSPhilippe Mathieu-Daudé }
109802c4dafSPhilippe Mathieu-Daudé
110802c4dafSPhilippe Mathieu-Daudé return true;
111802c4dafSPhilippe Mathieu-Daudé }
112802c4dafSPhilippe Mathieu-Daudé
accel_cpu_common_unrealize(CPUState * cpu)113802c4dafSPhilippe Mathieu-Daudé void accel_cpu_common_unrealize(CPUState *cpu)
114802c4dafSPhilippe Mathieu-Daudé {
115802c4dafSPhilippe Mathieu-Daudé AccelState *accel = current_accel();
116802c4dafSPhilippe Mathieu-Daudé AccelClass *acc = ACCEL_GET_CLASS(accel);
117802c4dafSPhilippe Mathieu-Daudé
118802c4dafSPhilippe Mathieu-Daudé /* generic unrealization */
119802c4dafSPhilippe Mathieu-Daudé if (acc->cpu_common_unrealize) {
120802c4dafSPhilippe Mathieu-Daudé acc->cpu_common_unrealize(cpu);
121802c4dafSPhilippe Mathieu-Daudé }
122802c4dafSPhilippe Mathieu-Daudé }
123802c4dafSPhilippe Mathieu-Daudé
accel_supported_gdbstub_sstep_flags(void)124802c4dafSPhilippe Mathieu-Daudé int accel_supported_gdbstub_sstep_flags(void)
125802c4dafSPhilippe Mathieu-Daudé {
126802c4dafSPhilippe Mathieu-Daudé AccelState *accel = current_accel();
127802c4dafSPhilippe Mathieu-Daudé AccelClass *acc = ACCEL_GET_CLASS(accel);
128802c4dafSPhilippe Mathieu-Daudé if (acc->gdbstub_supported_sstep_flags) {
129842e7eecSPhilippe Mathieu-Daudé return acc->gdbstub_supported_sstep_flags(accel);
130802c4dafSPhilippe Mathieu-Daudé }
131802c4dafSPhilippe Mathieu-Daudé return 0;
132802c4dafSPhilippe Mathieu-Daudé }
133802c4dafSPhilippe Mathieu-Daudé
134802c4dafSPhilippe Mathieu-Daudé static const TypeInfo accel_types[] = {
135802c4dafSPhilippe Mathieu-Daudé {
136802c4dafSPhilippe Mathieu-Daudé .name = TYPE_ACCEL,
137802c4dafSPhilippe Mathieu-Daudé .parent = TYPE_OBJECT,
138802c4dafSPhilippe Mathieu-Daudé .class_size = sizeof(AccelClass),
139802c4dafSPhilippe Mathieu-Daudé .instance_size = sizeof(AccelState),
140802c4dafSPhilippe Mathieu-Daudé .abstract = true,
141802c4dafSPhilippe Mathieu-Daudé },
142802c4dafSPhilippe Mathieu-Daudé };
143802c4dafSPhilippe Mathieu-Daudé
144802c4dafSPhilippe Mathieu-Daudé DEFINE_TYPES(accel_types)
145