aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/process.c')
-rw-r--r--arch/i386/kernel/process.c91
1 files changed, 41 insertions, 50 deletions
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 57d375900afb..99308510a17c 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -56,6 +56,7 @@
56 56
57#include <asm/tlbflush.h> 57#include <asm/tlbflush.h>
58#include <asm/cpu.h> 58#include <asm/cpu.h>
59#include <asm/pda.h>
59 60
60asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); 61asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
61 62
@@ -99,22 +100,18 @@ EXPORT_SYMBOL(enable_hlt);
99 */ 100 */
100void default_idle(void) 101void default_idle(void)
101{ 102{
102 local_irq_enable();
103
104 if (!hlt_counter && boot_cpu_data.hlt_works_ok) { 103 if (!hlt_counter && boot_cpu_data.hlt_works_ok) {
105 current_thread_info()->status &= ~TS_POLLING; 104 current_thread_info()->status &= ~TS_POLLING;
106 smp_mb__after_clear_bit(); 105 smp_mb__after_clear_bit();
107 while (!need_resched()) { 106 local_irq_disable();
108 local_irq_disable(); 107 if (!need_resched())
109 if (!need_resched()) 108 safe_halt(); /* enables interrupts racelessly */
110 safe_halt(); 109 else
111 else 110 local_irq_enable();
112 local_irq_enable();
113 }
114 current_thread_info()->status |= TS_POLLING; 111 current_thread_info()->status |= TS_POLLING;
115 } else { 112 } else {
116 while (!need_resched()) 113 /* loop is done by the caller */
117 cpu_relax(); 114 cpu_relax();
118 } 115 }
119} 116}
120#ifdef CONFIG_APM_MODULE 117#ifdef CONFIG_APM_MODULE
@@ -128,14 +125,7 @@ EXPORT_SYMBOL(default_idle);
128 */ 125 */
129static void poll_idle (void) 126static void poll_idle (void)
130{ 127{
131 local_irq_enable(); 128 cpu_relax();
132
133 asm volatile(
134 "2:"
135 "testl %0, %1;"
136 "rep; nop;"
137 "je 2b;"
138 : : "i"(_TIF_NEED_RESCHED), "m" (current_thread_info()->flags));
139} 129}
140 130
141#ifdef CONFIG_HOTPLUG_CPU 131#ifdef CONFIG_HOTPLUG_CPU
@@ -205,7 +195,7 @@ void cpu_idle(void)
205void cpu_idle_wait(void) 195void cpu_idle_wait(void)
206{ 196{
207 unsigned int cpu, this_cpu = get_cpu(); 197 unsigned int cpu, this_cpu = get_cpu();
208 cpumask_t map; 198 cpumask_t map, tmp = current->cpus_allowed;
209 199
210 set_cpus_allowed(current, cpumask_of_cpu(this_cpu)); 200 set_cpus_allowed(current, cpumask_of_cpu(this_cpu));
211 put_cpu(); 201 put_cpu();
@@ -227,6 +217,8 @@ void cpu_idle_wait(void)
227 } 217 }
228 cpus_and(map, map, cpu_online_map); 218 cpus_and(map, map, cpu_online_map);
229 } while (!cpus_empty(map)); 219 } while (!cpus_empty(map));
220
221 set_cpus_allowed(current, tmp);
230} 222}
231EXPORT_SYMBOL_GPL(cpu_idle_wait); 223EXPORT_SYMBOL_GPL(cpu_idle_wait);
232 224
@@ -254,8 +246,7 @@ void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
254static void mwait_idle(void) 246static void mwait_idle(void)
255{ 247{
256 local_irq_enable(); 248 local_irq_enable();
257 while (!need_resched()) 249 mwait_idle_with_hints(0, 0);
258 mwait_idle_with_hints(0, 0);
259} 250}
260 251
261void __devinit select_idle_routine(const struct cpuinfo_x86 *c) 252void __devinit select_idle_routine(const struct cpuinfo_x86 *c)
@@ -312,8 +303,8 @@ void show_regs(struct pt_regs * regs)
312 regs->eax,regs->ebx,regs->ecx,regs->edx); 303 regs->eax,regs->ebx,regs->ecx,regs->edx);
313 printk("ESI: %08lx EDI: %08lx EBP: %08lx", 304 printk("ESI: %08lx EDI: %08lx EBP: %08lx",
314 regs->esi, regs->edi, regs->ebp); 305 regs->esi, regs->edi, regs->ebp);
315 printk(" DS: %04x ES: %04x\n", 306 printk(" DS: %04x ES: %04x GS: %04x\n",
316 0xffff & regs->xds,0xffff & regs->xes); 307 0xffff & regs->xds,0xffff & regs->xes, 0xffff & regs->xgs);
317 308
318 cr0 = read_cr0(); 309 cr0 = read_cr0();
319 cr2 = read_cr2(); 310 cr2 = read_cr2();
@@ -336,7 +327,6 @@ extern void kernel_thread_helper(void);
336int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) 327int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
337{ 328{
338 struct pt_regs regs; 329 struct pt_regs regs;
339 int err;
340 330
341 memset(&regs, 0, sizeof(regs)); 331 memset(&regs, 0, sizeof(regs));
342 332
@@ -345,16 +335,14 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
345 335
346 regs.xds = __USER_DS; 336 regs.xds = __USER_DS;
347 regs.xes = __USER_DS; 337 regs.xes = __USER_DS;
338 regs.xgs = __KERNEL_PDA;
348 regs.orig_eax = -1; 339 regs.orig_eax = -1;
349 regs.eip = (unsigned long) kernel_thread_helper; 340 regs.eip = (unsigned long) kernel_thread_helper;
350 regs.xcs = __KERNEL_CS | get_kernel_rpl(); 341 regs.xcs = __KERNEL_CS | get_kernel_rpl();
351 regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2; 342 regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2;
352 343
353 /* Ok, create the new process.. */ 344 /* Ok, create the new process.. */
354 err = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL); 345 return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
355 if (err == 0) /* terminate kernel stack */
356 task_pt_regs(current)->eip = 0;
357 return err;
358} 346}
359EXPORT_SYMBOL(kernel_thread); 347EXPORT_SYMBOL(kernel_thread);
360 348
@@ -433,7 +421,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
433 p->thread.eip = (unsigned long) ret_from_fork; 421 p->thread.eip = (unsigned long) ret_from_fork;
434 422
435 savesegment(fs,p->thread.fs); 423 savesegment(fs,p->thread.fs);
436 savesegment(gs,p->thread.gs);
437 424
438 tsk = current; 425 tsk = current;
439 if (unlikely(test_tsk_thread_flag(tsk, TIF_IO_BITMAP))) { 426 if (unlikely(test_tsk_thread_flag(tsk, TIF_IO_BITMAP))) {
@@ -510,7 +497,7 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
510 dump->regs.ds = regs->xds; 497 dump->regs.ds = regs->xds;
511 dump->regs.es = regs->xes; 498 dump->regs.es = regs->xes;
512 savesegment(fs,dump->regs.fs); 499 savesegment(fs,dump->regs.fs);
513 savesegment(gs,dump->regs.gs); 500 dump->regs.gs = regs->xgs;
514 dump->regs.orig_eax = regs->orig_eax; 501 dump->regs.orig_eax = regs->orig_eax;
515 dump->regs.eip = regs->eip; 502 dump->regs.eip = regs->eip;
516 dump->regs.cs = regs->xcs; 503 dump->regs.cs = regs->xcs;
@@ -650,22 +637,27 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
650 637
651 __unlazy_fpu(prev_p); 638 __unlazy_fpu(prev_p);
652 639
640
641 /* we're going to use this soon, after a few expensive things */
642 if (next_p->fpu_counter > 5)
643 prefetch(&next->i387.fxsave);
644
653 /* 645 /*
654 * Reload esp0. 646 * Reload esp0.
655 */ 647 */
656 load_esp0(tss, next); 648 load_esp0(tss, next);
657 649
658 /* 650 /*
659 * Save away %fs and %gs. No need to save %es and %ds, as 651 * Save away %fs. No need to save %gs, as it was saved on the
660 * those are always kernel segments while inside the kernel. 652 * stack on entry. No need to save %es and %ds, as those are
661 * Doing this before setting the new TLS descriptors avoids 653 * always kernel segments while inside the kernel. Doing this
662 * the situation where we temporarily have non-reloadable 654 * before setting the new TLS descriptors avoids the situation
663 * segments in %fs and %gs. This could be an issue if the 655 * where we temporarily have non-reloadable segments in %fs
664 * NMI handler ever used %fs or %gs (it does not today), or 656 * and %gs. This could be an issue if the NMI handler ever
665 * if the kernel is running inside of a hypervisor layer. 657 * used %fs or %gs (it does not today), or if the kernel is
658 * running inside of a hypervisor layer.
666 */ 659 */
667 savesegment(fs, prev->fs); 660 savesegment(fs, prev->fs);
668 savesegment(gs, prev->gs);
669 661
670 /* 662 /*
671 * Load the per-thread Thread-Local Storage descriptor. 663 * Load the per-thread Thread-Local Storage descriptor.
@@ -673,22 +665,14 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
673 load_TLS(next, cpu); 665 load_TLS(next, cpu);
674 666
675 /* 667 /*
676 * Restore %fs and %gs if needed. 668 * Restore %fs if needed.
677 * 669 *
678 * Glibc normally makes %fs be zero, and %gs is one of 670 * Glibc normally makes %fs be zero.
679 * the TLS segments.
680 */ 671 */
681 if (unlikely(prev->fs | next->fs)) 672 if (unlikely(prev->fs | next->fs))
682 loadsegment(fs, next->fs); 673 loadsegment(fs, next->fs);
683 674
684 if (prev->gs | next->gs) 675 write_pda(pcurrent, next_p);
685 loadsegment(gs, next->gs);
686
687 /*
688 * Restore IOPL if needed.
689 */
690 if (unlikely(prev->iopl != next->iopl))
691 set_iopl_mask(next->iopl);
692 676
693 /* 677 /*
694 * Now maybe handle debug registers and/or IO bitmaps 678 * Now maybe handle debug registers and/or IO bitmaps
@@ -699,6 +683,13 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
699 683
700 disable_tsc(prev_p, next_p); 684 disable_tsc(prev_p, next_p);
701 685
686 /* If the task has used fpu the last 5 timeslices, just do a full
687 * restore of the math state immediately to avoid the trap; the
688 * chances of needing FPU soon are obviously high now
689 */
690 if (next_p->fpu_counter > 5)
691 math_state_restore();
692
702 return prev_p; 693 return prev_p;
703} 694}
704 695