diff options
Diffstat (limited to 'arch/s390/mm/vmem.c')
| -rw-r--r-- | arch/s390/mm/vmem.c | 53 |
1 files changed, 35 insertions, 18 deletions
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c index fd594d5fe142..fb9c5a85aa56 100644 --- a/arch/s390/mm/vmem.c +++ b/arch/s390/mm/vmem.c | |||
| @@ -73,31 +73,28 @@ static void __init_refok *vmem_alloc_pages(unsigned int order) | |||
| 73 | return alloc_bootmem_pages((1 << order) * PAGE_SIZE); | 73 | return alloc_bootmem_pages((1 << order) * PAGE_SIZE); |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | #define vmem_pud_alloc() ({ BUG(); ((pud_t *) NULL); }) | ||
| 77 | |||
| 76 | static inline pmd_t *vmem_pmd_alloc(void) | 78 | static inline pmd_t *vmem_pmd_alloc(void) |
| 77 | { | 79 | { |
| 78 | pmd_t *pmd; | 80 | pmd_t *pmd = NULL; |
| 79 | int i; | ||
| 80 | 81 | ||
| 81 | pmd = vmem_alloc_pages(PMD_ALLOC_ORDER); | 82 | #ifdef CONFIG_64BIT |
| 83 | pmd = vmem_alloc_pages(2); | ||
| 82 | if (!pmd) | 84 | if (!pmd) |
| 83 | return NULL; | 85 | return NULL; |
| 84 | for (i = 0; i < PTRS_PER_PMD; i++) | 86 | clear_table((unsigned long *) pmd, _SEGMENT_ENTRY_EMPTY, PAGE_SIZE*4); |
| 85 | pmd_clear_kernel(pmd + i); | 87 | #endif |
| 86 | return pmd; | 88 | return pmd; |
| 87 | } | 89 | } |
| 88 | 90 | ||
| 89 | static inline pte_t *vmem_pte_alloc(void) | 91 | static inline pte_t *vmem_pte_alloc(void) |
| 90 | { | 92 | { |
| 91 | pte_t *pte; | 93 | pte_t *pte = vmem_alloc_pages(0); |
| 92 | pte_t empty_pte; | ||
| 93 | int i; | ||
| 94 | 94 | ||
| 95 | pte = vmem_alloc_pages(PTE_ALLOC_ORDER); | ||
| 96 | if (!pte) | 95 | if (!pte) |
| 97 | return NULL; | 96 | return NULL; |
| 98 | pte_val(empty_pte) = _PAGE_TYPE_EMPTY; | 97 | clear_table((unsigned long *) pte, _PAGE_TYPE_EMPTY, PAGE_SIZE); |
| 99 | for (i = 0; i < PTRS_PER_PTE; i++) | ||
| 100 | pte[i] = empty_pte; | ||
| 101 | return pte; | 98 | return pte; |
| 102 | } | 99 | } |
| 103 | 100 | ||
| @@ -108,6 +105,7 @@ static int vmem_add_range(unsigned long start, unsigned long size) | |||
| 108 | { | 105 | { |
| 109 | unsigned long address; | 106 | unsigned long address; |
| 110 | pgd_t *pg_dir; | 107 | pgd_t *pg_dir; |
| 108 | pud_t *pu_dir; | ||
| 111 | pmd_t *pm_dir; | 109 | pmd_t *pm_dir; |
| 112 | pte_t *pt_dir; | 110 | pte_t *pt_dir; |
| 113 | pte_t pte; | 111 | pte_t pte; |
| @@ -116,13 +114,21 @@ static int vmem_add_range(unsigned long start, unsigned long size) | |||
| 116 | for (address = start; address < start + size; address += PAGE_SIZE) { | 114 | for (address = start; address < start + size; address += PAGE_SIZE) { |
| 117 | pg_dir = pgd_offset_k(address); | 115 | pg_dir = pgd_offset_k(address); |
| 118 | if (pgd_none(*pg_dir)) { | 116 | if (pgd_none(*pg_dir)) { |
| 117 | pu_dir = vmem_pud_alloc(); | ||
| 118 | if (!pu_dir) | ||
| 119 | goto out; | ||
| 120 | pgd_populate_kernel(&init_mm, pg_dir, pu_dir); | ||
| 121 | } | ||
| 122 | |||
| 123 | pu_dir = pud_offset(pg_dir, address); | ||
| 124 | if (pud_none(*pu_dir)) { | ||
| 119 | pm_dir = vmem_pmd_alloc(); | 125 | pm_dir = vmem_pmd_alloc(); |
| 120 | if (!pm_dir) | 126 | if (!pm_dir) |
| 121 | goto out; | 127 | goto out; |
| 122 | pgd_populate_kernel(&init_mm, pg_dir, pm_dir); | 128 | pud_populate_kernel(&init_mm, pu_dir, pm_dir); |
| 123 | } | 129 | } |
| 124 | 130 | ||
| 125 | pm_dir = pmd_offset(pg_dir, address); | 131 | pm_dir = pmd_offset(pu_dir, address); |
| 126 | if (pmd_none(*pm_dir)) { | 132 | if (pmd_none(*pm_dir)) { |
| 127 | pt_dir = vmem_pte_alloc(); | 133 | pt_dir = vmem_pte_alloc(); |
| 128 | if (!pt_dir) | 134 | if (!pt_dir) |
| @@ -148,6 +154,7 @@ static void vmem_remove_range(unsigned long start, unsigned long size) | |||
| 148 | { | 154 | { |
| 149 | unsigned long address; | 155 | unsigned long address; |
| 150 | pgd_t *pg_dir; | 156 | pgd_t *pg_dir; |
| 157 | pud_t *pu_dir; | ||
| 151 | pmd_t *pm_dir; | 158 | pmd_t *pm_dir; |
| 152 | pte_t *pt_dir; | 159 | pte_t *pt_dir; |
| 153 | pte_t pte; | 160 | pte_t pte; |
| @@ -155,9 +162,10 @@ static void vmem_remove_range(unsigned long start, unsigned long size) | |||
| 155 | pte_val(pte) = _PAGE_TYPE_EMPTY; | 162 | pte_val(pte) = _PAGE_TYPE_EMPTY; |
| 156 | for (address = start; address < start + size; address += PAGE_SIZE) { | 163 | for (address = start; address < start + size; address += PAGE_SIZE) { |
| 157 | pg_dir = pgd_offset_k(address); | 164 | pg_dir = pgd_offset_k(address); |
| 158 | if (pgd_none(*pg_dir)) | 165 | pu_dir = pud_offset(pg_dir, address); |
| 166 | if (pud_none(*pu_dir)) | ||
| 159 | continue; | 167 | continue; |
| 160 | pm_dir = pmd_offset(pg_dir, address); | 168 | pm_dir = pmd_offset(pu_dir, address); |
| 161 | if (pmd_none(*pm_dir)) | 169 | if (pmd_none(*pm_dir)) |
| 162 | continue; | 170 | continue; |
| 163 | pt_dir = pte_offset_kernel(pm_dir, address); | 171 | pt_dir = pte_offset_kernel(pm_dir, address); |
| @@ -174,6 +182,7 @@ static int vmem_add_mem_map(unsigned long start, unsigned long size) | |||
| 174 | unsigned long address, start_addr, end_addr; | 182 | unsigned long address, start_addr, end_addr; |
| 175 | struct page *map_start, *map_end; | 183 | struct page *map_start, *map_end; |
| 176 | pgd_t *pg_dir; | 184 | pgd_t *pg_dir; |
| 185 | pud_t *pu_dir; | ||
| 177 | pmd_t *pm_dir; | 186 | pmd_t *pm_dir; |
| 178 | pte_t *pt_dir; | 187 | pte_t *pt_dir; |
| 179 | pte_t pte; | 188 | pte_t pte; |
| @@ -188,13 +197,21 @@ static int vmem_add_mem_map(unsigned long start, unsigned long size) | |||
| 188 | for (address = start_addr; address < end_addr; address += PAGE_SIZE) { | 197 | for (address = start_addr; address < end_addr; address += PAGE_SIZE) { |
| 189 | pg_dir = pgd_offset_k(address); | 198 | pg_dir = pgd_offset_k(address); |
| 190 | if (pgd_none(*pg_dir)) { | 199 | if (pgd_none(*pg_dir)) { |
| 200 | pu_dir = vmem_pud_alloc(); | ||
| 201 | if (!pu_dir) | ||
| 202 | goto out; | ||
| 203 | pgd_populate_kernel(&init_mm, pg_dir, pu_dir); | ||
| 204 | } | ||
| 205 | |||
| 206 | pu_dir = pud_offset(pg_dir, address); | ||
| 207 | if (pud_none(*pu_dir)) { | ||
| 191 | pm_dir = vmem_pmd_alloc(); | 208 | pm_dir = vmem_pmd_alloc(); |
| 192 | if (!pm_dir) | 209 | if (!pm_dir) |
| 193 | goto out; | 210 | goto out; |
| 194 | pgd_populate_kernel(&init_mm, pg_dir, pm_dir); | 211 | pud_populate_kernel(&init_mm, pu_dir, pm_dir); |
| 195 | } | 212 | } |
| 196 | 213 | ||
| 197 | pm_dir = pmd_offset(pg_dir, address); | 214 | pm_dir = pmd_offset(pu_dir, address); |
| 198 | if (pmd_none(*pm_dir)) { | 215 | if (pmd_none(*pm_dir)) { |
| 199 | pt_dir = vmem_pte_alloc(); | 216 | pt_dir = vmem_pte_alloc(); |
| 200 | if (!pt_dir) | 217 | if (!pt_dir) |
