📄 process.c
字号:
/* * linux/arch/x86-64/kernel/process.c * * Copyright (C) 1995 Linus Torvalds * * Pentium III FXSR, SSE support * Gareth Hughes <gareth@valinux.com>, May 2000 * * X86-64 port * Andi Kleen. * * $Id: process.c,v 1.60 2003/01/10 15:16:30 ak Exp $ *//* * This file handles the architecture-dependent parts of process handling.. */#define __KERNEL_SYSCALLS__#include <stdarg.h>#include <linux/compiler.h>#include <linux/errno.h>#include <linux/sched.h>#include <linux/kernel.h>#include <linux/mm.h>#include <linux/smp.h>#include <linux/smp_lock.h>#include <linux/stddef.h>#include <linux/unistd.h>#include <linux/ptrace.h>#include <linux/slab.h>#include <linux/vmalloc.h>#include <linux/user.h>#include <linux/a.out.h>#include <linux/interrupt.h>#include <linux/config.h>#include <linux/delay.h>#include <linux/reboot.h>#include <linux/init.h>#include <linux/ctype.h>#include <linux/slab.h>#include <asm/uaccess.h>#include <asm/pgtable.h>#include <asm/system.h>#include <asm/io.h>#include <asm/ldt.h>#include <asm/processor.h>#include <asm/i387.h>#include <asm/desc.h>#include <asm/mmu_context.h>#include <asm/pda.h>#include <asm/prctl.h>#include <asm/kdebug.h>#include <asm/proto.h>#include <linux/irq.h>asmlinkage extern void ret_from_fork(void);int hlt_counter;/* * Powermanagement idle function, if any.. */void (*pm_idle)(void);/* * Power off function, if any */void (*pm_power_off)(void);void disable_hlt(void){ hlt_counter++;}void enable_hlt(void){ hlt_counter--;}/* * We use this if we don't have any better * idle routine.. */static void default_idle(void){ if (!hlt_counter) { __cli(); if (!current->need_resched) safe_halt(); else __sti(); }}/* * On SMP it's slightly faster (but much more power-consuming!) * to poll the ->need_resched flag instead of waiting for the * cross-CPU IPI to arrive. Use this option with caution. */static void poll_idle (void){ int oldval; __sti(); /* * Deal with another CPU just having chosen a thread to * run here: */ oldval = xchg(¤t->need_resched, -1); if (!oldval) asm volatile( "2:" "cmpl $-1, %0;" "rep; nop;" "je 2b;" : :"m" (current->need_resched));}/* * The idle thread. There's no useful work to be * done, so just try to conserve power and have a * low exit latency (ie sit in a loop waiting for * somebody to say that they'd like to reschedule) */void cpu_idle (void){ /* endless idle loop with no priority at all */ init_idle(); current->nice = 20; current->counter = -100; while (1) { void (*idle)(void) = pm_idle; if (!idle) idle = default_idle; while (!current->need_resched) idle(); schedule(); check_pgt_cache(); }}static int __init idle_setup (char *str){ if (!strncmp(str, "poll", 4)) { printk("using polling idle threads.\n"); pm_idle = poll_idle; } return 1;}__setup("idle=", idle_setup);static long no_idt[3];static int reboot_mode;#ifdef CONFIG_SMPint reboot_smp = 0;static int reboot_cpu = -1;#endifstatic int __init reboot_setup(char *str){ while(1) { switch (*str) { case 'w': /* "warm" reboot (no memory testing etc) */ reboot_mode = 0x1234; break; case 'c': /* "cold" reboot (with memory testing etc) */ reboot_mode = 0x0; break;#ifdef CONFIG_SMP case 's': /* "smp" reboot by executing reset on BSP or other CPU*/ reboot_smp = 1; if (isdigit(str[1])) sscanf(str+1, "%d", &reboot_cpu); else if (!strncmp(str,"smp",3)) sscanf(str+3, "%d", &reboot_cpu); /* we will leave sorting out the final value when we are ready to reboot, since we might not have set up boot_cpu_id or smp_num_cpu */ break;#endif } if((str = strchr(str,',')) != NULL) str++; else break; } return 1;}__setup("reboot=", reboot_setup);static inline void kb_wait(void){ int i; for (i=0; i<0x10000; i++) if ((inb_p(0x64) & 0x02) == 0) break;}void machine_restart(char * __unused){#if CONFIG_SMP int cpuid; cpuid = GET_APIC_ID(apic_read(APIC_ID)); if (reboot_smp) { /* check to see if reboot_cpu is valid if its not, default to the BSP */ if ((reboot_cpu == -1) || (reboot_cpu > (NR_CPUS -1)) || !(phys_cpu_present_map & (1<<cpuid))) reboot_cpu = boot_cpu_id; reboot_smp = 0; /* use this as a flag to only go through this once*/ /* re-run this function on the other CPUs it will fall though this section since we have cleared reboot_smp, and do the reboot if it is the correct CPU, otherwise it halts. */ if (reboot_cpu != cpuid) smp_call_function((void *)machine_restart , NULL, 1, 0); } /* if reboot_cpu is still -1, then we want a tradional reboot, and if we are not running on the reboot_cpu,, halt */ if ((reboot_cpu != -1) && (cpuid != reboot_cpu)) { for (;;) __asm__ __volatile__ ("hlt"); } /* * Stop all CPUs and turn off local APICs and the IO-APIC, so * other OSs see a clean IRQ state. */ if (notify_die(DIE_STOP,"cpustop",0,0) != NOTIFY_BAD) smp_send_stop(); disable_IO_APIC();#endif /* Could do reset through the northbridge of the Hammer here. */ /* rebooting needs to touch the page at absolute addr 0 */ *((unsigned short *)__va(0x472)) = reboot_mode; for (;;) { int i; /* First fondle with the keyboard controller. */ for (i=0; i<100; i++) { kb_wait(); udelay(50); outb(0xfe,0x64); /* pulse reset low */ udelay(50); } /* That didn't work - force a triple fault.. */ __asm__ __volatile__("lidt %0": :"m" (no_idt)); __asm__ __volatile__("int3"); }}void machine_halt(void){}void machine_power_off(void){ if (pm_power_off) pm_power_off();}extern int printk_address(unsigned long); /* Prints also some state that isn't saved in the pt_regs */ void show_regs(struct pt_regs * regs){ unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L, fs, gs, shadowgs; unsigned int fsindex,gsindex; unsigned int ds,cs,es; printk("\n"); printk("Pid: %d, comm: %.20s %s\n", current->pid, current->comm, print_tainted()); printk("RIP: %04lx:", regs->cs & 0xffff); printk_address(regs->rip); printk("\nRSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss, regs->rsp, regs->eflags); printk("RAX: %016lx RBX: %016lx RCX: %016lx\n", regs->rax, regs->rbx, regs->rcx); printk("RDX: %016lx RSI: %016lx RDI: %016lx\n", regs->rdx, regs->rsi, regs->rdi); printk("RBP: %016lx R08: %016lx R09: %016lx\n", regs->rbp, regs->r8, regs->r9); printk("R10: %016lx R11: %016lx R12: %016lx\n", regs->r10, regs->r11, regs->r12); printk("R13: %016lx R14: %016lx R15: %016lx\n", regs->r13, regs->r14, regs->r15); asm("movl %%ds,%0" : "=r" (ds)); asm("movl %%cs,%0" : "=r" (cs)); asm("movl %%es,%0" : "=r" (es)); asm("movl %%fs,%0" : "=r" (fsindex)); asm("movl %%gs,%0" : "=r" (gsindex)); rdmsrl(MSR_FS_BASE, fs); rdmsrl(MSR_GS_BASE, gs); rdmsrl(MSR_KERNEL_GS_BASE, shadowgs); asm("movq %%cr0, %0": "=r" (cr0)); asm("movq %%cr2, %0": "=r" (cr2)); asm("movq %%cr3, %0": "=r" (cr3)); asm("movq %%cr4, %0": "=r" (cr4)); printk("FS: %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n", fs,fsindex,gs,gsindex,shadowgs); printk("CS: %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds, es, cr0); printk("CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3, cr4);}/* * No need to lock the MM as we are the last user */void release_segments(struct mm_struct *mm){ void * ldt = mm->context.segments; /* * free the LDT */ if (ldt) { mm->context.segments = NULL; clear_LDT(); vfree(ldt); }}/* * Free current thread data structures etc.. */void exit_thread(void){ struct task_struct *me = current; if (me->thread.io_bitmap_ptr) { (init_tss + smp_processor_id())->io_map_base = INVALID_IO_BITMAP_OFFSET; kfree(me->thread.io_bitmap_ptr); me->thread.io_bitmap_ptr = NULL; } }void flush_thread(void)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -