]>
Commit | Line | Data |
---|---|---|
032c76bc CW |
1 | /* |
2 | * QEMU Nios II CPU | |
3 | * | |
4 | * Copyright (c) 2012 Chris Wulff <crwulff@gmail.com> | |
5 | * | |
6 | * This library is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU Lesser General Public | |
8 | * License as published by the Free Software Foundation; either | |
9 | * version 2.1 of the License, or (at your option) any later version. | |
10 | * | |
11 | * This library is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | * Lesser General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU Lesser General Public | |
17 | * License along with this library; if not, see | |
18 | * <http://www.gnu.org/licenses/lgpl-2.1.html> | |
19 | */ | |
20 | ||
21 | #include "qemu/osdep.h" | |
0b8fa32f | 22 | #include "qemu/module.h" |
032c76bc CW |
23 | #include "qapi/error.h" |
24 | #include "cpu.h" | |
25 | #include "exec/log.h" | |
26 | #include "exec/gdbstub.h" | |
27 | #include "hw/qdev-properties.h" | |
28 | ||
29 | static void nios2_cpu_set_pc(CPUState *cs, vaddr value) | |
30 | { | |
31 | Nios2CPU *cpu = NIOS2_CPU(cs); | |
32 | CPUNios2State *env = &cpu->env; | |
33 | ||
17a406ee | 34 | env->pc = value; |
032c76bc CW |
35 | } |
36 | ||
37 | static bool nios2_cpu_has_work(CPUState *cs) | |
38 | { | |
e8d12542 | 39 | return cs->interrupt_request & CPU_INTERRUPT_HARD; |
032c76bc CW |
40 | } |
41 | ||
781c67ca | 42 | static void nios2_cpu_reset(DeviceState *dev) |
032c76bc | 43 | { |
781c67ca | 44 | CPUState *cs = CPU(dev); |
032c76bc CW |
45 | Nios2CPU *cpu = NIOS2_CPU(cs); |
46 | Nios2CPUClass *ncc = NIOS2_CPU_GET_CLASS(cpu); | |
47 | CPUNios2State *env = &cpu->env; | |
48 | ||
781c67ca | 49 | ncc->parent_reset(dev); |
032c76bc | 50 | |
b8f036a9 RH |
51 | memset(env->regs, 0, sizeof(env->regs)); |
52 | memset(env->ctrl, 0, sizeof(env->ctrl)); | |
17a406ee | 53 | env->pc = cpu->reset_addr; |
032c76bc CW |
54 | |
55 | #if defined(CONFIG_USER_ONLY) | |
56 | /* Start in user mode with interrupts enabled. */ | |
2de70d2d | 57 | env->ctrl[CR_STATUS] = CR_STATUS_RSIE | CR_STATUS_U | CR_STATUS_PIE; |
032c76bc | 58 | #else |
2de70d2d | 59 | env->ctrl[CR_STATUS] = CR_STATUS_RSIE; |
032c76bc CW |
60 | #endif |
61 | } | |
62 | ||
cd2528de PM |
63 | #ifndef CONFIG_USER_ONLY |
64 | static void nios2_cpu_set_irq(void *opaque, int irq, int level) | |
65 | { | |
66 | Nios2CPU *cpu = opaque; | |
67 | CPUNios2State *env = &cpu->env; | |
68 | CPUState *cs = CPU(cpu); | |
69 | ||
b8f036a9 | 70 | env->ctrl[CR_IPENDING] = deposit32(env->ctrl[CR_IPENDING], irq, 1, !!level); |
cd2528de | 71 | |
b8f036a9 | 72 | if (env->ctrl[CR_IPENDING]) { |
cd2528de | 73 | cpu_interrupt(cs, CPU_INTERRUPT_HARD); |
b72c9d59 | 74 | } else { |
cd2528de PM |
75 | cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); |
76 | } | |
77 | } | |
78 | #endif | |
79 | ||
032c76bc CW |
80 | static void nios2_cpu_initfn(Object *obj) |
81 | { | |
032c76bc | 82 | Nios2CPU *cpu = NIOS2_CPU(obj); |
032c76bc | 83 | |
7506ed90 | 84 | cpu_set_cpustate_pointers(cpu); |
032c76bc CW |
85 | |
86 | #if !defined(CONFIG_USER_ONLY) | |
7506ed90 | 87 | mmu_init(&cpu->env); |
cd2528de PM |
88 | |
89 | /* | |
90 | * These interrupt lines model the IIC (internal interrupt | |
91 | * controller). QEMU does not currently support the EIC | |
92 | * (external interrupt controller) -- if we did it would be | |
93 | * a separate device in hw/intc with a custom interface to | |
94 | * the CPU, and boards using it would not wire up these IRQ lines. | |
95 | */ | |
96 | qdev_init_gpio_in_named(DEVICE(cpu), nios2_cpu_set_irq, "IRQ", 32); | |
032c76bc | 97 | #endif |
032c76bc CW |
98 | } |
99 | ||
da9cbe02 | 100 | static ObjectClass *nios2_cpu_class_by_name(const char *cpu_model) |
032c76bc | 101 | { |
da9cbe02 | 102 | return object_class_by_name(TYPE_NIOS2_CPU); |
032c76bc CW |
103 | } |
104 | ||
796945d5 RH |
105 | static void realize_cr_status(CPUState *cs) |
106 | { | |
107 | Nios2CPU *cpu = NIOS2_CPU(cs); | |
108 | ||
109 | /* Begin with all fields of all registers are reserved. */ | |
110 | memset(cpu->cr_state, 0, sizeof(cpu->cr_state)); | |
111 | ||
112 | /* | |
113 | * The combination of writable and readonly is the set of all | |
114 | * non-reserved fields. We apply writable as a mask to bits, | |
115 | * and merge in existing readonly bits, before storing. | |
116 | */ | |
117 | #define WR_REG(C) cpu->cr_state[C].writable = -1 | |
118 | #define RO_REG(C) cpu->cr_state[C].readonly = -1 | |
119 | #define WR_FIELD(C, F) cpu->cr_state[C].writable |= R_##C##_##F##_MASK | |
120 | #define RO_FIELD(C, F) cpu->cr_state[C].readonly |= R_##C##_##F##_MASK | |
121 | ||
122 | WR_FIELD(CR_STATUS, PIE); | |
123 | WR_REG(CR_ESTATUS); | |
124 | WR_REG(CR_BSTATUS); | |
125 | RO_REG(CR_CPUID); | |
126 | RO_REG(CR_EXCEPTION); | |
127 | WR_REG(CR_BADADDR); | |
128 | ||
129 | /* TODO: These control registers are not present with the EIC. */ | |
2de70d2d | 130 | RO_FIELD(CR_STATUS, RSIE); |
796945d5 RH |
131 | WR_REG(CR_IENABLE); |
132 | RO_REG(CR_IPENDING); | |
133 | ||
134 | if (cpu->mmu_present) { | |
135 | WR_FIELD(CR_STATUS, U); | |
136 | WR_FIELD(CR_STATUS, EH); | |
137 | ||
138 | WR_FIELD(CR_PTEADDR, VPN); | |
139 | WR_FIELD(CR_PTEADDR, PTBASE); | |
140 | ||
141 | RO_FIELD(CR_TLBMISC, D); | |
142 | RO_FIELD(CR_TLBMISC, PERM); | |
143 | RO_FIELD(CR_TLBMISC, BAD); | |
144 | RO_FIELD(CR_TLBMISC, DBL); | |
145 | WR_FIELD(CR_TLBMISC, PID); | |
146 | WR_FIELD(CR_TLBMISC, WE); | |
147 | WR_FIELD(CR_TLBMISC, RD); | |
148 | WR_FIELD(CR_TLBMISC, WAY); | |
149 | ||
150 | WR_REG(CR_TLBACC); | |
151 | } | |
152 | ||
153 | /* | |
154 | * TODO: ECC (config, eccinj) and MPU (config, mpubase, mpuacc) are | |
155 | * unimplemented, so their corresponding control regs remain reserved. | |
156 | */ | |
157 | ||
158 | #undef WR_REG | |
159 | #undef RO_REG | |
160 | #undef WR_FIELD | |
161 | #undef RO_FIELD | |
162 | } | |
163 | ||
032c76bc CW |
164 | static void nios2_cpu_realizefn(DeviceState *dev, Error **errp) |
165 | { | |
166 | CPUState *cs = CPU(dev); | |
b05550af | 167 | Nios2CPU *cpu = NIOS2_CPU(cs); |
032c76bc CW |
168 | Nios2CPUClass *ncc = NIOS2_CPU_GET_CLASS(dev); |
169 | Error *local_err = NULL; | |
170 | ||
171 | cpu_exec_realizefn(cs, &local_err); | |
172 | if (local_err != NULL) { | |
173 | error_propagate(errp, local_err); | |
174 | return; | |
175 | } | |
176 | ||
796945d5 | 177 | realize_cr_status(cs); |
032c76bc CW |
178 | qemu_init_vcpu(cs); |
179 | cpu_reset(cs); | |
180 | ||
b05550af RH |
181 | /* We have reserved storage for cpuid; might as well use it. */ |
182 | cpu->env.ctrl[CR_CPUID] = cs->cpu_index; | |
183 | ||
032c76bc CW |
184 | ncc->parent_realize(dev, errp); |
185 | } | |
186 | ||
dabfe133 | 187 | #ifndef CONFIG_USER_ONLY |
032c76bc CW |
188 | static bool nios2_cpu_exec_interrupt(CPUState *cs, int interrupt_request) |
189 | { | |
190 | Nios2CPU *cpu = NIOS2_CPU(cs); | |
191 | CPUNios2State *env = &cpu->env; | |
192 | ||
193 | if ((interrupt_request & CPU_INTERRUPT_HARD) && | |
b8f036a9 RH |
194 | (env->ctrl[CR_STATUS] & CR_STATUS_PIE) && |
195 | (env->ctrl[CR_IPENDING] & env->ctrl[CR_IENABLE])) { | |
032c76bc CW |
196 | cs->exception_index = EXCP_IRQ; |
197 | nios2_cpu_do_interrupt(cs); | |
198 | return true; | |
199 | } | |
200 | return false; | |
201 | } | |
dabfe133 | 202 | #endif /* !CONFIG_USER_ONLY */ |
032c76bc CW |
203 | |
204 | static void nios2_cpu_disas_set_info(CPUState *cpu, disassemble_info *info) | |
205 | { | |
206 | /* NOTE: NiosII R2 is not supported yet. */ | |
207 | info->mach = bfd_arch_nios2; | |
dcc99bd8 | 208 | info->print_insn = print_insn_nios2; |
032c76bc CW |
209 | } |
210 | ||
a010bdbe | 211 | static int nios2_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) |
032c76bc CW |
212 | { |
213 | Nios2CPU *cpu = NIOS2_CPU(cs); | |
032c76bc | 214 | CPUNios2State *env = &cpu->env; |
796945d5 | 215 | uint32_t val; |
032c76bc CW |
216 | |
217 | if (n < 32) { /* GP regs */ | |
796945d5 | 218 | val = env->regs[n]; |
032c76bc | 219 | } else if (n == 32) { /* PC */ |
796945d5 | 220 | val = env->pc; |
032c76bc | 221 | } else if (n < 49) { /* Status regs */ |
796945d5 RH |
222 | unsigned cr = n - 33; |
223 | if (nios2_cr_reserved(&cpu->cr_state[cr])) { | |
224 | val = 0; | |
225 | } else { | |
226 | val = env->ctrl[n - 33]; | |
227 | } | |
228 | } else { | |
229 | /* Invalid regs */ | |
230 | return 0; | |
032c76bc CW |
231 | } |
232 | ||
796945d5 | 233 | return gdb_get_reg32(mem_buf, val); |
032c76bc CW |
234 | } |
235 | ||
236 | static int nios2_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) | |
237 | { | |
238 | Nios2CPU *cpu = NIOS2_CPU(cs); | |
239 | CPUClass *cc = CPU_GET_CLASS(cs); | |
240 | CPUNios2State *env = &cpu->env; | |
796945d5 | 241 | uint32_t val; |
032c76bc CW |
242 | |
243 | if (n > cc->gdb_num_core_regs) { | |
244 | return 0; | |
245 | } | |
796945d5 | 246 | val = ldl_p(mem_buf); |
032c76bc CW |
247 | |
248 | if (n < 32) { /* GP regs */ | |
796945d5 | 249 | env->regs[n] = val; |
032c76bc | 250 | } else if (n == 32) { /* PC */ |
796945d5 | 251 | env->pc = val; |
032c76bc | 252 | } else if (n < 49) { /* Status regs */ |
796945d5 RH |
253 | unsigned cr = n - 33; |
254 | /* ??? Maybe allow the debugger to write to readonly fields. */ | |
255 | val &= cpu->cr_state[cr].writable; | |
256 | val |= cpu->cr_state[cr].readonly & env->ctrl[cr]; | |
257 | env->ctrl[cr] = val; | |
258 | } else { | |
259 | g_assert_not_reached(); | |
032c76bc CW |
260 | } |
261 | ||
262 | return 4; | |
263 | } | |
264 | ||
265 | static Property nios2_properties[] = { | |
266 | DEFINE_PROP_BOOL("mmu_present", Nios2CPU, mmu_present, true), | |
267 | /* ALTR,pid-num-bits */ | |
268 | DEFINE_PROP_UINT32("mmu_pid_num_bits", Nios2CPU, pid_num_bits, 8), | |
269 | /* ALTR,tlb-num-ways */ | |
270 | DEFINE_PROP_UINT32("mmu_tlb_num_ways", Nios2CPU, tlb_num_ways, 16), | |
271 | /* ALTR,tlb-num-entries */ | |
272 | DEFINE_PROP_UINT32("mmu_pid_num_entries", Nios2CPU, tlb_num_entries, 256), | |
273 | DEFINE_PROP_END_OF_LIST(), | |
274 | }; | |
275 | ||
8b80bd28 PMD |
276 | #ifndef CONFIG_USER_ONLY |
277 | #include "hw/core/sysemu-cpu-ops.h" | |
278 | ||
279 | static const struct SysemuCPUOps nios2_sysemu_ops = { | |
08928c6d | 280 | .get_phys_page_debug = nios2_cpu_get_phys_page_debug, |
8b80bd28 PMD |
281 | }; |
282 | #endif | |
283 | ||
78271684 CF |
284 | #include "hw/core/tcg-cpu-ops.h" |
285 | ||
11906557 | 286 | static const struct TCGCPUOps nios2_tcg_ops = { |
78271684 | 287 | .initialize = nios2_tcg_init, |
78271684 | 288 | |
fb4de9d2 | 289 | #ifndef CONFIG_USER_ONLY |
fac94cb3 | 290 | .tlb_fill = nios2_cpu_tlb_fill, |
dabfe133 | 291 | .cpu_exec_interrupt = nios2_cpu_exec_interrupt, |
78271684 CF |
292 | .do_interrupt = nios2_cpu_do_interrupt, |
293 | .do_unaligned_access = nios2_cpu_do_unaligned_access, | |
294 | #endif /* !CONFIG_USER_ONLY */ | |
295 | }; | |
032c76bc CW |
296 | |
297 | static void nios2_cpu_class_init(ObjectClass *oc, void *data) | |
298 | { | |
299 | DeviceClass *dc = DEVICE_CLASS(oc); | |
300 | CPUClass *cc = CPU_CLASS(oc); | |
301 | Nios2CPUClass *ncc = NIOS2_CPU_CLASS(oc); | |
302 | ||
bf853881 PMD |
303 | device_class_set_parent_realize(dc, nios2_cpu_realizefn, |
304 | &ncc->parent_realize); | |
4f67d30b | 305 | device_class_set_props(dc, nios2_properties); |
781c67ca | 306 | device_class_set_parent_reset(dc, nios2_cpu_reset, &ncc->parent_reset); |
032c76bc | 307 | |
da9cbe02 | 308 | cc->class_by_name = nios2_cpu_class_by_name; |
032c76bc | 309 | cc->has_work = nios2_cpu_has_work; |
032c76bc CW |
310 | cc->dump_state = nios2_cpu_dump_state; |
311 | cc->set_pc = nios2_cpu_set_pc; | |
312 | cc->disas_set_info = nios2_cpu_disas_set_info; | |
0137c93f | 313 | #ifndef CONFIG_USER_ONLY |
8b80bd28 | 314 | cc->sysemu_ops = &nios2_sysemu_ops; |
032c76bc CW |
315 | #endif |
316 | cc->gdb_read_register = nios2_cpu_gdb_read_register; | |
317 | cc->gdb_write_register = nios2_cpu_gdb_write_register; | |
318 | cc->gdb_num_core_regs = 49; | |
78271684 | 319 | cc->tcg_ops = &nios2_tcg_ops; |
032c76bc CW |
320 | } |
321 | ||
322 | static const TypeInfo nios2_cpu_type_info = { | |
323 | .name = TYPE_NIOS2_CPU, | |
324 | .parent = TYPE_CPU, | |
325 | .instance_size = sizeof(Nios2CPU), | |
326 | .instance_init = nios2_cpu_initfn, | |
327 | .class_size = sizeof(Nios2CPUClass), | |
328 | .class_init = nios2_cpu_class_init, | |
329 | }; | |
330 | ||
331 | static void nios2_cpu_register_types(void) | |
332 | { | |
333 | type_register_static(&nios2_cpu_type_info); | |
334 | } | |
335 | ||
336 | type_init(nios2_cpu_register_types) |