diff options
Diffstat (limited to 'arch/arc/mm/tlb.c')
-rw-r--r-- | arch/arc/mm/tlb.c | 57 |
1 files changed, 33 insertions, 24 deletions
diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c index 8ceefbf72fb0..4097764fea23 100644 --- a/arch/arc/mm/tlb.c +++ b/arch/arc/mm/tlb.c | |||
@@ -762,21 +762,23 @@ void read_decode_mmu_bcr(void) | |||
762 | tmp = read_aux_reg(ARC_REG_MMU_BCR); | 762 | tmp = read_aux_reg(ARC_REG_MMU_BCR); |
763 | mmu->ver = (tmp >> 24); | 763 | mmu->ver = (tmp >> 24); |
764 | 764 | ||
765 | if (mmu->ver <= 2) { | 765 | if (is_isa_arcompact()) { |
766 | mmu2 = (struct bcr_mmu_1_2 *)&tmp; | 766 | if (mmu->ver <= 2) { |
767 | mmu->pg_sz_k = TO_KB(0x2000); | 767 | mmu2 = (struct bcr_mmu_1_2 *)&tmp; |
768 | mmu->sets = 1 << mmu2->sets; | 768 | mmu->pg_sz_k = TO_KB(0x2000); |
769 | mmu->ways = 1 << mmu2->ways; | 769 | mmu->sets = 1 << mmu2->sets; |
770 | mmu->u_dtlb = mmu2->u_dtlb; | 770 | mmu->ways = 1 << mmu2->ways; |
771 | mmu->u_itlb = mmu2->u_itlb; | 771 | mmu->u_dtlb = mmu2->u_dtlb; |
772 | } else if (mmu->ver == 3) { | 772 | mmu->u_itlb = mmu2->u_itlb; |
773 | mmu3 = (struct bcr_mmu_3 *)&tmp; | 773 | } else { |
774 | mmu->pg_sz_k = 1 << (mmu3->pg_sz - 1); | 774 | mmu3 = (struct bcr_mmu_3 *)&tmp; |
775 | mmu->sets = 1 << mmu3->sets; | 775 | mmu->pg_sz_k = 1 << (mmu3->pg_sz - 1); |
776 | mmu->ways = 1 << mmu3->ways; | 776 | mmu->sets = 1 << mmu3->sets; |
777 | mmu->u_dtlb = mmu3->u_dtlb; | 777 | mmu->ways = 1 << mmu3->ways; |
778 | mmu->u_itlb = mmu3->u_itlb; | 778 | mmu->u_dtlb = mmu3->u_dtlb; |
779 | mmu->sasid = mmu3->sasid; | 779 | mmu->u_itlb = mmu3->u_itlb; |
780 | mmu->sasid = mmu3->sasid; | ||
781 | } | ||
780 | } else { | 782 | } else { |
781 | mmu4 = (struct bcr_mmu_4 *)&tmp; | 783 | mmu4 = (struct bcr_mmu_4 *)&tmp; |
782 | mmu->pg_sz_k = 1 << (mmu4->sz0 - 1); | 784 | mmu->pg_sz_k = 1 << (mmu4->sz0 - 1); |
@@ -818,8 +820,9 @@ int pae40_exist_but_not_enab(void) | |||
818 | 820 | ||
819 | void arc_mmu_init(void) | 821 | void arc_mmu_init(void) |
820 | { | 822 | { |
821 | char str[256]; | ||
822 | struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu; | 823 | struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu; |
824 | char str[256]; | ||
825 | int compat = 0; | ||
823 | 826 | ||
824 | pr_info("%s", arc_mmu_mumbojumbo(0, str, sizeof(str))); | 827 | pr_info("%s", arc_mmu_mumbojumbo(0, str, sizeof(str))); |
825 | 828 | ||
@@ -834,15 +837,21 @@ void arc_mmu_init(void) | |||
834 | */ | 837 | */ |
835 | BUILD_BUG_ON(!IS_ALIGNED(STACK_TOP, PMD_SIZE)); | 838 | BUILD_BUG_ON(!IS_ALIGNED(STACK_TOP, PMD_SIZE)); |
836 | 839 | ||
837 | /* For efficiency sake, kernel is compile time built for a MMU ver | 840 | /* |
838 | * This must match the hardware it is running on. | 841 | * Ensure that MMU features assumed by kernel exist in hardware. |
839 | * Linux built for MMU V2, if run on MMU V1 will break down because V1 | 842 | * For older ARC700 cpus, it has to be exact match, since the MMU |
840 | * hardware doesn't understand cmds such as WriteNI, or IVUTLB | 843 | * revisions were not backwards compatible (MMUv3 TLB layout changed |
841 | * On the other hand, Linux built for V1 if run on MMU V2 will do | 844 | * so even if kernel for v2 didn't use any new cmds of v3, it would |
842 | * un-needed workarounds to prevent memcpy thrashing. | 845 | * still not work. |
843 | * Similarly MMU V3 has new features which won't work on older MMU | 846 | * For HS cpus, MMUv4 was baseline and v5 is backwards compatible |
847 | * (will run older software). | ||
844 | */ | 848 | */ |
845 | if (mmu->ver != CONFIG_ARC_MMU_VER) { | 849 | if (is_isa_arcompact() && mmu->ver == CONFIG_ARC_MMU_VER) |
850 | compat = 1; | ||
851 | else if (is_isa_arcv2() && mmu->ver >= CONFIG_ARC_MMU_VER) | ||
852 | compat = 1; | ||
853 | |||
854 | if (!compat) { | ||
846 | panic("MMU ver %d doesn't match kernel built for %d...\n", | 855 | panic("MMU ver %d doesn't match kernel built for %d...\n", |
847 | mmu->ver, CONFIG_ARC_MMU_VER); | 856 | mmu->ver, CONFIG_ARC_MMU_VER); |
848 | } | 857 | } |