Skip to contentSkip to conversation

MIPS Read Inhibit/eXecute Inhibit support.

PATCH In review David Daney 2 participants 7 messages Feb 5, 2010 – Feb 8, 2010 MIPS

lore
Share & tools
lore
#0 lore raw

cover MIPS Read Inhibit/eXecute Inhibit support.

This patch set adds execute and read inhibit support. By default glibc based tool chains will create mappings for data areas of a program and shared libraries with PROT_EXEC cleared. With this patch applied, a SIGSEGV is correctly sent if an attempt is made to execute from data areas.

We have been running this patch for close to a year. So far it seems to work well, so I ported it to the HEAD for your enjoyment.

I will reply with the four patches.

David Daney (4):
MIPS: Use 64-bit stores to c0_entrylo on 64-bit kernels.
MIPS: Add accessor functions and bit definitions for c0_PageGrain
MIPS: Add TLBP to uasm.
MIPS: Implement Read Inhibit/eXecute Inhibit

 arch/mips/Kconfig                    |    7 ++
 arch/mips/include/asm/mipsregs.h     |   11 +++
 arch/mips/include/asm/pgtable-64.h   |    4 +
 arch/mips/include/asm/pgtable-bits.h |   59 ++++++++++++-
 arch/mips/include/asm/pgtable.h      |   39 ++++++++-
 arch/mips/include/asm/uasm.h         |    1 +
 arch/mips/mm/cache.c                 |   11 +++
 arch/mips/mm/fault.c                 |   23 +++++
 arch/mips/mm/init.c                  |    2 +-
 arch/mips/mm/tlb-r4k.c               |   15 +++-
 arch/mips/mm/tlbex.c                 |  165 
++++++++++++++++++++++++++++-----
 arch/mips/mm/uasm.c                  |    5 +-
 12 files changed, 308 insertions(+), 34 deletions(-)
#1 lore raw

PATCH 1/4 MIPS: Use 64-bit stores to c0_entrylo on 64-bit kernels.

64-bit CPUs have 64-bit c0_entrylo{0,1} registers. We should use the 64-bit dmtc0 instruction to set them. This becomes important if we want to set the RI and XI bits present in some processors.

---
 arch/mips/mm/tlbex.c |   20 ++++++++++----------
 1 files changed, 10 insertions(+), 10 deletions(-)
