aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/suspend_64.c39
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
200static 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
200static int set_up_temporary_mappings(void) 220static 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
232int swsusp_arch_resume(void) 259int swsusp_arch_resume(void)