diff options
Diffstat (limited to 'arch/sh/mm')
-rw-r--r-- | arch/sh/mm/Makefile_32 | 6 | ||||
-rw-r--r-- | arch/sh/mm/tlb-pteaex.c | 99 |
2 files changed, 103 insertions, 2 deletions
diff --git a/arch/sh/mm/Makefile_32 b/arch/sh/mm/Makefile_32 index 469ff1672451..986a1e055834 100644 --- a/arch/sh/mm/Makefile_32 +++ b/arch/sh/mm/Makefile_32 | |||
@@ -25,8 +25,10 @@ obj-$(CONFIG_CPU_SH4) += cache-debugfs.o | |||
25 | endif | 25 | endif |
26 | 26 | ||
27 | ifdef CONFIG_MMU | 27 | ifdef CONFIG_MMU |
28 | obj-$(CONFIG_CPU_SH3) += tlb-sh3.o | 28 | tlb-$(CONFIG_CPU_SH3) := tlb-sh3.o |
29 | obj-$(CONFIG_CPU_SH4) += tlb-sh4.o | 29 | tlb-$(CONFIG_CPU_SH4) := tlb-sh4.o |
30 | tlb-$(CONFIG_CPU_HAS_PTEAEX) := tlb-pteaex.o | ||
31 | obj-y += $(tlb-y) | ||
30 | ifndef CONFIG_CACHE_OFF | 32 | ifndef CONFIG_CACHE_OFF |
31 | obj-$(CONFIG_CPU_SH4) += pg-sh4.o | 33 | obj-$(CONFIG_CPU_SH4) += pg-sh4.o |
32 | obj-$(CONFIG_SH7705_CACHE_32KB) += pg-sh7705.o | 34 | obj-$(CONFIG_SH7705_CACHE_32KB) += pg-sh7705.o |
diff --git a/arch/sh/mm/tlb-pteaex.c b/arch/sh/mm/tlb-pteaex.c new file mode 100644 index 000000000000..5c9b2d781e08 --- /dev/null +++ b/arch/sh/mm/tlb-pteaex.c | |||
@@ -0,0 +1,99 @@ | |||
1 | /* | ||
2 | * arch/sh/mm/tlb-pteaex.c | ||
3 | * | ||
4 | * TLB operations for SH-X3 CPUs featuring PTE ASID Extensions. | ||
5 | * | ||
6 | * Copyright (C) 2009 Paul Mundt | ||
7 | * | ||
8 | * This file is subject to the terms and conditions of the GNU General Public | ||
9 | * License. See the file "COPYING" in the main directory of this archive | ||
10 | * for more details. | ||
11 | */ | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/mm.h> | ||
14 | #include <linux/io.h> | ||
15 | #include <asm/system.h> | ||
16 | #include <asm/mmu_context.h> | ||
17 | #include <asm/cacheflush.h> | ||
18 | |||
19 | void update_mmu_cache(struct vm_area_struct * vma, | ||
20 | unsigned long address, pte_t pte) | ||
21 | { | ||
22 | unsigned long flags; | ||
23 | unsigned long pteval; | ||
24 | unsigned long vpn; | ||
25 | |||
26 | /* Ptrace may call this routine. */ | ||
27 | if (vma && current->active_mm != vma->vm_mm) | ||
28 | return; | ||
29 | |||
30 | #ifndef CONFIG_CACHE_OFF | ||
31 | { | ||
32 | unsigned long pfn = pte_pfn(pte); | ||
33 | |||
34 | if (pfn_valid(pfn)) { | ||
35 | struct page *page = pfn_to_page(pfn); | ||
36 | |||
37 | if (!test_bit(PG_mapped, &page->flags)) { | ||
38 | unsigned long phys = pte_val(pte) & PTE_PHYS_MASK; | ||
39 | __flush_wback_region((void *)P1SEGADDR(phys), | ||
40 | PAGE_SIZE); | ||
41 | __set_bit(PG_mapped, &page->flags); | ||
42 | } | ||
43 | } | ||
44 | } | ||
45 | #endif | ||
46 | |||
47 | local_irq_save(flags); | ||
48 | |||
49 | /* Set PTEH register */ | ||
50 | vpn = address & MMU_VPN_MASK; | ||
51 | __raw_writel(vpn, MMU_PTEH); | ||
52 | |||
53 | /* Set PTEAEX */ | ||
54 | __raw_writel(get_asid(), MMU_PTEAEX); | ||
55 | |||
56 | pteval = pte.pte_low; | ||
57 | |||
58 | /* Set PTEA register */ | ||
59 | #ifdef CONFIG_X2TLB | ||
60 | /* | ||
61 | * For the extended mode TLB this is trivial, only the ESZ and | ||
62 | * EPR bits need to be written out to PTEA, with the remainder of | ||
63 | * the protection bits (with the exception of the compat-mode SZ | ||
64 | * and PR bits, which are cleared) being written out in PTEL. | ||
65 | */ | ||
66 | __raw_writel(pte.pte_high, MMU_PTEA); | ||
67 | #else | ||
68 | /* TODO: make this look less hacky */ | ||
69 | __raw_writel(((pteval >> 28) & 0xe) | (pteval & 0x1), MMU_PTEA); | ||
70 | #endif | ||
71 | |||
72 | /* Set PTEL register */ | ||
73 | pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */ | ||
74 | #ifdef CONFIG_CACHE_WRITETHROUGH | ||
75 | pteval |= _PAGE_WT; | ||
76 | #endif | ||
77 | /* conveniently, we want all the software flags to be 0 anyway */ | ||
78 | __raw_writel(pteval, MMU_PTEL); | ||
79 | |||
80 | /* Load the TLB */ | ||
81 | asm volatile("ldtlb": /* no output */ : /* no input */ : "memory"); | ||
82 | local_irq_restore(flags); | ||
83 | } | ||
84 | |||
85 | /* | ||
86 | * While SH-X2 extended TLB mode splits out the memory-mapped I/UTLB | ||
87 | * data arrays, SH-X3 cores with PTEAEX split out the memory-mapped | ||
88 | * address arrays. In compat mode the second array is inaccessible, while | ||
89 | * in extended mode, the legacy 8-bit ASID field in address array 1 has | ||
90 | * undefined behaviour. | ||
91 | */ | ||
92 | void __uses_jump_to_uncached local_flush_tlb_one(unsigned long asid, | ||
93 | unsigned long page) | ||
94 | { | ||
95 | jump_to_uncached(); | ||
96 | __raw_writel(page, MMU_UTLB_ADDRESS_ARRAY | MMU_PAGE_ASSOC_BIT); | ||
97 | __raw_writel(asid, MMU_UTLB_ADDRESS_ARRAY2 | MMU_PAGE_ASSOC_BIT); | ||
98 | back_to_cached(); | ||
99 | } | ||