#include "qemu/notify.h"
#include "qemu/log.h"
#include "exec/log.h"
+#include "exec/cpu-common.h"
#include "qemu/error-report.h"
#include "sysemu/sysemu.h"
+#include "hw/boards.h"
#include "hw/qdev-properties.h"
#include "trace-root.h"
-bool cpu_exists(int64_t id)
+CPUInterruptHandler cpu_interrupt_handler;
+
+CPUState *cpu_by_arch_id(int64_t id)
{
CPUState *cpu;
CPUClass *cc = CPU_GET_CLASS(cpu);
if (cc->get_arch_id(cpu) == id) {
- return true;
+ return cpu;
}
}
- return false;
+ return NULL;
}
-CPUState *cpu_generic_init(const char *typename, const char *cpu_model)
+bool cpu_exists(int64_t id)
+{
+ return !!cpu_by_arch_id(id);
+}
+
+CPUState *cpu_create(const char *typename)
+{
+ Error *err = NULL;
+ CPUState *cpu = CPU(object_new(typename));
+ object_property_set_bool(OBJECT(cpu), true, "realized", &err);
+ if (err != NULL) {
+ error_report_err(err);
+ object_unref(OBJECT(cpu));
+ exit(EXIT_FAILURE);
+ }
+ return cpu;
+}
+
+const char *cpu_parse_cpu_model(const char *typename, const char *cpu_model)
{
- char *str, *name, *featurestr;
- CPUState *cpu = NULL;
ObjectClass *oc;
CPUClass *cc;
- Error *err = NULL;
+ gchar **model_pieces;
+ const char *cpu_type;
- str = g_strdup(cpu_model);
- name = strtok(str, ",");
+ model_pieces = g_strsplit(cpu_model, ",", 2);
- oc = cpu_class_by_name(typename, name);
+ oc = cpu_class_by_name(typename, model_pieces[0]);
if (oc == NULL) {
- g_free(str);
- return NULL;
+ error_report("unable to find CPU model '%s'", model_pieces[0]);
+ g_strfreev(model_pieces);
+ exit(EXIT_FAILURE);
}
+ cpu_type = object_class_get_name(oc);
cc = CPU_CLASS(oc);
- featurestr = strtok(NULL, ",");
+ cc->parse_features(cpu_type, model_pieces[1], &error_fatal);
+ g_strfreev(model_pieces);
+ return cpu_type;
+}
+
+CPUState *cpu_generic_init(const char *typename, const char *cpu_model)
+{
/* TODO: all callers of cpu_generic_init() need to be converted to
- * call parse_features() only once, before calling cpu_generic_init().
+ * call cpu_parse_features() only once, before calling cpu_generic_init().
*/
- cc->parse_features(object_class_get_name(oc), featurestr, &err);
- g_free(str);
- if (err != NULL) {
- goto out;
- }
-
- cpu = CPU(object_new(object_class_get_name(oc)));
- object_property_set_bool(OBJECT(cpu), true, "realized", &err);
-
-out:
- if (err != NULL) {
- error_report_err(err);
- object_unref(OBJECT(cpu));
- return NULL;
- }
-
- return cpu;
+ return cpu_create(cpu_parse_cpu_model(typename, cpu_model));
}
bool cpu_paging_enabled(const CPUState *cpu)
static void cpu_common_reset(CPUState *cpu)
{
CPUClass *cc = CPU_GET_CLASS(cpu);
- int i;
if (qemu_loglevel_mask(CPU_LOG_RESET)) {
qemu_log("CPU Reset (CPU %d)\n", cpu->cpu_index);
cpu->can_do_io = 1;
cpu->exception_index = -1;
cpu->crash_occurred = false;
+ cpu->cflags_next_tb = -1;
if (tcg_enabled()) {
- for (i = 0; i < TB_JMP_CACHE_SIZE; ++i) {
- atomic_set(&cpu->tb_jmp_cache[i], NULL);
- }
+ cpu_tb_jmp_cache_clear(cpu);
-#ifdef CONFIG_SOFTMMU
- tlb_flush(cpu, 0);
-#endif
+ tcg_flush_softmmu_tlb(cpu);
}
}
ObjectClass *cpu_class_by_name(const char *typename, const char *cpu_model)
{
- CPUClass *cc = CPU_CLASS(object_class_by_name(typename));
+ CPUClass *cc;
+
+ if (!cpu_model) {
+ return NULL;
+ }
+ cc = CPU_CLASS(object_class_by_name(typename));
return cc->class_by_name(cpu_model);
}
static void cpu_common_realizefn(DeviceState *dev, Error **errp)
{
CPUState *cpu = CPU(dev);
+ Object *machine = qdev_get_machine();
+
+ /* qdev_get_machine() can return something that's not TYPE_MACHINE
+ * if this is one of the user-only emulators; in that case there's
+ * no need to check the ignore_memory_transaction_failures board flag.
+ */
+ if (object_dynamic_cast(machine, TYPE_MACHINE)) {
+ ObjectClass *oc = object_get_class(machine);
+ MachineClass *mc = MACHINE_CLASS(oc);
+
+ if (mc) {
+ cpu->ignore_memory_transaction_failures =
+ mc->ignore_memory_transaction_failures;
+ }
+ }
if (dev->hotplugged) {
cpu_synchronize_post_init(cpu);
static void cpu_common_initfn(Object *obj)
{
- uint32_t count;
CPUState *cpu = CPU(obj);
CPUClass *cc = CPU_GET_CLASS(obj);
QTAILQ_INIT(&cpu->breakpoints);
QTAILQ_INIT(&cpu->watchpoints);
- count = trace_get_vcpu_event_count();
- if (count) {
- cpu->trace_dstate = bitmap_new(count);
- }
-
cpu_exec_initfn(cpu);
}
static void cpu_common_finalize(Object *obj)
{
- CPUState *cpu = CPU(obj);
- g_free(cpu->trace_dstate);
}
static int64_t cpu_common_get_arch_id(CPUState *cpu)
return addr;
}
+static void generic_handle_interrupt(CPUState *cpu, int mask)
+{
+ cpu->interrupt_request |= mask;
+
+ if (!qemu_cpu_is_self(cpu)) {
+ qemu_cpu_kick(cpu);
+ }
+}
+
+CPUInterruptHandler cpu_interrupt_handler = generic_handle_interrupt;
+
static void cpu_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
set_bit(DEVICE_CATEGORY_CPU, dc->categories);
dc->realize = cpu_common_realizefn;
dc->unrealize = cpu_common_unrealizefn;
+ dc->props = cpu_common_props;
/*
* Reason: CPUs still need special care by board code: wiring up
* IRQs, adding reset handlers, halting non-first CPUs, ...
*/
- dc->cannot_instantiate_with_device_add_yet = true;
+ dc->user_creatable = false;
}
static const TypeInfo cpu_type_info = {