Section courante

A propos

Section administrative du site

linux/arch/i386/kernel/process.c

Linux 2.5.53

Description

Ce fichier contient les codes sources linux/arch/i386/kernel/process.c lequel permet la gestion des processus avec une architecture 80386.

Code source

Voici le code source en langage de programmation C du fichier du système d'exploitation Linux :

  1. /*
  2.  *  linux/arch/i386/kernel/process.c
  3.  *
  4.  *  Copyright (C) 1995  Linus Torvalds
  5.  *
  6.  *  Pentium III FXSR, SSE support
  7.  *    Gareth Hughes <gareth@valinux.com>, May 2000
  8.  */
  9. /*
  10.  * This file handles the architecture-dependent parts of process handling..
  11.  */
  12. #define __KERNEL_SYSCALLS__
  13. #include <stdarg.h>
  14. #include <linux/errno.h>
  15. #include <linux/sched.h>
  16. #include <linux/fs.h>
  17. #include <linux/kernel.h>
  18. #include <linux/mm.h>
  19. #include <linux/elfcore.h>
  20. #include <linux/smp.h>
  21. #include <linux/smp_lock.h>
  22. #include <linux/stddef.h>
  23. #include <linux/unistd.h>
  24. #include <linux/slab.h>
  25. #include <linux/vmalloc.h>
  26. #include <linux/user.h>
  27. #include <linux/a.out.h>
  28. #include <linux/interrupt.h>
  29. #include <linux/config.h>
  30. #include <linux/delay.h>
  31. #include <linux/reboot.h>
  32. #include <linux/init.h>
  33. #include <linux/mc146818rtc.h>
  34. #include <linux/module.h>
  35. #include <linux/kallsyms.h>
  36. #include <asm/uaccess.h>
  37. #include <asm/pgtable.h>
  38. #include <asm/system.h>
  39. #include <asm/io.h>
  40. #include <asm/ldt.h>
  41. #include <asm/processor.h>
  42. #include <asm/i387.h>
  43. #include <asm/irq.h>
  44. #include <asm/desc.h>
  45. #ifdef CONFIG_MATH_EMULATION
  46. #include <asm/math_emu.h>
  47. #endif
  48. #include <linux/irq.h>
  49. #include <linux/err.h>
  50. asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
  51. int hlt_counter;
  52. /*
  53.  * Return saved PC of a blocked thread.
  54.  */
  55. unsigned long thread_saved_pc(struct task_struct *tsk)
  56. {
  57.     return ((unsigned long *)tsk->thread.esp)[3];
  58. }
  59. /*
  60.  * Powermanagement idle function, if any..
  61.  */
  62. void (*pm_idle)(void);
  63. void disable_hlt(void)
  64. {
  65.     hlt_counter++;
  66. }
  67. void enable_hlt(void)
  68. {
  69.     hlt_counter--;
  70. }
  71. /*
  72.  * We use this if we don't have any better
  73.  * idle routine..
  74.  */
  75. void default_idle(void)
  76. {
  77.     if (current_cpu_data.hlt_works_ok && !hlt_counter) {
  78.         local_irq_disable();
  79.         if (!need_resched())
  80.             safe_halt();
  81.         else
  82.             local_irq_enable();
  83.     }
  84. }
  85. /*
  86.  * On SMP it's slightly faster (but much more power-consuming!)
  87.  * to poll the ->work.need_resched flag instead of waiting for the
  88.  * cross-CPU IPI to arrive. Use this option with caution.
  89.  */
  90. static void poll_idle (void)
  91. {
  92.     int oldval;
  93.     local_irq_enable();
  94.     /*
  95.      * Deal with another CPU just having chosen a thread to
  96.      * run here:
  97.      */
  98.     oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
  99.     if (!oldval) {
  100.         set_thread_flag(TIF_POLLING_NRFLAG);
  101.         asm volatile(
  102.             "2:"
  103.             "testl %0, %1;"
  104.             "rep; nop;"
  105.             "je 2b;"
  106.             : : "i"(_TIF_NEED_RESCHED), "m" (current_thread_info()->flags));
  107.         clear_thread_flag(TIF_POLLING_NRFLAG);
  108.     } else {
  109.         set_need_resched();
  110.     }
  111. }
  112. /*
  113.  * The idle thread. There's no useful work to be
  114.  * done, so just try to conserve power and have a
  115.  * low exit latency (ie sit in a loop waiting for
  116.  * somebody to say that they'd like to reschedule)
  117.  */
  118. void cpu_idle (void)
  119. {
  120.     /* endless idle loop with no priority at all */
  121.     while (1) {
  122.         void (*idle)(void) = pm_idle;
  123.         if (!idle)
  124.             idle = default_idle;
  125.         irq_stat[smp_processor_id()].idle_timestamp = jiffies;
  126.         while (!need_resched())
  127.             idle();
  128.         schedule();
  129.     }
  130. }
  131. static int __init idle_setup (char *str)
  132. {
  133.     if (!strncmp(str, "poll", 4)) {
  134.         printk("using polling idle threads.\n");
  135.         pm_idle = poll_idle;
  136.     }
  137.     return 1;
  138. }
  139. __setup("idle=", idle_setup);
  140. void show_regs(struct pt_regs * regs)
  141. {
  142.     unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;
  143.     printk("\n");
  144.     printk("Pid: %d, comm: %20s\n", current->pid, current->comm);
  145.     printk("EIP: %04x:[<%08lx>] CPU: %d\n",0xffff & regs->xcs,regs->eip, smp_processor_id());
  146.     print_symbol("EIP is at %s\n", regs->eip);
  147.     if (regs->xcs & 3)
  148.         printk(" ESP: %04x:%08lx",0xffff & regs->xss,regs->esp);
  149.     printk(" EFLAGS: %08lx %s\n",regs->eflags, print_tainted());
  150.     printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
  151.         regs->eax,regs->ebx,regs->ecx,regs->edx);
  152.     printk("ESI: %08lx EDI: %08lx EBP: %08lx",
  153.         regs->esi, regs->edi, regs->ebp);
  154.     printk(" DS: %04x ES: %04x\n",
  155.         0xffff & regs->xds,0xffff & regs->xes);
  156.     __asm__("movl %%cr0, %0": "=r" (cr0));
  157.     __asm__("movl %%cr2, %0": "=r" (cr2));
  158.     __asm__("movl %%cr3, %0": "=r" (cr3));
  159.     /* This could fault if %cr4 does not exist */
  160.     __asm__("1: movl %%cr4, %0 \n"
  161.         "2: \n"
  162.         ".section __ex_table,\"a\" \n"
  163.         ".long 1b,2b \n"
  164.         ".previous \n"
  165.         : "=r" (cr4): "0" (0));
  166.     printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4);
  167.     show_trace(&regs->esp);
  168. }
  169. /*
  170.  * This gets run with %ebx containing the
  171.  * function to call, and %edx containing
  172.  * the "args".
  173.  */
  174. extern void kernel_thread_helper(void);
  175. __asm__(".align 4\n"
  176.     "kernel_thread_helper:\n\t"
  177.     "movl %edx,%eax\n\t"
  178.     "pushl %edx\n\t"
  179.     "call *%ebx\n\t"
  180.     "pushl %eax\n\t"
  181.     "call do_exit");
  182. /*
  183.  * Create a kernel thread
  184.  */
  185. int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
  186. {
  187.     struct task_struct *p;
  188.     struct pt_regs regs;
  189.     memset(&regs, 0, sizeof(regs));
  190.     regs.ebx = (unsigned long) fn;
  191.     regs.edx = (unsigned long) arg;
  192.     regs.xds = __KERNEL_DS;
  193.     regs.xes = __KERNEL_DS;
  194.     regs.orig_eax = -1;
  195.     regs.eip = (unsigned long) kernel_thread_helper;
  196.     regs.xcs = __KERNEL_CS;
  197.     regs.eflags = 0x286;
  198.     /* Ok, create the new process.. */
  199.     p = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
  200.     return IS_ERR(p) ? PTR_ERR(p) : p->pid;
  201. }
  202. /*
  203.  * Free current thread data structures etc..
  204.  */
  205. void exit_thread(void)
  206. {
  207.     struct task_struct *tsk = current;
  208.     /* The process may have allocated an io port bitmap... nuke it. */
  209.     if (unlikely(NULL != tsk->thread.ts_io_bitmap)) {
  210.         kfree(tsk->thread.ts_io_bitmap);
  211.         tsk->thread.ts_io_bitmap = NULL;
  212.     }
  213. }
  214. void flush_thread(void)
  215. {
  216.     struct task_struct *tsk = current;
  217.     memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8);
  218.     memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));    
  219.     /*
  220.      * Forget coprocessor state..
  221.      */
  222.     clear_fpu(tsk);
  223.     tsk->used_math = 0;
  224. }
  225. void release_thread(struct task_struct *dead_task)
  226. {
  227.     if (dead_task->mm) {
  228.         // temporary debugging check
  229.         if (dead_task->mm->context.size) {
  230.             printk("WARNING: dead process %8s still has LDT? <%p/%d>\n",
  231.                     dead_task->comm,
  232.                     dead_task->mm->context.ldt,
  233.                     dead_task->mm->context.size);
  234.             BUG();
  235.         }
  236.     }
  237.     release_x86_irqs(dead_task);
  238. }
  239. /*
  240.  * Save a segment.
  241.  */
  242. #define savesegment(seg,value) \
  243.     asm volatile("movl %%" #seg ",%0":"=m" (*(int *)&(value)))
  244. int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
  245.     unsigned long unused,
  246.     struct task_struct * p, struct pt_regs * regs)
  247. {
  248.     struct pt_regs * childregs;
  249.     struct task_struct *tsk;
  250.     childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1;
  251.     struct_cpy(childregs, regs);
  252.     childregs->eax = 0;
  253.     childregs->esp = esp;
  254.     p->set_child_tid = p->clear_child_tid = NULL;
  255.     p->thread.esp = (unsigned long) childregs;
  256.     p->thread.esp0 = (unsigned long) (childregs+1);
  257.     p->thread.eip = (unsigned long) ret_from_fork;
  258.     savesegment(fs,p->thread.fs);
  259.     savesegment(gs,p->thread.gs);
  260.     tsk = current;
  261.     unlazy_fpu(tsk);
  262.     struct_cpy(&p->thread.i387, &tsk->thread.i387);
  263.     if (unlikely(NULL != tsk->thread.ts_io_bitmap)) {
  264.         p->thread.ts_io_bitmap = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
  265.         if (!p->thread.ts_io_bitmap)
  266.             return -ENOMEM;
  267.         memcpy(p->thread.ts_io_bitmap, tsk->thread.ts_io_bitmap,
  268.             IO_BITMAP_BYTES);
  269.     }
  270.     /*
  271.      * Set a new TLS for the child thread?
  272.      */
  273.     if (clone_flags & CLONE_SETTLS) {
  274.         struct desc_struct *desc;
  275.         struct user_desc info;
  276.         int idx;
  277.         if (copy_from_user(&info, (void *)childregs->esi, sizeof(info)))
  278.             return -EFAULT;
  279.         if (LDT_empty(&info))
  280.             return -EINVAL;
  281.         idx = info.entry_number;
  282.         if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
  283.             return -EINVAL;
  284.         desc = p->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;
  285.         desc->a = LDT_entry_a(&info);
  286.         desc->b = LDT_entry_b(&info);
  287.     }
  288.     return 0;
  289. }
  290. /*
  291.  * fill in the user structure for a core dump..
  292.  */
  293. void dump_thread(struct pt_regs * regs, struct user * dump)
  294. {
  295.     int i;
  296. /* changed the size calculations - should hopefully work better. lbt */
  297.     dump->magic = CMAGIC;
  298.     dump->start_code = 0;
  299.     dump->start_stack = regs->esp & ~(PAGE_SIZE - 1);
  300.     dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
  301.     dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT;
  302.     dump->u_dsize -= dump->u_tsize;
  303.     dump->u_ssize = 0;
  304.     for (i = 0; i < 8; i++)
  305.         dump->u_debugreg[i] = current->thread.debugreg[i];  
  306.     if (dump->start_stack < TASK_SIZE)
  307.         dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
  308.     dump->regs.ebx = regs->ebx;
  309.     dump->regs.ecx = regs->ecx;
  310.     dump->regs.edx = regs->edx;
  311.     dump->regs.esi = regs->esi;
  312.     dump->regs.edi = regs->edi;
  313.     dump->regs.ebp = regs->ebp;
  314.     dump->regs.eax = regs->eax;
  315.     dump->regs.ds = regs->xds;
  316.     dump->regs.es = regs->xes;
  317.     savesegment(fs,dump->regs.fs);
  318.     savesegment(gs,dump->regs.gs);
  319.     dump->regs.orig_eax = regs->orig_eax;
  320.     dump->regs.eip = regs->eip;
  321.     dump->regs.cs = regs->xcs;
  322.     dump->regs.eflags = regs->eflags;
  323.     dump->regs.esp = regs->esp;
  324.     dump->regs.ss = regs->xss;
  325.     dump->u_fpvalid = dump_fpu (regs, &dump->i387);
  326. }
  327. /* 
  328.  * Capture the user space registers if the task is not running (in user space)
  329.  */
  330. int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
  331. {
  332.     struct pt_regs ptregs;
  333.     
  334.     ptregs = *(struct pt_regs *)
  335.         ((unsigned long)tsk->thread_info+THREAD_SIZE - sizeof(ptregs));
  336.     ptregs.xcs &= 0xffff;
  337.     ptregs.xds &= 0xffff;
  338.     ptregs.xes &= 0xffff;
  339.     ptregs.xss &= 0xffff;
  340.     elf_core_copy_regs(regs, &ptregs);
  341.     return 1;
  342. }
  343. /*
  344.  * This special macro can be used to load a debugging register
  345.  */
  346. #define loaddebug(thread,register) \
  347.         __asm__("movl %0,%%db" #register \
  348.             : /* no output */ \
  349.             :"r" (thread->debugreg[register]))
  350. /*
  351.  *    switch_to(x,yn) should switch tasks from x to y.
  352.  *
  353.  * We fsave/fwait so that an exception goes off at the right time
  354.  * (as a call from the fsave or fwait in effect) rather than to
  355.  * the wrong process. Lazy FP saving no longer makes any sense
  356.  * with modern CPU's, and this simplifies a lot of things (SMP
  357.  * and UP become the same).
  358.  *
  359.  * NOTE! We used to use the x86 hardware context switching. The
  360.  * reason for not using it any more becomes apparent when you
  361.  * try to recover gracefully from saved state that is no longer
  362.  * valid (stale segment register values in particular). With the
  363.  * hardware task-switch, there is no way to fix up bad state in
  364.  * a reasonable manner.
  365.  *
  366.  * The fact that Intel documents the hardware task-switching to
  367.  * be slow is a fairly red herring - this code is not noticeably
  368.  * faster. However, there _is_ some room for improvement here,
  369.  * so the performance issues may eventually be a valid point.
  370.  * More important, however, is the fact that this allows us much
  371.  * more flexibility.
  372.  */
  373. void __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
  374. {
  375.     struct thread_struct *prev = &prev_p->thread,
  376.                  *next = &next_p->thread;
  377.     int cpu = smp_processor_id();
  378.     struct tss_struct *tss = init_tss + cpu;
  379.     /* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
  380.     unlazy_fpu(prev_p);
  381.     /*
  382.      * Reload esp0, LDT and the page table pointer:
  383.      */
  384.     load_esp0(tss, next->esp0);
  385.     /*
  386.      * Load the per-thread Thread-Local Storage descriptor.
  387.      */
  388.     load_TLS(next, cpu);
  389.     /*
  390.      * Save away %fs and %gs. No need to save %es and %ds, as
  391.      * those are always kernel segments while inside the kernel.
  392.      */
  393.     asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->fs));
  394.     asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->gs));
  395.     /*
  396.      * Restore %fs and %gs if needed.
  397.      */
  398.     if (unlikely(prev->fs | prev->gs | next->fs | next->gs)) {
  399.         loadsegment(fs, next->fs);
  400.         loadsegment(gs, next->gs);
  401.     }
  402.     /*
  403.      * Now maybe reload the debug registers
  404.      */
  405.     if (unlikely(next->debugreg[7])) {
  406.         loaddebug(next, 0);
  407.         loaddebug(next, 1);
  408.         loaddebug(next, 2);
  409.         loaddebug(next, 3);
  410.         /* no 4 and 5 */
  411.         loaddebug(next, 6);
  412.         loaddebug(next, 7);
  413.     }
  414.     if (unlikely(prev->ts_io_bitmap || next->ts_io_bitmap)) {
  415.         if (next->ts_io_bitmap) {
  416.             /*
  417.              * 4 cachelines copy ... not good, but not that
  418.              * bad either. Anyone got something better?
  419.              * This only affects processes which use ioperm().
  420.              * [Putting the TSSs into 4k-tlb mapped regions
  421.              * and playing VM tricks to switch the IO bitmap
  422.              * is not really acceptable.]
  423.              */
  424.             memcpy(tss->io_bitmap, next->ts_io_bitmap,
  425.                 IO_BITMAP_BYTES);
  426.             tss->bitmap = IO_BITMAP_OFFSET;
  427.         } else
  428.             /*
  429.              * a bitmap offset pointing outside of the TSS limit
  430.              * causes a nicely controllable SIGSEGV if a process
  431.              * tries to use a port IO instruction. The first
  432.              * sys_ioperm() call sets up the bitmap properly.
  433.              */
  434.             tss->bitmap = INVALID_IO_BITMAP_OFFSET;
  435.     }
  436. }
  437. asmlinkage int sys_fork(struct pt_regs regs)
  438. {
  439.     struct task_struct *p;
  440.     p = do_fork(SIGCHLD, regs.esp, &regs, 0, NULL, NULL);
  441.     return IS_ERR(p) ? PTR_ERR(p) : p->pid;
  442. }
  443. asmlinkage int sys_clone(struct pt_regs regs)
  444. {
  445.     struct task_struct *p;
  446.     unsigned long clone_flags;
  447.     unsigned long newsp;
  448.     int *parent_tidptr, *child_tidptr;
  449.     clone_flags = regs.ebx;
  450.     newsp = regs.ecx;
  451.     parent_tidptr = (int *)regs.edx;
  452.     child_tidptr = (int *)regs.edi;
  453.     if (!newsp)
  454.         newsp = regs.esp;
  455.     p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0, parent_tidptr, child_tidptr);
  456.     return IS_ERR(p) ? PTR_ERR(p) : p->pid;
  457. }
  458. /*
  459.  * This is trivial, and on the face of it looks like it
  460.  * could equally well be done in user mode.
  461.  *
  462.  * Not so, for quite unobvious reasons - register pressure.
  463.  * In user mode vfork() cannot have a stack frame, and if
  464.  * done by calling the "clone()" system call directly, you
  465.  * do not have enough call-clobbered registers to hold all
  466.  * the information you need.
  467.  */
  468. asmlinkage int sys_vfork(struct pt_regs regs)
  469. {
  470.     struct task_struct *p;
  471.     p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, &regs, 0, NULL, NULL);
  472.     return IS_ERR(p) ? PTR_ERR(p) : p->pid;
  473. }
  474. /*
  475.  * sys_execve() executes a new program.
  476.  */
  477. asmlinkage int sys_execve(struct pt_regs regs)
  478. {
  479.     int error;
  480.     char * filename;
  481.     filename = getname((char *) regs.ebx);
  482.     error = PTR_ERR(filename);
  483.     if (IS_ERR(filename))
  484.         goto out;
  485.     error = do_execve(filename, (char **) regs.ecx, (char **) regs.edx, &regs);
  486.     if (error == 0)
  487.         current->ptrace &= ~PT_DTRACE;
  488.     putname(filename);
  489. out:
  490.     return error;
  491. }
  492. /*
  493.  * These bracket the sleeping functions..
  494.  */
  495. extern void scheduling_functions_start_here(void);
  496. extern void scheduling_functions_end_here(void);
  497. #define first_sched ((unsigned long) scheduling_functions_start_here)
  498. #define last_sched ((unsigned long) scheduling_functions_end_here)
  499. unsigned long get_wchan(struct task_struct *p)
  500. {
  501.     unsigned long ebp, esp, eip;
  502.     unsigned long stack_page;
  503.     int count = 0;
  504.     if (!p || p == current || p->state == TASK_RUNNING)
  505.         return 0;
  506.     stack_page = (unsigned long)p->thread_info;
  507.     esp = p->thread.esp;
  508.     if (!stack_page || esp < stack_page || esp > 8188+stack_page)
  509.         return 0;
  510.     /* include/asm-i386/system.h:switch_to() pushes ebp last. */
  511.     ebp = *(unsigned long *) esp;
  512.     do {
  513.         if (ebp < stack_page || ebp > 8184+stack_page)
  514.             return 0;
  515.         eip = *(unsigned long *) (ebp+4);
  516.         if (eip < first_sched || eip >= last_sched)
  517.             return eip;
  518.         ebp = *(unsigned long *) ebp;
  519.     } while (count++ < 16);
  520.     return 0;
  521. }
  522. #undef last_sched
  523. #undef first_sched
  524. /*
  525.  * sys_alloc_thread_area: get a yet unused TLS descriptor index.
  526.  */
  527. static int get_free_idx(void)
  528. {
  529.     struct thread_struct *t = &current->thread;
  530.     int idx;
  531.     for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++)
  532.         if (desc_empty(t->tls_array + idx))
  533.             return idx + GDT_ENTRY_TLS_MIN;
  534.     return -ESRCH;
  535. }
  536. /*
  537.  * Set a given TLS descriptor:
  538.  */
  539. asmlinkage int sys_set_thread_area(struct user_desc *u_info)
  540. {
  541.     struct thread_struct *t = &current->thread;
  542.     struct user_desc info;
  543.     struct desc_struct *desc;
  544.     int cpu, idx;
  545.     if (copy_from_user(&info, u_info, sizeof(info)))
  546.         return -EFAULT;
  547.     idx = info.entry_number;
  548.     /*
  549.      * index -1 means the kernel should try to find and
  550.      * allocate an empty descriptor:
  551.      */
  552.     if (idx == -1) {
  553.         idx = get_free_idx();
  554.         if (idx < 0)
  555.             return idx;
  556.         if (put_user(idx, &u_info->entry_number))
  557.             return -EFAULT;
  558.     }
  559.     if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
  560.         return -EINVAL;
  561.     desc = t->tls_array + idx - GDT_ENTRY_TLS_MIN;
  562.     /*
  563.      * We must not get preempted while modifying the TLS.
  564.      */
  565.     cpu = get_cpu();
  566.     if (LDT_empty(&info)) {
  567.         desc->a = 0;
  568.         desc->b = 0;
  569.     } else {
  570.         desc->a = LDT_entry_a(&info);
  571.         desc->b = LDT_entry_b(&info);
  572.     }
  573.     load_TLS(t, cpu);
  574.     put_cpu();
  575.     return 0;
  576. }
  577. /*
  578.  * Get the current Thread-Local Storage area:
  579.  */
  580. #define GET_BASE(desc) ( \
  581.     (((desc)->a >> 16) & 0x0000ffff) | \
  582.     (((desc)->b << 16) & 0x00ff0000) | \
  583.     ( (desc)->b        & 0xff000000)   )
  584. #define GET_LIMIT(desc) ( \
  585.     ((desc)->a & 0x0ffff) | \
  586.      ((desc)->b & 0xf0000) )
  587.     
  588. #define GET_32BIT(desc) (((desc)->b >> 23) & 1)
  589. #define GET_CONTENTS(desc) (((desc)->b >> 10) & 3)
  590. #define GET_WRITABLE(desc) (((desc)->b >> 9) & 1)
  591. #define GET_LIMIT_PAGES(desc) (((desc)->b >> 23) & 1)
  592. #define GET_PRESENT(desc) (((desc)->b >> 15) & 1)
  593. #define GET_USEABLE(desc) (((desc)->b >> 20) & 1)
  594. asmlinkage int sys_get_thread_area(struct user_desc *u_info)
  595. {
  596.     struct user_desc info;
  597.     struct desc_struct *desc;
  598.     int idx;
  599.     if (get_user(idx, &u_info->entry_number))
  600.         return -EFAULT;
  601.     if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
  602.         return -EINVAL;
  603.     desc = current->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;
  604.     info.entry_number = idx;
  605.     info.base_addr = GET_BASE(desc);
  606.     info.limit = GET_LIMIT(desc);
  607.     info.seg_32bit = GET_32BIT(desc);
  608.     info.contents = GET_CONTENTS(desc);
  609.     info.read_exec_only = !GET_WRITABLE(desc);
  610.     info.limit_in_pages = GET_LIMIT_PAGES(desc);
  611.     info.seg_not_present = !GET_PRESENT(desc);
  612.     info.useable = GET_USEABLE(desc);
  613.     if (copy_to_user(u_info, &info, sizeof(info)))
  614.         return -EFAULT;
  615.     return 0;
  616. }


Dernière mise à jour : Samedi, le 2 juin 2018