aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arc/mm/tlb.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arc/mm/tlb.c')
-rw-r--r--arch/arc/mm/tlb.c57
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
819void arc_mmu_init(void) 821void 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 }