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/facility.h>
10 #include <asm/pgtable.h>
14 static inline unsigned long sske_frame(unsigned long addr
, unsigned char skey
)
16 asm volatile(".insn rrf,0xb22b0000,%[skey],%[addr],9,0"
17 : [addr
] "+a" (addr
) : [skey
] "d" (skey
));
21 void __storage_key_init_range(unsigned long start
, unsigned long end
)
23 unsigned long boundary
, size
;
26 if (MACHINE_HAS_EDAT1
) {
27 /* set storage keys for a 1MB frame */
29 boundary
= (start
+ size
) & ~(size
- 1);
30 if (boundary
<= end
) {
32 start
= sske_frame(start
, PAGE_DEFAULT_KEY
);
33 } while (start
< boundary
);
37 page_set_storage_key(start
, PAGE_DEFAULT_KEY
, 0);
43 static pte_t
*walk_page_table(unsigned long addr
)
50 pgdp
= pgd_offset_k(addr
);
53 pudp
= pud_offset(pgdp
, addr
);
54 if (pud_none(*pudp
) || pud_large(*pudp
))
56 pmdp
= pmd_offset(pudp
, addr
);
57 if (pmd_none(*pmdp
) || pmd_large(*pmdp
))
59 ptep
= pte_offset_kernel(pmdp
, addr
);
65 static void change_page_attr(unsigned long addr
, int numpages
,
71 for (i
= 0; i
< numpages
; i
++) {
72 ptep
= walk_page_table(addr
);
73 if (WARN_ON_ONCE(!ptep
))
81 int set_memory_ro(unsigned long addr
, int numpages
)
83 change_page_attr(addr
, numpages
, pte_wrprotect
);
87 int set_memory_rw(unsigned long addr
, int numpages
)
89 change_page_attr(addr
, numpages
, pte_mkwrite
);
94 int set_memory_nx(unsigned long addr
, int numpages
)
99 int set_memory_x(unsigned long addr
, int numpages
)
104 #ifdef CONFIG_DEBUG_PAGEALLOC
106 static void ipte_range(pte_t
*pte
, unsigned long address
, int nr
)
110 if (test_facility(13)) {
111 __ptep_ipte_range(address
, nr
- 1, pte
);
114 for (i
= 0; i
< nr
; i
++) {
115 __ptep_ipte(address
, pte
);
116 address
+= PAGE_SIZE
;
121 void __kernel_map_pages(struct page
*page
, int numpages
, int enable
)
123 unsigned long address
;
130 for (i
= 0; i
< numpages
;) {
131 address
= page_to_phys(page
+ i
);
132 pgd
= pgd_offset_k(address
);
133 pud
= pud_offset(pgd
, address
);
134 pmd
= pmd_offset(pud
, address
);
135 pte
= pte_offset_kernel(pmd
, address
);
136 nr
= (unsigned long)pte
>> ilog2(sizeof(long));
137 nr
= PTRS_PER_PTE
- (nr
& (PTRS_PER_PTE
- 1));
138 nr
= min(numpages
- i
, nr
);
140 for (j
= 0; j
< nr
; j
++) {
141 pte_val(*pte
) = __pa(address
);
142 address
+= PAGE_SIZE
;
146 ipte_range(pte
, address
, nr
);
152 #ifdef CONFIG_HIBERNATION
153 bool kernel_page_present(struct page
*page
)
158 addr
= page_to_phys(page
);
163 : "=d" (cc
), "+a" (addr
) : : "cc");
166 #endif /* CONFIG_HIBERNATION */
168 #endif /* CONFIG_DEBUG_PAGEALLOC */
This page took 0.035201 seconds and 6 git commands to generate.