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