x86 PM: consolidate suspend and hibernation code

Move the hibernation-specific code from arch/x86/power/suspend_64.c
to a separate file (hibernate_64.c) and the CPU-handling code to
cpu_64.c (in line with the corresponding 32-bit code).

Simplify arch/x86/power/Makefile .

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

authored by Rafael J. Wysocki and committed by Thomas Gleixner ef8b03fa c5759124

+171 -162
+2 -7
arch/x86/power/Makefile
··· 1 - ifeq ($(CONFIG_X86_64),y) 2 - obj-$(CONFIG_PM) += suspend_64.o 3 - obj-$(CONFIG_HIBERNATION) += hibernate_asm_64.o 4 - else 5 - obj-$(CONFIG_PM) += cpu_32.o 6 - obj-$(CONFIG_HIBERNATION) += hibernate_32.o hibernate_asm_32.o 7 - endif 1 + obj-$(CONFIG_PM_SLEEP) += cpu_$(BITS).o 2 + obj-$(CONFIG_HIBERNATION) += hibernate_$(BITS).o hibernate_asm_$(BITS).o
+169
arch/x86/power/hibernate_64.c
··· 1 + /* 2 + * Hibernation support for x86-64 3 + * 4 + * Distribute under GPLv2 5 + * 6 + * Copyright (c) 2007 Rafael J. Wysocki <rjw@sisk.pl> 7 + * Copyright (c) 2002 Pavel Machek <pavel@suse.cz> 8 + * Copyright (c) 2001 Patrick Mochel <mochel@osdl.org> 9 + */ 10 + 11 + #include <linux/smp.h> 12 + #include <linux/suspend.h> 13 + #include <asm/proto.h> 14 + #include <asm/page.h> 15 + #include <asm/pgtable.h> 16 + #include <asm/mtrr.h> 17 + 18 + /* References to section boundaries */ 19 + extern const void __nosave_begin, __nosave_end; 20 + 21 + /* Defined in arch/x86_64/kernel/suspend_asm.S */ 22 + extern int restore_image(void); 23 + 24 + /* 25 + * Address to jump to in the last phase of restore in order to get to the image 26 + * kernel's text (this value is passed in the image header). 27 + */ 28 + unsigned long restore_jump_address; 29 + 30 + /* 31 + * Value of the cr3 register from before the hibernation (this value is passed 32 + * in the image header). 33 + */ 34 + unsigned long restore_cr3; 35 + 36 + pgd_t *temp_level4_pgt; 37 + 38 + void *relocated_restore_code; 39 + 40 + static int res_phys_pud_init(pud_t *pud, unsigned long address, unsigned long end) 41 + { 42 + long i, j; 43 + 44 + i = pud_index(address); 45 + pud = pud + i; 46 + for (; i < PTRS_PER_PUD; pud++, i++) { 47 + unsigned long paddr; 48 + pmd_t *pmd; 49 + 50 + paddr = address + i*PUD_SIZE; 51 + if (paddr >= end) 52 + break; 53 + 54 + pmd = (pmd_t *)get_safe_page(GFP_ATOMIC); 55 + if (!pmd) 56 + return -ENOMEM; 57 + set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE)); 58 + for (j = 0; j < PTRS_PER_PMD; pmd++, j++, paddr += PMD_SIZE) { 59 + unsigned long pe; 60 + 61 + if (paddr >= end) 62 + break; 63 + pe = __PAGE_KERNEL_LARGE_EXEC | paddr; 64 + pe &= __supported_pte_mask; 65 + set_pmd(pmd, __pmd(pe)); 66 + } 67 + } 68 + return 0; 69 + } 70 + 71 + static int set_up_temporary_mappings(void) 72 + { 73 + unsigned long start, end, next; 74 + int error; 75 + 76 + temp_level4_pgt = (pgd_t *)get_safe_page(GFP_ATOMIC); 77 + if (!temp_level4_pgt) 78 + return -ENOMEM; 79 + 80 + /* It is safe to reuse the original kernel mapping */ 81 + set_pgd(temp_level4_pgt + pgd_index(__START_KERNEL_map), 82 + init_level4_pgt[pgd_index(__START_KERNEL_map)]); 83 + 84 + /* Set up the direct mapping from scratch */ 85 + start = (unsigned long)pfn_to_kaddr(0); 86 + end = (unsigned long)pfn_to_kaddr(end_pfn); 87 + 88 + for (; start < end; start = next) { 89 + pud_t *pud = (pud_t *)get_safe_page(GFP_ATOMIC); 90 + if (!pud) 91 + return -ENOMEM; 92 + next = start + PGDIR_SIZE; 93 + if (next > end) 94 + next = end; 95 + if ((error = res_phys_pud_init(pud, __pa(start), __pa(next)))) 96 + return error; 97 + set_pgd(temp_level4_pgt + pgd_index(start), 98 + mk_kernel_pgd(__pa(pud))); 99 + } 100 + return 0; 101 + } 102 + 103 + int swsusp_arch_resume(void) 104 + { 105 + int error; 106 + 107 + /* We have got enough memory and from now on we cannot recover */ 108 + if ((error = set_up_temporary_mappings())) 109 + return error; 110 + 111 + relocated_restore_code = (void *)get_safe_page(GFP_ATOMIC); 112 + if (!relocated_restore_code) 113 + return -ENOMEM; 114 + memcpy(relocated_restore_code, &core_restore_code, 115 + &restore_registers - &core_restore_code); 116 + 117 + restore_image(); 118 + return 0; 119 + } 120 + 121 + /* 122 + * pfn_is_nosave - check if given pfn is in the 'nosave' section 123 + */ 124 + 125 + int pfn_is_nosave(unsigned long pfn) 126 + { 127 + unsigned long nosave_begin_pfn = __pa_symbol(&__nosave_begin) >> PAGE_SHIFT; 128 + unsigned long nosave_end_pfn = PAGE_ALIGN(__pa_symbol(&__nosave_end)) >> PAGE_SHIFT; 129 + return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn); 130 + } 131 + 132 + struct restore_data_record { 133 + unsigned long jump_address; 134 + unsigned long cr3; 135 + unsigned long magic; 136 + }; 137 + 138 + #define RESTORE_MAGIC 0x0123456789ABCDEFUL 139 + 140 + /** 141 + * arch_hibernation_header_save - populate the architecture specific part 142 + * of a hibernation image header 143 + * @addr: address to save the data at 144 + */ 145 + int arch_hibernation_header_save(void *addr, unsigned int max_size) 146 + { 147 + struct restore_data_record *rdr = addr; 148 + 149 + if (max_size < sizeof(struct restore_data_record)) 150 + return -EOVERFLOW; 151 + rdr->jump_address = restore_jump_address; 152 + rdr->cr3 = restore_cr3; 153 + rdr->magic = RESTORE_MAGIC; 154 + return 0; 155 + } 156 + 157 + /** 158 + * arch_hibernation_header_restore - read the architecture specific data 159 + * from the hibernation image header 160 + * @addr: address to read the data from 161 + */ 162 + int arch_hibernation_header_restore(void *addr) 163 + { 164 + struct restore_data_record *rdr = addr; 165 + 166 + restore_jump_address = rdr->jump_address; 167 + restore_cr3 = rdr->cr3; 168 + return (rdr->magic == RESTORE_MAGIC) ? 0 : -EINVAL; 169 + }
-155
arch/x86/power/suspend_64.c arch/x86/power/cpu_64.c
··· 15 15 #include <asm/pgtable.h> 16 16 #include <asm/mtrr.h> 17 17 18 - /* References to section boundaries */ 19 - extern const void __nosave_begin, __nosave_end; 20 - 21 18 static void fix_processor_context(void); 22 19 23 20 struct saved_context saved_context; ··· 164 167 loaddebug(&current->thread, 7); 165 168 } 166 169 } 167 - 168 - #ifdef CONFIG_HIBERNATION 169 - /* Defined in arch/x86_64/kernel/suspend_asm.S */ 170 - extern int restore_image(void); 171 - 172 - /* 173 - * Address to jump to in the last phase of restore in order to get to the image 174 - * kernel's text (this value is passed in the image header). 175 - */ 176 - unsigned long restore_jump_address; 177 - 178 - /* 179 - * Value of the cr3 register from before the hibernation (this value is passed 180 - * in the image header). 181 - */ 182 - unsigned long restore_cr3; 183 - 184 - pgd_t *temp_level4_pgt; 185 - 186 - void *relocated_restore_code; 187 - 188 - static int res_phys_pud_init(pud_t *pud, unsigned long address, unsigned long end) 189 - { 190 - long i, j; 191 - 192 - i = pud_index(address); 193 - pud = pud + i; 194 - for (; i < PTRS_PER_PUD; pud++, i++) { 195 - unsigned long paddr; 196 - pmd_t *pmd; 197 - 198 - paddr = address + i*PUD_SIZE; 199 - if (paddr >= end) 200 - break; 201 - 202 - pmd = (pmd_t *)get_safe_page(GFP_ATOMIC); 203 - if (!pmd) 204 - return -ENOMEM; 205 - set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE)); 206 - for (j = 0; j < PTRS_PER_PMD; pmd++, j++, paddr += PMD_SIZE) { 207 - unsigned long pe; 208 - 209 - if (paddr >= end) 210 - break; 211 - pe = __PAGE_KERNEL_LARGE_EXEC | paddr; 212 - pe &= __supported_pte_mask; 213 - set_pmd(pmd, __pmd(pe)); 214 - } 215 - } 216 - return 0; 217 - } 218 - 219 - static int set_up_temporary_mappings(void) 220 - { 221 - unsigned long start, end, next; 222 - int error; 223 - 224 - temp_level4_pgt = (pgd_t *)get_safe_page(GFP_ATOMIC); 225 - if (!temp_level4_pgt) 226 - return -ENOMEM; 227 - 228 - /* It is safe to reuse the original kernel mapping */ 229 - set_pgd(temp_level4_pgt + pgd_index(__START_KERNEL_map), 230 - init_level4_pgt[pgd_index(__START_KERNEL_map)]); 231 - 232 - /* Set up the direct mapping from scratch */ 233 - start = (unsigned long)pfn_to_kaddr(0); 234 - end = (unsigned long)pfn_to_kaddr(end_pfn); 235 - 236 - for (; start < end; start = next) { 237 - pud_t *pud = (pud_t *)get_safe_page(GFP_ATOMIC); 238 - if (!pud) 239 - return -ENOMEM; 240 - next = start + PGDIR_SIZE; 241 - if (next > end) 242 - next = end; 243 - if ((error = res_phys_pud_init(pud, __pa(start), __pa(next)))) 244 - return error; 245 - set_pgd(temp_level4_pgt + pgd_index(start), 246 - mk_kernel_pgd(__pa(pud))); 247 - } 248 - return 0; 249 - } 250 - 251 - int swsusp_arch_resume(void) 252 - { 253 - int error; 254 - 255 - /* We have got enough memory and from now on we cannot recover */ 256 - if ((error = set_up_temporary_mappings())) 257 - return error; 258 - 259 - relocated_restore_code = (void *)get_safe_page(GFP_ATOMIC); 260 - if (!relocated_restore_code) 261 - return -ENOMEM; 262 - memcpy(relocated_restore_code, &core_restore_code, 263 - &restore_registers - &core_restore_code); 264 - 265 - restore_image(); 266 - return 0; 267 - } 268 - 269 - /* 270 - * pfn_is_nosave - check if given pfn is in the 'nosave' section 271 - */ 272 - 273 - int pfn_is_nosave(unsigned long pfn) 274 - { 275 - unsigned long nosave_begin_pfn = __pa_symbol(&__nosave_begin) >> PAGE_SHIFT; 276 - unsigned long nosave_end_pfn = PAGE_ALIGN(__pa_symbol(&__nosave_end)) >> PAGE_SHIFT; 277 - return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn); 278 - } 279 - 280 - struct restore_data_record { 281 - unsigned long jump_address; 282 - unsigned long cr3; 283 - unsigned long magic; 284 - }; 285 - 286 - #define RESTORE_MAGIC 0x0123456789ABCDEFUL 287 - 288 - /** 289 - * arch_hibernation_header_save - populate the architecture specific part 290 - * of a hibernation image header 291 - * @addr: address to save the data at 292 - */ 293 - int arch_hibernation_header_save(void *addr, unsigned int max_size) 294 - { 295 - struct restore_data_record *rdr = addr; 296 - 297 - if (max_size < sizeof(struct restore_data_record)) 298 - return -EOVERFLOW; 299 - rdr->jump_address = restore_jump_address; 300 - rdr->cr3 = restore_cr3; 301 - rdr->magic = RESTORE_MAGIC; 302 - return 0; 303 - } 304 - 305 - /** 306 - * arch_hibernation_header_restore - read the architecture specific data 307 - * from the hibernation image header 308 - * @addr: address to read the data from 309 - */ 310 - int arch_hibernation_header_restore(void *addr) 311 - { 312 - struct restore_data_record *rdr = addr; 313 - 314 - restore_jump_address = rdr->jump_address; 315 - restore_cr3 = rdr->cr3; 316 - return (rdr->magic == RESTORE_MAGIC) ? 0 : -EINVAL; 317 - } 318 - #endif /* CONFIG_HIBERNATION */