xref: /qemu/accel/accel-target.c (revision 463b0068)
1e8b845b9SPhilippe Mathieu-Daudé /*
2e8b845b9SPhilippe Mathieu-Daudé  * QEMU accel class, components common to system emulation and user mode
3e8b845b9SPhilippe Mathieu-Daudé  *
4e8b845b9SPhilippe Mathieu-Daudé  * Copyright (c) 2003-2008 Fabrice Bellard
5e8b845b9SPhilippe Mathieu-Daudé  * Copyright (c) 2014 Red Hat Inc.
6e8b845b9SPhilippe Mathieu-Daudé  *
7e8b845b9SPhilippe Mathieu-Daudé  * Permission is hereby granted, free of charge, to any person obtaining a copy
8e8b845b9SPhilippe Mathieu-Daudé  * of this software and associated documentation files (the "Software"), to deal
9e8b845b9SPhilippe Mathieu-Daudé  * in the Software without restriction, including without limitation the rights
10e8b845b9SPhilippe Mathieu-Daudé  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11e8b845b9SPhilippe Mathieu-Daudé  * copies of the Software, and to permit persons to whom the Software is
12e8b845b9SPhilippe Mathieu-Daudé  * furnished to do so, subject to the following conditions:
13e8b845b9SPhilippe Mathieu-Daudé  *
14e8b845b9SPhilippe Mathieu-Daudé  * The above copyright notice and this permission notice shall be included in
15e8b845b9SPhilippe Mathieu-Daudé  * all copies or substantial portions of the Software.
16e8b845b9SPhilippe Mathieu-Daudé  *
17e8b845b9SPhilippe Mathieu-Daudé  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18e8b845b9SPhilippe Mathieu-Daudé  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19e8b845b9SPhilippe Mathieu-Daudé  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20e8b845b9SPhilippe Mathieu-Daudé  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21e8b845b9SPhilippe Mathieu-Daudé  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22e8b845b9SPhilippe Mathieu-Daudé  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23e8b845b9SPhilippe Mathieu-Daudé  * THE SOFTWARE.
24e8b845b9SPhilippe Mathieu-Daudé  */
25e8b845b9SPhilippe Mathieu-Daudé 
26e8b845b9SPhilippe Mathieu-Daudé #include "qemu/osdep.h"
27e8b845b9SPhilippe Mathieu-Daudé #include "qemu/accel.h"
28e8b845b9SPhilippe Mathieu-Daudé 
29e8b845b9SPhilippe Mathieu-Daudé #include "cpu.h"
30e8b845b9SPhilippe Mathieu-Daudé #include "hw/core/accel-cpu.h"
31e8b845b9SPhilippe Mathieu-Daudé 
32e8b845b9SPhilippe Mathieu-Daudé #ifndef CONFIG_USER_ONLY
330017c64eSPhilippe Mathieu-Daudé #include "accel-system.h"
34e8b845b9SPhilippe Mathieu-Daudé #endif /* !CONFIG_USER_ONLY */
35e8b845b9SPhilippe Mathieu-Daudé 
36e8b845b9SPhilippe Mathieu-Daudé static const TypeInfo accel_type = {
37e8b845b9SPhilippe Mathieu-Daudé     .name = TYPE_ACCEL,
38e8b845b9SPhilippe Mathieu-Daudé     .parent = TYPE_OBJECT,
39e8b845b9SPhilippe Mathieu-Daudé     .class_size = sizeof(AccelClass),
40e8b845b9SPhilippe Mathieu-Daudé     .instance_size = sizeof(AccelState),
41e8b845b9SPhilippe Mathieu-Daudé };
42e8b845b9SPhilippe Mathieu-Daudé 
43e8b845b9SPhilippe Mathieu-Daudé /* Lookup AccelClass from opt_name. Returns NULL if not found */
accel_find(const char * opt_name)44e8b845b9SPhilippe Mathieu-Daudé AccelClass *accel_find(const char *opt_name)
45e8b845b9SPhilippe Mathieu-Daudé {
46e8b845b9SPhilippe Mathieu-Daudé     char *class_name = g_strdup_printf(ACCEL_CLASS_NAME("%s"), opt_name);
47e8b845b9SPhilippe Mathieu-Daudé     AccelClass *ac = ACCEL_CLASS(module_object_class_by_name(class_name));
48e8b845b9SPhilippe Mathieu-Daudé     g_free(class_name);
49e8b845b9SPhilippe Mathieu-Daudé     return ac;
50e8b845b9SPhilippe Mathieu-Daudé }
51e8b845b9SPhilippe Mathieu-Daudé 
52e8b845b9SPhilippe Mathieu-Daudé /* Return the name of the current accelerator */
current_accel_name(void)53e8b845b9SPhilippe Mathieu-Daudé const char *current_accel_name(void)
54e8b845b9SPhilippe Mathieu-Daudé {
55e8b845b9SPhilippe Mathieu-Daudé     AccelClass *ac = ACCEL_GET_CLASS(current_accel());
56e8b845b9SPhilippe Mathieu-Daudé 
57e8b845b9SPhilippe Mathieu-Daudé     return ac->name;
58e8b845b9SPhilippe Mathieu-Daudé }
59e8b845b9SPhilippe Mathieu-Daudé 
accel_init_cpu_int_aux(ObjectClass * klass,void * opaque)60e8b845b9SPhilippe Mathieu-Daudé static void accel_init_cpu_int_aux(ObjectClass *klass, void *opaque)
61e8b845b9SPhilippe Mathieu-Daudé {
62e8b845b9SPhilippe Mathieu-Daudé     CPUClass *cc = CPU_CLASS(klass);
63e8b845b9SPhilippe Mathieu-Daudé     AccelCPUClass *accel_cpu = opaque;
64e8b845b9SPhilippe Mathieu-Daudé 
65e8b845b9SPhilippe Mathieu-Daudé     /*
66e8b845b9SPhilippe Mathieu-Daudé      * The first callback allows accel-cpu to run initializations
67e8b845b9SPhilippe Mathieu-Daudé      * for the CPU, customizing CPU behavior according to the accelerator.
68e8b845b9SPhilippe Mathieu-Daudé      *
69e8b845b9SPhilippe Mathieu-Daudé      * The second one allows the CPU to customize the accel-cpu
70e8b845b9SPhilippe Mathieu-Daudé      * behavior according to the CPU.
71e8b845b9SPhilippe Mathieu-Daudé      *
72e8b845b9SPhilippe Mathieu-Daudé      * The second is currently only used by TCG, to specialize the
73e8b845b9SPhilippe Mathieu-Daudé      * TCGCPUOps depending on the CPU type.
74e8b845b9SPhilippe Mathieu-Daudé      */
75e8b845b9SPhilippe Mathieu-Daudé     cc->accel_cpu = accel_cpu;
76e8b845b9SPhilippe Mathieu-Daudé     if (accel_cpu->cpu_class_init) {
77e8b845b9SPhilippe Mathieu-Daudé         accel_cpu->cpu_class_init(cc);
78e8b845b9SPhilippe Mathieu-Daudé     }
79e8b845b9SPhilippe Mathieu-Daudé     if (cc->init_accel_cpu) {
80e8b845b9SPhilippe Mathieu-Daudé         cc->init_accel_cpu(accel_cpu, cc);
81e8b845b9SPhilippe Mathieu-Daudé     }
82e8b845b9SPhilippe Mathieu-Daudé }
83e8b845b9SPhilippe Mathieu-Daudé 
84e8b845b9SPhilippe Mathieu-Daudé /* initialize the arch-specific accel CpuClass interfaces */
accel_init_cpu_interfaces(AccelClass * ac)85e8b845b9SPhilippe Mathieu-Daudé static void accel_init_cpu_interfaces(AccelClass *ac)
86e8b845b9SPhilippe Mathieu-Daudé {
87e8b845b9SPhilippe Mathieu-Daudé     const char *ac_name; /* AccelClass name */
88e8b845b9SPhilippe Mathieu-Daudé     char *acc_name;      /* AccelCPUClass name */
89e8b845b9SPhilippe Mathieu-Daudé     ObjectClass *acc;    /* AccelCPUClass */
90e8b845b9SPhilippe Mathieu-Daudé 
91e8b845b9SPhilippe Mathieu-Daudé     ac_name = object_class_get_name(OBJECT_CLASS(ac));
92e8b845b9SPhilippe Mathieu-Daudé     g_assert(ac_name != NULL);
93e8b845b9SPhilippe Mathieu-Daudé 
94e8b845b9SPhilippe Mathieu-Daudé     acc_name = g_strdup_printf("%s-%s", ac_name, CPU_RESOLVING_TYPE);
95e8b845b9SPhilippe Mathieu-Daudé     acc = object_class_by_name(acc_name);
96e8b845b9SPhilippe Mathieu-Daudé     g_free(acc_name);
97e8b845b9SPhilippe Mathieu-Daudé 
98e8b845b9SPhilippe Mathieu-Daudé     if (acc) {
99e8b845b9SPhilippe Mathieu-Daudé         object_class_foreach(accel_init_cpu_int_aux,
100e8b845b9SPhilippe Mathieu-Daudé                              CPU_RESOLVING_TYPE, false, acc);
101e8b845b9SPhilippe Mathieu-Daudé     }
102e8b845b9SPhilippe Mathieu-Daudé }
103e8b845b9SPhilippe Mathieu-Daudé 
accel_init_interfaces(AccelClass * ac)104e8b845b9SPhilippe Mathieu-Daudé void accel_init_interfaces(AccelClass *ac)
105e8b845b9SPhilippe Mathieu-Daudé {
106e8b845b9SPhilippe Mathieu-Daudé #ifndef CONFIG_USER_ONLY
107*463b0068SPhilippe Mathieu-Daudé     accel_system_init_ops_interfaces(ac);
108e8b845b9SPhilippe Mathieu-Daudé #endif /* !CONFIG_USER_ONLY */
109e8b845b9SPhilippe Mathieu-Daudé 
110e8b845b9SPhilippe Mathieu-Daudé     accel_init_cpu_interfaces(ac);
111e8b845b9SPhilippe Mathieu-Daudé }
112e8b845b9SPhilippe Mathieu-Daudé 
accel_cpu_instance_init(CPUState * cpu)113e8b845b9SPhilippe Mathieu-Daudé void accel_cpu_instance_init(CPUState *cpu)
114e8b845b9SPhilippe Mathieu-Daudé {
115e8b845b9SPhilippe Mathieu-Daudé     CPUClass *cc = CPU_GET_CLASS(cpu);
116e8b845b9SPhilippe Mathieu-Daudé 
117e8b845b9SPhilippe Mathieu-Daudé     if (cc->accel_cpu && cc->accel_cpu->cpu_instance_init) {
118e8b845b9SPhilippe Mathieu-Daudé         cc->accel_cpu->cpu_instance_init(cpu);
119e8b845b9SPhilippe Mathieu-Daudé     }
120e8b845b9SPhilippe Mathieu-Daudé }
121e8b845b9SPhilippe Mathieu-Daudé 
accel_cpu_common_realize(CPUState * cpu,Error ** errp)122e8b845b9SPhilippe Mathieu-Daudé bool accel_cpu_common_realize(CPUState *cpu, Error **errp)
123e8b845b9SPhilippe Mathieu-Daudé {
124e8b845b9SPhilippe Mathieu-Daudé     CPUClass *cc = CPU_GET_CLASS(cpu);
125e8b845b9SPhilippe Mathieu-Daudé     AccelState *accel = current_accel();
126e8b845b9SPhilippe Mathieu-Daudé     AccelClass *acc = ACCEL_GET_CLASS(accel);
127e8b845b9SPhilippe Mathieu-Daudé 
128e8b845b9SPhilippe Mathieu-Daudé     /* target specific realization */
129e8b845b9SPhilippe Mathieu-Daudé     if (cc->accel_cpu && cc->accel_cpu->cpu_target_realize
130e8b845b9SPhilippe Mathieu-Daudé         && !cc->accel_cpu->cpu_target_realize(cpu, errp)) {
131e8b845b9SPhilippe Mathieu-Daudé         return false;
132e8b845b9SPhilippe Mathieu-Daudé     }
133e8b845b9SPhilippe Mathieu-Daudé 
134e8b845b9SPhilippe Mathieu-Daudé     /* generic realization */
135e8b845b9SPhilippe Mathieu-Daudé     if (acc->cpu_common_realize && !acc->cpu_common_realize(cpu, errp)) {
136e8b845b9SPhilippe Mathieu-Daudé         return false;
137e8b845b9SPhilippe Mathieu-Daudé     }
138e8b845b9SPhilippe Mathieu-Daudé 
139e8b845b9SPhilippe Mathieu-Daudé     return true;
140e8b845b9SPhilippe Mathieu-Daudé }
141e8b845b9SPhilippe Mathieu-Daudé 
accel_cpu_common_unrealize(CPUState * cpu)142e8b845b9SPhilippe Mathieu-Daudé void accel_cpu_common_unrealize(CPUState *cpu)
143e8b845b9SPhilippe Mathieu-Daudé {
144e8b845b9SPhilippe Mathieu-Daudé     AccelState *accel = current_accel();
145e8b845b9SPhilippe Mathieu-Daudé     AccelClass *acc = ACCEL_GET_CLASS(accel);
146e8b845b9SPhilippe Mathieu-Daudé 
147e8b845b9SPhilippe Mathieu-Daudé     /* generic unrealization */
148e8b845b9SPhilippe Mathieu-Daudé     if (acc->cpu_common_unrealize) {
149e8b845b9SPhilippe Mathieu-Daudé         acc->cpu_common_unrealize(cpu);
150e8b845b9SPhilippe Mathieu-Daudé     }
151e8b845b9SPhilippe Mathieu-Daudé }
152e8b845b9SPhilippe Mathieu-Daudé 
accel_supported_gdbstub_sstep_flags(void)153e8b845b9SPhilippe Mathieu-Daudé int accel_supported_gdbstub_sstep_flags(void)
154e8b845b9SPhilippe Mathieu-Daudé {
155e8b845b9SPhilippe Mathieu-Daudé     AccelState *accel = current_accel();
156e8b845b9SPhilippe Mathieu-Daudé     AccelClass *acc = ACCEL_GET_CLASS(accel);
157e8b845b9SPhilippe Mathieu-Daudé     if (acc->gdbstub_supported_sstep_flags) {
158e8b845b9SPhilippe Mathieu-Daudé         return acc->gdbstub_supported_sstep_flags();
159e8b845b9SPhilippe Mathieu-Daudé     }
160e8b845b9SPhilippe Mathieu-Daudé     return 0;
161e8b845b9SPhilippe Mathieu-Daudé }
162e8b845b9SPhilippe Mathieu-Daudé 
163e8b845b9SPhilippe Mathieu-Daudé static const TypeInfo accel_cpu_type = {
164e8b845b9SPhilippe Mathieu-Daudé     .name = TYPE_ACCEL_CPU,
165e8b845b9SPhilippe Mathieu-Daudé     .parent = TYPE_OBJECT,
166e8b845b9SPhilippe Mathieu-Daudé     .abstract = true,
167e8b845b9SPhilippe Mathieu-Daudé     .class_size = sizeof(AccelCPUClass),
168e8b845b9SPhilippe Mathieu-Daudé };
169e8b845b9SPhilippe Mathieu-Daudé 
register_accel_types(void)170e8b845b9SPhilippe Mathieu-Daudé static void register_accel_types(void)
171e8b845b9SPhilippe Mathieu-Daudé {
172e8b845b9SPhilippe Mathieu-Daudé     type_register_static(&accel_type);
173e8b845b9SPhilippe Mathieu-Daudé     type_register_static(&accel_cpu_type);
174e8b845b9SPhilippe Mathieu-Daudé }
175e8b845b9SPhilippe Mathieu-Daudé 
176e8b845b9SPhilippe Mathieu-Daudé type_init(register_accel_types);
177