diff options
author | Sergio Luis <sergio@larces.uece.br> | 2009-04-27 18:27:05 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rjw@sisk.pl> | 2009-06-12 15:32:30 -0400 |
commit | 3134d04b7790f7239b221f16c2d97db4d96ac3c0 (patch) | |
tree | 45cb28131345c0556098c8b77c552cb8a9de64e3 /arch/x86/power/cpu_64.c | |
parent | f9ebbe53e79c5978d0e8ead0843a3717b41ad3d5 (diff) |
x86: unify power/cpu_(32|64) regarding restoring processor state
In this step we do unify cpu_32.c and cpu_64.c functions that
work on restoring the saved processor state. Also, we do
eliminate the forward declaration of fix_processor_context()
for X86_64, as it's not needed anymore.
Signed-off-by: Sergio Luis <sergio@larces.uece.br>
Signed-off-by: Lauro Salmito <laurosalmito@gmail.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'arch/x86/power/cpu_64.c')
-rw-r--r-- | arch/x86/power/cpu_64.c | 118 |
1 files changed, 82 insertions, 36 deletions
diff --git a/arch/x86/power/cpu_64.c b/arch/x86/power/cpu_64.c index 11ea7d0ba5d9..5c8bdc002b8b 100644 --- a/arch/x86/power/cpu_64.c +++ b/arch/x86/power/cpu_64.c | |||
@@ -28,8 +28,6 @@ unsigned long saved_context_esi, saved_context_edi; | |||
28 | unsigned long saved_context_eflags; | 28 | unsigned long saved_context_eflags; |
29 | #else | 29 | #else |
30 | /* CONFIG_X86_64 */ | 30 | /* CONFIG_X86_64 */ |
31 | static void fix_processor_context(void); | ||
32 | |||
33 | struct saved_context saved_context; | 31 | struct saved_context saved_context; |
34 | #endif | 32 | #endif |
35 | 33 | ||
@@ -120,11 +118,57 @@ EXPORT_SYMBOL(save_processor_state); | |||
120 | static void do_fpu_end(void) | 118 | static void do_fpu_end(void) |
121 | { | 119 | { |
122 | /* | 120 | /* |
123 | * Restore FPU regs if necessary | 121 | * Restore FPU regs if necessary. |
124 | */ | 122 | */ |
125 | kernel_fpu_end(); | 123 | kernel_fpu_end(); |
126 | } | 124 | } |
127 | 125 | ||
126 | static void fix_processor_context(void) | ||
127 | { | ||
128 | int cpu = smp_processor_id(); | ||
129 | struct tss_struct *t = &per_cpu(init_tss, cpu); | ||
130 | |||
131 | set_tss_desc(cpu, t); /* | ||
132 | * This just modifies memory; should not be | ||
133 | * necessary. But... This is necessary, because | ||
134 | * 386 hardware has concept of busy TSS or some | ||
135 | * similar stupidity. | ||
136 | */ | ||
137 | |||
138 | #ifdef CONFIG_X86_64 | ||
139 | get_cpu_gdt_table(cpu)[GDT_ENTRY_TSS].type = 9; | ||
140 | |||
141 | syscall_init(); /* This sets MSR_*STAR and related */ | ||
142 | #endif | ||
143 | load_TR_desc(); /* This does ltr */ | ||
144 | load_LDT(¤t->active_mm->context); /* This does lldt */ | ||
145 | |||
146 | /* | ||
147 | * Now maybe reload the debug registers | ||
148 | */ | ||
149 | if (current->thread.debugreg7) { | ||
150 | #ifdef CONFIG_X86_32 | ||
151 | set_debugreg(current->thread.debugreg0, 0); | ||
152 | set_debugreg(current->thread.debugreg1, 1); | ||
153 | set_debugreg(current->thread.debugreg2, 2); | ||
154 | set_debugreg(current->thread.debugreg3, 3); | ||
155 | /* no 4 and 5 */ | ||
156 | set_debugreg(current->thread.debugreg6, 6); | ||
157 | set_debugreg(current->thread.debugreg7, 7); | ||
158 | #else | ||
159 | /* CONFIG_X86_64 */ | ||
160 | loaddebug(¤t->thread, 0); | ||
161 | loaddebug(¤t->thread, 1); | ||
162 | loaddebug(¤t->thread, 2); | ||
163 | loaddebug(¤t->thread, 3); | ||
164 | /* no 4 and 5 */ | ||
165 | loaddebug(¤t->thread, 6); | ||
166 | loaddebug(¤t->thread, 7); | ||
167 | #endif | ||
168 | } | ||
169 | |||
170 | } | ||
171 | |||
128 | /** | 172 | /** |
129 | * __restore_processor_state - restore the contents of CPU registers saved | 173 | * __restore_processor_state - restore the contents of CPU registers saved |
130 | * by __save_processor_state() | 174 | * by __save_processor_state() |
@@ -135,9 +179,16 @@ static void __restore_processor_state(struct saved_context *ctxt) | |||
135 | /* | 179 | /* |
136 | * control registers | 180 | * control registers |
137 | */ | 181 | */ |
182 | /* cr4 was introduced in the Pentium CPU */ | ||
183 | #ifdef CONFIG_X86_32 | ||
184 | if (ctxt->cr4) | ||
185 | write_cr4(ctxt->cr4); | ||
186 | #else | ||
187 | /* CONFIG X86_64 */ | ||
138 | wrmsrl(MSR_EFER, ctxt->efer); | 188 | wrmsrl(MSR_EFER, ctxt->efer); |
139 | write_cr8(ctxt->cr8); | 189 | write_cr8(ctxt->cr8); |
140 | write_cr4(ctxt->cr4); | 190 | write_cr4(ctxt->cr4); |
191 | #endif | ||
141 | write_cr3(ctxt->cr3); | 192 | write_cr3(ctxt->cr3); |
142 | write_cr2(ctxt->cr2); | 193 | write_cr2(ctxt->cr2); |
143 | write_cr0(ctxt->cr0); | 194 | write_cr0(ctxt->cr0); |
@@ -146,13 +197,31 @@ static void __restore_processor_state(struct saved_context *ctxt) | |||
146 | * now restore the descriptor tables to their proper values | 197 | * now restore the descriptor tables to their proper values |
147 | * ltr is done i fix_processor_context(). | 198 | * ltr is done i fix_processor_context(). |
148 | */ | 199 | */ |
200 | #ifdef CONFIG_X86_32 | ||
201 | load_gdt(&ctxt->gdt); | ||
202 | load_idt(&ctxt->idt); | ||
203 | #else | ||
204 | /* CONFIG_X86_64 */ | ||
149 | load_gdt((const struct desc_ptr *)&ctxt->gdt_limit); | 205 | load_gdt((const struct desc_ptr *)&ctxt->gdt_limit); |
150 | load_idt((const struct desc_ptr *)&ctxt->idt_limit); | 206 | load_idt((const struct desc_ptr *)&ctxt->idt_limit); |
151 | 207 | #endif | |
152 | 208 | ||
153 | /* | 209 | /* |
154 | * segment registers | 210 | * segment registers |
155 | */ | 211 | */ |
212 | #ifdef CONFIG_X86_32 | ||
213 | loadsegment(es, ctxt->es); | ||
214 | loadsegment(fs, ctxt->fs); | ||
215 | loadsegment(gs, ctxt->gs); | ||
216 | loadsegment(ss, ctxt->ss); | ||
217 | |||
218 | /* | ||
219 | * sysenter MSRs | ||
220 | */ | ||
221 | if (boot_cpu_has(X86_FEATURE_SEP)) | ||
222 | enable_sep_cpu(); | ||
223 | #else | ||
224 | /* CONFIG_X86_64 */ | ||
156 | asm volatile ("movw %0, %%ds" :: "r" (ctxt->ds)); | 225 | asm volatile ("movw %0, %%ds" :: "r" (ctxt->ds)); |
157 | asm volatile ("movw %0, %%es" :: "r" (ctxt->es)); | 226 | asm volatile ("movw %0, %%es" :: "r" (ctxt->es)); |
158 | asm volatile ("movw %0, %%fs" :: "r" (ctxt->fs)); | 227 | asm volatile ("movw %0, %%fs" :: "r" (ctxt->fs)); |
@@ -162,6 +231,7 @@ static void __restore_processor_state(struct saved_context *ctxt) | |||
162 | wrmsrl(MSR_FS_BASE, ctxt->fs_base); | 231 | wrmsrl(MSR_FS_BASE, ctxt->fs_base); |
163 | wrmsrl(MSR_GS_BASE, ctxt->gs_base); | 232 | wrmsrl(MSR_GS_BASE, ctxt->gs_base); |
164 | wrmsrl(MSR_KERNEL_GS_BASE, ctxt->gs_kernel_base); | 233 | wrmsrl(MSR_KERNEL_GS_BASE, ctxt->gs_kernel_base); |
234 | #endif | ||
165 | 235 | ||
166 | /* | 236 | /* |
167 | * restore XCR0 for xsave capable cpu's. | 237 | * restore XCR0 for xsave capable cpu's. |
@@ -173,41 +243,17 @@ static void __restore_processor_state(struct saved_context *ctxt) | |||
173 | 243 | ||
174 | do_fpu_end(); | 244 | do_fpu_end(); |
175 | mtrr_ap_init(); | 245 | mtrr_ap_init(); |
246 | |||
247 | #ifdef CONFIG_X86_32 | ||
248 | mcheck_init(&boot_cpu_data); | ||
249 | #endif | ||
176 | } | 250 | } |
177 | 251 | ||
252 | /* Needed by apm.c */ | ||
178 | void restore_processor_state(void) | 253 | void restore_processor_state(void) |
179 | { | 254 | { |
180 | __restore_processor_state(&saved_context); | 255 | __restore_processor_state(&saved_context); |
181 | } | 256 | } |
182 | 257 | #ifdef CONFIG_X86_32 | |
183 | static void fix_processor_context(void) | 258 | EXPORT_SYMBOL(restore_processor_state); |
184 | { | 259 | #endif |
185 | int cpu = smp_processor_id(); | ||
186 | struct tss_struct *t = &per_cpu(init_tss, cpu); | ||
187 | |||
188 | /* | ||
189 | * This just modifies memory; should not be necessary. But... This | ||
190 | * is necessary, because 386 hardware has concept of busy TSS or some | ||
191 | * similar stupidity. | ||
192 | */ | ||
193 | set_tss_desc(cpu, t); | ||
194 | |||
195 | get_cpu_gdt_table(cpu)[GDT_ENTRY_TSS].type = 9; | ||
196 | |||
197 | syscall_init(); /* This sets MSR_*STAR and related */ | ||
198 | load_TR_desc(); /* This does ltr */ | ||
199 | load_LDT(¤t->active_mm->context); /* This does lldt */ | ||
200 | |||
201 | /* | ||
202 | * Now maybe reload the debug registers | ||
203 | */ | ||
204 | if (current->thread.debugreg7){ | ||
205 | loaddebug(¤t->thread, 0); | ||
206 | loaddebug(¤t->thread, 1); | ||
207 | loaddebug(¤t->thread, 2); | ||
208 | loaddebug(¤t->thread, 3); | ||
209 | /* no 4 and 5 */ | ||
210 | loaddebug(¤t->thread, 6); | ||
211 | loaddebug(¤t->thread, 7); | ||
212 | } | ||
213 | } | ||