| 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 */ |
| 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 */ |
| 28 | const char *current_accel_name(void) |
| 29 | { |
| 30 | AccelClass *ac = ACCEL_GET_CLASS(current_accel()); |
| 31 | |
| 32 | return ac->name; |
| 33 | } |
| 34 | |
| 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 | cc->accel_cpu = accel_cpu; |
| 41 | if (accel_cpu->cpu_class_init) { |
| 42 | accel_cpu->cpu_class_init(cc); |
| 43 | } |
| 44 | } |
| 45 | |
| 46 | /* initialize the arch-specific accel CpuClass interfaces */ |
| 47 | static void accel_init_cpu_interfaces(AccelClass *ac) |
| 48 | { |
| 49 | const char *ac_name; /* AccelClass name */ |
| 50 | char *acc_name; /* AccelCPUClass name */ |
| 51 | ObjectClass *acc; /* AccelCPUClass */ |
| 52 | const char *cpu_resolving_type = target_cpu_type(); |
| 53 | |
| 54 | ac_name = object_class_get_name(OBJECT_CLASS(ac)); |
| 55 | g_assert(ac_name != NULL); |
| 56 | |
| 57 | acc_name = g_strdup_printf("%s-%s", ac_name, cpu_resolving_type); |
| 58 | acc = object_class_by_name(acc_name); |
| 59 | g_free(acc_name); |
| 60 | |
| 61 | if (acc) { |
| 62 | object_class_foreach(accel_init_cpu_int_aux, |
| 63 | cpu_resolving_type, false, acc); |
| 64 | } |
| 65 | } |
| 66 | |
| 67 | void accel_init_interfaces(AccelClass *ac) |
| 68 | { |
| 69 | accel_init_ops_interfaces(ac); |
| 70 | accel_init_cpu_interfaces(ac); |
| 71 | } |
| 72 | |
| 73 | bool accel_supports_guest_debug(AccelState *accel) |
| 74 | { |
| 75 | return accel->gdbstub.sstep_flags & SSTEP_ENABLE; |
| 76 | } |
| 77 | |
| 78 | void accel_cpu_instance_init(CPUState *cpu) |
| 79 | { |
| 80 | if (cpu->cc->accel_cpu && cpu->cc->accel_cpu->cpu_instance_init) { |
| 81 | cpu->cc->accel_cpu->cpu_instance_init(cpu); |
| 82 | } |
| 83 | } |
| 84 | |
| 85 | bool accel_cpu_common_realize(CPUState *cpu, Error **errp) |
| 86 | { |
| 87 | AccelState *accel = current_accel(); |
| 88 | AccelClass *acc = ACCEL_GET_CLASS(accel); |
| 89 | |
| 90 | /* target specific realization */ |
| 91 | if (cpu->cc->accel_cpu |
| 92 | && cpu->cc->accel_cpu->cpu_target_realize |
| 93 | && !cpu->cc->accel_cpu->cpu_target_realize(cpu, errp)) { |
| 94 | return false; |
| 95 | } |
| 96 | |
| 97 | /* generic realization */ |
| 98 | if (acc->cpu_common_realize && !acc->cpu_common_realize(cpu, errp)) { |
| 99 | return false; |
| 100 | } |
| 101 | if (acc->ops |
| 102 | && acc->ops->cpu_target_realize |
| 103 | && !acc->ops->cpu_target_realize(cpu, errp)) { |
| 104 | return false; |
| 105 | } |
| 106 | |
| 107 | return true; |
| 108 | } |
| 109 | |
| 110 | void accel_cpu_common_unrealize(CPUState *cpu) |
| 111 | { |
| 112 | AccelState *accel = current_accel(); |
| 113 | AccelClass *acc = ACCEL_GET_CLASS(accel); |
| 114 | |
| 115 | /* generic unrealization */ |
| 116 | if (acc->cpu_common_unrealize) { |
| 117 | acc->cpu_common_unrealize(cpu); |
| 118 | } |
| 119 | } |
| 120 | |
| 121 | static const TypeInfo accel_types[] = { |
| 122 | { |
| 123 | .name = TYPE_ACCEL, |
| 124 | .parent = TYPE_OBJECT, |
| 125 | .class_size = sizeof(AccelClass), |
| 126 | .instance_size = sizeof(AccelState), |
| 127 | .abstract = true, |
| 128 | }, |
| 129 | }; |
| 130 | |
| 131 | DEFINE_TYPES(accel_types) |
| 132 | |
| 133 | static void register_accel_target_type(void) |
| 134 | { |
| 135 | g_autofree char *name = g_strconcat("accel-", target_cpu_type(), NULL); |
| 136 | const TypeInfo accel_cpu_type = { |
| 137 | .name = name, |
| 138 | .parent = TYPE_OBJECT, |
| 139 | .abstract = true, |
| 140 | .class_size = sizeof(AccelCPUClass), |
| 141 | }; |
| 142 | |
| 143 | type_register_static(&accel_cpu_type); |
| 144 | } |
| 145 | |
| 146 | type_init(register_accel_target_type); |