xref: /openbmc/qemu/accel/accel-common.c (revision f96b157ebb93f94cd56ebbc99bc20982b8fd86ef)
1 /*
2  * QEMU accel class, components common to system emulation and user mode
3  *
4  * Copyright (c) 2003-2008 Fabrice Bellard
5  * Copyright (c) 2014 Red Hat Inc.
6  *
7  * SPDX-License-Identifier: MIT
8  */
9 
10 #include "qemu/osdep.h"
11 #include "qemu/accel.h"
12 #include "qemu/target-info.h"
13 #include "accel/accel-ops.h"
14 #include "accel/accel-cpu.h"
15 #include "accel/accel-cpu-ops.h"
16 #include "accel-internal.h"
17 
18 /* Lookup AccelClass from opt_name. Returns NULL if not found */
accel_find(const char * opt_name)19 AccelClass *accel_find(const char *opt_name)
20 {
21     char *class_name = g_strdup_printf(ACCEL_CLASS_NAME("%s"), opt_name);
22     AccelClass *ac = ACCEL_CLASS(module_object_class_by_name(class_name));
23     g_free(class_name);
24     return ac;
25 }
26 
27 /* Return the name of the current accelerator */
current_accel_name(void)28 const char *current_accel_name(void)
29 {
30     AccelClass *ac = ACCEL_GET_CLASS(current_accel());
31 
32     return ac->name;
33 }
34 
accel_init_cpu_int_aux(ObjectClass * klass,void * opaque)35 static void accel_init_cpu_int_aux(ObjectClass *klass, void *opaque)
36 {
37     CPUClass *cc = CPU_CLASS(klass);
38     AccelCPUClass *accel_cpu = opaque;
39 
40     /*
41      * The first callback allows accel-cpu to run initializations
42      * for the CPU, customizing CPU behavior according to the accelerator.
43      *
44      * The second one allows the CPU to customize the accel-cpu
45      * behavior according to the CPU.
46      *
47      * The second is currently only used by TCG, to specialize the
48      * TCGCPUOps depending on the CPU type.
49      */
50     cc->accel_cpu = accel_cpu;
51     if (accel_cpu->cpu_class_init) {
52         accel_cpu->cpu_class_init(cc);
53     }
54     if (cc->init_accel_cpu) {
55         cc->init_accel_cpu(accel_cpu, cc);
56     }
57 }
58 
59 /* initialize the arch-specific accel CpuClass interfaces */
accel_init_cpu_interfaces(AccelClass * ac)60 static void accel_init_cpu_interfaces(AccelClass *ac)
61 {
62     const char *ac_name; /* AccelClass name */
63     char *acc_name;      /* AccelCPUClass name */
64     ObjectClass *acc;    /* AccelCPUClass */
65     const char *cpu_resolving_type = target_cpu_type();
66 
67     ac_name = object_class_get_name(OBJECT_CLASS(ac));
68     g_assert(ac_name != NULL);
69 
70     acc_name = g_strdup_printf("%s-%s", ac_name, cpu_resolving_type);
71     acc = object_class_by_name(acc_name);
72     g_free(acc_name);
73 
74     if (acc) {
75         object_class_foreach(accel_init_cpu_int_aux,
76                              cpu_resolving_type, false, acc);
77     }
78 }
79 
accel_init_interfaces(AccelClass * ac)80 void accel_init_interfaces(AccelClass *ac)
81 {
82     accel_init_ops_interfaces(ac);
83     accel_init_cpu_interfaces(ac);
84 }
85 
accel_cpu_instance_init(CPUState * cpu)86 void accel_cpu_instance_init(CPUState *cpu)
87 {
88     if (cpu->cc->accel_cpu && cpu->cc->accel_cpu->cpu_instance_init) {
89         cpu->cc->accel_cpu->cpu_instance_init(cpu);
90     }
91 }
92 
accel_cpu_common_realize(CPUState * cpu,Error ** errp)93 bool accel_cpu_common_realize(CPUState *cpu, Error **errp)
94 {
95     AccelState *accel = current_accel();
96     AccelClass *acc = ACCEL_GET_CLASS(accel);
97 
98     /* target specific realization */
99     if (cpu->cc->accel_cpu
100         && cpu->cc->accel_cpu->cpu_target_realize
101         && !cpu->cc->accel_cpu->cpu_target_realize(cpu, errp)) {
102         return false;
103     }
104 
105     /* generic realization */
106     if (acc->cpu_common_realize && !acc->cpu_common_realize(cpu, errp)) {
107         return false;
108     }
109 
110     return true;
111 }
112 
accel_cpu_common_unrealize(CPUState * cpu)113 void accel_cpu_common_unrealize(CPUState *cpu)
114 {
115     AccelState *accel = current_accel();
116     AccelClass *acc = ACCEL_GET_CLASS(accel);
117 
118     /* generic unrealization */
119     if (acc->cpu_common_unrealize) {
120         acc->cpu_common_unrealize(cpu);
121     }
122 }
123 
accel_supported_gdbstub_sstep_flags(void)124 int accel_supported_gdbstub_sstep_flags(void)
125 {
126     AccelState *accel = current_accel();
127     AccelClass *acc = ACCEL_GET_CLASS(accel);
128     if (acc->gdbstub_supported_sstep_flags) {
129         return acc->gdbstub_supported_sstep_flags(accel);
130     }
131     return 0;
132 }
133 
134 static const TypeInfo accel_types[] = {
135     {
136         .name           = TYPE_ACCEL,
137         .parent         = TYPE_OBJECT,
138         .class_size     = sizeof(AccelClass),
139         .instance_size  = sizeof(AccelState),
140         .abstract       = true,
141     },
142 };
143 
144 DEFINE_TYPES(accel_types)
145