diff options
Diffstat (limited to 'arch/x86/power/hibernate_32.c')
| -rw-r--r-- | arch/x86/power/hibernate_32.c | 52 | 
1 files changed, 38 insertions, 14 deletions
| diff --git a/arch/x86/power/hibernate_32.c b/arch/x86/power/hibernate_32.c index afc4ed7b1578..15695e30f982 100644 --- a/arch/x86/power/hibernate_32.c +++ b/arch/x86/power/hibernate_32.c @@ -14,9 +14,7 @@  #include <asm/pgtable.h>  #include <asm/mmzone.h>  #include <asm/sections.h> - -/* Defined in hibernate_asm_32.S */ -extern int restore_image(void); +#include <asm/suspend.h>  /* Pointer to the temporary resume page tables */  pgd_t *resume_pg_dir; @@ -145,6 +143,32 @@ static inline void resume_init_first_level_page_table(pgd_t *pg_dir)  #endif  } +static int set_up_temporary_text_mapping(pgd_t *pgd_base) +{ +	pgd_t *pgd; +	pmd_t *pmd; +	pte_t *pte; + +	pgd = pgd_base + pgd_index(restore_jump_address); + +	pmd = resume_one_md_table_init(pgd); +	if (!pmd) +		return -ENOMEM; + +	if (boot_cpu_has(X86_FEATURE_PSE)) { +		set_pmd(pmd + pmd_index(restore_jump_address), +		__pmd((jump_address_phys & PMD_MASK) | pgprot_val(PAGE_KERNEL_LARGE_EXEC))); +	} else { +		pte = resume_one_page_table_init(pmd); +		if (!pte) +			return -ENOMEM; +		set_pte(pte + pte_index(restore_jump_address), +		__pte((jump_address_phys & PAGE_MASK) | pgprot_val(PAGE_KERNEL_EXEC))); +	} + +	return 0; +} +  asmlinkage int swsusp_arch_resume(void)  {  	int error; @@ -154,22 +178,22 @@ asmlinkage int swsusp_arch_resume(void)  		return -ENOMEM;  	resume_init_first_level_page_table(resume_pg_dir); + +	error = set_up_temporary_text_mapping(resume_pg_dir); +	if (error) +		return error; +  	error = resume_physical_mapping_init(resume_pg_dir);  	if (error)  		return error; +	temp_pgt = __pa(resume_pg_dir); + +	error = relocate_restore_code(); +	if (error) +		return error; +  	/* We have got enough memory and from now on we cannot recover */  	restore_image();  	return 0;  } - -/* - *	pfn_is_nosave - check if given pfn is in the 'nosave' section - */ - -int pfn_is_nosave(unsigned long pfn) -{ -	unsigned long nosave_begin_pfn = __pa_symbol(&__nosave_begin) >> PAGE_SHIFT; -	unsigned long nosave_end_pfn = PAGE_ALIGN(__pa_symbol(&__nosave_end)) >> PAGE_SHIFT; -	return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn); -} |