Commit ce8198612e08f737057d9984a9fa1bf18af8ce4b

Authored by pbrook
1 parent 94554550

ARM946 CPU support.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2783 c046a42c-6fe2-441c-8c8c-71466251a162
hw/pxa2xx.c
... ... @@ -251,7 +251,7 @@ static void pxa2xx_clkpwr_write(void *opaque, int op2, int reg, int crm,
251 251 ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
252 252 s->env->cp15.c1_sys = 0;
253 253 s->env->cp15.c1_coproc = 0;
254   - s->env->cp15.c2 = 0;
  254 + s->env->cp15.c2_base = 0;
255 255 s->env->cp15.c3 = 0;
256 256 s->pm_regs[PSSR >> 2] |= 0x8; /* Set STS */
257 257 s->pm_regs[RCSR >> 2] |= 0x8; /* Set GPR */
... ...
qemu-doc.texi
... ... @@ -77,7 +77,7 @@ For system emulation, the following hardware targets are supported:
77 77 @item Sun4m (32-bit Sparc processor)
78 78 @item Sun4u (64-bit Sparc processor, in progress)
79 79 @item Malta board (32-bit MIPS processor)
80   -@item ARM Integrator/CP (ARM926E or 1026E processor)
  80 +@item ARM Integrator/CP (ARM926E, 1026E or 946E processor)
81 81 @item ARM Versatile baseboard (ARM926E)
82 82 @item ARM RealView Emulation baseboard (ARM926EJ-S)
83 83 @item Spitz, Akita, Borzoi and Terrier PDAs (PXA270 processor)
... ... @@ -1722,7 +1722,7 @@ devices:
1722 1722  
1723 1723 @itemize @minus
1724 1724 @item
1725   -ARM926E or ARM1026E CPU
  1725 +ARM926E, ARM1026E or ARM946E CPU
1726 1726 @item
1727 1727 Two PL011 UARTs
1728 1728 @item
... ...
target-arm/cpu.h
... ... @@ -83,10 +83,14 @@ typedef struct CPUARMState {
83 83 uint32_t c0_cachetype;
84 84 uint32_t c1_sys; /* System control register. */
85 85 uint32_t c1_coproc; /* Coprocessor access register. */
86   - uint32_t c2; /* MMU translation table base. */
87   - uint32_t c3; /* MMU domain access control register. */
  86 + uint32_t c2_base; /* MMU translation table base. */
  87 + uint32_t c2_data; /* MPU data cachable bits. */
  88 + uint32_t c2_insn; /* MPU instruction cachable bits. */
  89 + uint32_t c3; /* MMU domain access control register
  90 + MPU write buffer control. */
88 91 uint32_t c5_insn; /* Fault status registers. */
89 92 uint32_t c5_data;
  93 + uint32_t c6_region[8]; /* MPU base/size registers. */
90 94 uint32_t c6_insn; /* Fault address registers. */
91 95 uint32_t c6_data;
92 96 uint32_t c9_insn; /* Cache lockdown registers. */
... ... @@ -241,7 +245,8 @@ enum arm_features {
241 245 ARM_FEATURE_VFP,
242 246 ARM_FEATURE_AUXCR, /* ARM1026 Auxiliary control register. */
243 247 ARM_FEATURE_XSCALE, /* Intel XScale extensions. */
244   - ARM_FEATURE_IWMMXT /* Intel iwMMXt extension. */
  248 + ARM_FEATURE_IWMMXT, /* Intel iwMMXt extension. */
  249 + ARM_FEATURE_MPU /* Only has Memory Protection Unit, not full MMU. */
245 250 };
246 251  
247 252 static inline int arm_feature(CPUARMState *env, int feature)
... ... @@ -258,6 +263,7 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
258 263  
259 264 #define ARM_CPUID_ARM1026 0x4106a262
260 265 #define ARM_CPUID_ARM926 0x41069265
  266 +#define ARM_CPUID_ARM946 0x41059461
261 267 #define ARM_CPUID_PXA250 0x69052100
262 268 #define ARM_CPUID_PXA255 0x69052d00
263 269 #define ARM_CPUID_PXA260 0x69052903
... ...
target-arm/helper.c
... ... @@ -19,6 +19,10 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
19 19 env->vfp.xregs[ARM_VFP_FPSID] = 0x41011090;
20 20 env->cp15.c0_cachetype = 0x1dd20d2;
21 21 break;
  22 + case ARM_CPUID_ARM946:
  23 + set_feature(env, ARM_FEATURE_MPU);
  24 + env->cp15.c0_cachetype = 0x0f004006;
  25 + break;
22 26 case ARM_CPUID_ARM1026:
23 27 set_feature(env, ARM_FEATURE_VFP);
24 28 set_feature(env, ARM_FEATURE_AUXCR);
... ... @@ -90,6 +94,7 @@ struct arm_cpu_t {
90 94  
91 95 static const struct arm_cpu_t arm_cpu_names[] = {
92 96 { ARM_CPUID_ARM926, "arm926"},
  97 + { ARM_CPUID_ARM946, "arm946"},
93 98 { ARM_CPUID_ARM1026, "arm1026"},
94 99 { ARM_CPUID_PXA250, "pxa250" },
95 100 { ARM_CPUID_PXA255, "pxa255" },
... ... @@ -392,13 +397,67 @@ static int get_phys_addr(CPUState *env, uint32_t address, int access_type,
392 397 address += env->cp15.c13_fcse;
393 398  
394 399 if ((env->cp15.c1_sys & 1) == 0) {
395   - /* MMU diusabled. */
  400 + /* MMU/MPU disabled. */
396 401 *phys_ptr = address;
397 402 *prot = PAGE_READ | PAGE_WRITE;
  403 + } else if (arm_feature(env, ARM_FEATURE_MPU)) {
  404 + int n;
  405 + uint32_t mask;
  406 + uint32_t base;
  407 +
  408 + *phys_ptr = address;
  409 + for (n = 7; n >= 0; n--) {
  410 + base = env->cp15.c6_region[n];
  411 + if ((base & 1) == 0)
  412 + continue;
  413 + mask = 1 << ((base >> 1) & 0x1f);
  414 + /* Keep this shift separate from the above to avoid an
  415 + (undefined) << 32. */
  416 + mask = (mask << 1) - 1;
  417 + if (((base ^ address) & ~mask) == 0)
  418 + break;
  419 + }
  420 + if (n < 0)
  421 + return 2;
  422 +
  423 + if (access_type == 2) {
  424 + mask = env->cp15.c5_insn;
  425 + } else {
  426 + mask = env->cp15.c5_data;
  427 + }
  428 + mask = (mask >> (n * 4)) & 0xf;
  429 + switch (mask) {
  430 + case 0:
  431 + return 1;
  432 + case 1:
  433 + if (is_user)
  434 + return 1;
  435 + *prot = PAGE_READ | PAGE_WRITE;
  436 + break;
  437 + case 2:
  438 + *prot = PAGE_READ;
  439 + if (!is_user)
  440 + *prot |= PAGE_WRITE;
  441 + break;
  442 + case 3:
  443 + *prot = PAGE_READ | PAGE_WRITE;
  444 + break;
  445 + case 5:
  446 + if (is_user)
  447 + return 1;
  448 + *prot = PAGE_READ;
  449 + break;
  450 + case 6:
  451 + *prot = PAGE_READ;
  452 + break;
  453 + default:
  454 + /* Bad permission. */
  455 + return 1;
  456 + }
398 457 } else {
399 458 /* Pagetable walk. */
400 459 /* Lookup l1 descriptor. */
401   - table = (env->cp15.c2 & 0xffffc000) | ((address >> 18) & 0x3ffc);
  460 + table = (env->cp15.c2_base & 0xffffc000) | ((address >> 18) & 0x3ffc);
402 461 desc = ldl_phys(table);
403 462 type = (desc & 3);
404 463 domain = (env->cp15.c3 >> ((desc >> 4) & 0x1e)) & 3;
... ... @@ -539,18 +598,50 @@ uint32_t helper_get_cp(CPUState *env, uint32_t insn)
539 598 return 0;
540 599 }
541 600  
  601 +/* Return basic MPU access permission bits. */
  602 +static uint32_t simple_mpu_ap_bits(uint32_t val)
  603 +{
  604 + uint32_t ret;
  605 + uint32_t mask;
  606 + int i;
  607 + ret = 0;
  608 + mask = 3;
  609 + for (i = 0; i < 16; i += 2) {
  610 + ret |= (val >> i) & mask;
  611 + mask <<= 2;
  612 + }
  613 + return ret;
  614 +}
  615 +
  616 +/* Pad basic MPU access permission bits to extended format. */
  617 +static uint32_t extended_mpu_ap_bits(uint32_t val)
  618 +{
  619 + uint32_t ret;
  620 + uint32_t mask;
  621 + int i;
  622 + ret = 0;
  623 + mask = 3;
  624 + for (i = 0; i < 16; i += 2) {
  625 + ret |= (val & mask) << i;
  626 + mask <<= 2;
  627 + }
  628 + return ret;
  629 +}
  630 +
542 631 void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
543 632 {
544 633 uint32_t op2;
  634 + uint32_t crm;
545 635  
546 636 op2 = (insn >> 5) & 7;
  637 + crm = insn & 0xf;
547 638 switch ((insn >> 16) & 0xf) {
548 639 case 0: /* ID codes. */
549 640 goto bad_reg;
550 641 case 1: /* System configuration. */
551 642 switch (op2) {
552 643 case 0:
553   - if (!arm_feature(env, ARM_FEATURE_XSCALE) || (insn & 0xf) == 0)
  644 + if (!arm_feature(env, ARM_FEATURE_XSCALE) || crm == 0)
554 645 env->cp15.c1_sys = val;
555 646 /* ??? Lots of these bits are not implemented. */
556 647 /* This may enable/disable the MMU, so do a TLB flush. */
... ... @@ -571,38 +662,71 @@ void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
571 662 goto bad_reg;
572 663 }
573 664 break;
574   - case 2: /* MMU Page table control. */
575   - env->cp15.c2 = val;
  665 + case 2: /* MMU Page table control / MPU cache control. */
  666 + if (arm_feature(env, ARM_FEATURE_MPU)) {
  667 + switch (op2) {
  668 + case 0:
  669 + env->cp15.c2_data = val;
  670 + break;
  671 + case 1:
  672 + env->cp15.c2_insn = val;
  673 + break;
  674 + default:
  675 + goto bad_reg;
  676 + }
  677 + } else {
  678 + env->cp15.c2_base = val;
  679 + }
576 680 break;
577   - case 3: /* MMU Domain access control. */
  681 + case 3: /* MMU Domain access control / MPU write buffer control. */
578 682 env->cp15.c3 = val;
579 683 break;
580 684 case 4: /* Reserved. */
581 685 goto bad_reg;
582   - case 5: /* MMU Fault status. */
  686 + case 5: /* MMU Fault status / MPU access permission. */
583 687 switch (op2) {
584 688 case 0:
  689 + if (arm_feature(env, ARM_FEATURE_MPU))
  690 + val = extended_mpu_ap_bits(val);
585 691 env->cp15.c5_data = val;
586 692 break;
587 693 case 1:
  694 + if (arm_feature(env, ARM_FEATURE_MPU))
  695 + val = extended_mpu_ap_bits(val);
588 696 env->cp15.c5_insn = val;
589 697 break;
590   - default:
591   - goto bad_reg;
592   - }
593   - break;
594   - case 6: /* MMU Fault address. */
595   - switch (op2) {
596   - case 0:
597   - env->cp15.c6_data = val;
  698 + case 2:
  699 + if (!arm_feature(env, ARM_FEATURE_MPU))
  700 + goto bad_reg;
  701 + env->cp15.c5_data = val;
598 702 break;
599   - case 1:
600   - env->cp15.c6_insn = val;
  703 + case 3:
  704 + if (!arm_feature(env, ARM_FEATURE_MPU))
  705 + goto bad_reg;
  706 + env->cp15.c5_insn = val;
601 707 break;
602 708 default:
603 709 goto bad_reg;
604 710 }
605 711 break;
  712 + case 6: /* MMU Fault address / MPU base/size. */
  713 + if (arm_feature(env, ARM_FEATURE_MPU)) {
  714 + if (crm >= 8)
  715 + goto bad_reg;
  716 + env->cp15.c6_region[crm] = val;
  717 + } else {
  718 + switch (op2) {
  719 + case 0:
  720 + env->cp15.c6_data = val;
  721 + break;
  722 + case 1:
  723 + env->cp15.c6_insn = val;
  724 + break;
  725 + default:
  726 + goto bad_reg;
  727 + }
  728 + }
  729 + break;
606 730 case 7: /* Cache control. */
607 731 /* No cache, so nothing to do. */
608 732 break;
... ... @@ -629,14 +753,23 @@ void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
629 753 goto bad_reg;
630 754 }
631 755 break;
632   - case 9: /* Cache lockdown. */
633   - switch (op2) {
634   - case 0:
635   - env->cp15.c9_data = val;
636   - break;
637   - case 1:
638   - env->cp15.c9_insn = val;
  756 + case 9:
  757 + switch (crm) {
  758 + case 0: /* Cache lockdown. */
  759 + switch (op2) {
  760 + case 0:
  761 + env->cp15.c9_data = val;
  762 + break;
  763 + case 1:
  764 + env->cp15.c9_insn = val;
  765 + break;
  766 + default:
  767 + goto bad_reg;
  768 + }
639 769 break;
  770 + case 1: /* TCM memory region registers. */
  771 + /* Not implemented. */
  772 + goto bad_reg;
640 773 default:
641 774 goto bad_reg;
642 775 }
... ... @@ -644,12 +777,13 @@ void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
644 777 case 10: /* MMU TLB lockdown. */
645 778 /* ??? TLB lockdown not implemented. */
646 779 break;
647   - case 11: /* TCM DMA control. */
648 780 case 12: /* Reserved. */
649 781 goto bad_reg;
650 782 case 13: /* Process ID. */
651 783 switch (op2) {
652 784 case 0:
  785 + if (!arm_feature(env, ARM_FEATURE_MPU))
  786 + goto bad_reg;
653 787 /* Unlike real hardware the qemu TLB uses virtual addresses,
654 788 not modified virtual addresses, so this causes a TLB flush.
655 789 */
... ... @@ -659,7 +793,8 @@ void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
659 793 break;
660 794 case 1:
661 795 /* This changes the ASID, so do a TLB flush. */
662   - if (env->cp15.c13_context != val)
  796 + if (env->cp15.c13_context != val
  797 + && !arm_feature(env, ARM_FEATURE_MPU))
663 798 tlb_flush(env, 0);
664 799 env->cp15.c13_context = val;
665 800 break;
... ... @@ -671,7 +806,7 @@ void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
671 806 goto bad_reg;
672 807 case 15: /* Implementation specific. */
673 808 if (arm_feature(env, ARM_FEATURE_XSCALE)) {
674   - if (op2 == 0 && (insn & 0xf) == 1) {
  809 + if (op2 == 0 && crm == 1) {
675 810 /* Changes cp0 to cp13 behavior, so needs a TB flush. */
676 811 tb_flush(env);
677 812 env->cp15.c15_cpar = (val & 0x3fff) | 2;
... ... @@ -717,31 +852,64 @@ uint32_t helper_get_cp15(CPUState *env, uint32_t insn)
717 852 default:
718 853 goto bad_reg;
719 854 }
720   - case 2: /* MMU Page table control. */
721   - return env->cp15.c2;
722   - case 3: /* MMU Domain access control. */
  855 + case 2: /* MMU Page table control / MPU cache control. */
  856 + if (arm_feature(env, ARM_FEATURE_MPU)) {
  857 + switch (op2) {
  858 + case 0:
  859 + return env->cp15.c2_data;
  860 + break;
  861 + case 1:
  862 + return env->cp15.c2_insn;
  863 + break;
  864 + default:
  865 + goto bad_reg;
  866 + }
  867 + } else {
  868 + return env->cp15.c2_base;
  869 + }
  870 + case 3: /* MMU Domain access control / MPU write buffer control. */
723 871 return env->cp15.c3;
724 872 case 4: /* Reserved. */
725 873 goto bad_reg;
726   - case 5: /* MMU Fault status. */
  874 + case 5: /* MMU Fault status / MPU access permission. */
727 875 switch (op2) {
728 876 case 0:
  877 + if (arm_feature(env, ARM_FEATURE_MPU))
  878 + return simple_mpu_ap_bits(env->cp15.c5_data);
729 879 return env->cp15.c5_data;
730 880 case 1:
  881 + if (arm_feature(env, ARM_FEATURE_MPU))
  882 + return simple_mpu_ap_bits(env->cp15.c5_data);
  883 + return env->cp15.c5_insn;
  884 + case 2:
  885 + if (!arm_feature(env, ARM_FEATURE_MPU))
  886 + goto bad_reg;
  887 + return env->cp15.c5_data;
  888 + case 3:
  889 + if (!arm_feature(env, ARM_FEATURE_MPU))
  890 + goto bad_reg;
731 891 return env->cp15.c5_insn;
732 892 default:
733 893 goto bad_reg;
734 894 }
735   - case 6: /* MMU Fault address. */
736   - switch (op2) {
737   - case 0:
738   - return env->cp15.c6_data;
739   - case 1:
740   - /* Arm9 doesn't have an IFAR, but implementing it anyway shouldn't
741   - do any harm. */
742   - return env->cp15.c6_insn;
743   - default:
744   - goto bad_reg;
  895 + case 6: /* MMU Fault address / MPU base/size. */
  896 + if (arm_feature(env, ARM_FEATURE_MPU)) {
  897 + int n;
  898 + n = (insn & 0xf);
  899 + if (n >= 8)
  900 + goto bad_reg;
  901 + return env->cp15.c6_region[n];
  902 + } else {
  903 + switch (op2) {
  904 + case 0:
  905 + return env->cp15.c6_data;
  906 + case 1:
  907 + /* Arm9 doesn't have an IFAR, but implementing it anyway
  908 + shouldn't do any harm. */
  909 + return env->cp15.c6_insn;
  910 + default:
  911 + goto bad_reg;
  912 + }
745 913 }
746 914 case 7: /* Cache control. */
747 915 /* ??? This is for test, clean and invaidate operations that set the
... ...