MIPS: mm: Don't do MTHC0 if XPA not present
authorJames Hogan <james.hogan@imgtec.com>
Tue, 19 Apr 2016 08:25:10 +0000 (09:25 +0100)
committerRalf Baechle <ralf@linux-mips.org>
Fri, 13 May 2016 13:30:25 +0000 (15:30 +0200)
Performing an MTHC0 instruction without XPA being present will trigger a
reserved instruction exception, therefore conditionalise the use of this
instruction when building TLB handlers (build_update_entries()), and in
__update_tlb().

This allows an XPA kernel to run on non XPA hardware without that
instruction implemented, just like it can run on XPA capable hardware
without XPA in use (with the noxpa kernel argument) or with XPA not
configured in hardware.

[paul.burton@imgtec.com:
  - Rebase atop other TLB work.
  - Add "mm" to subject.
  - Handle the __kmap_pgprot case.]

Fixes: c5b367835cfc ("MIPS: Add support for XPA.")
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: David Hildenbrand <dahi@linux.vnet.ibm.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Jerome Marchand <jmarchan@redhat.com>
Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/13124/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/mm/init.c
arch/mips/mm/tlb-r4k.c
arch/mips/mm/tlbex.c

index 134c988bc61fb15c9fff99306ee502f339fc43b8..9b58eb5fd0d57e4f9492dbacd16eda8b4aa69f10 100644 (file)
@@ -112,9 +112,11 @@ static void *__kmap_pgprot(struct page *page, unsigned long addr, pgprot_t prot)
        write_c0_entrylo0(entrylo);
        write_c0_entrylo1(entrylo);
 #ifdef CONFIG_XPA
-       entrylo = (pte.pte_low & _PFNX_MASK);
-       writex_c0_entrylo0(entrylo);
-       writex_c0_entrylo1(entrylo);
+       if (cpu_has_xpa) {
+               entrylo = (pte.pte_low & _PFNX_MASK);
+               writex_c0_entrylo0(entrylo);
+               writex_c0_entrylo1(entrylo);
+       }
 #endif
        tlbidx = read_c0_wired();
        write_c0_wired(tlbidx + 1);
index 61f1f1ba4a1746df0182e8051abd275b46440cb0..5a5c7fec645e8f328fe0b1cd5f8f810be86049ce 100644 (file)
@@ -339,10 +339,12 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
 #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
 #ifdef CONFIG_XPA
                write_c0_entrylo0(pte_to_entrylo(ptep->pte_high));
-               writex_c0_entrylo0(ptep->pte_low & _PFNX_MASK);
+               if (cpu_has_xpa)
+                       writex_c0_entrylo0(ptep->pte_low & _PFNX_MASK);
                ptep++;
                write_c0_entrylo1(pte_to_entrylo(ptep->pte_high));
-               writex_c0_entrylo1(ptep->pte_low & _PFNX_MASK);
+               if (cpu_has_xpa)
+                       writex_c0_entrylo1(ptep->pte_low & _PFNX_MASK);
 #else
                write_c0_entrylo0(ptep->pte_high);
                ptep++;
index 588bde3bdbe7d7e889112ca94ba1a93b2d23cb43..0efa6211cc4094c3a7dd56f179ac6236edc7a91a 100644 (file)
@@ -1030,17 +1030,21 @@ static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep)
                UASM_i_ROTR(p, tmp, tmp, ilog2(_PAGE_GLOBAL));
                UASM_i_MTC0(p, tmp, C0_ENTRYLO0);
 
-               uasm_i_lw(p, tmp, 0, ptep);
-               uasm_i_ext(p, tmp, tmp, 0, 24);
-               uasm_i_mthc0(p, tmp, C0_ENTRYLO0);
+               if (cpu_has_xpa && !mips_xpa_disabled) {
+                       uasm_i_lw(p, tmp, 0, ptep);
+                       uasm_i_ext(p, tmp, tmp, 0, 24);
+                       uasm_i_mthc0(p, tmp, C0_ENTRYLO0);
+               }
 
                uasm_i_lw(p, tmp, pte_off_odd, ptep); /* odd pte */
                UASM_i_ROTR(p, tmp, tmp, ilog2(_PAGE_GLOBAL));
                UASM_i_MTC0(p, tmp, C0_ENTRYLO1);
 
-               uasm_i_lw(p, tmp, sizeof(pte_t), ptep);
-               uasm_i_ext(p, tmp, tmp, 0, 24);
-               uasm_i_mthc0(p, tmp, C0_ENTRYLO1);
+               if (cpu_has_xpa && !mips_xpa_disabled) {
+                       uasm_i_lw(p, tmp, sizeof(pte_t), ptep);
+                       uasm_i_ext(p, tmp, tmp, 0, 24);
+                       uasm_i_mthc0(p, tmp, C0_ENTRYLO1);
+               }
                return;
        }