diff options
Diffstat (limited to 'arch/x86/power')
-rw-r--r-- | arch/x86/power/cpu_32.c | 55 | ||||
-rw-r--r-- | arch/x86/power/cpu_64.c | 118 |
2 files changed, 135 insertions, 38 deletions
diff --git a/arch/x86/power/cpu_32.c b/arch/x86/power/cpu_32.c index 294e78baff75..29b9c0a1ca62 100644 --- a/arch/x86/power/cpu_32.c +++ b/arch/x86/power/cpu_32.c | |||
@@ -27,8 +27,6 @@ unsigned long saved_context_esi, saved_context_edi; | |||
27 | unsigned long saved_context_eflags; | 27 | unsigned long saved_context_eflags; |
28 | #else | 28 | #else |
29 | /* CONFIG_X86_64 */ | 29 | /* CONFIG_X86_64 */ |
30 | static void fix_processor_context(void); | ||
31 | |||
32 | struct saved_context saved_context; | 30 | struct saved_context saved_context; |
33 | #endif | 31 | #endif |
34 | 32 | ||
@@ -136,6 +134,11 @@ static void fix_processor_context(void) | |||
136 | * similar stupidity. | 134 | * similar stupidity. |
137 | */ | 135 | */ |
138 | 136 | ||
137 | #ifdef CONFIG_X86_64 | ||
138 | get_cpu_gdt_table(cpu)[GDT_ENTRY_TSS].type = 9; | ||
139 | |||
140 | syscall_init(); /* This sets MSR_*STAR and related */ | ||
141 | #endif | ||
139 | load_TR_desc(); /* This does ltr */ | 142 | load_TR_desc(); /* This does ltr */ |
140 | load_LDT(¤t->active_mm->context); /* This does lldt */ | 143 | load_LDT(¤t->active_mm->context); /* This does lldt */ |
141 | 144 | ||
@@ -143,6 +146,7 @@ static void fix_processor_context(void) | |||
143 | * Now maybe reload the debug registers | 146 | * Now maybe reload the debug registers |
144 | */ | 147 | */ |
145 | if (current->thread.debugreg7) { | 148 | if (current->thread.debugreg7) { |
149 | #ifdef CONFIG_X86_32 | ||
146 | set_debugreg(current->thread.debugreg0, 0); | 150 | set_debugreg(current->thread.debugreg0, 0); |
147 | set_debugreg(current->thread.debugreg1, 1); | 151 | set_debugreg(current->thread.debugreg1, 1); |
148 | set_debugreg(current->thread.debugreg2, 2); | 152 | set_debugreg(current->thread.debugreg2, 2); |
@@ -150,18 +154,40 @@ static void fix_processor_context(void) | |||
150 | /* no 4 and 5 */ | 154 | /* no 4 and 5 */ |
151 | set_debugreg(current->thread.debugreg6, 6); | 155 | set_debugreg(current->thread.debugreg6, 6); |
152 | set_debugreg(current->thread.debugreg7, 7); | 156 | set_debugreg(current->thread.debugreg7, 7); |
157 | #else | ||
158 | /* CONFIG_X86_64 */ | ||
159 | loaddebug(¤t->thread, 0); | ||
160 | loaddebug(¤t->thread, 1); | ||
161 | loaddebug(¤t->thread, 2); | ||
162 | loaddebug(¤t->thread, 3); | ||
163 | /* no 4 and 5 */ | ||
164 | loaddebug(¤t->thread, 6); | ||
165 | loaddebug(¤t->thread, 7); | ||
166 | #endif | ||
153 | } | 167 | } |
154 | 168 | ||
155 | } | 169 | } |
156 | 170 | ||
171 | /** | ||
172 | * __restore_processor_state - restore the contents of CPU registers saved | ||
173 | * by __save_processor_state() | ||
174 | * @ctxt - structure to load the registers contents from | ||
175 | */ | ||
157 | static void __restore_processor_state(struct saved_context *ctxt) | 176 | static void __restore_processor_state(struct saved_context *ctxt) |
158 | { | 177 | { |
159 | /* | 178 | /* |
160 | * control registers | 179 | * control registers |
161 | */ | 180 | */ |
162 | /* cr4 was introduced in the Pentium CPU */ | 181 | /* cr4 was introduced in the Pentium CPU */ |
182 | #ifdef CONFIG_X86_32 | ||
163 | if (ctxt->cr4) | 183 | if (ctxt->cr4) |
164 | write_cr4(ctxt->cr4); | 184 | write_cr4(ctxt->cr4); |
185 | #else | ||
186 | /* CONFIG X86_64 */ | ||
187 | wrmsrl(MSR_EFER, ctxt->efer); | ||
188 | write_cr8(ctxt->cr8); | ||
189 | write_cr4(ctxt->cr4); | ||
190 | #endif | ||
165 | write_cr3(ctxt->cr3); | 191 | write_cr3(ctxt->cr3); |
166 | write_cr2(ctxt->cr2); | 192 | write_cr2(ctxt->cr2); |
167 | write_cr0(ctxt->cr0); | 193 | write_cr0(ctxt->cr0); |
@@ -170,12 +196,19 @@ static void __restore_processor_state(struct saved_context *ctxt) | |||
170 | * now restore the descriptor tables to their proper values | 196 | * now restore the descriptor tables to their proper values |
171 | * ltr is done i fix_processor_context(). | 197 | * ltr is done i fix_processor_context(). |
172 | */ | 198 | */ |
199 | #ifdef CONFIG_X86_32 | ||
173 | load_gdt(&ctxt->gdt); | 200 | load_gdt(&ctxt->gdt); |
174 | load_idt(&ctxt->idt); | 201 | load_idt(&ctxt->idt); |
202 | #else | ||
203 | /* CONFIG_X86_64 */ | ||
204 | load_gdt((const struct desc_ptr *)&ctxt->gdt_limit); | ||
205 | load_idt((const struct desc_ptr *)&ctxt->idt_limit); | ||
206 | #endif | ||
175 | 207 | ||
176 | /* | 208 | /* |
177 | * segment registers | 209 | * segment registers |
178 | */ | 210 | */ |
211 | #ifdef CONFIG_X86_32 | ||
179 | loadsegment(es, ctxt->es); | 212 | loadsegment(es, ctxt->es); |
180 | loadsegment(fs, ctxt->fs); | 213 | loadsegment(fs, ctxt->fs); |
181 | loadsegment(gs, ctxt->gs); | 214 | loadsegment(gs, ctxt->gs); |
@@ -186,6 +219,18 @@ static void __restore_processor_state(struct saved_context *ctxt) | |||
186 | */ | 219 | */ |
187 | if (boot_cpu_has(X86_FEATURE_SEP)) | 220 | if (boot_cpu_has(X86_FEATURE_SEP)) |
188 | enable_sep_cpu(); | 221 | enable_sep_cpu(); |
222 | #else | ||
223 | /* CONFIG_X86_64 */ | ||
224 | asm volatile ("movw %0, %%ds" :: "r" (ctxt->ds)); | ||
225 | asm volatile ("movw %0, %%es" :: "r" (ctxt->es)); | ||
226 | asm volatile ("movw %0, %%fs" :: "r" (ctxt->fs)); | ||
227 | load_gs_index(ctxt->gs); | ||
228 | asm volatile ("movw %0, %%ss" :: "r" (ctxt->ss)); | ||
229 | |||
230 | wrmsrl(MSR_FS_BASE, ctxt->fs_base); | ||
231 | wrmsrl(MSR_GS_BASE, ctxt->gs_base); | ||
232 | wrmsrl(MSR_KERNEL_GS_BASE, ctxt->gs_kernel_base); | ||
233 | #endif | ||
189 | 234 | ||
190 | /* | 235 | /* |
191 | * restore XCR0 for xsave capable cpu's. | 236 | * restore XCR0 for xsave capable cpu's. |
@@ -194,9 +239,13 @@ static void __restore_processor_state(struct saved_context *ctxt) | |||
194 | xsetbv(XCR_XFEATURE_ENABLED_MASK, pcntxt_mask); | 239 | xsetbv(XCR_XFEATURE_ENABLED_MASK, pcntxt_mask); |
195 | 240 | ||
196 | fix_processor_context(); | 241 | fix_processor_context(); |
242 | |||
197 | do_fpu_end(); | 243 | do_fpu_end(); |
198 | mtrr_ap_init(); | 244 | mtrr_ap_init(); |
245 | |||
246 | #ifdef CONFIG_X86_32 | ||
199 | mcheck_init(&boot_cpu_data); | 247 | mcheck_init(&boot_cpu_data); |
248 | #endif | ||
200 | } | 249 | } |
201 | 250 | ||
202 | /* Needed by apm.c */ | 251 | /* Needed by apm.c */ |
@@ -204,4 +253,6 @@ void restore_processor_state(void) | |||
204 | { | 253 | { |
205 | __restore_processor_state(&saved_context); | 254 | __restore_processor_state(&saved_context); |
206 | } | 255 | } |
256 | #ifdef CONFIG_X86_32 | ||
207 | EXPORT_SYMBOL(restore_processor_state); | 257 | EXPORT_SYMBOL(restore_processor_state); |
258 | #endif | ||
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 | } | ||