linux/arch/x86_64/kernel/reboot.c
<<
>>
Prefs
   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 <linux/pm.h>
  10#include <linux/kdebug.h>
  11#include <linux/sched.h>
  12#include <asm/io.h>
  13#include <asm/delay.h>
  14#include <asm/hw_irq.h>
  15#include <asm/system.h>
  16#include <asm/pgtable.h>
  17#include <asm/tlbflush.h>
  18#include <asm/apic.h>
  19#include <asm/iommu.h>
  20
  21/*
  22 * Power off function, if any
  23 */
  24void (*pm_power_off)(void);
  25EXPORT_SYMBOL(pm_power_off);
  26
  27static long no_idt[3];
  28static enum { 
  29        BOOT_TRIPLE = 't',
  30        BOOT_KBD = 'k'
  31} reboot_type = BOOT_KBD;
  32static int reboot_mode = 0;
  33int reboot_force;
  34
  35/* reboot=t[riple] | k[bd] [, [w]arm | [c]old]
  36   warm   Don't set the cold reboot flag
  37   cold   Set the cold reboot flag
  38   triple Force a triple fault (init)
  39   kbd    Use the keyboard controller. cold reset (default)
  40   force  Avoid anything that could hang.
  41 */ 
  42static int __init reboot_setup(char *str)
  43{
  44        for (;;) {
  45                switch (*str) {
  46                case 'w': 
  47                        reboot_mode = 0x1234;
  48                        break;
  49
  50                case 'c':
  51                        reboot_mode = 0;
  52                        break;
  53
  54                case 't':
  55                case 'b':
  56                case 'k':
  57                        reboot_type = *str;
  58                        break;
  59                case 'f':
  60                        reboot_force = 1;
  61                        break;
  62                }
  63                if((str = strchr(str,',')) != NULL)
  64                        str++;
  65                else
  66                        break;
  67        }
  68        return 1;
  69}
  70
  71__setup("reboot=", reboot_setup);
  72
  73static inline void kb_wait(void)
  74{
  75        int i;
  76
  77        for (i=0; i<0x10000; i++)
  78                if ((inb_p(0x64) & 0x02) == 0)
  79                        break;
  80}
  81
  82void machine_shutdown(void)
  83{
  84        unsigned long flags;
  85
  86        /* Stop the cpus and apics */
  87#ifdef CONFIG_SMP
  88        int reboot_cpu_id;
  89
  90        /* The boot cpu is always logical cpu 0 */
  91        reboot_cpu_id = 0;
  92
  93        /* Make certain the cpu I'm about to reboot on is online */
  94        if (!cpu_isset(reboot_cpu_id, cpu_online_map)) {
  95                reboot_cpu_id = smp_processor_id();
  96        }
  97
  98        /* Make certain I only run on the appropriate processor */
  99        set_cpus_allowed(current, cpumask_of_cpu(reboot_cpu_id));
 100
 101        /* O.K Now that I'm on the appropriate processor,
 102         * stop all of the others.
 103         */
 104        smp_send_stop();
 105#endif
 106
 107        local_irq_save(flags);
 108
 109#ifndef CONFIG_SMP
 110        disable_local_APIC();
 111#endif
 112
 113        disable_IO_APIC();
 114
 115        local_irq_restore(flags);
 116
 117        pci_iommu_shutdown();
 118}
 119
 120void machine_emergency_restart(void)
 121{
 122        int i;
 123
 124        /* Tell the BIOS if we want cold or warm reboot */
 125        *((unsigned short *)__va(0x472)) = reboot_mode;
 126       
 127        for (;;) {
 128                /* Could also try the reset bit in the Hammer NB */
 129                switch (reboot_type) { 
 130                case BOOT_KBD:
 131                for (i=0; i<10; i++) {
 132                        kb_wait();
 133                        udelay(50);
 134                        outb(0xfe,0x64);         /* pulse reset low */
 135                        udelay(50);
 136                }
 137
 138                case BOOT_TRIPLE: 
 139                        __asm__ __volatile__("lidt (%0)": :"r" (&no_idt));
 140                        __asm__ __volatile__("int3");
 141
 142                        reboot_type = BOOT_KBD;
 143                        break;
 144                }      
 145        }      
 146}
 147
 148void machine_restart(char * __unused)
 149{
 150        printk("machine restart\n");
 151
 152        if (!reboot_force) {
 153                machine_shutdown();
 154        }
 155        machine_emergency_restart();
 156}
 157
 158void machine_halt(void)
 159{
 160}
 161
 162void machine_power_off(void)
 163{
 164        if (pm_power_off) {
 165                if (!reboot_force) {
 166                        machine_shutdown();
 167                }
 168                pm_power_off();
 169        }
 170}
 171
 172
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.