2 * Copyright IBM Corp. 2011
3 * Author(s): Jan Glauber <jang@linux.vnet.ibm.com>
5 #include <linux/hugetlb.h>
6 #include <linux/module.h>
8 #include <asm/cacheflush.h>
9 #include <asm/pgtable.h>
12 void storage_key_init_range(unsigned long start
, unsigned long end
)
14 unsigned long boundary
, function
, size
;
17 if (MACHINE_HAS_EDAT2
) {
18 /* set storage keys for a 2GB frame */
19 function
= 0x22000 | PAGE_DEFAULT_KEY
;
21 boundary
= (start
+ size
) & ~(size
- 1);
22 if (boundary
<= end
) {
24 start
= pfmf(function
, start
);
25 } while (start
< boundary
);
29 if (MACHINE_HAS_EDAT1
) {
30 /* set storage keys for a 1MB frame */
31 function
= 0x21000 | PAGE_DEFAULT_KEY
;
33 boundary
= (start
+ size
) & ~(size
- 1);
34 if (boundary
<= end
) {
36 start
= pfmf(function
, start
);
37 } while (start
< boundary
);
41 page_set_storage_key(start
, PAGE_DEFAULT_KEY
, 0);
46 static pte_t
*walk_page_table(unsigned long addr
)
53 pgdp
= pgd_offset_k(addr
);
56 pudp
= pud_offset(pgdp
, addr
);
57 if (pud_none(*pudp
) || pud_large(*pudp
))
59 pmdp
= pmd_offset(pudp
, addr
);
60 if (pmd_none(*pmdp
) || pmd_large(*pmdp
))
62 ptep
= pte_offset_kernel(pmdp
, addr
);
68 static void change_page_attr(unsigned long addr
, int numpages
,
74 for (i
= 0; i
< numpages
; i
++) {
75 ptep
= walk_page_table(addr
);
76 if (WARN_ON_ONCE(!ptep
))
80 __ptep_ipte(addr
, ptep
);
86 int set_memory_ro(unsigned long addr
, int numpages
)
88 change_page_attr(addr
, numpages
, pte_wrprotect
);
92 int set_memory_rw(unsigned long addr
, int numpages
)
94 change_page_attr(addr
, numpages
, pte_mkwrite
);
99 int set_memory_nx(unsigned long addr
, int numpages
)
104 int set_memory_x(unsigned long addr
, int numpages
)
109 #ifdef CONFIG_DEBUG_PAGEALLOC
110 void kernel_map_pages(struct page
*page
, int numpages
, int enable
)
112 unsigned long address
;
119 for (i
= 0; i
< numpages
; i
++) {
120 address
= page_to_phys(page
+ i
);
121 pgd
= pgd_offset_k(address
);
122 pud
= pud_offset(pgd
, address
);
123 pmd
= pmd_offset(pud
, address
);
124 pte
= pte_offset_kernel(pmd
, address
);
126 __ptep_ipte(address
, pte
);
127 pte_val(*pte
) = _PAGE_TYPE_EMPTY
;
130 *pte
= mk_pte_phys(address
, __pgprot(_PAGE_TYPE_RW
));
134 #ifdef CONFIG_HIBERNATION
135 bool kernel_page_present(struct page
*page
)
140 addr
= page_to_phys(page
);
145 : "=d" (cc
), "+a" (addr
) : : "cc");
148 #endif /* CONFIG_HIBERNATION */
150 #endif /* CONFIG_DEBUG_PAGEALLOC */