diff options
Diffstat (limited to 'arch/i386/kernel/process.c')
-rw-r--r-- | arch/i386/kernel/process.c | 43 |
1 files changed, 25 insertions, 18 deletions
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index e3f362e8af5b..b45cbf93d439 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c | |||
@@ -164,7 +164,7 @@ static inline void play_dead(void) | |||
164 | */ | 164 | */ |
165 | local_irq_disable(); | 165 | local_irq_disable(); |
166 | while (1) | 166 | while (1) |
167 | __asm__ __volatile__("hlt":::"memory"); | 167 | halt(); |
168 | } | 168 | } |
169 | #else | 169 | #else |
170 | static inline void play_dead(void) | 170 | static inline void play_dead(void) |
@@ -313,16 +313,12 @@ void show_regs(struct pt_regs * regs) | |||
313 | printk(" DS: %04x ES: %04x\n", | 313 | printk(" DS: %04x ES: %04x\n", |
314 | 0xffff & regs->xds,0xffff & regs->xes); | 314 | 0xffff & regs->xds,0xffff & regs->xes); |
315 | 315 | ||
316 | __asm__("movl %%cr0, %0": "=r" (cr0)); | 316 | cr0 = read_cr0(); |
317 | __asm__("movl %%cr2, %0": "=r" (cr2)); | 317 | cr2 = read_cr2(); |
318 | __asm__("movl %%cr3, %0": "=r" (cr3)); | 318 | cr3 = read_cr3(); |
319 | /* This could fault if %cr4 does not exist */ | 319 | if (current_cpu_data.x86 > 4) { |
320 | __asm__("1: movl %%cr4, %0 \n" | 320 | cr4 = read_cr4(); |
321 | "2: \n" | 321 | } |
322 | ".section __ex_table,\"a\" \n" | ||
323 | ".long 1b,2b \n" | ||
324 | ".previous \n" | ||
325 | : "=r" (cr4): "0" (0)); | ||
326 | printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4); | 322 | printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4); |
327 | show_trace(NULL, ®s->esp); | 323 | show_trace(NULL, ®s->esp); |
328 | } | 324 | } |
@@ -682,21 +678,26 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas | |||
682 | __unlazy_fpu(prev_p); | 678 | __unlazy_fpu(prev_p); |
683 | 679 | ||
684 | /* | 680 | /* |
685 | * Reload esp0, LDT and the page table pointer: | 681 | * Reload esp0. |
686 | */ | 682 | */ |
687 | load_esp0(tss, next); | 683 | load_esp0(tss, next); |
688 | 684 | ||
689 | /* | 685 | /* |
690 | * Load the per-thread Thread-Local Storage descriptor. | 686 | * Save away %fs and %gs. No need to save %es and %ds, as |
687 | * those are always kernel segments while inside the kernel. | ||
688 | * Doing this before setting the new TLS descriptors avoids | ||
689 | * the situation where we temporarily have non-reloadable | ||
690 | * segments in %fs and %gs. This could be an issue if the | ||
691 | * NMI handler ever used %fs or %gs (it does not today), or | ||
692 | * if the kernel is running inside of a hypervisor layer. | ||
691 | */ | 693 | */ |
692 | load_TLS(next, cpu); | 694 | savesegment(fs, prev->fs); |
695 | savesegment(gs, prev->gs); | ||
693 | 696 | ||
694 | /* | 697 | /* |
695 | * Save away %fs and %gs. No need to save %es and %ds, as | 698 | * Load the per-thread Thread-Local Storage descriptor. |
696 | * those are always kernel segments while inside the kernel. | ||
697 | */ | 699 | */ |
698 | asm volatile("mov %%fs,%0":"=m" (prev->fs)); | 700 | load_TLS(next, cpu); |
699 | asm volatile("mov %%gs,%0":"=m" (prev->gs)); | ||
700 | 701 | ||
701 | /* | 702 | /* |
702 | * Restore %fs and %gs if needed. | 703 | * Restore %fs and %gs if needed. |
@@ -711,6 +712,12 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas | |||
711 | loadsegment(gs, next->gs); | 712 | loadsegment(gs, next->gs); |
712 | 713 | ||
713 | /* | 714 | /* |
715 | * Restore IOPL if needed. | ||
716 | */ | ||
717 | if (unlikely(prev->iopl != next->iopl)) | ||
718 | set_iopl_mask(next->iopl); | ||
719 | |||
720 | /* | ||
714 | * Now maybe reload the debug registers | 721 | * Now maybe reload the debug registers |
715 | */ | 722 | */ |
716 | if (unlikely(next->debugreg[7])) { | 723 | if (unlikely(next->debugreg[7])) { |