| .. | .. |
|---|
| 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 | } |
|---|