http://lxr.linux.no/#linux+v2.6.31/arch/x86/kernel/process_64.c#L347
371
372
373
374
375
376
377
378
379
380
381__notrace_funcgraph struct task_struct *
382__switch_to(struct task_struct *prev_p, struct task_struct *next_p)
383{
384 struct thread_struct *prev = &prev_p->thread;
385 struct thread_struct *next = &next_p->thread;
386 int cpu = smp_processor_id();
387 struct tss_struct *tss = &per_cpu(init_tss, cpu);
388 unsigned fsindex, gsindex;
389
390
391 if (next_p->fpu_counter > 5)
392 prefetch(next->xstate);
393
394
395
396
397 load_sp0(tss, next);
398
399
400
401
402
403 savesegment(es, prev->es);
404 if (unlikely(next->es | prev->es))
405 loadsegment(es, next->es);
406
407 savesegment(ds, prev->ds);
408 if (unlikely(next->ds | prev->ds))
409 loadsegment(ds, next->ds);
410
411
412
413
414
415
416
417 savesegment(fs, fsindex);
418 savesegment(gs, gsindex);
419
420 load_TLS(next, cpu);
421
422
423
424
425
426
427
428
429 arch_end_context_switch(next_p);
430
431
432
433
434
435
436
437
438 if (unlikely(fsindex | next->fsindex | prev->fs)) {
439 loadsegment(fs, next->fsindex);
440
441
442
443
444
445 if (fsindex)
446 prev->fs = 0;
447 }
448
449 if (next->fs)
450 wrmsrl(MSR_FS_BASE, next->fs);
451 prev->fsindex = fsindex;
452
453 if (unlikely(gsindex | next->gsindex | prev->gs)) {
454 load_gs_index(next->gsindex);
455 if (gsindex)
456 prev->gs = 0;
457 }
458 if (next->gs)
459 wrmsrl(MSR_KERNEL_GS_BASE, next->gs);
460 prev->gsindex = gsindex;
461
462
463 unlazy_fpu(prev_p);
464
465
466
467
468 prev->usersp = percpu_read(old_rsp);
469 percpu_write(old_rsp, next->usersp);
470 percpu_write(current_task, next_p);
471
472 percpu_write(kernel_stack,
473 (unsigned long)task_stack_page(next_p) +
474 THREAD_SIZE - KERNEL_STACK_OFFSET);
475
476
477
478
479 if (unlikely(task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT ||
480 task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV))
481 __switch_to_xtra(prev_p, next_p, tss);
482
483
484
485
486
487
488
489
490 if (tsk_used_math(next_p) && next_p->fpu_counter > 5)
491 math_state_restore();
492 return prev_p;
493}
494
|