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

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