|
@@ -404,6 +404,38 @@ int swsusp_arch_resume(void)
|
|
void __noreturn (*hibernate_exit)(phys_addr_t, phys_addr_t, void *,
|
|
void __noreturn (*hibernate_exit)(phys_addr_t, phys_addr_t, void *,
|
|
void *, phys_addr_t, phys_addr_t);
|
|
void *, phys_addr_t, phys_addr_t);
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Restoring the memory image will overwrite the ttbr1 page tables.
|
|
|
|
+ * Create a second copy of just the linear map, and use this when
|
|
|
|
+ * restoring.
|
|
|
|
+ */
|
|
|
|
+ tmp_pg_dir = (pgd_t *)get_safe_page(GFP_ATOMIC);
|
|
|
|
+ if (!tmp_pg_dir) {
|
|
|
|
+ pr_err("Failed to allocate memory for temporary page tables.");
|
|
|
|
+ rc = -ENOMEM;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ rc = copy_page_tables(tmp_pg_dir, PAGE_OFFSET, 0);
|
|
|
|
+ if (rc)
|
|
|
|
+ goto out;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Since we only copied the linear map, we need to find restore_pblist's
|
|
|
|
+ * linear map address.
|
|
|
|
+ */
|
|
|
|
+ lm_restore_pblist = LMADDR(restore_pblist);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * We need a zero page that is zero before & after resume in order to
|
|
|
|
+ * to break before make on the ttbr1 page tables.
|
|
|
|
+ */
|
|
|
|
+ zero_page = (void *)get_safe_page(GFP_ATOMIC);
|
|
|
|
+ if (!zero_page) {
|
|
|
|
+ pr_err("Failed to allocate zero page.");
|
|
|
|
+ rc = -ENOMEM;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Locate the exit code in the bottom-but-one page, so that *NULL
|
|
* Locate the exit code in the bottom-but-one page, so that *NULL
|
|
* still has disastrous affects.
|
|
* still has disastrous affects.
|
|
@@ -429,27 +461,6 @@ int swsusp_arch_resume(void)
|
|
*/
|
|
*/
|
|
__flush_dcache_area(hibernate_exit, exit_size);
|
|
__flush_dcache_area(hibernate_exit, exit_size);
|
|
|
|
|
|
- /*
|
|
|
|
- * Restoring the memory image will overwrite the ttbr1 page tables.
|
|
|
|
- * Create a second copy of just the linear map, and use this when
|
|
|
|
- * restoring.
|
|
|
|
- */
|
|
|
|
- tmp_pg_dir = (pgd_t *)get_safe_page(GFP_ATOMIC);
|
|
|
|
- if (!tmp_pg_dir) {
|
|
|
|
- pr_err("Failed to allocate memory for temporary page tables.");
|
|
|
|
- rc = -ENOMEM;
|
|
|
|
- goto out;
|
|
|
|
- }
|
|
|
|
- rc = copy_page_tables(tmp_pg_dir, PAGE_OFFSET, 0);
|
|
|
|
- if (rc)
|
|
|
|
- goto out;
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * Since we only copied the linear map, we need to find restore_pblist's
|
|
|
|
- * linear map address.
|
|
|
|
- */
|
|
|
|
- lm_restore_pblist = LMADDR(restore_pblist);
|
|
|
|
-
|
|
|
|
/*
|
|
/*
|
|
* KASLR will cause the el2 vectors to be in a different location in
|
|
* KASLR will cause the el2 vectors to be in a different location in
|
|
* the resumed kernel. Load hibernate's temporary copy into el2.
|
|
* the resumed kernel. Load hibernate's temporary copy into el2.
|
|
@@ -464,12 +475,6 @@ int swsusp_arch_resume(void)
|
|
__hyp_set_vectors(el2_vectors);
|
|
__hyp_set_vectors(el2_vectors);
|
|
}
|
|
}
|
|
|
|
|
|
- /*
|
|
|
|
- * We need a zero page that is zero before & after resume in order to
|
|
|
|
- * to break before make on the ttbr1 page tables.
|
|
|
|
- */
|
|
|
|
- zero_page = (void *)get_safe_page(GFP_ATOMIC);
|
|
|
|
-
|
|
|
|
hibernate_exit(virt_to_phys(tmp_pg_dir), resume_hdr.ttbr1_el1,
|
|
hibernate_exit(virt_to_phys(tmp_pg_dir), resume_hdr.ttbr1_el1,
|
|
resume_hdr.reenter_kernel, lm_restore_pblist,
|
|
resume_hdr.reenter_kernel, lm_restore_pblist,
|
|
resume_hdr.__hyp_stub_vectors, virt_to_phys(zero_page));
|
|
resume_hdr.__hyp_stub_vectors, virt_to_phys(zero_page));
|