root/arch/i386/kernel/process.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. disable_hlt
  2. enable_hlt
  3. sys_pipe
  4. sys_idle
  5. kb_wait
  6. hard_reset_now
  7. show_regs
  8. exit_thread
  9. flush_thread
  10. copy_thread
  11. dump_thread
  12. sys_fork
  13. sys_clone
  14. sys_execve

   1 /*
   2  *  linux/arch/i386/kernel/process.c
   3  *
   4  *  Copyright (C) 1995  Linus Torvalds
   5  */
   6 
   7 /*
   8  * This file handles the architecture-dependent parts of process handling..
   9  */
  10 
  11 #include <linux/errno.h>
  12 #include <linux/sched.h>
  13 #include <linux/kernel.h>
  14 #include <linux/mm.h>
  15 #include <linux/stddef.h>
  16 #include <linux/unistd.h>
  17 #include <linux/ptrace.h>
  18 #include <linux/malloc.h>
  19 #include <linux/ldt.h>
  20 #include <linux/user.h>
  21 #include <linux/a.out.h>
  22 
  23 #include <asm/segment.h>
  24 #include <asm/pgtable.h>
  25 #include <asm/system.h>
  26 #include <asm/io.h>
  27 
  28 asmlinkage void ret_from_sys_call(void) __asm__("ret_from_sys_call");
  29 
  30 static int hlt_counter=0;
  31 
  32 void disable_hlt(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  33 {
  34         hlt_counter++;
  35 }
  36 
  37 void enable_hlt(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  38 {
  39         hlt_counter--;
  40 }
  41 
  42 asmlinkage int sys_pipe(unsigned long * fildes)
     /* [previous][next][first][last][top][bottom][index][help] */
  43 {
  44         int fd[2];
  45         int error;
  46 
  47         error = verify_area(VERIFY_WRITE,fildes,8);
  48         if (error)
  49                 return error;
  50         error = do_pipe(fd);
  51         if (error)
  52                 return error;
  53         put_fs_long(fd[0],0+fildes);
  54         put_fs_long(fd[1],1+fildes);
  55         return 0;
  56 }
  57 
  58 /*
  59  * The idle loop on a i386..
  60  */
  61 asmlinkage int sys_idle(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  62 {
  63         int i;
  64         pmd_t * pmd;
  65 
  66         if (current->pid != 0)
  67                 return -EPERM;
  68 
  69         /* Map out the low memory: it's no longer needed */
  70         pmd = pmd_offset(swapper_pg_dir, 0);
  71         for (i = 0 ; i < 768 ; i++)
  72                 pmd_clear(pmd++);
  73 
  74         /* endless idle loop with no priority at all */
  75         current->counter = -100;
  76         for (;;) {
  77                 if (hlt_works_ok && !hlt_counter && !need_resched)
  78                         __asm__("hlt");
  79                 schedule();
  80         }
  81 }
  82 
  83 /*
  84  * This routine reboots the machine by asking the keyboard
  85  * controller to pulse the reset-line low. We try that for a while,
  86  * and if it doesn't work, we do some other stupid things.
  87  */
  88 static long no_idt[2] = {0, 0};
  89 
  90 static inline void kb_wait(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  91 {
  92         int i;
  93 
  94         for (i=0; i<0x10000; i++)
  95                 if ((inb_p(0x64) & 0x02) == 0)
  96                         break;
  97 }
  98 
  99 void hard_reset_now(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 100 {
 101         int i, j;
 102 
 103         sti();
 104 /* rebooting needs to touch the page at absolute addr 0 */
 105         pg0[0] = 7;
 106         *((unsigned short *)0x472) = 0x1234;
 107         for (;;) {
 108                 for (i=0; i<100; i++) {
 109                         kb_wait();
 110                         for(j = 0; j < 100000 ; j++)
 111                                 /* nothing */;
 112                         outb(0xfe,0x64);         /* pulse reset low */
 113                 }
 114                 __asm__ __volatile__("\tlidt %0": "=m" (no_idt));
 115         }
 116 }
 117 
 118 void show_regs(struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 119 {
 120         printk("\n");
 121         printk("EIP: %04x:%08lx",0xffff & regs->cs,regs->eip);
 122         if (regs->cs & 3)
 123                 printk(" ESP: %04x:%08lx",0xffff & regs->ss,regs->esp);
 124         printk(" EFLAGS: %08lx\n",regs->eflags);
 125         printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
 126                 regs->eax,regs->ebx,regs->ecx,regs->edx);
 127         printk("ESI: %08lx EDI: %08lx EBP: %08lx",
 128                 regs->esi, regs->edi, regs->ebp);
 129         printk(" DS: %04x ES: %04x FS: %04x GS: %04x\n",
 130                 0xffff & regs->ds,0xffff & regs->es,
 131                 0xffff & regs->fs,0xffff & regs->gs);
 132 }
 133 
 134 /*
 135  * Free current thread data structures etc..
 136  */
 137 void exit_thread(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 138 {
 139         /* forget local segments */
 140         __asm__ __volatile__("mov %w0,%%fs ; mov %w0,%%gs ; lldt %w0"
 141                 : /* no outputs */
 142                 : "r" (0));
 143         current->tss.ldt = 0;
 144         if (current->ldt) {
 145                 void * ldt = current->ldt;
 146                 current->ldt = NULL;
 147                 vfree(ldt);
 148         }
 149 }
 150 
 151 void flush_thread(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 152 {
 153         int i;
 154 
 155         if (current->ldt) {
 156                 free_page((unsigned long) current->ldt);
 157                 current->ldt = NULL;
 158                 for (i=1 ; i<NR_TASKS ; i++) {
 159                         if (task[i] == current)  {
 160                                 set_ldt_desc(gdt+(i<<1)+
 161                                              FIRST_LDT_ENTRY,&default_ldt, 1);
 162                                 load_ldt(i);
 163                         }
 164                 }       
 165         }
 166 
 167         for (i=0 ; i<8 ; i++)
 168                 current->debugreg[i] = 0;
 169 }
 170 
 171 void copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
     /* [previous][next][first][last][top][bottom][index][help] */
 172         struct task_struct * p, struct pt_regs * regs)
 173 {
 174         int i;
 175         struct pt_regs * childregs;
 176 
 177         p->tss.es = KERNEL_DS;
 178         p->tss.cs = KERNEL_CS;
 179         p->tss.ss = KERNEL_DS;
 180         p->tss.ds = KERNEL_DS;
 181         p->tss.fs = USER_DS;
 182         p->tss.gs = KERNEL_DS;
 183         p->tss.ss0 = KERNEL_DS;
 184         p->tss.esp0 = p->kernel_stack_page + PAGE_SIZE;
 185         p->tss.tr = _TSS(nr);
 186         childregs = ((struct pt_regs *) (p->kernel_stack_page + PAGE_SIZE)) - 1;
 187         p->tss.esp = (unsigned long) childregs;
 188         p->tss.eip = (unsigned long) ret_from_sys_call;
 189         *childregs = *regs;
 190         childregs->eax = 0;
 191         childregs->esp = esp;
 192         p->tss.back_link = 0;
 193         p->tss.eflags = regs->eflags & 0xffffcfff;      /* iopl is always 0 for a new process */
 194         p->tss.ldt = _LDT(nr);
 195         if (p->ldt) {
 196                 p->ldt = (struct desc_struct*) vmalloc(LDT_ENTRIES*LDT_ENTRY_SIZE);
 197                 if (p->ldt != NULL)
 198                         memcpy(p->ldt, current->ldt, LDT_ENTRIES*LDT_ENTRY_SIZE);
 199         }
 200         set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss));
 201         if (p->ldt)
 202                 set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY,p->ldt, 512);
 203         else
 204                 set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY,&default_ldt, 1);
 205         p->tss.bitmap = offsetof(struct thread_struct,io_bitmap);
 206         for (i = 0; i < IO_BITMAP_SIZE+1 ; i++) /* IO bitmap is actually SIZE+1 */
 207                 p->tss.io_bitmap[i] = ~0;
 208         if (last_task_used_math == current)
 209                 __asm__("clts ; fnsave %0 ; frstor %0":"=m" (p->tss.i387));
 210 }
 211 
 212 /*
 213  * fill in the user structure for a core dump..
 214  */
 215 void dump_thread(struct pt_regs * regs, struct user * dump)
     /* [previous][next][first][last][top][bottom][index][help] */
 216 {
 217         int i;
 218 
 219 /* changed the size calculations - should hopefully work better. lbt */
 220         dump->magic = CMAGIC;
 221         dump->start_code = 0;
 222         dump->start_stack = regs->esp & ~(PAGE_SIZE - 1);
 223         dump->u_tsize = ((unsigned long) current->mm->end_code) >> 12;
 224         dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> 12;
 225         dump->u_dsize -= dump->u_tsize;
 226         dump->u_ssize = 0;
 227         for (i = 0; i < 8; i++)
 228                 dump->u_debugreg[i] = current->debugreg[i];  
 229 
 230         if (dump->start_stack < TASK_SIZE)
 231                 dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> 12;
 232 
 233         dump->regs = *regs;
 234 
 235 /* Flag indicating the math stuff is valid. We don't support this for the
 236    soft-float routines yet */
 237         if (hard_math) {
 238                 if ((dump->u_fpvalid = current->used_math) != 0) {
 239                         if (last_task_used_math == current)
 240                                 __asm__("clts ; fnsave %0": :"m" (dump->i387));
 241                         else
 242                                 memcpy(&dump->i387,&current->tss.i387.hard,sizeof(dump->i387));
 243                 }
 244         } else {
 245                 /* we should dump the emulator state here, but we need to
 246                    convert it into standard 387 format first.. */
 247                 dump->u_fpvalid = 0;
 248         }
 249 }
 250 
 251 asmlinkage int sys_fork(struct pt_regs regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 252 {
 253         return do_fork(COPYVM | SIGCHLD, regs.esp, &regs);
 254 }
 255 
 256 asmlinkage int sys_clone(struct pt_regs regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 257 {
 258 #ifdef CLONE_ACTUALLY_WORKS_OK
 259         unsigned long clone_flags;
 260         unsigned long newsp;
 261 
 262         newsp = regs.ebx;
 263         clone_flags = regs.ecx;
 264         if (!newsp)
 265                 newsp = regs.esp;
 266         if (newsp == regs.esp)
 267                 clone_flags |= COPYVM;
 268         return do_fork(clone_flags, newsp, &regs);
 269 #else
 270         return -ENOSYS;
 271 #endif
 272 }
 273 
 274 /*
 275  * sys_execve() executes a new program.
 276  */
 277 asmlinkage int sys_execve(struct pt_regs regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 278 {
 279         int error;
 280         char * filename;
 281 
 282         error = getname((char *) regs.ebx, &filename);
 283         if (error)
 284                 return error;
 285         error = do_execve(filename, (char **) regs.ecx, (char **) regs.edx, &regs);
 286         putname(filename);
 287         return error;
 288 }

/* [previous][next][first][last][top][bottom][index][help] */