diff options
-rw-r--r-- | arch/x86/kernel/suspend_64.c | 39 |
1 files changed, 33 insertions, 6 deletions
diff --git a/arch/x86/kernel/suspend_64.c b/arch/x86/kernel/suspend_64.c index da10eef4c3ef..f8fafe527ff1 100644 --- a/arch/x86/kernel/suspend_64.c +++ b/arch/x86/kernel/suspend_64.c | |||
@@ -197,25 +197,42 @@ static int res_phys_pud_init(pud_t *pud, unsigned long address, unsigned long en | |||
197 | return 0; | 197 | return 0; |
198 | } | 198 | } |
199 | 199 | ||
200 | static int res_kernel_text_pud_init(pud_t *pud, unsigned long start) | ||
201 | { | ||
202 | pmd_t *pmd; | ||
203 | unsigned long paddr; | ||
204 | |||
205 | pmd = (pmd_t *)get_safe_page(GFP_ATOMIC); | ||
206 | if (!pmd) | ||
207 | return -ENOMEM; | ||
208 | set_pud(pud + pud_index(start), __pud(__pa(pmd) | _KERNPG_TABLE)); | ||
209 | for (paddr = 0; paddr < KERNEL_TEXT_SIZE; pmd++, paddr += PMD_SIZE) { | ||
210 | unsigned long pe; | ||
211 | |||
212 | pe = __PAGE_KERNEL_LARGE_EXEC | _PAGE_GLOBAL | paddr; | ||
213 | pe &= __supported_pte_mask; | ||
214 | set_pmd(pmd, __pmd(pe)); | ||
215 | } | ||
216 | |||
217 | return 0; | ||
218 | } | ||
219 | |||
200 | static int set_up_temporary_mappings(void) | 220 | static int set_up_temporary_mappings(void) |
201 | { | 221 | { |
202 | unsigned long start, end, next; | 222 | unsigned long start, end, next; |
223 | pud_t *pud; | ||
203 | int error; | 224 | int error; |
204 | 225 | ||
205 | temp_level4_pgt = (pgd_t *)get_safe_page(GFP_ATOMIC); | 226 | temp_level4_pgt = (pgd_t *)get_safe_page(GFP_ATOMIC); |
206 | if (!temp_level4_pgt) | 227 | if (!temp_level4_pgt) |
207 | return -ENOMEM; | 228 | return -ENOMEM; |
208 | 229 | ||
209 | /* It is safe to reuse the original kernel mapping */ | ||
210 | set_pgd(temp_level4_pgt + pgd_index(__START_KERNEL_map), | ||
211 | init_level4_pgt[pgd_index(__START_KERNEL_map)]); | ||
212 | |||
213 | /* Set up the direct mapping from scratch */ | 230 | /* Set up the direct mapping from scratch */ |
214 | start = (unsigned long)pfn_to_kaddr(0); | 231 | start = (unsigned long)pfn_to_kaddr(0); |
215 | end = (unsigned long)pfn_to_kaddr(end_pfn); | 232 | end = (unsigned long)pfn_to_kaddr(end_pfn); |
216 | 233 | ||
217 | for (; start < end; start = next) { | 234 | for (; start < end; start = next) { |
218 | pud_t *pud = (pud_t *)get_safe_page(GFP_ATOMIC); | 235 | pud = (pud_t *)get_safe_page(GFP_ATOMIC); |
219 | if (!pud) | 236 | if (!pud) |
220 | return -ENOMEM; | 237 | return -ENOMEM; |
221 | next = start + PGDIR_SIZE; | 238 | next = start + PGDIR_SIZE; |
@@ -226,7 +243,17 @@ static int set_up_temporary_mappings(void) | |||
226 | set_pgd(temp_level4_pgt + pgd_index(start), | 243 | set_pgd(temp_level4_pgt + pgd_index(start), |
227 | mk_kernel_pgd(__pa(pud))); | 244 | mk_kernel_pgd(__pa(pud))); |
228 | } | 245 | } |
229 | return 0; | 246 | |
247 | /* Set up the kernel text mapping from scratch */ | ||
248 | pud = (pud_t *)get_safe_page(GFP_ATOMIC); | ||
249 | if (!pud) | ||
250 | return -ENOMEM; | ||
251 | error = res_kernel_text_pud_init(pud, __START_KERNEL_map); | ||
252 | if (!error) | ||
253 | set_pgd(temp_level4_pgt + pgd_index(__START_KERNEL_map), | ||
254 | __pgd(__pa(pud) | _PAGE_TABLE)); | ||
255 | |||
256 | return error; | ||
230 | } | 257 | } |
231 | 258 | ||
232 | int swsusp_arch_resume(void) | 259 | int swsusp_arch_resume(void) |