root / target-xtensa / cpu.c @ 5b50e790
History | View | Annotate | Download (5 kB)
1 |
/*
|
---|---|
2 |
* QEMU Xtensa CPU
|
3 |
*
|
4 |
* Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
|
5 |
* Copyright (c) 2012 SUSE LINUX Products GmbH
|
6 |
* All rights reserved.
|
7 |
*
|
8 |
* Redistribution and use in source and binary forms, with or without
|
9 |
* modification, are permitted provided that the following conditions are met:
|
10 |
* * Redistributions of source code must retain the above copyright
|
11 |
* notice, this list of conditions and the following disclaimer.
|
12 |
* * Redistributions in binary form must reproduce the above copyright
|
13 |
* notice, this list of conditions and the following disclaimer in the
|
14 |
* documentation and/or other materials provided with the distribution.
|
15 |
* * Neither the name of the Open Source and Linux Lab nor the
|
16 |
* names of its contributors may be used to endorse or promote products
|
17 |
* derived from this software without specific prior written permission.
|
18 |
*
|
19 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20 |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
23 |
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
24 |
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
25 |
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
26 |
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
27 |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
28 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29 |
*/
|
30 |
|
31 |
#include "cpu.h" |
32 |
#include "qemu-common.h" |
33 |
#include "migration/vmstate.h" |
34 |
|
35 |
|
36 |
static void xtensa_cpu_set_pc(CPUState *cs, vaddr value) |
37 |
{ |
38 |
XtensaCPU *cpu = XTENSA_CPU(cs); |
39 |
|
40 |
cpu->env.pc = value; |
41 |
} |
42 |
|
43 |
/* CPUClass::reset() */
|
44 |
static void xtensa_cpu_reset(CPUState *s) |
45 |
{ |
46 |
XtensaCPU *cpu = XTENSA_CPU(s); |
47 |
XtensaCPUClass *xcc = XTENSA_CPU_GET_CLASS(cpu); |
48 |
CPUXtensaState *env = &cpu->env; |
49 |
|
50 |
xcc->parent_reset(s); |
51 |
|
52 |
env->exception_taken = 0;
|
53 |
env->pc = env->config->exception_vector[EXC_RESET]; |
54 |
env->sregs[LITBASE] &= ~1;
|
55 |
env->sregs[PS] = xtensa_option_enabled(env->config, |
56 |
XTENSA_OPTION_INTERRUPT) ? 0x1f : 0x10; |
57 |
env->sregs[VECBASE] = env->config->vecbase; |
58 |
env->sregs[IBREAKENABLE] = 0;
|
59 |
env->sregs[CACHEATTR] = 0x22222222;
|
60 |
env->sregs[ATOMCTL] = xtensa_option_enabled(env->config, |
61 |
XTENSA_OPTION_ATOMCTL) ? 0x28 : 0x15; |
62 |
|
63 |
env->pending_irq_level = 0;
|
64 |
reset_mmu(env); |
65 |
} |
66 |
|
67 |
static ObjectClass *xtensa_cpu_class_by_name(const char *cpu_model) |
68 |
{ |
69 |
ObjectClass *oc; |
70 |
char *typename;
|
71 |
|
72 |
if (cpu_model == NULL) { |
73 |
return NULL; |
74 |
} |
75 |
|
76 |
typename = g_strdup_printf("%s-" TYPE_XTENSA_CPU, cpu_model);
|
77 |
oc = object_class_by_name(typename); |
78 |
g_free(typename); |
79 |
if (oc == NULL || !object_class_dynamic_cast(oc, TYPE_XTENSA_CPU) || |
80 |
object_class_is_abstract(oc)) { |
81 |
return NULL; |
82 |
} |
83 |
return oc;
|
84 |
} |
85 |
|
86 |
static void xtensa_cpu_realizefn(DeviceState *dev, Error **errp) |
87 |
{ |
88 |
CPUState *cs = CPU(dev); |
89 |
XtensaCPUClass *xcc = XTENSA_CPU_GET_CLASS(dev); |
90 |
|
91 |
cs->gdb_num_regs = xcc->config->gdb_regmap.num_regs; |
92 |
|
93 |
xcc->parent_realize(dev, errp); |
94 |
} |
95 |
|
96 |
static void xtensa_cpu_initfn(Object *obj) |
97 |
{ |
98 |
CPUState *cs = CPU(obj); |
99 |
XtensaCPU *cpu = XTENSA_CPU(obj); |
100 |
XtensaCPUClass *xcc = XTENSA_CPU_GET_CLASS(obj); |
101 |
CPUXtensaState *env = &cpu->env; |
102 |
static bool tcg_inited; |
103 |
|
104 |
cs->env_ptr = env; |
105 |
env->config = xcc->config; |
106 |
cpu_exec_init(env); |
107 |
|
108 |
if (tcg_enabled() && !tcg_inited) {
|
109 |
tcg_inited = true;
|
110 |
xtensa_translate_init(); |
111 |
cpu_set_debug_excp_handler(xtensa_breakpoint_handler); |
112 |
} |
113 |
} |
114 |
|
115 |
static const VMStateDescription vmstate_xtensa_cpu = { |
116 |
.name = "cpu",
|
117 |
.unmigratable = 1,
|
118 |
}; |
119 |
|
120 |
static void xtensa_cpu_class_init(ObjectClass *oc, void *data) |
121 |
{ |
122 |
DeviceClass *dc = DEVICE_CLASS(oc); |
123 |
CPUClass *cc = CPU_CLASS(oc); |
124 |
XtensaCPUClass *xcc = XTENSA_CPU_CLASS(cc); |
125 |
|
126 |
xcc->parent_realize = dc->realize; |
127 |
dc->realize = xtensa_cpu_realizefn; |
128 |
|
129 |
xcc->parent_reset = cc->reset; |
130 |
cc->reset = xtensa_cpu_reset; |
131 |
|
132 |
cc->class_by_name = xtensa_cpu_class_by_name; |
133 |
cc->do_interrupt = xtensa_cpu_do_interrupt; |
134 |
cc->dump_state = xtensa_cpu_dump_state; |
135 |
cc->set_pc = xtensa_cpu_set_pc; |
136 |
cc->gdb_read_register = xtensa_cpu_gdb_read_register; |
137 |
cc->gdb_write_register = xtensa_cpu_gdb_write_register; |
138 |
#ifndef CONFIG_USER_ONLY
|
139 |
cc->get_phys_page_debug = xtensa_cpu_get_phys_page_debug; |
140 |
#endif
|
141 |
dc->vmsd = &vmstate_xtensa_cpu; |
142 |
} |
143 |
|
144 |
static const TypeInfo xtensa_cpu_type_info = { |
145 |
.name = TYPE_XTENSA_CPU, |
146 |
.parent = TYPE_CPU, |
147 |
.instance_size = sizeof(XtensaCPU),
|
148 |
.instance_init = xtensa_cpu_initfn, |
149 |
.abstract = true,
|
150 |
.class_size = sizeof(XtensaCPUClass),
|
151 |
.class_init = xtensa_cpu_class_init, |
152 |
}; |
153 |
|
154 |
static void xtensa_cpu_register_types(void) |
155 |
{ |
156 |
type_register_static(&xtensa_cpu_type_info); |
157 |
} |
158 |
|
159 |
type_init(xtensa_cpu_register_types) |