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