[CPUFREQ] powernow-k8 compile fix.
[linux-2.6] / arch / i386 / kernel / reboot.c
1 /*
2  *  linux/arch/i386/kernel/reboot.c
3  */
4
5 #include <linux/mm.h>
6 #include <linux/module.h>
7 #include <linux/delay.h>
8 #include <linux/init.h>
9 #include <linux/interrupt.h>
10 #include <linux/mc146818rtc.h>
11 #include <linux/efi.h>
12 #include <linux/dmi.h>
13 #include <linux/ctype.h>
14 #include <linux/pm.h>
15 #include <linux/reboot.h>
16 #include <asm/uaccess.h>
17 #include <asm/apic.h>
18 #include <asm/desc.h>
19 #include "mach_reboot.h"
20 #include <asm/reboot_fixups.h>
21 #include <asm/reboot.h>
22
23 /*
24  * Power off function, if any
25  */
26 void (*pm_power_off)(void);
27 EXPORT_SYMBOL(pm_power_off);
28
29 static int reboot_mode;
30 static int reboot_thru_bios;
31
32 #ifdef CONFIG_SMP
33 static int reboot_cpu = -1;
34 #endif
35 static int __init reboot_setup(char *str)
36 {
37         while(1) {
38                 switch (*str) {
39                 case 'w': /* "warm" reboot (no memory testing etc) */
40                         reboot_mode = 0x1234;
41                         break;
42                 case 'c': /* "cold" reboot (with memory testing etc) */
43                         reboot_mode = 0x0;
44                         break;
45                 case 'b': /* "bios" reboot by jumping through the BIOS */
46                         reboot_thru_bios = 1;
47                         break;
48                 case 'h': /* "hard" reboot by toggling RESET and/or crashing the CPU */
49                         reboot_thru_bios = 0;
50                         break;
51 #ifdef CONFIG_SMP
52                 case 's': /* "smp" reboot by executing reset on BSP or other CPU*/
53                         if (isdigit(*(str+1))) {
54                                 reboot_cpu = (int) (*(str+1) - '0');
55                                 if (isdigit(*(str+2)))
56                                         reboot_cpu = reboot_cpu*10 + (int)(*(str+2) - '0');
57                         }
58                                 /* we will leave sorting out the final value 
59                                 when we are ready to reboot, since we might not
60                                 have set up boot_cpu_id or smp_num_cpu */
61                         break;
62 #endif
63                 }
64                 if((str = strchr(str,',')) != NULL)
65                         str++;
66                 else
67                         break;
68         }
69         return 1;
70 }
71
72 __setup("reboot=", reboot_setup);
73
74 /*
75  * Reboot options and system auto-detection code provided by
76  * Dell Inc. so their systems "just work". :-)
77  */
78
79 /*
80  * Some machines require the "reboot=b"  commandline option, this quirk makes that automatic.
81  */
82 static int __init set_bios_reboot(struct dmi_system_id *d)
83 {
84         if (!reboot_thru_bios) {
85                 reboot_thru_bios = 1;
86                 printk(KERN_INFO "%s series board detected. Selecting BIOS-method for reboots.\n", d->ident);
87         }
88         return 0;
89 }
90
91 static struct dmi_system_id __initdata reboot_dmi_table[] = {
92         {       /* Handle problems with rebooting on Dell E520's */
93                 .callback = set_bios_reboot,
94                 .ident = "Dell E520",
95                 .matches = {
96                         DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
97                         DMI_MATCH(DMI_PRODUCT_NAME, "Dell DM061"),
98                 },
99         },
100         {       /* Handle problems with rebooting on Dell 1300's */
101                 .callback = set_bios_reboot,
102                 .ident = "Dell PowerEdge 1300",
103                 .matches = {
104                         DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
105                         DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1300/"),
106                 },
107         },
108         {       /* Handle problems with rebooting on Dell 300's */
109                 .callback = set_bios_reboot,
110                 .ident = "Dell PowerEdge 300",
111                 .matches = {
112                         DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
113                         DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"),
114                 },
115         },
116         {       /* Handle problems with rebooting on Dell 2400's */
117                 .callback = set_bios_reboot,
118                 .ident = "Dell PowerEdge 2400",
119                 .matches = {
120                         DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
121                         DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"),
122                 },
123         },
124         {       /* Handle problems with rebooting on HP laptops */
125                 .callback = set_bios_reboot,
126                 .ident = "HP Compaq Laptop",
127                 .matches = {
128                         DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
129                         DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq"),
130                 },
131         },
132         { }
133 };
134
135 static int __init reboot_init(void)
136 {
137         dmi_check_system(reboot_dmi_table);
138         return 0;
139 }
140
141 core_initcall(reboot_init);
142
143 /* The following code and data reboots the machine by switching to real
144    mode and jumping to the BIOS reset entry point, as if the CPU has
145    really been reset.  The previous version asked the keyboard
146    controller to pulse the CPU reset line, which is more thorough, but
147    doesn't work with at least one type of 486 motherboard.  It is easy
148    to stop this code working; hence the copious comments. */
149
150 static unsigned long long
151 real_mode_gdt_entries [3] =
152 {
153         0x0000000000000000ULL,  /* Null descriptor */
154         0x00009a000000ffffULL,  /* 16-bit real-mode 64k code at 0x00000000 */
155         0x000092000100ffffULL   /* 16-bit real-mode 64k data at 0x00000100 */
156 };
157
158 static struct Xgt_desc_struct
159 real_mode_gdt = { sizeof (real_mode_gdt_entries) - 1, (long)real_mode_gdt_entries },
160 real_mode_idt = { 0x3ff, 0 },
161 no_idt = { 0, 0 };
162
163
164 /* This is 16-bit protected mode code to disable paging and the cache,
165    switch to real mode and jump to the BIOS reset code.
166
167    The instruction that switches to real mode by writing to CR0 must be
168    followed immediately by a far jump instruction, which set CS to a
169    valid value for real mode, and flushes the prefetch queue to avoid
170    running instructions that have already been decoded in protected
171    mode.
172
173    Clears all the flags except ET, especially PG (paging), PE
174    (protected-mode enable) and TS (task switch for coprocessor state
175    save).  Flushes the TLB after paging has been disabled.  Sets CD and
176    NW, to disable the cache on a 486, and invalidates the cache.  This
177    is more like the state of a 486 after reset.  I don't know if
178    something else should be done for other chips.
179
180    More could be done here to set up the registers as if a CPU reset had
181    occurred; hopefully real BIOSs don't assume much. */
182
183 static unsigned char real_mode_switch [] =
184 {
185         0x66, 0x0f, 0x20, 0xc0,                 /*    movl  %cr0,%eax        */
186         0x66, 0x83, 0xe0, 0x11,                 /*    andl  $0x00000011,%eax */
187         0x66, 0x0d, 0x00, 0x00, 0x00, 0x60,     /*    orl   $0x60000000,%eax */
188         0x66, 0x0f, 0x22, 0xc0,                 /*    movl  %eax,%cr0        */
189         0x66, 0x0f, 0x22, 0xd8,                 /*    movl  %eax,%cr3        */
190         0x66, 0x0f, 0x20, 0xc3,                 /*    movl  %cr0,%ebx        */
191         0x66, 0x81, 0xe3, 0x00, 0x00, 0x00, 0x60,       /*    andl  $0x60000000,%ebx */
192         0x74, 0x02,                             /*    jz    f                */
193         0x0f, 0x09,                             /*    wbinvd                 */
194         0x24, 0x10,                             /* f: andb  $0x10,al         */
195         0x66, 0x0f, 0x22, 0xc0                  /*    movl  %eax,%cr0        */
196 };
197 static unsigned char jump_to_bios [] =
198 {
199         0xea, 0x00, 0x00, 0xff, 0xff            /*    ljmp  $0xffff,$0x0000  */
200 };
201
202 /*
203  * Switch to real mode and then execute the code
204  * specified by the code and length parameters.
205  * We assume that length will aways be less that 100!
206  */
207 void machine_real_restart(unsigned char *code, int length)
208 {
209         local_irq_disable();
210
211         /* Write zero to CMOS register number 0x0f, which the BIOS POST
212            routine will recognize as telling it to do a proper reboot.  (Well
213            that's what this book in front of me says -- it may only apply to
214            the Phoenix BIOS though, it's not clear).  At the same time,
215            disable NMIs by setting the top bit in the CMOS address register,
216            as we're about to do peculiar things to the CPU.  I'm not sure if
217            `outb_p' is needed instead of just `outb'.  Use it to be on the
218            safe side.  (Yes, CMOS_WRITE does outb_p's. -  Paul G.)
219          */
220
221         spin_lock(&rtc_lock);
222         CMOS_WRITE(0x00, 0x8f);
223         spin_unlock(&rtc_lock);
224
225         /* Remap the kernel at virtual address zero, as well as offset zero
226            from the kernel segment.  This assumes the kernel segment starts at
227            virtual address PAGE_OFFSET. */
228
229         memcpy (swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
230                 sizeof (swapper_pg_dir [0]) * KERNEL_PGD_PTRS);
231
232         /*
233          * Use `swapper_pg_dir' as our page directory.
234          */
235         load_cr3(swapper_pg_dir);
236
237         /* Write 0x1234 to absolute memory location 0x472.  The BIOS reads
238            this on booting to tell it to "Bypass memory test (also warm
239            boot)".  This seems like a fairly standard thing that gets set by
240            REBOOT.COM programs, and the previous reset routine did this
241            too. */
242
243         *((unsigned short *)0x472) = reboot_mode;
244
245         /* For the switch to real mode, copy some code to low memory.  It has
246            to be in the first 64k because it is running in 16-bit mode, and it
247            has to have the same physical and virtual address, because it turns
248            off paging.  Copy it near the end of the first page, out of the way
249            of BIOS variables. */
250
251         memcpy ((void *) (0x1000 - sizeof (real_mode_switch) - 100),
252                 real_mode_switch, sizeof (real_mode_switch));
253         memcpy ((void *) (0x1000 - 100), code, length);
254
255         /* Set up the IDT for real mode. */
256
257         load_idt(&real_mode_idt);
258
259         /* Set up a GDT from which we can load segment descriptors for real
260            mode.  The GDT is not used in real mode; it is just needed here to
261            prepare the descriptors. */
262
263         load_gdt(&real_mode_gdt);
264
265         /* Load the data segment registers, and thus the descriptors ready for
266            real mode.  The base address of each segment is 0x100, 16 times the
267            selector value being loaded here.  This is so that the segment
268            registers don't have to be reloaded after switching to real mode:
269            the values are consistent for real mode operation already. */
270
271         __asm__ __volatile__ ("movl $0x0010,%%eax\n"
272                                 "\tmovl %%eax,%%ds\n"
273                                 "\tmovl %%eax,%%es\n"
274                                 "\tmovl %%eax,%%fs\n"
275                                 "\tmovl %%eax,%%gs\n"
276                                 "\tmovl %%eax,%%ss" : : : "eax");
277
278         /* Jump to the 16-bit code that we copied earlier.  It disables paging
279            and the cache, switches to real mode, and jumps to the BIOS reset
280            entry point. */
281
282         __asm__ __volatile__ ("ljmp $0x0008,%0"
283                                 :
284                                 : "i" ((void *) (0x1000 - sizeof (real_mode_switch) - 100)));
285 }
286 #ifdef CONFIG_APM_MODULE
287 EXPORT_SYMBOL(machine_real_restart);
288 #endif
289
290 static void native_machine_shutdown(void)
291 {
292 #ifdef CONFIG_SMP
293         int reboot_cpu_id;
294
295         /* The boot cpu is always logical cpu 0 */
296         reboot_cpu_id = 0;
297
298         /* See if there has been given a command line override */
299         if ((reboot_cpu != -1) && (reboot_cpu < NR_CPUS) &&
300                 cpu_isset(reboot_cpu, cpu_online_map)) {
301                 reboot_cpu_id = reboot_cpu;
302         }
303
304         /* Make certain the cpu I'm rebooting on is online */
305         if (!cpu_isset(reboot_cpu_id, cpu_online_map)) {
306                 reboot_cpu_id = smp_processor_id();
307         }
308
309         /* Make certain I only run on the appropriate processor */
310         set_cpus_allowed(current, cpumask_of_cpu(reboot_cpu_id));
311
312         /* O.K. Now that I'm on the appropriate processor, stop
313          * all of the others, and disable their local APICs.
314          */
315
316         smp_send_stop();
317 #endif /* CONFIG_SMP */
318
319         lapic_shutdown();
320
321 #ifdef CONFIG_X86_IO_APIC
322         disable_IO_APIC();
323 #endif
324 }
325
326 void __attribute__((weak)) mach_reboot_fixups(void)
327 {
328 }
329
330 static void native_machine_emergency_restart(void)
331 {
332         if (!reboot_thru_bios) {
333                 if (efi_enabled) {
334                         efi.reset_system(EFI_RESET_COLD, EFI_SUCCESS, 0, NULL);
335                         load_idt(&no_idt);
336                         __asm__ __volatile__("int3");
337                 }
338                 /* rebooting needs to touch the page at absolute addr 0 */
339                 *((unsigned short *)__va(0x472)) = reboot_mode;
340                 for (;;) {
341                         mach_reboot_fixups(); /* for board specific fixups */
342                         mach_reboot();
343                         /* That didn't work - force a triple fault.. */
344                         load_idt(&no_idt);
345                         __asm__ __volatile__("int3");
346                 }
347         }
348         if (efi_enabled)
349                 efi.reset_system(EFI_RESET_WARM, EFI_SUCCESS, 0, NULL);
350
351         machine_real_restart(jump_to_bios, sizeof(jump_to_bios));
352 }
353
354 static void native_machine_restart(char * __unused)
355 {
356         machine_shutdown();
357         machine_emergency_restart();
358 }
359
360 static void native_machine_halt(void)
361 {
362 }
363
364 static void native_machine_power_off(void)
365 {
366         if (pm_power_off) {
367                 machine_shutdown();
368                 pm_power_off();
369         }
370 }
371
372
373 struct machine_ops machine_ops = {
374         .power_off = native_machine_power_off,
375         .shutdown = native_machine_shutdown,
376         .emergency_restart = native_machine_emergency_restart,
377         .restart = native_machine_restart,
378         .halt = native_machine_halt,
379 };
380
381 void machine_power_off(void)
382 {
383         machine_ops.power_off();
384 }
385
386 void machine_shutdown(void)
387 {
388         machine_ops.shutdown();
389 }
390
391 void machine_emergency_restart(void)
392 {
393         machine_ops.emergency_restart();
394 }
395
396 void machine_restart(char *cmd)
397 {
398         machine_ops.restart(cmd);
399 }
400
401 void machine_halt(void)
402 {
403         machine_ops.halt();
404 }