|
@@ -762,21 +762,23 @@ void read_decode_mmu_bcr(void)
|
|
|
tmp = read_aux_reg(ARC_REG_MMU_BCR);
|
|
|
mmu->ver = (tmp >> 24);
|
|
|
|
|
|
- if (mmu->ver <= 2) {
|
|
|
- mmu2 = (struct bcr_mmu_1_2 *)&tmp;
|
|
|
- mmu->pg_sz_k = TO_KB(0x2000);
|
|
|
- mmu->sets = 1 << mmu2->sets;
|
|
|
- mmu->ways = 1 << mmu2->ways;
|
|
|
- mmu->u_dtlb = mmu2->u_dtlb;
|
|
|
- mmu->u_itlb = mmu2->u_itlb;
|
|
|
- } else if (mmu->ver == 3) {
|
|
|
- mmu3 = (struct bcr_mmu_3 *)&tmp;
|
|
|
- mmu->pg_sz_k = 1 << (mmu3->pg_sz - 1);
|
|
|
- mmu->sets = 1 << mmu3->sets;
|
|
|
- mmu->ways = 1 << mmu3->ways;
|
|
|
- mmu->u_dtlb = mmu3->u_dtlb;
|
|
|
- mmu->u_itlb = mmu3->u_itlb;
|
|
|
- mmu->sasid = mmu3->sasid;
|
|
|
+ if (is_isa_arcompact()) {
|
|
|
+ if (mmu->ver <= 2) {
|
|
|
+ mmu2 = (struct bcr_mmu_1_2 *)&tmp;
|
|
|
+ mmu->pg_sz_k = TO_KB(0x2000);
|
|
|
+ mmu->sets = 1 << mmu2->sets;
|
|
|
+ mmu->ways = 1 << mmu2->ways;
|
|
|
+ mmu->u_dtlb = mmu2->u_dtlb;
|
|
|
+ mmu->u_itlb = mmu2->u_itlb;
|
|
|
+ } else {
|
|
|
+ mmu3 = (struct bcr_mmu_3 *)&tmp;
|
|
|
+ mmu->pg_sz_k = 1 << (mmu3->pg_sz - 1);
|
|
|
+ mmu->sets = 1 << mmu3->sets;
|
|
|
+ mmu->ways = 1 << mmu3->ways;
|
|
|
+ mmu->u_dtlb = mmu3->u_dtlb;
|
|
|
+ mmu->u_itlb = mmu3->u_itlb;
|
|
|
+ mmu->sasid = mmu3->sasid;
|
|
|
+ }
|
|
|
} else {
|
|
|
mmu4 = (struct bcr_mmu_4 *)&tmp;
|
|
|
mmu->pg_sz_k = 1 << (mmu4->sz0 - 1);
|
|
@@ -818,8 +820,9 @@ int pae40_exist_but_not_enab(void)
|
|
|
|
|
|
void arc_mmu_init(void)
|
|
|
{
|
|
|
- char str[256];
|
|
|
struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu;
|
|
|
+ char str[256];
|
|
|
+ int compat = 0;
|
|
|
|
|
|
pr_info("%s", arc_mmu_mumbojumbo(0, str, sizeof(str)));
|
|
|
|
|
@@ -834,15 +837,21 @@ void arc_mmu_init(void)
|
|
|
*/
|
|
|
BUILD_BUG_ON(!IS_ALIGNED(STACK_TOP, PMD_SIZE));
|
|
|
|
|
|
- /* For efficiency sake, kernel is compile time built for a MMU ver
|
|
|
- * This must match the hardware it is running on.
|
|
|
- * Linux built for MMU V2, if run on MMU V1 will break down because V1
|
|
|
- * hardware doesn't understand cmds such as WriteNI, or IVUTLB
|
|
|
- * On the other hand, Linux built for V1 if run on MMU V2 will do
|
|
|
- * un-needed workarounds to prevent memcpy thrashing.
|
|
|
- * Similarly MMU V3 has new features which won't work on older MMU
|
|
|
+ /*
|
|
|
+ * Ensure that MMU features assumed by kernel exist in hardware.
|
|
|
+ * For older ARC700 cpus, it has to be exact match, since the MMU
|
|
|
+ * revisions were not backwards compatible (MMUv3 TLB layout changed
|
|
|
+ * so even if kernel for v2 didn't use any new cmds of v3, it would
|
|
|
+ * still not work.
|
|
|
+ * For HS cpus, MMUv4 was baseline and v5 is backwards compatible
|
|
|
+ * (will run older software).
|
|
|
*/
|
|
|
- if (mmu->ver != CONFIG_ARC_MMU_VER) {
|
|
|
+ if (is_isa_arcompact() && mmu->ver == CONFIG_ARC_MMU_VER)
|
|
|
+ compat = 1;
|
|
|
+ else if (is_isa_arcv2() && mmu->ver >= CONFIG_ARC_MMU_VER)
|
|
|
+ compat = 1;
|
|
|
+
|
|
|
+ if (!compat) {
|
|
|
panic("MMU ver %d doesn't match kernel built for %d...\n",
|
|
|
mmu->ver, CONFIG_ARC_MMU_VER);
|
|
|
}
|