10 #include <linux/errno.h>
11 #include <linux/kernel.h>
13 #include <linux/types.h>
17 #include <asm/pgtable.h>
18 #include <asm/uaccess.h>
19 #include <asm/tlbflush.h>
28 struct subpage_prot_table *spt = &mm->
context.spt;
32 for (i = 0; i < 4; ++
i) {
33 if (spt->low_prot[i]) {
34 free_page((
unsigned long)spt->low_prot[i]);
35 spt->low_prot[
i] =
NULL;
39 for (i = 0; i < 2; ++
i) {
43 spt->protptrs[
i] =
NULL;
44 for (j = 0; j < SBP_L2_COUNT && addr < spt->maxaddr;
55 struct subpage_prot_table *spt = &mm->
context.spt;
57 memset(spt, 0,
sizeof(*spt));
60 static void hpte_flush_range(
struct mm_struct *mm,
unsigned long addr,
78 pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
80 for (; npages > 0; --npages) {
86 pte_unmap_unlock(pte - 1, ptl);
93 static void subpage_prot_clear(
unsigned long addr,
unsigned long len)
96 struct subpage_prot_table *spt = &mm->
context.spt;
104 if (limit > spt->maxaddr)
105 limit = spt->maxaddr;
108 if (addr < 0x100000000) {
111 spm = spt->protptrs[addr >> SBP_L3_SHIFT];
115 spp = spm[(addr >> SBP_L2_SHIFT) & (SBP_L2_COUNT - 1)];
118 spp += (addr >>
PAGE_SHIFT) & (SBP_L1_COUNT - 1);
128 hpte_flush_range(mm, addr, nw);
146 struct subpage_prot_table *spt = &mm->
context.spt;
163 subpage_prot_clear(addr, len);
171 for (limit = addr + len; addr <
limit; addr =
next) {
174 if (addr < 0x100000000) {
177 spm = spt->protptrs[addr >> SBP_L3_SHIFT];
182 spt->protptrs[addr >> SBP_L3_SHIFT] = spm;
185 spm += (addr >> SBP_L2_SHIFT) & (SBP_L2_COUNT - 1);
193 spp += (addr >>
PAGE_SHIFT) & (SBP_L1_COUNT - 1);
212 hpte_flush_range(mm, addr, nw);
214 if (limit > spt->maxaddr)
215 spt->maxaddr =
limit;