aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/power/cpu_32.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/power/cpu_32.c')
-rw-r--r--arch/x86/power/cpu_32.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/arch/x86/power/cpu_32.c b/arch/x86/power/cpu_32.c
index de1a86b2cffa..294e78baff75 100644
--- a/arch/x86/power/cpu_32.c
+++ b/arch/x86/power/cpu_32.c
@@ -32,25 +32,65 @@ static void fix_processor_context(void);
32struct saved_context saved_context; 32struct saved_context saved_context;
33#endif 33#endif
34 34
35/**
36 * __save_processor_state - save CPU registers before creating a
37 * hibernation image and before restoring the memory state from it
38 * @ctxt - structure to store the registers contents in
39 *
40 * NOTE: If there is a CPU register the modification of which by the
41 * boot kernel (ie. the kernel used for loading the hibernation image)
42 * might affect the operations of the restored target kernel (ie. the one
43 * saved in the hibernation image), then its contents must be saved by this
44 * function. In other words, if kernel A is hibernated and different
45 * kernel B is used for loading the hibernation image into memory, the
46 * kernel A's __save_processor_state() function must save all registers
47 * needed by kernel A, so that it can operate correctly after the resume
48 * regardless of what kernel B does in the meantime.
49 */
35static void __save_processor_state(struct saved_context *ctxt) 50static void __save_processor_state(struct saved_context *ctxt)
36{ 51{
52#ifdef CONFIG_X86_32
37 mtrr_save_fixed_ranges(NULL); 53 mtrr_save_fixed_ranges(NULL);
54#endif
38 kernel_fpu_begin(); 55 kernel_fpu_begin();
39 56
40 /* 57 /*
41 * descriptor tables 58 * descriptor tables
42 */ 59 */
60#ifdef CONFIG_X86_32
43 store_gdt(&ctxt->gdt); 61 store_gdt(&ctxt->gdt);
44 store_idt(&ctxt->idt); 62 store_idt(&ctxt->idt);
63#else
64/* CONFIG_X86_64 */
65 store_gdt((struct desc_ptr *)&ctxt->gdt_limit);
66 store_idt((struct desc_ptr *)&ctxt->idt_limit);
67#endif
45 store_tr(ctxt->tr); 68 store_tr(ctxt->tr);
46 69
70 /* XMM0..XMM15 should be handled by kernel_fpu_begin(). */
47 /* 71 /*
48 * segment registers 72 * segment registers
49 */ 73 */
74#ifdef CONFIG_X86_32
50 savesegment(es, ctxt->es); 75 savesegment(es, ctxt->es);
51 savesegment(fs, ctxt->fs); 76 savesegment(fs, ctxt->fs);
52 savesegment(gs, ctxt->gs); 77 savesegment(gs, ctxt->gs);
53 savesegment(ss, ctxt->ss); 78 savesegment(ss, ctxt->ss);
79#else
80/* CONFIG_X86_64 */
81 asm volatile ("movw %%ds, %0" : "=m" (ctxt->ds));
82 asm volatile ("movw %%es, %0" : "=m" (ctxt->es));
83 asm volatile ("movw %%fs, %0" : "=m" (ctxt->fs));
84 asm volatile ("movw %%gs, %0" : "=m" (ctxt->gs));
85 asm volatile ("movw %%ss, %0" : "=m" (ctxt->ss));
86
87 rdmsrl(MSR_FS_BASE, ctxt->fs_base);
88 rdmsrl(MSR_GS_BASE, ctxt->gs_base);
89 rdmsrl(MSR_KERNEL_GS_BASE, ctxt->gs_kernel_base);
90 mtrr_save_fixed_ranges(NULL);
91
92 rdmsrl(MSR_EFER, ctxt->efer);
93#endif
54 94
55 /* 95 /*
56 * control registers 96 * control registers
@@ -58,7 +98,13 @@ static void __save_processor_state(struct saved_context *ctxt)
58 ctxt->cr0 = read_cr0(); 98 ctxt->cr0 = read_cr0();
59 ctxt->cr2 = read_cr2(); 99 ctxt->cr2 = read_cr2();
60 ctxt->cr3 = read_cr3(); 100 ctxt->cr3 = read_cr3();
101#ifdef CONFIG_X86_32
61 ctxt->cr4 = read_cr4_safe(); 102 ctxt->cr4 = read_cr4_safe();
103#else
104/* CONFIG_X86_64 */
105 ctxt->cr4 = read_cr4();
106 ctxt->cr8 = read_cr8();
107#endif
62} 108}
63 109
64/* Needed by apm.c */ 110/* Needed by apm.c */
@@ -66,7 +112,9 @@ void save_processor_state(void)
66{ 112{
67 __save_processor_state(&saved_context); 113 __save_processor_state(&saved_context);
68} 114}
115#ifdef CONFIG_X86_32
69EXPORT_SYMBOL(save_processor_state); 116EXPORT_SYMBOL(save_processor_state);
117#endif
70 118
71static void do_fpu_end(void) 119static void do_fpu_end(void)
72{ 120{