#include "qemu/osdep.h"
#include "qapi/error.h"
-#include "qemu-common.h"
#include "qom/cpu.h"
#include "sysemu/hw_accel.h"
#include "qemu/notify.h"
#include "qemu/log.h"
+#include "qemu/main-loop.h"
#include "exec/log.h"
-#include "exec/cpu-common.h"
#include "qemu/error-report.h"
+#include "qemu/qemu-print.h"
#include "sysemu/sysemu.h"
+#include "sysemu/tcg.h"
+#include "hw/boards.h"
#include "hw/qdev-properties.h"
#include "trace-root.h"
CPUInterruptHandler cpu_interrupt_handler;
-bool cpu_exists(int64_t id)
+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)
{
- char *str, *name, *featurestr;
- CPUState *cpu = NULL;
- ObjectClass *oc;
- CPUClass *cc;
- Error *err = NULL;
-
- str = g_strdup(cpu_model);
- name = strtok(str, ",");
-
- oc = cpu_class_by_name(typename, name);
- if (oc == NULL) {
- g_free(str);
- return NULL;
- }
-
- cc = CPU_CLASS(oc);
- featurestr = strtok(NULL, ",");
- /* TODO: all callers of cpu_generic_init() need to be converted to
- * call 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;
- }
+ return !!cpu_by_arch_id(id);
+}
- cpu = CPU(object_new(object_class_get_name(oc)));
+CPUState *cpu_create(const char *typename)
+{
+ Error *err = NULL;
+ CPUState *cpu = CPU(object_new(typename));
object_property_set_bool(OBJECT(cpu), true, "realized", &err);
-
-out:
if (err != NULL) {
error_report_err(err);
object_unref(OBJECT(cpu));
- return NULL;
+ exit(EXIT_FAILURE);
}
-
return cpu;
}
atomic_set(&cpu->exit_request, 1);
/* Ensure cpu_exec will see the exit request after TCG has exited. */
smp_wmb();
- atomic_set(&cpu->icount_decr.u16.high, -1);
+ atomic_set(&cpu->icount_decr_ptr->u16.high, -1);
}
int cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
return true;
}
-bool target_words_bigendian(void);
static bool cpu_common_virtio_is_big_endian(CPUState *cpu)
{
return target_words_bigendian();
return res;
}
-void cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
- int flags)
+void cpu_dump_state(CPUState *cpu, FILE *f, int flags)
{
CPUClass *cc = CPU_GET_CLASS(cpu);
if (cc->dump_state) {
cpu_synchronize_state(cpu);
- cc->dump_state(cpu, f, cpu_fprintf, flags);
+ cc->dump_state(cpu, f, flags);
}
}
-void cpu_dump_statistics(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
- int flags)
+void cpu_dump_statistics(CPUState *cpu, int flags)
{
CPUClass *cc = CPU_GET_CLASS(cpu);
if (cc->dump_statistics) {
- cc->dump_statistics(cpu, f, cpu_fprintf, flags);
+ cc->dump_statistics(cpu, flags);
}
}
cpu->mem_io_pc = 0;
cpu->mem_io_vaddr = 0;
cpu->icount_extra = 0;
- cpu->icount_decr.u32 = 0;
+ atomic_set(&cpu->icount_decr_ptr->u32, 0);
cpu->can_do_io = 1;
cpu->exception_index = -1;
cpu->crash_occurred = false;
+ cpu->cflags_next_tb = -1;
if (tcg_enabled()) {
cpu_tb_jmp_cache_clear(cpu);
{
CPUClass *cc = CPU_CLASS(object_class_by_name(typename));
+ assert(cpu_model && cc->class_by_name);
return cc->class_by_name(cpu_model);
}
-static ObjectClass *cpu_common_class_by_name(const char *cpu_model)
-{
- return NULL;
-}
-
static void cpu_common_parse_features(const char *typename, char *features,
Error **errp)
{
- char *featurestr; /* Single "key=value" string being parsed */
char *val;
static bool cpu_globals_initialized;
+ /* Single "key=value" string being parsed */
+ char *featurestr = features ? strtok(features, ",") : NULL;
- /* TODO: all callers of ->parse_features() need to be changed to
- * call it only once, so we can remove this check (or change it
- * to assert(!cpu_globals_initialized).
- * Current callers of ->parse_features() are:
- * - cpu_generic_init()
- */
- if (cpu_globals_initialized) {
- return;
- }
+ /* should be called only once, catch invalid users */
+ assert(!cpu_globals_initialized);
cpu_globals_initialized = true;
- featurestr = features ? strtok(features, ",") : NULL;
-
while (featurestr) {
val = strchr(featurestr, '=');
if (val) {
prop->driver = typename;
prop->property = g_strdup(featurestr);
prop->value = g_strdup(val);
- prop->errp = &error_fatal;
qdev_prop_register_global(prop);
} else {
error_setg(errp, "Expected key=value format, found %s.",
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);
cpu->cpu_index = UNASSIGNED_CPU_INDEX;
+ cpu->cluster_index = UNASSIGNED_CLUSTER_INDEX;
cpu->gdb_num_regs = cpu->gdb_num_g_regs = cc->gdb_num_core_regs;
/* *-user doesn't have configurable SMP topology */
/* the default value is changed by qemu_init_vcpu() for softmmu */
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);
+
+ qemu_mutex_destroy(&cpu->work_mutex);
}
static int64_t cpu_common_get_arch_id(CPUState *cpu)
DeviceClass *dc = DEVICE_CLASS(klass);
CPUClass *k = CPU_CLASS(klass);
- k->class_by_name = cpu_common_class_by_name;
k->parse_features = cpu_common_parse_features;
k->reset = cpu_common_reset;
k->get_arch_id = cpu_common_get_arch_id;
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, ...