Fix ARM fine pagetables.
[qemu] / target-arm / helper.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #include "cpu.h"
6 #include "exec-all.h"
7
8 static inline void set_feature(CPUARMState *env, int feature)
9 {
10     env->features |= 1u << feature;
11 }
12
13 static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
14 {
15     env->cp15.c0_cpuid = id;
16     switch (id) {
17     case ARM_CPUID_ARM926:
18         set_feature(env, ARM_FEATURE_VFP);
19         env->vfp.xregs[ARM_VFP_FPSID] = 0x41011090;
20         break;
21     case ARM_CPUID_ARM1026:
22         set_feature(env, ARM_FEATURE_VFP);
23         set_feature(env, ARM_FEATURE_AUXCR);
24         env->vfp.xregs[ARM_VFP_FPSID] = 0x410110a0;
25         break;
26     default:
27         cpu_abort(env, "Bad CPU ID: %x\n", id);
28         break;
29     }
30 }
31
32 void cpu_reset(CPUARMState *env)
33 {
34     uint32_t id;
35     id = env->cp15.c0_cpuid;
36     memset(env, 0, offsetof(CPUARMState, breakpoints));
37     if (id)
38         cpu_reset_model_id(env, id);
39 #if defined (CONFIG_USER_ONLY)
40     env->uncached_cpsr = ARM_CPU_MODE_USR;
41     env->vfp.xregs[ARM_VFP_FPEXC] = 1 << 30;
42 #else
43     /* SVC mode with interrupts disabled.  */
44     env->uncached_cpsr = ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
45     env->vfp.xregs[ARM_VFP_FPEXC] = 0;
46 #endif
47     env->regs[15] = 0;
48     tlb_flush(env, 1);
49 }
50
51 CPUARMState *cpu_arm_init(void)
52 {
53     CPUARMState *env;
54
55     env = qemu_mallocz(sizeof(CPUARMState));
56     if (!env)
57         return NULL;
58     cpu_exec_init(env);
59     cpu_reset(env);
60     return env;
61 }
62
63 struct arm_cpu_t {
64     uint32_t id;
65     const char *name;
66 };
67
68 static const struct arm_cpu_t arm_cpu_names[] = {
69     { ARM_CPUID_ARM926, "arm926"},
70     { ARM_CPUID_ARM1026, "arm1026"},
71     { 0, NULL}
72 };
73
74 void arm_cpu_list(void)
75 {
76     int i;
77
78     printf ("Available CPUs:\n");
79     for (i = 0; arm_cpu_names[i].name; i++) {
80         printf("  %s\n", arm_cpu_names[i].name);
81     }
82 }
83
84 void cpu_arm_set_model(CPUARMState *env, const char *name)
85 {
86     int i;
87     uint32_t id;
88
89     id = 0;
90     i = 0;
91     for (i = 0; arm_cpu_names[i].name; i++) {
92         if (strcmp(name, arm_cpu_names[i].name) == 0) {
93             id = arm_cpu_names[i].id;
94             break;
95         }
96     }
97     if (!id) {
98         cpu_abort(env, "Unknown CPU '%s'", name);
99         return;
100     }
101     cpu_reset_model_id(env, id);
102 }
103
104 void cpu_arm_close(CPUARMState *env)
105 {
106     free(env);
107 }
108
109 #if defined(CONFIG_USER_ONLY) 
110
111 void do_interrupt (CPUState *env)
112 {
113     env->exception_index = -1;
114 }
115
116 int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
117                               int is_user, int is_softmmu)
118 {
119     if (rw == 2) {
120         env->exception_index = EXCP_PREFETCH_ABORT;
121         env->cp15.c6_insn = address;
122     } else {
123         env->exception_index = EXCP_DATA_ABORT;
124         env->cp15.c6_data = address;
125     }
126     return 1;
127 }
128
129 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
130 {
131     return addr;
132 }
133
134 /* These should probably raise undefined insn exceptions.  */
135 void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
136 {
137     cpu_abort(env, "cp15 insn %08x\n", insn);
138 }
139
140 uint32_t helper_get_cp15(CPUState *env, uint32_t insn)
141 {
142     cpu_abort(env, "cp15 insn %08x\n", insn);
143     return 0;
144 }
145
146 void switch_mode(CPUState *env, int mode)
147 {
148     if (mode != ARM_CPU_MODE_USR)
149         cpu_abort(env, "Tried to switch out of user mode\n");
150 }
151
152 #else
153
154 extern int semihosting_enabled;
155
156 /* Map CPU modes onto saved register banks.  */
157 static inline int bank_number (int mode)
158 {
159     switch (mode) {
160     case ARM_CPU_MODE_USR:
161     case ARM_CPU_MODE_SYS:
162         return 0;
163     case ARM_CPU_MODE_SVC:
164         return 1;
165     case ARM_CPU_MODE_ABT:
166         return 2;
167     case ARM_CPU_MODE_UND:
168         return 3;
169     case ARM_CPU_MODE_IRQ:
170         return 4;
171     case ARM_CPU_MODE_FIQ:
172         return 5;
173     }
174     cpu_abort(cpu_single_env, "Bad mode %x\n", mode);
175     return -1;
176 }
177
178 void switch_mode(CPUState *env, int mode)
179 {
180     int old_mode;
181     int i;
182
183     old_mode = env->uncached_cpsr & CPSR_M;
184     if (mode == old_mode)
185         return;
186
187     if (old_mode == ARM_CPU_MODE_FIQ) {
188         memcpy (env->fiq_regs, env->regs + 8, 5 * sizeof(uint32_t));
189         memcpy (env->regs + 8, env->usr_regs, 5 * sizeof(uint32_t));
190     } else if (mode == ARM_CPU_MODE_FIQ) {
191         memcpy (env->usr_regs, env->regs + 8, 5 * sizeof(uint32_t));
192         memcpy (env->regs + 8, env->fiq_regs, 5 * sizeof(uint32_t));
193     }
194
195     i = bank_number(old_mode);
196     env->banked_r13[i] = env->regs[13];
197     env->banked_r14[i] = env->regs[14];
198     env->banked_spsr[i] = env->spsr;
199
200     i = bank_number(mode);
201     env->regs[13] = env->banked_r13[i];
202     env->regs[14] = env->banked_r14[i];
203     env->spsr = env->banked_spsr[i];
204 }
205
206 /* Handle a CPU exception.  */
207 void do_interrupt(CPUARMState *env)
208 {
209     uint32_t addr;
210     uint32_t mask;
211     int new_mode;
212     uint32_t offset;
213
214     /* TODO: Vectored interrupt controller.  */
215     switch (env->exception_index) {
216     case EXCP_UDEF:
217         new_mode = ARM_CPU_MODE_UND;
218         addr = 0x04;
219         mask = CPSR_I;
220         if (env->thumb)
221             offset = 2;
222         else
223             offset = 4;
224         break;
225     case EXCP_SWI:
226         if (semihosting_enabled) {
227             /* Check for semihosting interrupt.  */
228             if (env->thumb) {
229                 mask = lduw_code(env->regs[15] - 2) & 0xff;
230             } else {
231                 mask = ldl_code(env->regs[15] - 4) & 0xffffff;
232             }
233             /* Only intercept calls from privileged modes, to provide some
234                semblance of security.  */
235             if (((mask == 0x123456 && !env->thumb)
236                     || (mask == 0xab && env->thumb))
237                   && (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {
238                 env->regs[0] = do_arm_semihosting(env);
239                 return;
240             }
241         }
242         new_mode = ARM_CPU_MODE_SVC;
243         addr = 0x08;
244         mask = CPSR_I;
245         /* The PC already points to the next instructon.  */
246         offset = 0;
247         break;
248     case EXCP_PREFETCH_ABORT:
249     case EXCP_BKPT:
250         new_mode = ARM_CPU_MODE_ABT;
251         addr = 0x0c;
252         mask = CPSR_A | CPSR_I;
253         offset = 4;
254         break;
255     case EXCP_DATA_ABORT:
256         new_mode = ARM_CPU_MODE_ABT;
257         addr = 0x10;
258         mask = CPSR_A | CPSR_I;
259         offset = 8;
260         break;
261     case EXCP_IRQ:
262         new_mode = ARM_CPU_MODE_IRQ;
263         addr = 0x18;
264         /* Disable IRQ and imprecise data aborts.  */
265         mask = CPSR_A | CPSR_I;
266         offset = 4;
267         break;
268     case EXCP_FIQ:
269         new_mode = ARM_CPU_MODE_FIQ;
270         addr = 0x1c;
271         /* Disable FIQ, IRQ and imprecise data aborts.  */
272         mask = CPSR_A | CPSR_I | CPSR_F;
273         offset = 4;
274         break;
275     default:
276         cpu_abort(env, "Unhandled exception 0x%x\n", env->exception_index);
277         return; /* Never happens.  Keep compiler happy.  */
278     }
279     /* High vectors.  */
280     if (env->cp15.c1_sys & (1 << 13)) {
281         addr += 0xffff0000;
282     }
283     switch_mode (env, new_mode);
284     env->spsr = cpsr_read(env);
285     /* Switch to the new mode, and switch to Arm mode.  */
286     /* ??? Thumb interrupt handlers not implemented.  */
287     env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
288     env->uncached_cpsr |= mask;
289     env->thumb = 0;
290     env->regs[14] = env->regs[15] + offset;
291     env->regs[15] = addr;
292     env->interrupt_request |= CPU_INTERRUPT_EXITTB;
293 }
294
295 /* Check section/page access permissions.
296    Returns the page protection flags, or zero if the access is not
297    permitted.  */
298 static inline int check_ap(CPUState *env, int ap, int domain, int access_type,
299                            int is_user)
300 {
301   if (domain == 3)
302     return PAGE_READ | PAGE_WRITE;
303
304   switch (ap) {
305   case 0:
306       if (access_type == 1)
307           return 0;
308       switch ((env->cp15.c1_sys >> 8) & 3) {
309       case 1:
310           return is_user ? 0 : PAGE_READ;
311       case 2:
312           return PAGE_READ;
313       default:
314           return 0;
315       }
316   case 1:
317       return is_user ? 0 : PAGE_READ | PAGE_WRITE;
318   case 2:
319       if (is_user)
320           return (access_type == 1) ? 0 : PAGE_READ;
321       else
322           return PAGE_READ | PAGE_WRITE;
323   case 3:
324       return PAGE_READ | PAGE_WRITE;
325   default:
326       abort();
327   }
328 }
329
330 static int get_phys_addr(CPUState *env, uint32_t address, int access_type,
331                          int is_user, uint32_t *phys_ptr, int *prot)
332 {
333     int code;
334     uint32_t table;
335     uint32_t desc;
336     int type;
337     int ap;
338     int domain;
339     uint32_t phys_addr;
340
341     /* Fast Context Switch Extension.  */
342     if (address < 0x02000000)
343         address += env->cp15.c13_fcse;
344
345     if ((env->cp15.c1_sys & 1) == 0) {
346         /* MMU diusabled.  */
347         *phys_ptr = address;
348         *prot = PAGE_READ | PAGE_WRITE;
349     } else {
350         /* Pagetable walk.  */
351         /* Lookup l1 descriptor.  */
352         table = (env->cp15.c2 & 0xffffc000) | ((address >> 18) & 0x3ffc);
353         desc = ldl_phys(table);
354         type = (desc & 3);
355         domain = (env->cp15.c3 >> ((desc >> 4) & 0x1e)) & 3;
356         if (type == 0) {
357             /* Secton translation fault.  */
358             code = 5;
359             goto do_fault;
360         }
361         if (domain == 0 || domain == 2) {
362             if (type == 2)
363                 code = 9; /* Section domain fault.  */
364             else
365                 code = 11; /* Page domain fault.  */
366             goto do_fault;
367         }
368         if (type == 2) {
369             /* 1Mb section.  */
370             phys_addr = (desc & 0xfff00000) | (address & 0x000fffff);
371             ap = (desc >> 10) & 3;
372             code = 13;
373         } else {
374             /* Lookup l2 entry.  */
375             if (type == 1) {
376                 /* Coarse pagetable.  */
377                 table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
378             } else {
379                 /* Fine pagetable.  */
380                 table = (desc & 0xfffff000) | ((address >> 8) & 0xffc);
381             }
382             desc = ldl_phys(table);
383             switch (desc & 3) {
384             case 0: /* Page translation fault.  */
385                 code = 7;
386                 goto do_fault;
387             case 1: /* 64k page.  */
388                 phys_addr = (desc & 0xffff0000) | (address & 0xffff);
389                 ap = (desc >> (4 + ((address >> 13) & 6))) & 3;
390                 break;
391             case 2: /* 4k page.  */
392                 phys_addr = (desc & 0xfffff000) | (address & 0xfff);
393                 ap = (desc >> (4 + ((address >> 13) & 6))) & 3;
394                 break;
395             case 3: /* 1k page.  */
396                 if (type == 1) {
397                     /* Page translation fault.  */
398                     code = 7;
399                     goto do_fault;
400                 }
401                 phys_addr = (desc & 0xfffffc00) | (address & 0x3ff);
402                 ap = (desc >> 4) & 3;
403                 break;
404             default:
405                 /* Never happens, but compiler isn't smart enough to tell.  */
406                 abort();
407             }
408             code = 15;
409         }
410         *prot = check_ap(env, ap, domain, access_type, is_user);
411         if (!*prot) {
412             /* Access permission fault.  */
413             goto do_fault;
414         }
415         *phys_ptr = phys_addr;
416     }
417     return 0;
418 do_fault:
419     return code | (domain << 4);
420 }
421
422 int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address,
423                               int access_type, int is_user, int is_softmmu)
424 {
425     uint32_t phys_addr;
426     int prot;
427     int ret;
428
429     ret = get_phys_addr(env, address, access_type, is_user, &phys_addr, &prot);
430     if (ret == 0) {
431         /* Map a single [sub]page.  */
432         phys_addr &= ~(uint32_t)0x3ff;
433         address &= ~(uint32_t)0x3ff;
434         return tlb_set_page (env, address, phys_addr, prot, is_user,
435                              is_softmmu);
436     }
437
438     if (access_type == 2) {
439         env->cp15.c5_insn = ret;
440         env->cp15.c6_insn = address;
441         env->exception_index = EXCP_PREFETCH_ABORT;
442     } else {
443         env->cp15.c5_data = ret;
444         env->cp15.c6_data = address;
445         env->exception_index = EXCP_DATA_ABORT;
446     }
447     return 1;
448 }
449
450 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
451 {
452     uint32_t phys_addr;
453     int prot;
454     int ret;
455
456     ret = get_phys_addr(env, addr, 0, 0, &phys_addr, &prot);
457
458     if (ret != 0)
459         return -1;
460
461     return phys_addr;
462 }
463
464 void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
465 {
466     uint32_t op2;
467
468     op2 = (insn >> 5) & 7;
469     switch ((insn >> 16) & 0xf) {
470     case 0: /* ID codes.  */
471         goto bad_reg;
472     case 1: /* System configuration.  */
473         switch (op2) {
474         case 0:
475             env->cp15.c1_sys = val;
476             /* ??? Lots of these bits are not implemented.  */
477             /* This may enable/disable the MMU, so do a TLB flush.  */
478             tlb_flush(env, 1);
479             break;
480         case 2:
481             env->cp15.c1_coproc = val;
482             /* ??? Is this safe when called from within a TB?  */
483             tb_flush(env);
484         default:
485             goto bad_reg;
486         }
487         break;
488     case 2: /* MMU Page table control.  */
489         env->cp15.c2 = val;
490         break;
491     case 3: /* MMU Domain access control.  */
492         env->cp15.c3 = val;
493         break;
494     case 4: /* Reserved.  */
495         goto bad_reg;
496     case 5: /* MMU Fault status.  */
497         switch (op2) {
498         case 0:
499             env->cp15.c5_data = val;
500             break;
501         case 1:
502             env->cp15.c5_insn = val;
503             break;
504         default:
505             goto bad_reg;
506         }
507         break;
508     case 6: /* MMU Fault address.  */
509         switch (op2) {
510         case 0:
511             env->cp15.c6_data = val;
512             break;
513         case 1:
514             env->cp15.c6_insn = val;
515             break;
516         default:
517             goto bad_reg;
518         }
519         break;
520     case 7: /* Cache control.  */
521         /* No cache, so nothing to do.  */
522         break;
523     case 8: /* MMU TLB control.  */
524         switch (op2) {
525         case 0: /* Invalidate all.  */
526             tlb_flush(env, 0);
527             break;
528         case 1: /* Invalidate single TLB entry.  */
529 #if 0
530             /* ??? This is wrong for large pages and sections.  */
531             /* As an ugly hack to make linux work we always flush a 4K
532                pages.  */
533             val &= 0xfffff000;
534             tlb_flush_page(env, val);
535             tlb_flush_page(env, val + 0x400);
536             tlb_flush_page(env, val + 0x800);
537             tlb_flush_page(env, val + 0xc00);
538 #else
539             tlb_flush(env, 1);
540 #endif
541             break;
542         default:
543             goto bad_reg;
544         }
545         break;
546     case 9: /* Cache lockdown.  */
547         switch (op2) {
548         case 0:
549             env->cp15.c9_data = val;
550             break;
551         case 1:
552             env->cp15.c9_insn = val;
553             break;
554         default:
555             goto bad_reg;
556         }
557         break;
558     case 10: /* MMU TLB lockdown.  */
559         /* ??? TLB lockdown not implemented.  */
560         break;
561     case 11: /* TCM DMA control.  */
562     case 12: /* Reserved.  */
563         goto bad_reg;
564     case 13: /* Process ID.  */
565         switch (op2) {
566         case 0:
567             /* Unlike real hardware the qemu TLB uses virtual addresses,
568                not modified virtual addresses, so this causes a TLB flush.
569              */
570             if (env->cp15.c13_fcse != val)
571               tlb_flush(env, 1);
572             env->cp15.c13_fcse = val;
573             break;
574         case 1:
575             /* This changes the ASID, so do a TLB flush.  */
576             if (env->cp15.c13_context != val)
577               tlb_flush(env, 0);
578             env->cp15.c13_context = val;
579             break;
580         default:
581             goto bad_reg;
582         }
583         break;
584     case 14: /* Reserved.  */
585         goto bad_reg;
586     case 15: /* Implementation specific.  */
587         /* ??? Internal registers not implemented.  */
588         break;
589     }
590     return;
591 bad_reg:
592     /* ??? For debugging only.  Should raise illegal instruction exception.  */
593     cpu_abort(env, "Unimplemented cp15 register read\n");
594 }
595
596 uint32_t helper_get_cp15(CPUState *env, uint32_t insn)
597 {
598     uint32_t op2;
599
600     op2 = (insn >> 5) & 7;
601     switch ((insn >> 16) & 0xf) {
602     case 0: /* ID codes.  */
603         switch (op2) {
604         default: /* Device ID.  */
605             return env->cp15.c0_cpuid;
606         case 1: /* Cache Type.  */
607             return 0x1dd20d2;
608         case 2: /* TCM status.  */
609             return 0;
610         }
611     case 1: /* System configuration.  */
612         switch (op2) {
613         case 0: /* Control register.  */
614             return env->cp15.c1_sys;
615         case 1: /* Auxiliary control register.  */
616             if (arm_feature(env, ARM_FEATURE_AUXCR))
617                 return 1;
618             goto bad_reg;
619         case 2: /* Coprocessor access register.  */
620             return env->cp15.c1_coproc;
621         default:
622             goto bad_reg;
623         }
624     case 2: /* MMU Page table control.  */
625         return env->cp15.c2;
626     case 3: /* MMU Domain access control.  */
627         return env->cp15.c3;
628     case 4: /* Reserved.  */
629         goto bad_reg;
630     case 5: /* MMU Fault status.  */
631         switch (op2) {
632         case 0:
633             return env->cp15.c5_data;
634         case 1:
635             return env->cp15.c5_insn;
636         default:
637             goto bad_reg;
638         }
639     case 6: /* MMU Fault address.  */
640         switch (op2) {
641         case 0:
642             return env->cp15.c6_data;
643         case 1:
644             /* Arm9 doesn't have an IFAR, but implementing it anyway shouldn't
645                do any harm.  */
646             return env->cp15.c6_insn;
647         default:
648             goto bad_reg;
649         }
650     case 7: /* Cache control.  */
651         /* ??? This is for test, clean and invaidate operations that set the
652            Z flag.  We can't represent N = Z = 1, so it also clears clears
653            the N flag.  Oh well.  */
654         env->NZF = 0;
655         return 0;
656     case 8: /* MMU TLB control.  */
657         goto bad_reg;
658     case 9: /* Cache lockdown.  */
659         switch (op2) {
660         case 0:
661             return env->cp15.c9_data;
662         case 1:
663             return env->cp15.c9_insn;
664         default:
665             goto bad_reg;
666         }
667     case 10: /* MMU TLB lockdown.  */
668         /* ??? TLB lockdown not implemented.  */
669         return 0;
670     case 11: /* TCM DMA control.  */
671     case 12: /* Reserved.  */
672         goto bad_reg;
673     case 13: /* Process ID.  */
674         switch (op2) {
675         case 0:
676             return env->cp15.c13_fcse;
677         case 1:
678             return env->cp15.c13_context;
679         default:
680             goto bad_reg;
681         }
682     case 14: /* Reserved.  */
683         goto bad_reg;
684     case 15: /* Implementation specific.  */
685         /* ??? Internal registers not implemented.  */
686         return 0;
687     }
688 bad_reg:
689     /* ??? For debugging only.  Should raise illegal instruction exception.  */
690     cpu_abort(env, "Unimplemented cp15 register read\n");
691     return 0;
692 }
693
694 #endif