@@ -182,39 +182,15 @@ int arch_hibernation_header_restore(void *addr)
182
182
}
183
183
EXPORT_SYMBOL (arch_hibernation_header_restore );
184
184
185
- /*
186
- * Copies length bytes, starting at src_start into an new page,
187
- * perform cache maintentance, then maps it at the specified address low
188
- * address as executable.
189
- *
190
- * This is used by hibernate to copy the code it needs to execute when
191
- * overwriting the kernel text. This function generates a new set of page
192
- * tables, which it loads into ttbr0.
193
- *
194
- * Length is provided as we probably only want 4K of data, even on a 64K
195
- * page system.
196
- */
197
- static int create_safe_exec_page (void * src_start , size_t length ,
198
- unsigned long dst_addr ,
199
- phys_addr_t * phys_dst_addr )
185
+ static int trans_pgd_map_page (pgd_t * trans_pgd , void * page ,
186
+ unsigned long dst_addr ,
187
+ pgprot_t pgprot )
200
188
{
201
- void * page = (void * )get_safe_page (GFP_ATOMIC );
202
- pgd_t * trans_pgd ;
203
189
pgd_t * pgdp ;
204
190
pud_t * pudp ;
205
191
pmd_t * pmdp ;
206
192
pte_t * ptep ;
207
193
208
- if (!page )
209
- return - ENOMEM ;
210
-
211
- memcpy (page , src_start , length );
212
- __flush_icache_range ((unsigned long )page , (unsigned long )page + length );
213
-
214
- trans_pgd = (void * )get_safe_page (GFP_ATOMIC );
215
- if (!trans_pgd )
216
- return - ENOMEM ;
217
-
218
194
pgdp = pgd_offset_raw (trans_pgd , dst_addr );
219
195
if (pgd_none (READ_ONCE (* pgdp ))) {
220
196
pudp = (void * )get_safe_page (GFP_ATOMIC );
@@ -242,6 +218,44 @@ static int create_safe_exec_page(void *src_start, size_t length,
242
218
ptep = pte_offset_kernel (pmdp , dst_addr );
243
219
set_pte (ptep , pfn_pte (virt_to_pfn (page ), PAGE_KERNEL_EXEC ));
244
220
221
+ return 0 ;
222
+ }
223
+
224
+ /*
225
+ * Copies length bytes, starting at src_start into an new page,
226
+ * perform cache maintenance, then maps it at the specified address low
227
+ * address as executable.
228
+ *
229
+ * This is used by hibernate to copy the code it needs to execute when
230
+ * overwriting the kernel text. This function generates a new set of page
231
+ * tables, which it loads into ttbr0.
232
+ *
233
+ * Length is provided as we probably only want 4K of data, even on a 64K
234
+ * page system.
235
+ */
236
+ static int create_safe_exec_page (void * src_start , size_t length ,
237
+ unsigned long dst_addr ,
238
+ phys_addr_t * phys_dst_addr )
239
+ {
240
+ void * page = (void * )get_safe_page (GFP_ATOMIC );
241
+ pgd_t * trans_pgd ;
242
+ int rc ;
243
+
244
+ if (!page )
245
+ return - ENOMEM ;
246
+
247
+ memcpy (page , src_start , length );
248
+ __flush_icache_range ((unsigned long )page , (unsigned long )page + length );
249
+
250
+ trans_pgd = (void * )get_safe_page (GFP_ATOMIC );
251
+ if (!trans_pgd )
252
+ return - ENOMEM ;
253
+
254
+ rc = trans_pgd_map_page (trans_pgd , page , dst_addr ,
255
+ PAGE_KERNEL_EXEC );
256
+ if (rc )
257
+ return rc ;
258
+
245
259
/*
246
260
* Load our new page tables. A strict BBM approach requires that we
247
261
* ensure that TLBs are free of any entries that may overlap with the
@@ -462,6 +476,24 @@ static int copy_page_tables(pgd_t *dst_pgdp, unsigned long start,
462
476
return 0 ;
463
477
}
464
478
479
+ static int trans_pgd_create_copy (pgd_t * * dst_pgdp , unsigned long start ,
480
+ unsigned long end )
481
+ {
482
+ int rc ;
483
+ pgd_t * trans_pgd = (pgd_t * )get_safe_page (GFP_ATOMIC );
484
+
485
+ if (!trans_pgd ) {
486
+ pr_err ("Failed to allocate memory for temporary page tables.\n" );
487
+ return - ENOMEM ;
488
+ }
489
+
490
+ rc = copy_page_tables (trans_pgd , start , end );
491
+ if (!rc )
492
+ * dst_pgdp = trans_pgd ;
493
+
494
+ return rc ;
495
+ }
496
+
465
497
/*
466
498
* Setup then Resume from the hibernate image using swsusp_arch_suspend_exit().
467
499
*
@@ -483,12 +515,7 @@ int swsusp_arch_resume(void)
483
515
* Create a second copy of just the linear map, and use this when
484
516
* restoring.
485
517
*/
486
- tmp_pg_dir = (pgd_t * )get_safe_page (GFP_ATOMIC );
487
- if (!tmp_pg_dir ) {
488
- pr_err ("Failed to allocate memory for temporary page tables.\n" );
489
- return - ENOMEM ;
490
- }
491
- rc = copy_page_tables (tmp_pg_dir , PAGE_OFFSET , PAGE_END );
518
+ rc = trans_pgd_create_copy (& tmp_pg_dir , PAGE_OFFSET , PAGE_END );
492
519
if (rc )
493
520
return rc ;
494
521
0 commit comments