pageattr.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright IBM Corp. 2011
  4. * Author(s): Jan Glauber <[email protected]>
  5. */
  6. #include <linux/hugetlb.h>
  7. #include <linux/mm.h>
  8. #include <asm/cacheflush.h>
  9. #include <asm/facility.h>
  10. #include <asm/pgalloc.h>
  11. #include <asm/kfence.h>
  12. #include <asm/page.h>
  13. #include <asm/set_memory.h>
  14. static inline unsigned long sske_frame(unsigned long addr, unsigned char skey)
  15. {
  16. asm volatile(".insn rrf,0xb22b0000,%[skey],%[addr],1,0"
  17. : [addr] "+a" (addr) : [skey] "d" (skey));
  18. return addr;
  19. }
  20. void __storage_key_init_range(unsigned long start, unsigned long end)
  21. {
  22. unsigned long boundary, size;
  23. while (start < end) {
  24. if (MACHINE_HAS_EDAT1) {
  25. /* set storage keys for a 1MB frame */
  26. size = 1UL << 20;
  27. boundary = (start + size) & ~(size - 1);
  28. if (boundary <= end) {
  29. do {
  30. start = sske_frame(start, PAGE_DEFAULT_KEY);
  31. } while (start < boundary);
  32. continue;
  33. }
  34. }
  35. page_set_storage_key(start, PAGE_DEFAULT_KEY, 1);
  36. start += PAGE_SIZE;
  37. }
  38. }
  39. #ifdef CONFIG_PROC_FS
  40. atomic_long_t direct_pages_count[PG_DIRECT_MAP_MAX];
  41. void arch_report_meminfo(struct seq_file *m)
  42. {
  43. seq_printf(m, "DirectMap4k: %8lu kB\n",
  44. atomic_long_read(&direct_pages_count[PG_DIRECT_MAP_4K]) << 2);
  45. seq_printf(m, "DirectMap1M: %8lu kB\n",
  46. atomic_long_read(&direct_pages_count[PG_DIRECT_MAP_1M]) << 10);
  47. seq_printf(m, "DirectMap2G: %8lu kB\n",
  48. atomic_long_read(&direct_pages_count[PG_DIRECT_MAP_2G]) << 21);
  49. }
  50. #endif /* CONFIG_PROC_FS */
  51. static void pgt_set(unsigned long *old, unsigned long new, unsigned long addr,
  52. unsigned long dtt)
  53. {
  54. unsigned long *table, mask;
  55. mask = 0;
  56. if (MACHINE_HAS_EDAT2) {
  57. switch (dtt) {
  58. case CRDTE_DTT_REGION3:
  59. mask = ~(PTRS_PER_PUD * sizeof(pud_t) - 1);
  60. break;
  61. case CRDTE_DTT_SEGMENT:
  62. mask = ~(PTRS_PER_PMD * sizeof(pmd_t) - 1);
  63. break;
  64. case CRDTE_DTT_PAGE:
  65. mask = ~(PTRS_PER_PTE * sizeof(pte_t) - 1);
  66. break;
  67. }
  68. table = (unsigned long *)((unsigned long)old & mask);
  69. crdte(*old, new, table, dtt, addr, S390_lowcore.kernel_asce);
  70. } else if (MACHINE_HAS_IDTE) {
  71. cspg(old, *old, new);
  72. } else {
  73. csp((unsigned int *)old + 1, *old, new);
  74. }
  75. }
  76. static int walk_pte_level(pmd_t *pmdp, unsigned long addr, unsigned long end,
  77. unsigned long flags)
  78. {
  79. pte_t *ptep, new;
  80. if (flags == SET_MEMORY_4K)
  81. return 0;
  82. ptep = pte_offset_kernel(pmdp, addr);
  83. do {
  84. new = *ptep;
  85. if (pte_none(new))
  86. return -EINVAL;
  87. if (flags & SET_MEMORY_RO)
  88. new = pte_wrprotect(new);
  89. else if (flags & SET_MEMORY_RW)
  90. new = pte_mkwrite(pte_mkdirty(new));
  91. if (flags & SET_MEMORY_NX)
  92. new = set_pte_bit(new, __pgprot(_PAGE_NOEXEC));
  93. else if (flags & SET_MEMORY_X)
  94. new = clear_pte_bit(new, __pgprot(_PAGE_NOEXEC));
  95. pgt_set((unsigned long *)ptep, pte_val(new), addr, CRDTE_DTT_PAGE);
  96. ptep++;
  97. addr += PAGE_SIZE;
  98. cond_resched();
  99. } while (addr < end);
  100. return 0;
  101. }
  102. static int split_pmd_page(pmd_t *pmdp, unsigned long addr)
  103. {
  104. unsigned long pte_addr, prot;
  105. pte_t *pt_dir, *ptep;
  106. pmd_t new;
  107. int i, ro, nx;
  108. pt_dir = vmem_pte_alloc();
  109. if (!pt_dir)
  110. return -ENOMEM;
  111. pte_addr = pmd_pfn(*pmdp) << PAGE_SHIFT;
  112. ro = !!(pmd_val(*pmdp) & _SEGMENT_ENTRY_PROTECT);
  113. nx = !!(pmd_val(*pmdp) & _SEGMENT_ENTRY_NOEXEC);
  114. prot = pgprot_val(ro ? PAGE_KERNEL_RO : PAGE_KERNEL);
  115. if (!nx)
  116. prot &= ~_PAGE_NOEXEC;
  117. ptep = pt_dir;
  118. for (i = 0; i < PTRS_PER_PTE; i++) {
  119. set_pte(ptep, __pte(pte_addr | prot));
  120. pte_addr += PAGE_SIZE;
  121. ptep++;
  122. }
  123. new = __pmd(__pa(pt_dir) | _SEGMENT_ENTRY);
  124. pgt_set((unsigned long *)pmdp, pmd_val(new), addr, CRDTE_DTT_SEGMENT);
  125. update_page_count(PG_DIRECT_MAP_4K, PTRS_PER_PTE);
  126. update_page_count(PG_DIRECT_MAP_1M, -1);
  127. return 0;
  128. }
  129. static void modify_pmd_page(pmd_t *pmdp, unsigned long addr,
  130. unsigned long flags)
  131. {
  132. pmd_t new = *pmdp;
  133. if (flags & SET_MEMORY_RO)
  134. new = pmd_wrprotect(new);
  135. else if (flags & SET_MEMORY_RW)
  136. new = pmd_mkwrite(pmd_mkdirty(new));
  137. if (flags & SET_MEMORY_NX)
  138. new = set_pmd_bit(new, __pgprot(_SEGMENT_ENTRY_NOEXEC));
  139. else if (flags & SET_MEMORY_X)
  140. new = clear_pmd_bit(new, __pgprot(_SEGMENT_ENTRY_NOEXEC));
  141. pgt_set((unsigned long *)pmdp, pmd_val(new), addr, CRDTE_DTT_SEGMENT);
  142. }
  143. static int walk_pmd_level(pud_t *pudp, unsigned long addr, unsigned long end,
  144. unsigned long flags)
  145. {
  146. unsigned long next;
  147. int need_split;
  148. pmd_t *pmdp;
  149. int rc = 0;
  150. pmdp = pmd_offset(pudp, addr);
  151. do {
  152. if (pmd_none(*pmdp))
  153. return -EINVAL;
  154. next = pmd_addr_end(addr, end);
  155. if (pmd_large(*pmdp)) {
  156. need_split = !!(flags & SET_MEMORY_4K);
  157. need_split |= !!(addr & ~PMD_MASK);
  158. need_split |= !!(addr + PMD_SIZE > next);
  159. if (need_split) {
  160. rc = split_pmd_page(pmdp, addr);
  161. if (rc)
  162. return rc;
  163. continue;
  164. }
  165. modify_pmd_page(pmdp, addr, flags);
  166. } else {
  167. rc = walk_pte_level(pmdp, addr, next, flags);
  168. if (rc)
  169. return rc;
  170. }
  171. pmdp++;
  172. addr = next;
  173. cond_resched();
  174. } while (addr < end);
  175. return rc;
  176. }
  177. static int split_pud_page(pud_t *pudp, unsigned long addr)
  178. {
  179. unsigned long pmd_addr, prot;
  180. pmd_t *pm_dir, *pmdp;
  181. pud_t new;
  182. int i, ro, nx;
  183. pm_dir = vmem_crst_alloc(_SEGMENT_ENTRY_EMPTY);
  184. if (!pm_dir)
  185. return -ENOMEM;
  186. pmd_addr = pud_pfn(*pudp) << PAGE_SHIFT;
  187. ro = !!(pud_val(*pudp) & _REGION_ENTRY_PROTECT);
  188. nx = !!(pud_val(*pudp) & _REGION_ENTRY_NOEXEC);
  189. prot = pgprot_val(ro ? SEGMENT_KERNEL_RO : SEGMENT_KERNEL);
  190. if (!nx)
  191. prot &= ~_SEGMENT_ENTRY_NOEXEC;
  192. pmdp = pm_dir;
  193. for (i = 0; i < PTRS_PER_PMD; i++) {
  194. set_pmd(pmdp, __pmd(pmd_addr | prot));
  195. pmd_addr += PMD_SIZE;
  196. pmdp++;
  197. }
  198. new = __pud(__pa(pm_dir) | _REGION3_ENTRY);
  199. pgt_set((unsigned long *)pudp, pud_val(new), addr, CRDTE_DTT_REGION3);
  200. update_page_count(PG_DIRECT_MAP_1M, PTRS_PER_PMD);
  201. update_page_count(PG_DIRECT_MAP_2G, -1);
  202. return 0;
  203. }
  204. static void modify_pud_page(pud_t *pudp, unsigned long addr,
  205. unsigned long flags)
  206. {
  207. pud_t new = *pudp;
  208. if (flags & SET_MEMORY_RO)
  209. new = pud_wrprotect(new);
  210. else if (flags & SET_MEMORY_RW)
  211. new = pud_mkwrite(pud_mkdirty(new));
  212. if (flags & SET_MEMORY_NX)
  213. new = set_pud_bit(new, __pgprot(_REGION_ENTRY_NOEXEC));
  214. else if (flags & SET_MEMORY_X)
  215. new = clear_pud_bit(new, __pgprot(_REGION_ENTRY_NOEXEC));
  216. pgt_set((unsigned long *)pudp, pud_val(new), addr, CRDTE_DTT_REGION3);
  217. }
  218. static int walk_pud_level(p4d_t *p4d, unsigned long addr, unsigned long end,
  219. unsigned long flags)
  220. {
  221. unsigned long next;
  222. int need_split;
  223. pud_t *pudp;
  224. int rc = 0;
  225. pudp = pud_offset(p4d, addr);
  226. do {
  227. if (pud_none(*pudp))
  228. return -EINVAL;
  229. next = pud_addr_end(addr, end);
  230. if (pud_large(*pudp)) {
  231. need_split = !!(flags & SET_MEMORY_4K);
  232. need_split |= !!(addr & ~PUD_MASK);
  233. need_split |= !!(addr + PUD_SIZE > next);
  234. if (need_split) {
  235. rc = split_pud_page(pudp, addr);
  236. if (rc)
  237. break;
  238. continue;
  239. }
  240. modify_pud_page(pudp, addr, flags);
  241. } else {
  242. rc = walk_pmd_level(pudp, addr, next, flags);
  243. }
  244. pudp++;
  245. addr = next;
  246. cond_resched();
  247. } while (addr < end && !rc);
  248. return rc;
  249. }
  250. static int walk_p4d_level(pgd_t *pgd, unsigned long addr, unsigned long end,
  251. unsigned long flags)
  252. {
  253. unsigned long next;
  254. p4d_t *p4dp;
  255. int rc = 0;
  256. p4dp = p4d_offset(pgd, addr);
  257. do {
  258. if (p4d_none(*p4dp))
  259. return -EINVAL;
  260. next = p4d_addr_end(addr, end);
  261. rc = walk_pud_level(p4dp, addr, next, flags);
  262. p4dp++;
  263. addr = next;
  264. cond_resched();
  265. } while (addr < end && !rc);
  266. return rc;
  267. }
  268. DEFINE_MUTEX(cpa_mutex);
  269. static int change_page_attr(unsigned long addr, unsigned long end,
  270. unsigned long flags)
  271. {
  272. unsigned long next;
  273. int rc = -EINVAL;
  274. pgd_t *pgdp;
  275. if (addr == end)
  276. return 0;
  277. if (end >= MODULES_END)
  278. return -EINVAL;
  279. mutex_lock(&cpa_mutex);
  280. pgdp = pgd_offset_k(addr);
  281. do {
  282. if (pgd_none(*pgdp))
  283. break;
  284. next = pgd_addr_end(addr, end);
  285. rc = walk_p4d_level(pgdp, addr, next, flags);
  286. if (rc)
  287. break;
  288. cond_resched();
  289. } while (pgdp++, addr = next, addr < end && !rc);
  290. mutex_unlock(&cpa_mutex);
  291. return rc;
  292. }
  293. int __set_memory(unsigned long addr, int numpages, unsigned long flags)
  294. {
  295. if (!MACHINE_HAS_NX)
  296. flags &= ~(SET_MEMORY_NX | SET_MEMORY_X);
  297. if (!flags)
  298. return 0;
  299. addr &= PAGE_MASK;
  300. return change_page_attr(addr, addr + numpages * PAGE_SIZE, flags);
  301. }
  302. #if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KFENCE)
  303. static void ipte_range(pte_t *pte, unsigned long address, int nr)
  304. {
  305. int i;
  306. if (test_facility(13)) {
  307. __ptep_ipte_range(address, nr - 1, pte, IPTE_GLOBAL);
  308. return;
  309. }
  310. for (i = 0; i < nr; i++) {
  311. __ptep_ipte(address, pte, 0, 0, IPTE_GLOBAL);
  312. address += PAGE_SIZE;
  313. pte++;
  314. }
  315. }
  316. void __kernel_map_pages(struct page *page, int numpages, int enable)
  317. {
  318. unsigned long address;
  319. pte_t *ptep, pte;
  320. int nr, i, j;
  321. for (i = 0; i < numpages;) {
  322. address = (unsigned long)page_to_virt(page + i);
  323. ptep = virt_to_kpte(address);
  324. nr = (unsigned long)ptep >> ilog2(sizeof(long));
  325. nr = PTRS_PER_PTE - (nr & (PTRS_PER_PTE - 1));
  326. nr = min(numpages - i, nr);
  327. if (enable) {
  328. for (j = 0; j < nr; j++) {
  329. pte = clear_pte_bit(*ptep, __pgprot(_PAGE_INVALID));
  330. set_pte(ptep, pte);
  331. address += PAGE_SIZE;
  332. ptep++;
  333. }
  334. } else {
  335. ipte_range(ptep, address, nr);
  336. }
  337. i += nr;
  338. }
  339. }
  340. #endif /* CONFIG_DEBUG_PAGEALLOC */