/* * QEMU Xtensa CPU * * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab. * Copyright (c) 2012 SUSE LINUX Products GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Open Source and Linux Lab nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "cpu.h" #include "qemu-common.h" #include "migration/vmstate.h" /* CPUClass::reset() */ static void xtensa_cpu_reset(CPUState *s) { XtensaCPU *cpu = XTENSA_CPU(s); XtensaCPUClass *xcc = XTENSA_CPU_GET_CLASS(cpu); CPUXtensaState *env = &cpu->env; xcc->parent_reset(s); env->exception_taken = 0; env->pc = env->config->exception_vector[EXC_RESET]; env->sregs[LITBASE] &= ~1; env->sregs[PS] = xtensa_option_enabled(env->config, XTENSA_OPTION_INTERRUPT) ? 0x1f : 0x10; env->sregs[VECBASE] = env->config->vecbase; env->sregs[IBREAKENABLE] = 0; env->sregs[CACHEATTR] = 0x22222222; env->sregs[ATOMCTL] = xtensa_option_enabled(env->config, XTENSA_OPTION_ATOMCTL) ? 0x28 : 0x15; env->pending_irq_level = 0; reset_mmu(env); } static void xtensa_cpu_realizefn(DeviceState *dev, Error **errp) { XtensaCPU *cpu = XTENSA_CPU(dev); XtensaCPUClass *xcc = XTENSA_CPU_GET_CLASS(dev); qemu_init_vcpu(&cpu->env); xcc->parent_realize(dev, errp); } static void xtensa_cpu_initfn(Object *obj) { CPUState *cs = CPU(obj); XtensaCPU *cpu = XTENSA_CPU(obj); CPUXtensaState *env = &cpu->env; static bool tcg_inited; cs->env_ptr = env; cpu_exec_init(env); if (tcg_enabled() && !tcg_inited) { tcg_inited = true; xtensa_translate_init(); cpu_set_debug_excp_handler(xtensa_breakpoint_handler); } } static const VMStateDescription vmstate_xtensa_cpu = { .name = "cpu", .unmigratable = 1, }; static void xtensa_cpu_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); CPUClass *cc = CPU_CLASS(oc); XtensaCPUClass *xcc = XTENSA_CPU_CLASS(cc); xcc->parent_realize = dc->realize; dc->realize = xtensa_cpu_realizefn; xcc->parent_reset = cc->reset; cc->reset = xtensa_cpu_reset; cc->do_interrupt = xtensa_cpu_do_interrupt; dc->vmsd = &vmstate_xtensa_cpu; } static const TypeInfo xtensa_cpu_type_info = { .name = TYPE_XTENSA_CPU, .parent = TYPE_CPU, .instance_size = sizeof(XtensaCPU), .instance_init = xtensa_cpu_initfn, .abstract = false, .class_size = sizeof(XtensaCPUClass), .class_init = xtensa_cpu_class_init, }; static void xtensa_cpu_register_types(void) { type_register_static(&xtensa_cpu_type_info); } type_init(xtensa_cpu_register_types)