~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/s390/mm/pageattr.c

Version: ~ [ linux-5.13-rc1 ] ~ [ linux-5.12.2 ] ~ [ linux-5.11.19 ] ~ [ linux-5.10.35 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.117 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.190 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.232 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.268 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.268 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * Copyright IBM Corp. 2011
  3  * Author(s): Jan Glauber <jang@linux.vnet.ibm.com>
  4  */
  5 #include <linux/hugetlb.h>
  6 #include <linux/module.h>
  7 #include <linux/mm.h>
  8 #include <asm/cacheflush.h>
  9 #include <asm/facility.h>
 10 #include <asm/pgtable.h>
 11 #include <asm/page.h>
 12 
 13 #if PAGE_DEFAULT_KEY
 14 static inline unsigned long sske_frame(unsigned long addr, unsigned char skey)
 15 {
 16         asm volatile(".insn rrf,0xb22b0000,%[skey],%[addr],9,0"
 17                      : [addr] "+a" (addr) : [skey] "d" (skey));
 18         return addr;
 19 }
 20 
 21 void __storage_key_init_range(unsigned long start, unsigned long end)
 22 {
 23         unsigned long boundary, size;
 24 
 25         while (start < end) {
 26                 if (MACHINE_HAS_EDAT1) {
 27                         /* set storage keys for a 1MB frame */
 28                         size = 1UL << 20;
 29                         boundary = (start + size) & ~(size - 1);
 30                         if (boundary <= end) {
 31                                 do {
 32                                         start = sske_frame(start, PAGE_DEFAULT_KEY);
 33                                 } while (start < boundary);
 34                                 continue;
 35                         }
 36                 }
 37                 page_set_storage_key(start, PAGE_DEFAULT_KEY, 0);
 38                 start += PAGE_SIZE;
 39         }
 40 }
 41 #endif
 42 
 43 static pte_t *walk_page_table(unsigned long addr)
 44 {
 45         pgd_t *pgdp;
 46         pud_t *pudp;
 47         pmd_t *pmdp;
 48         pte_t *ptep;
 49 
 50         pgdp = pgd_offset_k(addr);
 51         if (pgd_none(*pgdp))
 52                 return NULL;
 53         pudp = pud_offset(pgdp, addr);
 54         if (pud_none(*pudp) || pud_large(*pudp))
 55                 return NULL;
 56         pmdp = pmd_offset(pudp, addr);
 57         if (pmd_none(*pmdp) || pmd_large(*pmdp))
 58                 return NULL;
 59         ptep = pte_offset_kernel(pmdp, addr);
 60         if (pte_none(*ptep))
 61                 return NULL;
 62         return ptep;
 63 }
 64 
 65 static void change_page_attr(unsigned long addr, int numpages,
 66                              pte_t (*set) (pte_t))
 67 {
 68         pte_t *ptep, pte;
 69         int i;
 70 
 71         for (i = 0; i < numpages; i++) {
 72                 ptep = walk_page_table(addr);
 73                 if (WARN_ON_ONCE(!ptep))
 74                         break;
 75                 pte = *ptep;
 76                 pte = set(pte);
 77                 __ptep_ipte(addr, ptep);
 78                 *ptep = pte;
 79                 addr += PAGE_SIZE;
 80         }
 81 }
 82 
 83 int set_memory_ro(unsigned long addr, int numpages)
 84 {
 85         change_page_attr(addr, numpages, pte_wrprotect);
 86         return 0;
 87 }
 88 
 89 int set_memory_rw(unsigned long addr, int numpages)
 90 {
 91         change_page_attr(addr, numpages, pte_mkwrite);
 92         return 0;
 93 }
 94 
 95 /* not possible */
 96 int set_memory_nx(unsigned long addr, int numpages)
 97 {
 98         return 0;
 99 }
100 
101 int set_memory_x(unsigned long addr, int numpages)
102 {
103         return 0;
104 }
105 
106 #ifdef CONFIG_DEBUG_PAGEALLOC
107 
108 static void ipte_range(pte_t *pte, unsigned long address, int nr)
109 {
110         int i;
111 
112         if (test_facility(13)) {
113                 __ptep_ipte_range(address, nr - 1, pte);
114                 return;
115         }
116         for (i = 0; i < nr; i++) {
117                 __ptep_ipte(address, pte);
118                 address += PAGE_SIZE;
119                 pte++;
120         }
121 }
122 
123 void __kernel_map_pages(struct page *page, int numpages, int enable)
124 {
125         unsigned long address;
126         int nr, i, j;
127         pgd_t *pgd;
128         pud_t *pud;
129         pmd_t *pmd;
130         pte_t *pte;
131 
132         for (i = 0; i < numpages;) {
133                 address = page_to_phys(page + i);
134                 pgd = pgd_offset_k(address);
135                 pud = pud_offset(pgd, address);
136                 pmd = pmd_offset(pud, address);
137                 pte = pte_offset_kernel(pmd, address);
138                 nr = (unsigned long)pte >> ilog2(sizeof(long));
139                 nr = PTRS_PER_PTE - (nr & (PTRS_PER_PTE - 1));
140                 nr = min(numpages - i, nr);
141                 if (enable) {
142                         for (j = 0; j < nr; j++) {
143                                 pte_val(*pte) = __pa(address);
144                                 address += PAGE_SIZE;
145                                 pte++;
146                         }
147                 } else {
148                         ipte_range(pte, address, nr);
149                 }
150                 i += nr;
151         }
152 }
153 
154 #ifdef CONFIG_HIBERNATION
155 bool kernel_page_present(struct page *page)
156 {
157         unsigned long addr;
158         int cc;
159 
160         addr = page_to_phys(page);
161         asm volatile(
162                 "       lra     %1,0(%1)\n"
163                 "       ipm     %0\n"
164                 "       srl     %0,28"
165                 : "=d" (cc), "+a" (addr) : : "cc");
166         return cc == 0;
167 }
168 #endif /* CONFIG_HIBERNATION */
169 
170 #endif /* CONFIG_DEBUG_PAGEALLOC */
171 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp