.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Hibernation support specific for i386 - temporary page tables |
---|
3 | | - * |
---|
4 | | - * Distribute under GPLv2 |
---|
5 | 4 | * |
---|
6 | 5 | * Copyright (c) 2006 Rafael J. Wysocki <rjw@sisk.pl> |
---|
7 | 6 | */ |
---|
8 | 7 | |
---|
9 | 8 | #include <linux/gfp.h> |
---|
10 | 9 | #include <linux/suspend.h> |
---|
11 | | -#include <linux/bootmem.h> |
---|
| 10 | +#include <linux/memblock.h> |
---|
| 11 | +#include <linux/pgtable.h> |
---|
12 | 12 | |
---|
13 | 13 | #include <asm/page.h> |
---|
14 | | -#include <asm/pgtable.h> |
---|
15 | 14 | #include <asm/mmzone.h> |
---|
16 | 15 | #include <asm/sections.h> |
---|
17 | | - |
---|
18 | | -/* Defined in hibernate_asm_32.S */ |
---|
19 | | -extern int restore_image(void); |
---|
| 16 | +#include <asm/suspend.h> |
---|
20 | 17 | |
---|
21 | 18 | /* Pointer to the temporary resume page tables */ |
---|
22 | 19 | pgd_t *resume_pg_dir; |
---|
.. | .. |
---|
145 | 142 | #endif |
---|
146 | 143 | } |
---|
147 | 144 | |
---|
| 145 | +static int set_up_temporary_text_mapping(pgd_t *pgd_base) |
---|
| 146 | +{ |
---|
| 147 | + pgd_t *pgd; |
---|
| 148 | + pmd_t *pmd; |
---|
| 149 | + pte_t *pte; |
---|
| 150 | + |
---|
| 151 | + pgd = pgd_base + pgd_index(restore_jump_address); |
---|
| 152 | + |
---|
| 153 | + pmd = resume_one_md_table_init(pgd); |
---|
| 154 | + if (!pmd) |
---|
| 155 | + return -ENOMEM; |
---|
| 156 | + |
---|
| 157 | + if (boot_cpu_has(X86_FEATURE_PSE)) { |
---|
| 158 | + set_pmd(pmd + pmd_index(restore_jump_address), |
---|
| 159 | + __pmd((jump_address_phys & PMD_MASK) | pgprot_val(PAGE_KERNEL_LARGE_EXEC))); |
---|
| 160 | + } else { |
---|
| 161 | + pte = resume_one_page_table_init(pmd); |
---|
| 162 | + if (!pte) |
---|
| 163 | + return -ENOMEM; |
---|
| 164 | + set_pte(pte + pte_index(restore_jump_address), |
---|
| 165 | + __pte((jump_address_phys & PAGE_MASK) | pgprot_val(PAGE_KERNEL_EXEC))); |
---|
| 166 | + } |
---|
| 167 | + |
---|
| 168 | + return 0; |
---|
| 169 | +} |
---|
| 170 | + |
---|
148 | 171 | asmlinkage int swsusp_arch_resume(void) |
---|
149 | 172 | { |
---|
150 | 173 | int error; |
---|
.. | .. |
---|
154 | 177 | return -ENOMEM; |
---|
155 | 178 | |
---|
156 | 179 | resume_init_first_level_page_table(resume_pg_dir); |
---|
| 180 | + |
---|
| 181 | + error = set_up_temporary_text_mapping(resume_pg_dir); |
---|
| 182 | + if (error) |
---|
| 183 | + return error; |
---|
| 184 | + |
---|
157 | 185 | error = resume_physical_mapping_init(resume_pg_dir); |
---|
| 186 | + if (error) |
---|
| 187 | + return error; |
---|
| 188 | + |
---|
| 189 | + temp_pgt = __pa(resume_pg_dir); |
---|
| 190 | + |
---|
| 191 | + error = relocate_restore_code(); |
---|
158 | 192 | if (error) |
---|
159 | 193 | return error; |
---|
160 | 194 | |
---|
161 | 195 | /* We have got enough memory and from now on we cannot recover */ |
---|
162 | 196 | restore_image(); |
---|
163 | 197 | return 0; |
---|
164 | | -} |
---|
165 | | - |
---|
166 | | -/* |
---|
167 | | - * pfn_is_nosave - check if given pfn is in the 'nosave' section |
---|
168 | | - */ |
---|
169 | | - |
---|
170 | | -int pfn_is_nosave(unsigned long pfn) |
---|
171 | | -{ |
---|
172 | | - unsigned long nosave_begin_pfn = __pa_symbol(&__nosave_begin) >> PAGE_SHIFT; |
---|
173 | | - unsigned long nosave_end_pfn = PAGE_ALIGN(__pa_symbol(&__nosave_end)) >> PAGE_SHIFT; |
---|
174 | | - return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn); |
---|
175 | 198 | } |
---|