PowerPC embedded timers fixes.
[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             table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
376             desc = ldl_phys(table);
377             switch (desc & 3) {
378             case 0: /* Page translation fault.  */
379                 code = 7;
380                 goto do_fault;
381             case 1: /* 64k page.  */
382                 phys_addr = (desc & 0xffff0000) | (address & 0xffff);
383                 ap = (desc >> (4 + ((address >> 13) & 6))) & 3;
384                 break;
385             case 2: /* 4k page.  */
386                 phys_addr = (desc & 0xfffff000) | (address & 0xfff);
387                 ap = (desc >> (4 + ((address >> 13) & 6))) & 3;
388                 break;
389             case 3: /* 1k page.  */
390                 if (type == 1) {
391                     /* Page translation fault.  */
392                     code = 7;
393                     goto do_fault;
394                 }
395                 phys_addr = (desc & 0xfffffc00) | (address & 0x3ff);
396                 ap = (desc >> 4) & 3;
397                 break;
398             default:
399                 /* Never happens, but compiler isn't smart enough to tell.  */
400                 abort();
401             }
402             code = 15;
403         }
404         *prot = check_ap(env, ap, domain, access_type, is_user);
405         if (!*prot) {
406             /* Access permission fault.  */
407             goto do_fault;
408         }
409         *phys_ptr = phys_addr;
410     }
411     return 0;
412 do_fault:
413     return code | (domain << 4);
414 }
415
416 int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address,
417                               int access_type, int is_user, int is_softmmu)
418 {
419     uint32_t phys_addr;
420     int prot;
421     int ret;
422
423     ret = get_phys_addr(env, address, access_type, is_user, &phys_addr, &prot);
424     if (ret == 0) {
425         /* Map a single [sub]page.  */
426         phys_addr &= ~(uint32_t)0x3ff;
427         address &= ~(uint32_t)0x3ff;
428         return tlb_set_page (env, address, phys_addr, prot, is_user,
429                              is_softmmu);
430     }
431
432     if (access_type == 2) {
433         env->cp15.c5_insn = ret;
434         env->cp15.c6_insn = address;
435         env->exception_index = EXCP_PREFETCH_ABORT;
436     } else {
437         env->cp15.c5_data = ret;
438         env->cp15.c6_data = address;
439         env->exception_index = EXCP_DATA_ABORT;
440     }
441     return 1;
442 }
443
444 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
445 {
446     uint32_t phys_addr;
447     int prot;
448     int ret;
449
450     ret = get_phys_addr(env, addr, 0, 0, &phys_addr, &prot);
451
452     if (ret != 0)
453         return -1;
454
455     return phys_addr;
456 }
457
458 void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
459 {
460     uint32_t op2;
461
462     op2 = (insn >> 5) & 7;
463     switch ((insn >> 16) & 0xf) {
464     case 0: /* ID codes.  */
465         goto bad_reg;
466     case 1: /* System configuration.  */
467         switch (op2) {
468         case 0:
469             env->cp15.c1_sys = val;
470             /* ??? Lots of these bits are not implemented.  */
471             /* This may enable/disable the MMU, so do a TLB flush.  */
472             tlb_flush(env, 1);
473             break;
474         case 2:
475             env->cp15.c1_coproc = val;
476             /* ??? Is this safe when called from within a TB?  */
477             tb_flush(env);
478         default:
479             goto bad_reg;
480         }
481         break;
482     case 2: /* MMU Page table control.  */
483         env->cp15.c2 = val;
484         break;
485     case 3: /* MMU Domain access control.  */
486         env->cp15.c3 = val;
487         break;
488     case 4: /* Reserved.  */
489         goto bad_reg;
490     case 5: /* MMU Fault status.  */
491         switch (op2) {
492         case 0:
493             env->cp15.c5_data = val;
494             break;
495         case 1:
496             env->cp15.c5_insn = val;
497             break;
498         default:
499             goto bad_reg;
500         }
501         break;
502     case 6: /* MMU Fault address.  */
503         switch (op2) {
504         case 0:
505             env->cp15.c6_data = val;
506             break;
507         case 1:
508             env->cp15.c6_insn = val;
509             break;
510         default:
511             goto bad_reg;
512         }
513         break;
514     case 7: /* Cache control.  */
515         /* No cache, so nothing to do.  */
516         break;
517     case 8: /* MMU TLB control.  */
518         switch (op2) {
519         case 0: /* Invalidate all.  */
520             tlb_flush(env, 0);
521             break;
522         case 1: /* Invalidate single TLB entry.  */
523 #if 0
524             /* ??? This is wrong for large pages and sections.  */
525             /* As an ugly hack to make linux work we always flush a 4K
526                pages.  */
527             val &= 0xfffff000;
528             tlb_flush_page(env, val);
529             tlb_flush_page(env, val + 0x400);
530             tlb_flush_page(env, val + 0x800);
531             tlb_flush_page(env, val + 0xc00);
532 #else
533             tlb_flush(env, 1);
534 #endif
535             break;
536         default:
537             goto bad_reg;
538         }
539         break;
540     case 9: /* Cache lockdown.  */
541         switch (op2) {
542         case 0:
543             env->cp15.c9_data = val;
544             break;
545         case 1:
546             env->cp15.c9_insn = val;
547             break;
548         default:
549             goto bad_reg;
550         }
551         break;
552     case 10: /* MMU TLB lockdown.  */
553         /* ??? TLB lockdown not implemented.  */
554         break;
555     case 11: /* TCM DMA control.  */
556     case 12: /* Reserved.  */
557         goto bad_reg;
558     case 13: /* Process ID.  */
559         switch (op2) {
560         case 0:
561             /* Unlike real hardware the qemu TLB uses virtual addresses,
562                not modified virtual addresses, so this causes a TLB flush.
563              */
564             if (env->cp15.c13_fcse != val)
565               tlb_flush(env, 1);
566             env->cp15.c13_fcse = val;
567             break;
568         case 1:
569             /* This changes the ASID, so do a TLB flush.  */
570             if (env->cp15.c13_context != val)
571               tlb_flush(env, 0);
572             env->cp15.c13_context = val;
573             break;
574         default:
575             goto bad_reg;
576         }
577         break;
578     case 14: /* Reserved.  */
579         goto bad_reg;
580     case 15: /* Implementation specific.  */
581         /* ??? Internal registers not implemented.  */
582         break;
583     }
584     return;
585 bad_reg:
586     /* ??? For debugging only.  Should raise illegal instruction exception.  */
587     cpu_abort(env, "Unimplemented cp15 register read\n");
588 }
589
590 uint32_t helper_get_cp15(CPUState *env, uint32_t insn)
591 {
592     uint32_t op2;
593
594     op2 = (insn >> 5) & 7;
595     switch ((insn >> 16) & 0xf) {
596     case 0: /* ID codes.  */
597         switch (op2) {
598         default: /* Device ID.  */
599             return env->cp15.c0_cpuid;
600         case 1: /* Cache Type.  */
601             return 0x1dd20d2;
602         case 2: /* TCM status.  */
603             return 0;
604         }
605     case 1: /* System configuration.  */
606         switch (op2) {
607         case 0: /* Control register.  */
608             return env->cp15.c1_sys;
609         case 1: /* Auxiliary control register.  */
610             if (arm_feature(env, ARM_FEATURE_AUXCR))
611                 return 1;
612             goto bad_reg;
613         case 2: /* Coprocessor access register.  */
614             return env->cp15.c1_coproc;
615         default:
616             goto bad_reg;
617         }
618     case 2: /* MMU Page table control.  */
619         return env->cp15.c2;
620     case 3: /* MMU Domain access control.  */
621         return env->cp15.c3;
622     case 4: /* Reserved.  */
623         goto bad_reg;
624     case 5: /* MMU Fault status.  */
625         switch (op2) {
626         case 0:
627             return env->cp15.c5_data;
628         case 1:
629             return env->cp15.c5_insn;
630         default:
631             goto bad_reg;
632         }
633     case 6: /* MMU Fault address.  */
634         switch (op2) {
635         case 0:
636             return env->cp15.c6_data;
637         case 1:
638             /* Arm9 doesn't have an IFAR, but implementing it anyway shouldn't
639                do any harm.  */
640             return env->cp15.c6_insn;
641         default:
642             goto bad_reg;
643         }
644     case 7: /* Cache control.  */
645         /* ??? This is for test, clean and invaidate operations that set the
646            Z flag.  We can't represent N = Z = 1, so it also clears clears
647            the N flag.  Oh well.  */
648         env->NZF = 0;
649         return 0;
650     case 8: /* MMU TLB control.  */
651         goto bad_reg;
652     case 9: /* Cache lockdown.  */
653         switch (op2) {
654         case 0:
655             return env->cp15.c9_data;
656         case 1:
657             return env->cp15.c9_insn;
658         default:
659             goto bad_reg;
660         }
661     case 10: /* MMU TLB lockdown.  */
662         /* ??? TLB lockdown not implemented.  */
663         return 0;
664     case 11: /* TCM DMA control.  */
665     case 12: /* Reserved.  */
666         goto bad_reg;
667     case 13: /* Process ID.  */
668         switch (op2) {
669         case 0:
670             return env->cp15.c13_fcse;
671         case 1:
672             return env->cp15.c13_context;
673         default:
674             goto bad_reg;
675         }
676     case 14: /* Reserved.  */
677         goto bad_reg;
678     case 15: /* Implementation specific.  */
679         /* ??? Internal registers not implemented.  */
680         return 0;
681     }
682 bad_reg:
683     /* ??? For debugging only.  Should raise illegal instruction exception.  */
684     cpu_abort(env, "Unimplemented cp15 register read\n");
685     return 0;
686 }
687
688 #endif