aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/mm
diff options
context:
space:
mode:
authorMatt Fleming <matt@console-pimps.org>2009-11-17 17:03:41 -0500
committerMatt Fleming <matt@console-pimps.org>2010-01-16 09:29:23 -0500
commit07cad4dc1bfdaefd20c6329e9d8179ad1c600e92 (patch)
tree1ca1e2758dc14245315fc9a9d7334d739d3f0816 /arch/sh/mm
parent24ef7fc4dcc57afa0c33166c25bfe7676ffd4296 (diff)
sh: Generalise the pte handling code for the fixmap path
Generalise the code for setting and clearing pte's and allow TLB entries to be pinned and unpinned if the _PAGE_WIRED flag is present. Signed-off-by: Matt Fleming <matt@console-pimps.org>
Diffstat (limited to 'arch/sh/mm')
-rw-r--r--arch/sh/mm/init.c44
1 files changed, 40 insertions, 4 deletions
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index d5fb014279ad..30a9b530d456 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -39,7 +39,7 @@ unsigned long cached_to_uncached = P2SEG - P1SEG;
39#endif 39#endif
40 40
41#ifdef CONFIG_MMU 41#ifdef CONFIG_MMU
42static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot) 42static pte_t *__get_pte_phys(unsigned long addr)
43{ 43{
44 pgd_t *pgd; 44 pgd_t *pgd;
45 pud_t *pud; 45 pud_t *pud;
@@ -49,22 +49,30 @@ static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
49 pgd = pgd_offset_k(addr); 49 pgd = pgd_offset_k(addr);
50 if (pgd_none(*pgd)) { 50 if (pgd_none(*pgd)) {
51 pgd_ERROR(*pgd); 51 pgd_ERROR(*pgd);
52 return; 52 return NULL;
53 } 53 }
54 54
55 pud = pud_alloc(NULL, pgd, addr); 55 pud = pud_alloc(NULL, pgd, addr);
56 if (unlikely(!pud)) { 56 if (unlikely(!pud)) {
57 pud_ERROR(*pud); 57 pud_ERROR(*pud);
58 return; 58 return NULL;
59 } 59 }
60 60
61 pmd = pmd_alloc(NULL, pud, addr); 61 pmd = pmd_alloc(NULL, pud, addr);
62 if (unlikely(!pmd)) { 62 if (unlikely(!pmd)) {
63 pmd_ERROR(*pmd); 63 pmd_ERROR(*pmd);
64 return; 64 return NULL;
65 } 65 }
66 66
67 pte = pte_offset_kernel(pmd, addr); 67 pte = pte_offset_kernel(pmd, addr);
68 return pte;
69}
70
71static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
72{
73 pte_t *pte;
74
75 pte = __get_pte_phys(addr);
68 if (!pte_none(*pte)) { 76 if (!pte_none(*pte)) {
69 pte_ERROR(*pte); 77 pte_ERROR(*pte);
70 return; 78 return;
@@ -72,6 +80,22 @@ static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
72 80
73 set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, prot)); 81 set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, prot));
74 local_flush_tlb_one(get_asid(), addr); 82 local_flush_tlb_one(get_asid(), addr);
83
84 if (pgprot_val(prot) & _PAGE_WIRED)
85 tlb_wire_entry(NULL, addr, *pte);
86}
87
88static void clear_pte_phys(unsigned long addr, pgprot_t prot)
89{
90 pte_t *pte;
91
92 pte = __get_pte_phys(addr);
93
94 if (pgprot_val(prot) & _PAGE_WIRED)
95 tlb_unwire_entry();
96
97 set_pte(pte, pfn_pte(0, __pgprot(0)));
98 local_flush_tlb_one(get_asid(), addr);
75} 99}
76 100
77/* 101/*
@@ -101,6 +125,18 @@ void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
101 set_pte_phys(address, phys, prot); 125 set_pte_phys(address, phys, prot);
102} 126}
103 127
128void __clear_fixmap(enum fixed_addresses idx, pgprot_t prot)
129{
130 unsigned long address = __fix_to_virt(idx);
131
132 if (idx >= __end_of_fixed_addresses) {
133 BUG();
134 return;
135 }
136
137 clear_pte_phys(address, prot);
138}
139
104void __init page_table_range_init(unsigned long start, unsigned long end, 140void __init page_table_range_init(unsigned long start, unsigned long end,
105 pgd_t *pgd_base) 141 pgd_t *pgd_base)
106{ 142{