PageRenderTime 38ms CodeModel.GetById 11ms app.highlight 19ms RepoModel.GetById 2ms app.codeStats 0ms

/arch/x86_64/kernel/reboot.c

https://bitbucket.org/evzijst/gittest
C | 163 lines | 121 code | 27 blank | 15 comment | 18 complexity | 1cf1b1080305a888792a7e200d36aecb MD5 | raw file
  1/* Various gunk just to reboot the machine. */ 
  2#include <linux/module.h>
  3#include <linux/reboot.h>
  4#include <linux/init.h>
  5#include <linux/smp.h>
  6#include <linux/kernel.h>
  7#include <linux/ctype.h>
  8#include <linux/string.h>
  9#include <asm/io.h>
 10#include <asm/kdebug.h>
 11#include <asm/delay.h>
 12#include <asm/hw_irq.h>
 13#include <asm/system.h>
 14#include <asm/pgtable.h>
 15#include <asm/tlbflush.h>
 16#include <asm/apic.h>
 17
 18/*
 19 * Power off function, if any
 20 */
 21void (*pm_power_off)(void);
 22
 23static long no_idt[3];
 24static enum { 
 25	BOOT_TRIPLE = 't',
 26	BOOT_KBD = 'k'
 27} reboot_type = BOOT_KBD;
 28static int reboot_mode = 0;
 29int reboot_force;
 30
 31/* reboot=t[riple] | k[bd] [, [w]arm | [c]old]
 32   warm   Don't set the cold reboot flag
 33   cold   Set the cold reboot flag
 34   triple Force a triple fault (init)
 35   kbd    Use the keyboard controller. cold reset (default)
 36   force  Avoid anything that could hang.
 37 */ 
 38static int __init reboot_setup(char *str)
 39{
 40	for (;;) {
 41		switch (*str) {
 42		case 'w': 
 43			reboot_mode = 0x1234;
 44			break;
 45
 46		case 'c':
 47			reboot_mode = 0;
 48			break;
 49
 50		case 't':
 51		case 'b':
 52		case 'k':
 53			reboot_type = *str;
 54			break;
 55		case 'f':
 56			reboot_force = 1;
 57			break;
 58		}
 59		if((str = strchr(str,',')) != NULL)
 60			str++;
 61		else
 62			break;
 63	}
 64	return 1;
 65}
 66
 67__setup("reboot=", reboot_setup);
 68
 69#ifdef CONFIG_SMP
 70static void smp_halt(void)
 71{
 72	int cpuid = safe_smp_processor_id(); 
 73	static int first_entry = 1;
 74
 75	if (reboot_force)
 76		return;
 77
 78	if (first_entry) {
 79		first_entry = 0;
 80		smp_call_function((void *)machine_restart, NULL, 1, 0);
 81	}
 82			
 83	smp_stop_cpu(); 
 84
 85	/* AP calling this. Just halt */
 86	if (cpuid != boot_cpu_id) { 
 87		for (;;) 
 88			asm("hlt");
 89	}
 90
 91	/* Wait for all other CPUs to have run smp_stop_cpu */
 92	while (!cpus_empty(cpu_online_map))
 93		rep_nop(); 
 94}
 95#endif
 96
 97static inline void kb_wait(void)
 98{
 99	int i;
100
101	for (i=0; i<0x10000; i++)
102		if ((inb_p(0x64) & 0x02) == 0)
103			break;
104}
105
106void machine_restart(char * __unused)
107{
108	int i;
109
110	printk("machine restart\n");
111
112#ifdef CONFIG_SMP
113	smp_halt(); 
114#endif
115
116	if (!reboot_force) {
117		local_irq_disable();
118#ifndef CONFIG_SMP
119		disable_local_APIC();
120#endif
121		disable_IO_APIC();
122		local_irq_enable();
123	}
124	
125	/* Tell the BIOS if we want cold or warm reboot */
126	*((unsigned short *)__va(0x472)) = reboot_mode;
127       
128	for (;;) {
129		/* Could also try the reset bit in the Hammer NB */
130		switch (reboot_type) { 
131		case BOOT_KBD:
132		for (i=0; i<100; i++) {
133			kb_wait();
134			udelay(50);
135			outb(0xfe,0x64);         /* pulse reset low */
136			udelay(50);
137		}
138
139		case BOOT_TRIPLE: 
140			__asm__ __volatile__("lidt (%0)": :"r" (&no_idt));
141			__asm__ __volatile__("int3");
142
143			reboot_type = BOOT_KBD;
144			break;
145		}      
146	}      
147}
148
149EXPORT_SYMBOL(machine_restart);
150
151void machine_halt(void)
152{
153}
154
155EXPORT_SYMBOL(machine_halt);
156
157void machine_power_off(void)
158{
159	if (pm_power_off)
160		pm_power_off();
161}
162
163EXPORT_SYMBOL(machine_power_off);