arch/mips/mm/tlbex.c +10 -10
index 2c68849..35431e1 100644
@@ -460,14 +460,14 @@ static __cpuinit void build_huge_update_entries(u32 **p,
 		uasm_i_lui(p, tmp, HPAGE_SIZE >> (7 + 16));
 
 	UASM_i_SRL(p, pte, pte, 6); /* convert to entrylo */
-	uasm_i_mtc0(p, pte, C0_ENTRYLO0); /* load it */
+	UASM_i_MTC0(p, pte, C0_ENTRYLO0); /* load it */
 	/* convert to entrylo1 */
 	if (small_sequence)
 		UASM_i_ADDIU(p, pte, pte, HPAGE_SIZE >> 7);
 	else
 		UASM_i_ADDU(p, pte, pte, tmp);
 
-	uasm_i_mtc0(p, pte, C0_ENTRYLO1); /* load it */
+	UASM_i_MTC0(p, pte, C0_ENTRYLO1); /* load it */
 }
 
 static __cpuinit void build_huge_handler_tail(u32 **p,
@@ -686,18 +686,18 @@ static void __cpuinit build_update_entries(u32 **p, unsigned int tmp,
 		uasm_i_ld(p, tmp, 0, ptep); /* get even pte */
 		uasm_i_ld(p, ptep, sizeof(pte_t), ptep); /* get odd pte */
 		uasm_i_dsrl(p, tmp, tmp, 6); /* convert to entrylo0 */
-		uasm_i_mtc0(p, tmp, C0_ENTRYLO0); /* load it */
+		UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */
 		uasm_i_dsrl(p, ptep, ptep, 6); /* convert to entrylo1 */
-		uasm_i_mtc0(p, ptep, C0_ENTRYLO1); /* load it */
+		UASM_i_MTC0(p, ptep, C0_ENTRYLO1); /* load it */
 	} else {
 		int pte_off_even = sizeof(pte_t) / 2;
 		int pte_off_odd = pte_off_even + sizeof(pte_t);
 
 		/* The pte entries are pre-shifted */
 		uasm_i_lw(p, tmp, pte_off_even, ptep); /* get even pte */
-		uasm_i_mtc0(p, tmp, C0_ENTRYLO0); /* load it */
+		UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */
 		uasm_i_lw(p, ptep, pte_off_odd, ptep); /* get odd pte */
-		uasm_i_mtc0(p, ptep, C0_ENTRYLO1); /* load it */
+		UASM_i_MTC0(p, ptep, C0_ENTRYLO1); /* load it */
 	}
 #else
 	UASM_i_LW(p, tmp, 0, ptep); /* get even pte */
@@ -706,14 +706,14 @@ static void __cpuinit build_update_entries(u32 **p, unsigned int tmp,
 		build_tlb_probe_entry(p);
 	UASM_i_SRL(p, tmp, tmp, 6); /* convert to entrylo0 */
 	if (r4k_250MHZhwbug())
-		uasm_i_mtc0(p, 0, C0_ENTRYLO0);
-	uasm_i_mtc0(p, tmp, C0_ENTRYLO0); /* load it */
+		UASM_i_MTC0(p, 0, C0_ENTRYLO0);
+	UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */
 	UASM_i_SRL(p, ptep, ptep, 6); /* convert to entrylo1 */
 	if (r45k_bvahwbug())
 		uasm_i_mfc0(p, tmp, C0_INDEX);
 	if (r4k_250MHZhwbug())
-		uasm_i_mtc0(p, 0, C0_ENTRYLO1);
-	uasm_i_mtc0(p, ptep, C0_ENTRYLO1); /* load it */
+		UASM_i_MTC0(p, 0, C0_ENTRYLO1);
+	UASM_i_MTC0(p, ptep, C0_ENTRYLO1); /* load it */
 #endif
 }
 
Signature · 1 line
1.6.0.6
#2 lore raw

PATCH 2/4 MIPS: Add accessor functions and bit definitions for c0_PageGrain

In reply to David Daney
---
 arch/mips/include/asm/mipsregs.h |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)
arch/mips/include/asm/mipsregs.h +11 -0
index b30819c..9893758 100644
@@ -251,6 +251,14 @@
 #define PL_256M		28
 
 /*
+ * PageGrain bits
+ */
+#define PG_RIE		(_ULCAST_(1) <<  31)
+#define PG_XIE		(_ULCAST_(1) <<  30)
+#define PG_ELPA		(_ULCAST_(1) <<  29)
+#define PG_ESP		(_ULCAST_(1) <<  28)
+
+/*
  * R4x00 interrupt enable / cause bits
  */
 #define IE_SW0          (_ULCAST_(1) <<  8)
@@ -840,6 +848,9 @@ do {									\
 #define read_c0_pagemask()	__read_32bit_c0_register($5, 0)
 #define write_c0_pagemask(val)	__write_32bit_c0_register($5, 0, val)
 
+#define read_c0_pagegrain()	__read_32bit_c0_register($5, 1)
+#define write_c0_pagegrain(val)	__write_32bit_c0_register($5, 1, val)
+
 #define read_c0_wired()		__read_32bit_c0_register($6, 0)
 #define write_c0_wired(val)	__write_32bit_c0_register($6, 0, val)
 
Signature · 1 line
1.6.0.6
#3 lore raw

PATCH 3/4 MIPS: Add TLBP to uasm.

In reply to David Daney

The soon to follow Read Inhibit/eXecute Inhibit patch needs TLBP support in uasm.

---
 arch/mips/include/asm/uasm.h |    1 +
 arch/mips/mm/uasm.c          |    5 ++++-
 2 files changed, 5 insertions(+), 1 deletions(-)
arch/mips/include/asm/uasm.h +1 -0
index 3d153ed..b18588b 100644
@@ -95,6 +95,7 @@ Ip_u2u1u3(_srl);
 Ip_u3u1u2(_subu);
 Ip_u2s3u1(_sw);
 Ip_0(_tlbp);
+Ip_0(_tlbr);
 Ip_0(_tlbwi);
 Ip_0(_tlbwr);
 Ip_u3u1u2(_xor);
arch/mips/mm/uasm.c +4 -1
index e3ca0f7..8f4f14d 100644
@@ -63,7 +63,8 @@ enum opcode {
 	insn_jr, insn_ld, insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0,
 	insn_mtc0, insn_ori, insn_pref, insn_rfe, insn_sc, insn_scd,
 	insn_sd, insn_sll, insn_sra, insn_srl, insn_subu, insn_sw,
-	insn_tlbp, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori, insn_dins
+	insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori,
+	insn_dins
 };
 
 struct insn {
@@ -128,6 +129,7 @@ static struct insn insn_table[] __cpuinitdata = {
 	{ insn_subu,  M(spec_op, 0, 0, 0, 0, subu_op),  RS | RT | RD },
 	{ insn_sw,  M(sw_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
 	{ insn_tlbp,  M(cop0_op, cop_op, 0, 0, 0, tlbp_op),  0 },
+	{ insn_tlbr,  M(cop0_op, cop_op, 0, 0, 0, tlbr_op),  0 },
 	{ insn_tlbwi,  M(cop0_op, cop_op, 0, 0, 0, tlbwi_op),  0 },
 	{ insn_tlbwr,  M(cop0_op, cop_op, 0, 0, 0, tlbwr_op),  0 },
 	{ insn_xor,  M(spec_op, 0, 0, 0, 0, xor_op),  RS | RT | RD },
@@ -381,6 +383,7 @@ I_u2u1u3(_srl)
 I_u3u1u2(_subu)
 I_u2s3u1(_sw)
 I_0(_tlbp)
+I_0(_tlbr)
 I_0(_tlbwi)
 I_0(_tlbwr)
 I_u3u1u2(_xor)
Signature · 1 line
1.6.0.6
#4 lore raw

Re: [PATCH 3/4] MIPS: Add TLBP to uasm.

Hello.

Quoted 2 lines · David Daney

The soon to follow Read Inhibit/eXecute Inhibit patch needs TLBP

But you're adding TLBR support, not TLBP?

Quoted 44 lines

support in uasm.

---
 arch/mips/include/asm/uasm.h |    1 +
 arch/mips/mm/uasm.c          |    5 ++++-
 2 files changed, 5 insertions(+), 1 deletions(-)
arch/mips/include/asm/uasm.h +1 -0
index 3d153ed..b18588b 100644
@@ -95,6 +95,7 @@ Ip_u2u1u3(_srl);
 Ip_u3u1u2(_subu);
 Ip_u2s3u1(_sw);
 Ip_0(_tlbp);
+Ip_0(_tlbr);
 Ip_0(_tlbwi);
 Ip_0(_tlbwr);
 Ip_u3u1u2(_xor);
arch/mips/mm/uasm.c +3 -1
index e3ca0f7..8f4f14d 100644
@@ -63,7 +63,8 @@ enum opcode {
 	insn_jr, insn_ld, insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0,
 	insn_mtc0, insn_ori, insn_pref, insn_rfe, insn_sc, insn_scd,
 	insn_sd, insn_sll, insn_sra, insn_srl, insn_subu, insn_sw,
-	insn_tlbp, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori, insn_dins
+	insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori,
+	insn_dins
 };
 
 struct insn {
@@ -128,6 +129,7 @@ static struct insn insn_table[] __cpuinitdata = {
 	{ insn_subu,  M(spec_op, 0, 0, 0, 0, subu_op),  RS | RT | RD },
 	{ insn_sw,  M(sw_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
 	{ insn_tlbp,  M(cop0_op, cop_op, 0, 0, 0, tlbp_op),  0 },
+	{ insn_tlbr,  M(cop0_op, cop_op, 0, 0, 0, tlbr_op),  0 },
 	{ insn_tlbwi,  M(cop0_op, cop_op, 0, 0, 0, tlbwi_op),  0 },
 	{ insn_tlbwr,  M(cop0_op, cop_op, 0, 0, 0, tlbwr_op),  0 },
 	{ insn_xor,  M(spec_op, 0, 0, 0, 0, xor_op),  RS | RT | RD },

arch/mips/mm/uasm.c I_u2u1u3(_srl) · line 389

Quoted 7 lines
arch/mips/mm/uasm.c +1 -0
@@ -381,6 +383,7 @@ I_u2u1u3(_srl)
 I_u3u1u2(_subu)
 I_u2s3u1(_sw)
 I_0(_tlbp)
+I_0(_tlbr)
 I_0(_tlbwi)
 I_0(_tlbwr)
 I_u3u1u2(_xor)

WBR, Sergei

#5 lore raw

Re: [PATCH 3/4] MIPS: Add TLBP to uasm.

Quoted 9 lines · Sergei Shtylyov

Hello.

Quoted 2 lines · David Daney

The soon to follow Read Inhibit/eXecute Inhibit patch needs TLBP

But you're adding TLBR support, not TLBP?

Right.

I am making more changes to this patch set and will correct that.

Thanks,
David Daney

#6 lore raw

PATCH 4/4 MIPS: Implement Read Inhibit/eXecute Inhibit

In reply to David Daney

The SmartMIPS ASE specifies how Read Inhibit (RI) and eXecute Inhibit (XI) bits in the page tables work. The upper two bits of EntryLo{0,1} are RI and XI when the feature is enabled in the PageGrain register. SmartMIPS only covers 32-bit systems. Cavium Octeon+ extends this to 64-bit systems by continuing to place the RI and XI bits in the top of EntryLo even when EntryLo is 64-bits wide.

This patch only targets Octeon+, but should be trivial to adapt for and 32-bit SmartMIPS system.

Because we need to carry the RI and XI bits in the PTE, the layout of the PTE is changed. There is a two instruction overhead in the TLB refill hot path to get the EntryLo bits into the proper position. Also the TLB load exception has to probe the TLB to check if RI or XI caused the exception.

---
 arch/mips/Kconfig                    |    7 ++
 arch/mips/include/asm/pgtable-64.h   |    4 +
 arch/mips/include/asm/pgtable-bits.h |   59 ++++++++++++++-
 arch/mips/include/asm/pgtable.h      |   39 +++++++++-
 arch/mips/mm/cache.c                 |   11 +++
 arch/mips/mm/fault.c                 |   23 ++++++
 arch/mips/mm/init.c                  |    2 +-
 arch/mips/mm/tlb-r4k.c               |   15 +++-
 arch/mips/mm/tlbex.c                 |  145 ++++++++++++++++++++++++++++++----
 9 files changed, 282 insertions(+), 23 deletions(-)
arch/mips/Kconfig +7 -0
index ed8d5b5..a79c424 100644
@@ -1484,6 +1484,13 @@ config 64BIT
 
 endchoice
 
+config USE_RI_XI_PAGE_BITS
+	bool "Use Read Inhibit (RI) and eXecute Inhibit (XI) page bits"
+	depends on CPU_CAVIUM_OCTEON
+	help
+	  This option enables the kernel to enforce PROT_EXEC and
+	  PROT_READ memory protection in mapped memory.
+
 choice
 	prompt "Kernel page size"
 	default PAGE_SIZE_4KB
arch/mips/include/asm/pgtable-64.h +4 -0
index 2c1d194..9606d26 100644
@@ -215,6 +215,10 @@ static inline void pud_clear(pud_t *pudp)
 #ifdef CONFIG_CPU_VR41XX
 #define pte_pfn(x)		((unsigned long)((x).pte >> (PAGE_SHIFT + 2)))
 #define pfn_pte(pfn, prot)	__pte(((pfn) << (PAGE_SHIFT + 2)) | pgprot_val(prot))
+#elif defined(_PAGE_NO_EXEC)
+/* The NO_READ and NO_EXEC added an extra two bits */
+#define pte_pfn(x)		((unsigned long)((x).pte >> (PAGE_SHIFT + 2)))
+#define pfn_pte(pfn, prot)	__pte(((pfn) << (PAGE_SHIFT + 2)) | pgprot_val(prot))
 #else
 #define pte_pfn(x)		((unsigned long)((x).pte >> PAGE_SHIFT))
 #define pfn_pte(pfn, prot)	__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
arch/mips/include/asm/pgtable-bits.h +58 -1

78 lines not on this page · raw message

arch/mips/include/asm/pgtable.h +36 -3
index 02335fd..9c2e5c9 100644
@@ -21,6 +21,31 @@
 struct mm_struct;
 struct vm_area_struct;
 
+#ifdef _PAGE_NO_READ
+#define PAGE_BASE_FLAGS (_PAGE_PRESENT | _page_cachable_default)
+#define PAGE_NONE	__pgprot(_PAGE_PRESENT | _CACHE_CACHABLE_NONCOHERENT)
+#define PAGE_SHARED	__pgprot(PAGE_BASE_FLAGS | _PAGE_WRITE)
+#define PAGE_COPY __pgprot(PAGE_BASE_FLAGS | _PAGE_NO_EXEC)
+#define PAGE_READONLY __pgprot(PAGE_BASE_FLAGS)
+#define PAGE_KERNEL __pgprot(PAGE_BASE_FLAGS | __READABLE | __WRITEABLE | _PAGE_GLOBAL)
+#define __P000	__pgprot(_PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_NO_READ)
+#define __P001	__pgprot(_PAGE_PRESENT | _PAGE_NO_EXEC)
+#define __P010	__pgprot(_PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_NO_READ)
+#define __P011	__pgprot(_PAGE_PRESENT | _PAGE_NO_EXEC)
+#define __P100	__pgprot(_PAGE_PRESENT | _PAGE_NO_READ)
+#define __P101	__pgprot(_PAGE_PRESENT)
+#define __P110	__pgprot(_PAGE_PRESENT | _PAGE_NO_READ)
+#define __P111	__pgprot(_PAGE_PRESENT)
+
+#define __S000	__pgprot(_PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_NO_READ)
+#define __S001	__pgprot(_PAGE_PRESENT | _PAGE_NO_EXEC)
+#define __S010	__pgprot(_PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_WRITE | _PAGE_NO_READ)
+#define __S011	__pgprot(_PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_WRITE)
+#define __S100	__pgprot(_PAGE_PRESENT | _PAGE_NO_READ)
+#define __S101	__pgprot(_PAGE_PRESENT)
+#define __S110	__pgprot(_PAGE_PRESENT | _PAGE_WRITE  | _PAGE_NO_READ)
+#define __S111	__pgprot(_PAGE_PRESENT | _PAGE_WRITE)
+#else
 #define PAGE_NONE	__pgprot(_PAGE_PRESENT | _CACHE_CACHABLE_NONCOHERENT)
 #define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
 				 _page_cachable_default)
@@ -36,9 +61,10 @@ struct vm_area_struct;
 			__WRITEABLE | _PAGE_GLOBAL | _CACHE_UNCACHED)
 
 /*
- * MIPS can't do page protection for execute, and considers that the same like
- * read. Also, write permissions imply read permissions. This is the closest
- * we can get by reasonable means..
+ * If _PAGE_NO_EXEC is not defined, we can't do page protection for
+ * execute, and consider it to be the same as read. Also, write
+ * permissions imply read permissions. This is the closest we can get
+ * by reasonable means..
  */
 
 /*
@@ -63,6 +89,8 @@ struct vm_area_struct;
 #define __S110 __pgprot(0)
 #define __S111 __pgprot(0)
 
+#endif
+
 extern unsigned long _page_cachable_default;
 
 /*
@@ -298,8 +326,13 @@ static inline pte_t pte_mkdirty(pte_t pte)
 static inline pte_t pte_mkyoung(pte_t pte)
 {
 	pte_val(pte) |= _PAGE_ACCESSED;
+#ifdef _PAGE_NO_READ
+	if (!(pte_val(pte) & _PAGE_NO_READ))
+		pte_val(pte) |= _PAGE_SILENT_READ;
+#else
 	if (pte_val(pte) & _PAGE_READ)
 		pte_val(pte) |= _PAGE_SILENT_READ;
+#endif
 	return pte;
 }
 
arch/mips/mm/cache.c +11 -0
index e716caf..31d7f0f 100644
@@ -137,6 +137,16 @@ EXPORT_SYMBOL_GPL(_page_cachable_default);
 
 static inline void setup_protection_map(void)
 {
+#ifdef _PAGE_NO_READ
+	/*
+	 * It was statically initialized with everything but the
+	 * _page_cachable_default bits.
+	 */
+	int i;
+	for (i = 0; i < 16; i++)
+		protection_map[i] = __pgprot(pgprot_val(protection_map[i]) |
+					_page_cachable_default);
+#else
 	protection_map[0] = PAGE_NONE;
 	protection_map[1] = PAGE_READONLY;
 	protection_map[2] = PAGE_COPY;
@@ -153,6 +163,7 @@ static inline void setup_protection_map(void)
 	protection_map[13] = PAGE_READONLY;
 	protection_map[14] = PAGE_SHARED;
 	protection_map[15] = PAGE_SHARED;
+#endif
 }
 
 void __cpuinit cpu_cache_init(void)
arch/mips/mm/fault.c +23 -0
index e97a7a2..24990be 100644
@@ -99,8 +99,31 @@ good_area:
 		if (!(vma->vm_flags & VM_WRITE))
 			goto bad_area;
 	} else {
+#ifdef _PAGE_NO_READ
+		if (address == regs->cp0_epc && !(vma->vm_flags & VM_EXEC)) {
+#if 0
+			pr_notice("Cpu%d[%s:%d:%0*lx:%ld:%0*lx] XI violation\n",
+				  raw_smp_processor_id(),
+				  current->comm, current->pid,
+				  field, address, write,
+				  field, regs->cp0_epc);
+#endif
+			goto bad_area;
+		}
+		if (!(vma->vm_flags & VM_READ)) {
+#if 0
+			pr_notice("Cpu%d[%s:%d:%0*lx:%ld:%0*lx] RI violation\n",
+				  raw_smp_processor_id(),
+				  current->comm, current->pid,
+				  field, address, write,
+				  field, regs->cp0_epc);
+#endif
+			goto bad_area;
+		}
+#else
 		if (!(vma->vm_flags & (VM_READ | VM_WRITE | VM_EXEC)))
 			goto bad_area;
+#endif
 	}
 
 	/*
arch/mips/mm/init.c +1 -1
index 3c5b7de..9a8e9f1 100644
@@ -143,7 +143,7 @@ void *kmap_coherent(struct page *page, unsigned long addr)
 #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
 	entrylo = pte.pte_high;
 #else
-	entrylo = pte_val(pte) >> 6;
+	entrylo = pte_to_entrylo(pte.pte);
 #endif
 
 	ENTER_CRITICAL(flags);
arch/mips/mm/tlb-r4k.c +12 -3
index e551559..c9ae7a8 100644
@@ -303,7 +303,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
 		unsigned long lo;
 		write_c0_pagemask(PM_HUGE_MASK);
 		ptep = (pte_t *)pmdp;
-		lo = pte_val(*ptep) >> 6;
+		lo = pte_to_entrylo(pte_val(*ptep));
 		write_c0_entrylo0(lo);
 		write_c0_entrylo1(lo + (HPAGE_SIZE >> 7));
 
@@ -323,8 +323,8 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
 		ptep++;
 		write_c0_entrylo1(ptep->pte_high);
 #else
-		write_c0_entrylo0(pte_val(*ptep++) >> 6);
-		write_c0_entrylo1(pte_val(*ptep) >> 6);
+		write_c0_entrylo0(pte_to_entrylo(pte_val(*ptep++)));
+		write_c0_entrylo1(pte_to_entrylo(pte_val(*ptep)));
 #endif
 		mtc0_tlbw_hazard();
 		if (idx < 0)
@@ -439,6 +439,15 @@ void __cpuinit tlb_init(void)
 	    current_cpu_type() == CPU_R12000 ||
 	    current_cpu_type() == CPU_R14000)
 		write_c0_framemask(0);
+
+#ifdef _PAGE_NO_READ
+	/*
+	 * Enable the no read, no exec bits, and enable large virtual
+	 * address.
+	 */
+	write_c0_pagegrain(PG_RIE | PG_XIE | PG_ELPA);
+#endif
+
 	temp_tlb_entry = current_cpu_data.tlbsize - 1;
 
         /* From this point on the ARC firmware is dead.  */
arch/mips/mm/tlbex.c +130 -15

223 lines not on this page · raw message

Signature · 1 line
1.6.0.6