8 void cpu_reset(CPUARMState *env)
10 #if defined (CONFIG_USER_ONLY)
11 env->uncached_cpsr = ARM_CPU_MODE_USR;
12 env->vfp.xregs[ARM_VFP_FPEXC] = 1 << 30;
14 /* SVC mode with interrupts disabled. */
15 env->uncached_cpsr = ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
16 env->vfp.xregs[ARM_VFP_FPEXC] = 0;
21 CPUARMState *cpu_arm_init(void)
25 env = qemu_mallocz(sizeof(CPUARMState));
34 static inline void set_feature(CPUARMState *env, int feature)
36 env->features |= 1u << feature;
39 void cpu_arm_set_model(CPUARMState *env, uint32_t id)
41 env->cp15.c0_cpuid = id;
43 case ARM_CPUID_ARM926:
44 set_feature(env, ARM_FEATURE_VFP);
45 env->vfp.xregs[ARM_VFP_FPSID] = 0x41011090;
47 case ARM_CPUID_ARM1026:
48 set_feature(env, ARM_FEATURE_VFP);
49 set_feature(env, ARM_FEATURE_AUXCR);
50 env->vfp.xregs[ARM_VFP_FPSID] = 0x410110a0;
53 cpu_abort(env, "Bad CPU ID: %x\n", id);
58 void cpu_arm_close(CPUARMState *env)
63 #if defined(CONFIG_USER_ONLY)
65 void do_interrupt (CPUState *env)
67 env->exception_index = -1;
70 int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
71 int is_user, int is_softmmu)
74 env->exception_index = EXCP_PREFETCH_ABORT;
75 env->cp15.c6_insn = address;
77 env->exception_index = EXCP_DATA_ABORT;
78 env->cp15.c6_data = address;
83 target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
88 /* These should probably raise undefined insn exceptions. */
89 void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
91 cpu_abort(env, "cp15 insn %08x\n", insn);
94 uint32_t helper_get_cp15(CPUState *env, uint32_t insn)
96 cpu_abort(env, "cp15 insn %08x\n", insn);
100 void switch_mode(CPUState *env, int mode)
102 if (mode != ARM_CPU_MODE_USR)
103 cpu_abort(env, "Tried to switch out of user mode\n");
108 /* Map CPU modes onto saved register banks. */
109 static inline int bank_number (int mode)
112 case ARM_CPU_MODE_USR:
113 case ARM_CPU_MODE_SYS:
115 case ARM_CPU_MODE_SVC:
117 case ARM_CPU_MODE_ABT:
119 case ARM_CPU_MODE_UND:
121 case ARM_CPU_MODE_IRQ:
123 case ARM_CPU_MODE_FIQ:
126 cpu_abort(cpu_single_env, "Bad mode %x\n", mode);
130 void switch_mode(CPUState *env, int mode)
135 old_mode = env->uncached_cpsr & CPSR_M;
136 if (mode == old_mode)
139 if (old_mode == ARM_CPU_MODE_FIQ) {
140 memcpy (env->fiq_regs, env->regs + 8, 5 * sizeof(uint32_t));
141 memcpy (env->regs + 8, env->usr_regs, 5 * sizeof(uint32_t));
142 } else if (mode == ARM_CPU_MODE_FIQ) {
143 memcpy (env->usr_regs, env->regs + 8, 5 * sizeof(uint32_t));
144 memcpy (env->regs + 8, env->fiq_regs, 5 * sizeof(uint32_t));
147 i = bank_number(old_mode);
148 env->banked_r13[i] = env->regs[13];
149 env->banked_r14[i] = env->regs[14];
150 env->banked_spsr[i] = env->spsr;
152 i = bank_number(mode);
153 env->regs[13] = env->banked_r13[i];
154 env->regs[14] = env->banked_r14[i];
155 env->spsr = env->banked_spsr[i];
158 /* Handle a CPU exception. */
159 void do_interrupt(CPUARMState *env)
166 /* TODO: Vectored interrupt controller. */
167 switch (env->exception_index) {
169 new_mode = ARM_CPU_MODE_UND;
178 new_mode = ARM_CPU_MODE_SVC;
181 /* The PC already points to the next instructon. */
184 case EXCP_PREFETCH_ABORT:
186 new_mode = ARM_CPU_MODE_ABT;
188 mask = CPSR_A | CPSR_I;
191 case EXCP_DATA_ABORT:
192 new_mode = ARM_CPU_MODE_ABT;
194 mask = CPSR_A | CPSR_I;
198 new_mode = ARM_CPU_MODE_IRQ;
200 /* Disable IRQ and imprecise data aborts. */
201 mask = CPSR_A | CPSR_I;
205 new_mode = ARM_CPU_MODE_FIQ;
207 /* Disable FIQ, IRQ and imprecise data aborts. */
208 mask = CPSR_A | CPSR_I | CPSR_F;
212 cpu_abort(env, "Unhandled exception 0x%x\n", env->exception_index);
213 return; /* Never happens. Keep compiler happy. */
216 if (env->cp15.c1_sys & (1 << 13)) {
219 switch_mode (env, new_mode);
220 env->spsr = cpsr_read(env);
221 /* Switch to the new mode, and switch to Arm mode. */
222 /* ??? Thumb interrupt handlers not implemented. */
223 env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
224 env->uncached_cpsr |= mask;
226 env->regs[14] = env->regs[15] + offset;
227 env->regs[15] = addr;
228 env->interrupt_request |= CPU_INTERRUPT_EXITTB;
231 /* Check section/page access permissions.
232 Returns the page protection flags, or zero if the access is not
234 static inline int check_ap(CPUState *env, int ap, int domain, int access_type,
238 return PAGE_READ | PAGE_WRITE;
242 if (access_type != 1)
244 switch ((env->cp15.c1_sys >> 8) & 3) {
246 return is_user ? 0 : PAGE_READ;
253 return is_user ? 0 : PAGE_READ | PAGE_WRITE;
256 return (access_type == 1) ? 0 : PAGE_READ;
258 return PAGE_READ | PAGE_WRITE;
260 return PAGE_READ | PAGE_WRITE;
266 static int get_phys_addr(CPUState *env, uint32_t address, int access_type,
267 int is_user, uint32_t *phys_ptr, int *prot)
277 /* Fast Context Switch Extension. */
278 if (address < 0x02000000)
279 address += env->cp15.c13_fcse;
281 if ((env->cp15.c1_sys & 1) == 0) {
284 *prot = PAGE_READ | PAGE_WRITE;
286 /* Pagetable walk. */
287 /* Lookup l1 descriptor. */
288 table = (env->cp15.c2 & 0xffffc000) | ((address >> 18) & 0x3ffc);
289 desc = ldl_phys(table);
291 domain = (env->cp15.c3 >> ((desc >> 4) & 0x1e)) & 3;
293 /* Secton translation fault. */
297 if (domain == 0 || domain == 2) {
299 code = 9; /* Section domain fault. */
301 code = 11; /* Page domain fault. */
306 phys_addr = (desc & 0xfff00000) | (address & 0x000fffff);
307 ap = (desc >> 10) & 3;
310 /* Lookup l2 entry. */
311 table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
312 desc = ldl_phys(table);
314 case 0: /* Page translation fault. */
317 case 1: /* 64k page. */
318 phys_addr = (desc & 0xffff0000) | (address & 0xffff);
319 ap = (desc >> (4 + ((address >> 13) & 6))) & 3;
321 case 2: /* 4k page. */
322 phys_addr = (desc & 0xfffff000) | (address & 0xfff);
323 ap = (desc >> (4 + ((address >> 13) & 6))) & 3;
325 case 3: /* 1k page. */
327 /* Page translation fault. */
331 phys_addr = (desc & 0xfffffc00) | (address & 0x3ff);
332 ap = (desc >> 4) & 3;
335 /* Never happens, but compiler isn't smart enough to tell. */
340 *prot = check_ap(env, ap, domain, access_type, is_user);
342 /* Access permission fault. */
345 *phys_ptr = phys_addr;
349 return code | (domain << 4);
352 int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address,
353 int access_type, int is_user, int is_softmmu)
359 ret = get_phys_addr(env, address, access_type, is_user, &phys_addr, &prot);
361 /* Map a single [sub]page. */
362 phys_addr &= ~(uint32_t)0x3ff;
363 address &= ~(uint32_t)0x3ff;
364 return tlb_set_page (env, address, phys_addr, prot, is_user,
368 if (access_type == 2) {
369 env->cp15.c5_insn = ret;
370 env->cp15.c6_insn = address;
371 env->exception_index = EXCP_PREFETCH_ABORT;
373 env->cp15.c5_data = ret;
374 env->cp15.c6_data = address;
375 env->exception_index = EXCP_DATA_ABORT;
380 target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
386 ret = get_phys_addr(env, addr, 0, 0, &phys_addr, &prot);
394 void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
398 op2 = (insn >> 5) & 7;
399 switch ((insn >> 16) & 0xf) {
400 case 0: /* ID codes. */
402 case 1: /* System configuration. */
405 env->cp15.c1_sys = val;
406 /* ??? Lots of these bits are not implemented. */
407 /* This may enable/disable the MMU, so do a TLB flush. */
411 env->cp15.c1_coproc = val;
412 /* ??? Is this safe when called from within a TB? */
418 case 2: /* MMU Page table control. */
421 case 3: /* MMU Domain access control. */
424 case 4: /* Reserved. */
426 case 5: /* MMU Fault status. */
429 env->cp15.c5_data = val;
432 env->cp15.c5_insn = val;
438 case 6: /* MMU Fault address. */
441 env->cp15.c6_data = val;
444 env->cp15.c6_insn = val;
450 case 7: /* Cache control. */
451 /* No cache, so nothing to do. */
453 case 8: /* MMU TLB control. */
455 case 0: /* Invalidate all. */
458 case 1: /* Invalidate single TLB entry. */
460 /* ??? This is wrong for large pages and sections. */
461 /* As an ugly hack to make linux work we always flush a 4K
464 tlb_flush_page(env, val);
465 tlb_flush_page(env, val + 0x400);
466 tlb_flush_page(env, val + 0x800);
467 tlb_flush_page(env, val + 0xc00);
476 case 9: /* Cache lockdown. */
479 env->cp15.c9_data = val;
482 env->cp15.c9_insn = val;
488 case 10: /* MMU TLB lockdown. */
489 /* ??? TLB lockdown not implemented. */
491 case 11: /* TCM DMA control. */
492 case 12: /* Reserved. */
494 case 13: /* Process ID. */
497 /* Unlike real hardware the qemu TLB uses virtual addresses,
498 not modified virtual addresses, so this causes a TLB flush.
500 if (env->cp15.c13_fcse != val)
502 env->cp15.c13_fcse = val;
505 /* This changes the ASID, so do a TLB flush. */
506 if (env->cp15.c13_context != val)
508 env->cp15.c13_context = val;
514 case 14: /* Reserved. */
516 case 15: /* Implementation specific. */
517 /* ??? Internal registers not implemented. */
522 /* ??? For debugging only. Should raise illegal instruction exception. */
523 cpu_abort(env, "Unimplemented cp15 register read\n");
526 uint32_t helper_get_cp15(CPUState *env, uint32_t insn)
530 op2 = (insn >> 5) & 7;
531 switch ((insn >> 16) & 0xf) {
532 case 0: /* ID codes. */
534 default: /* Device ID. */
535 return env->cp15.c0_cpuid;
536 case 1: /* Cache Type. */
538 case 2: /* TCM status. */
541 case 1: /* System configuration. */
543 case 0: /* Control register. */
544 return env->cp15.c1_sys;
545 case 1: /* Auxiliary control register. */
546 if (arm_feature(env, ARM_FEATURE_AUXCR))
549 case 2: /* Coprocessor access register. */
550 return env->cp15.c1_coproc;
554 case 2: /* MMU Page table control. */
556 case 3: /* MMU Domain access control. */
558 case 4: /* Reserved. */
560 case 5: /* MMU Fault status. */
563 return env->cp15.c5_data;
565 return env->cp15.c5_insn;
569 case 6: /* MMU Fault address. */
572 return env->cp15.c6_data;
574 /* Arm9 doesn't have an IFAR, but implementing it anyway shouldn't
576 return env->cp15.c6_insn;
580 case 7: /* Cache control. */
581 /* ??? This is for test, clean and invaidate operations that set the
582 Z flag. We can't represent N = Z = 1, so it also clears clears
583 the N flag. Oh well. */
586 case 8: /* MMU TLB control. */
588 case 9: /* Cache lockdown. */
591 return env->cp15.c9_data;
593 return env->cp15.c9_insn;
597 case 10: /* MMU TLB lockdown. */
598 /* ??? TLB lockdown not implemented. */
600 case 11: /* TCM DMA control. */
601 case 12: /* Reserved. */
603 case 13: /* Process ID. */
606 return env->cp15.c13_fcse;
608 return env->cp15.c13_context;
612 case 14: /* Reserved. */
614 case 15: /* Implementation specific. */
615 /* ??? Internal registers not implemented. */
619 /* ??? For debugging only. Should raise illegal instruction exception. */
620 cpu_abort(env, "Unimplemented cp15 register read\n");