ia64/xen-unstable

view xen/arch/x86/shutdown.c @ 17828:5bf5fb8117c0

x86/64: Fix build.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Jun 10 15:30:50 2008 +0100 (2008-06-10)
parents c7d361cf5793
children a3319f32496f
line source
1 /******************************************************************************
2 * arch/x86/shutdown.c
3 *
4 * x86-specific shutdown handling.
5 */
7 #include <xen/config.h>
8 #include <xen/init.h>
9 #include <xen/lib.h>
10 #include <xen/sched.h>
11 #include <xen/smp.h>
12 #include <xen/delay.h>
13 #include <xen/dmi.h>
14 #include <xen/irq.h>
15 #include <xen/console.h>
16 #include <xen/shutdown.h>
17 #include <xen/acpi.h>
18 #include <asm/msr.h>
19 #include <asm/regs.h>
20 #include <asm/mc146818rtc.h>
21 #include <asm/system.h>
22 #include <asm/io.h>
23 #include <asm/processor.h>
24 #include <asm/mpspec.h>
25 #include <asm/tboot.h>
27 enum reboot_type {
28 BOOT_TRIPLE = 't',
29 BOOT_KBD = 'k',
30 BOOT_ACPI = 'a',
31 BOOT_BIOS = 'b',
32 };
34 static long no_idt[2];
35 static int reboot_mode;
37 /*
38 * reboot=b[ios] | t[riple] | k[bd] | [, [w]arm | [c]old]
39 * warm Don't set the cold reboot flag
40 * cold Set the cold reboot flag
41 * bios Reboot by jumping through the BIOS (only for X86_32)
42 * triple Force a triple fault (init)
43 * kbd Use the keyboard controller. cold reset (default)
44 * acpi Use the RESET_REG in the FADT
45 */
46 static enum reboot_type reboot_type = BOOT_ACPI;
47 static void __init set_reboot_type(char *str)
48 {
49 for ( ; ; )
50 {
51 switch ( *str )
52 {
53 case 'w': /* "warm" reboot (no memory testing etc) */
54 reboot_mode = 0x1234;
55 break;
56 case 'c': /* "cold" reboot (with memory testing etc) */
57 reboot_mode = 0x0;
58 break;
59 case 'b':
60 case 'a':
61 case 'k':
62 case 't':
63 reboot_type = *str;
64 break;
65 }
66 if ( (str = strchr(str, ',')) == NULL )
67 break;
68 str++;
69 }
70 }
71 custom_param("reboot", set_reboot_type);
73 static inline void kb_wait(void)
74 {
75 int i;
77 for ( i = 0; i < 0x10000; i++ )
78 if ( (inb_p(0x64) & 0x02) == 0 )
79 break;
80 }
82 static void __attribute__((noreturn)) __machine_halt(void *unused)
83 {
84 local_irq_disable();
85 for ( ; ; )
86 halt();
87 }
89 void machine_halt(void)
90 {
91 watchdog_disable();
92 console_start_sync();
93 smp_call_function(__machine_halt, NULL, 1, 0);
94 __machine_halt(NULL);
95 }
97 #ifdef __i386__
99 /* The following code and data reboots the machine by switching to real
100 mode and jumping to the BIOS reset entry point, as if the CPU has
101 really been reset. The previous version asked the keyboard
102 controller to pulse the CPU reset line, which is more thorough, but
103 doesn't work with at least one type of 486 motherboard. It is easy
104 to stop this code working; hence the copious comments. */
106 static unsigned long long
107 real_mode_gdt_entries [3] =
108 {
109 0x0000000000000000ULL, /* Null descriptor */
110 0x00009a000000ffffULL, /* 16-bit real-mode 64k code at 0x00000000 */
111 0x000092000100ffffULL /* 16-bit real-mode 64k data at 0x00000100 */
112 };
114 static const struct
115 {
116 unsigned short size __attribute__ ((packed));
117 unsigned long long * base __attribute__ ((packed));
118 }
119 real_mode_gdt = { sizeof (real_mode_gdt_entries) - 1, real_mode_gdt_entries },
120 real_mode_idt = { 0x3ff, NULL };
123 /* This is 16-bit protected mode code to disable paging and the cache,
124 switch to real mode and jump to the BIOS reset code.
126 The instruction that switches to real mode by writing to CR0 must be
127 followed immediately by a far jump instruction, which set CS to a
128 valid value for real mode, and flushes the prefetch queue to avoid
129 running instructions that have already been decoded in protected
130 mode.
132 Clears all the flags except ET, especially PG (paging), PE
133 (protected-mode enable) and TS (task switch for coprocessor state
134 save). Flushes the TLB after paging has been disabled. Sets CD and
135 NW, to disable the cache on a 486, and invalidates the cache. This
136 is more like the state of a 486 after reset. I don't know if
137 something else should be done for other chips.
139 More could be done here to set up the registers as if a CPU reset had
140 occurred; hopefully real BIOSs don't assume much. */
142 static const unsigned char real_mode_switch [] =
143 {
144 0x0f, 0x20, 0xc0, /* movl %cr0,%eax */
145 0x66, 0x83, 0xe0, 0x11, /* andl $0x00000011,%eax */
146 0x66, 0x0d, 0x00, 0x00, 0x00, 0x60, /* orl $0x60000000,%eax */
147 0x0f, 0x22, 0xc0, /* movl %eax,%cr0 */
148 0x0f, 0x22, 0xd8, /* movl %eax,%cr3 */
149 0x0f, 0x20, 0xc2, /* movl %cr0,%edx */
150 0x66, 0x81, 0xe2, 0x00, 0x00, 0x00, 0x60, /* andl $0x60000000,%edx */
151 0x74, 0x02, /* jz f */
152 0x0f, 0x09, /* wbinvd */
153 0x24, 0x10, /* f: andb $0x10,al */
154 0x0f, 0x22, 0xc0 /* movl %eax,%cr0 */
155 };
156 #define MAX_LENGTH 0x40
157 static const unsigned char jump_to_bios [] =
158 {
159 0xea, 0xf0, 0xff, 0x00, 0xf0 /* ljmp $0xf000,$0xfff0 */
160 };
162 /*
163 * Switch to real mode and then execute the code
164 * specified by the code and length parameters.
165 * We assume that length will aways be less that MAX_LENGTH!
166 */
167 static void machine_real_restart(const unsigned char *code, unsigned length)
168 {
169 local_irq_disable();
171 /* Write zero to CMOS register number 0x0f, which the BIOS POST
172 routine will recognize as telling it to do a proper reboot. (Well
173 that's what this book in front of me says -- it may only apply to
174 the Phoenix BIOS though, it's not clear). At the same time,
175 disable NMIs by setting the top bit in the CMOS address register,
176 as we're about to do peculiar things to the CPU. */
178 spin_lock(&rtc_lock);
179 CMOS_WRITE(0x00, 0x8f);
180 spin_unlock(&rtc_lock);
182 /* Identity-map virtual address zero. */
184 map_pages_to_xen(0, 0, 1, __PAGE_HYPERVISOR|MAP_SMALL_PAGES);
185 set_current(idle_vcpu[0]);
186 write_ptbase(idle_vcpu[0]);
188 /* For the switch to real mode, copy some code to low memory. It has
189 to be in the first 64k because it is running in 16-bit mode, and it
190 has to have the same physical and virtual address, because it turns
191 off paging. Copy it near the end of the first page, out of the way
192 of BIOS variables. */
194 memcpy((void *)(PAGE_SIZE - sizeof(real_mode_switch) - MAX_LENGTH),
195 real_mode_switch, sizeof(real_mode_switch));
196 memcpy((void *)(PAGE_SIZE - MAX_LENGTH), code, length);
198 /* Set up the IDT for real mode. */
200 __asm__ __volatile__("lidt %0": : "m" (real_mode_idt));
202 /* Set up a GDT from which we can load segment descriptors for real
203 mode. The GDT is not used in real mode; it is just needed here to
204 prepare the descriptors. */
206 __asm__ __volatile__("lgdt %0": : "m" (real_mode_gdt));
208 /* Load the data segment registers, and thus the descriptors ready for
209 real mode. The base address of each segment is 0x100, 16 times the
210 selector value being loaded here. This is so that the segment
211 registers don't have to be reloaded after switching to real mode:
212 the values are consistent for real mode operation already. */
214 __asm__ __volatile__ ("\tmov %0,%%ds\n"
215 "\tmov %0,%%es\n"
216 "\tmov %0,%%fs\n"
217 "\tmov %0,%%gs\n"
218 "\tmov %0,%%ss"
219 :
220 : "r" (0x0010));
222 /* Jump to the 16-bit code that we copied earlier. It disables paging
223 and the cache, switches to real mode, and jumps to the BIOS reset
224 entry point. */
226 __asm__ __volatile__ ("ljmp $0x0008,%0"
227 :
228 : "i" ((void *)(PAGE_SIZE -
229 sizeof(real_mode_switch) -
230 MAX_LENGTH)));
231 }
233 static int __init set_bios_reboot(struct dmi_system_id *d)
234 {
235 if ( reboot_type != BOOT_BIOS )
236 {
237 reboot_type = BOOT_BIOS;
238 printk("%s series board detected. "
239 "Selecting BIOS-method for reboots.\n", d->ident);
240 }
241 return 0;
242 }
244 static struct dmi_system_id __initdata reboot_dmi_table[] = {
245 { /* Handle problems with rebooting on Dell 1300's */
246 .callback = set_bios_reboot,
247 .ident = "Dell PowerEdge 1300",
248 .matches = {
249 DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
250 DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1300/"),
251 },
252 },
253 { /* Handle problems with rebooting on Dell 300's */
254 .callback = set_bios_reboot,
255 .ident = "Dell PowerEdge 300",
256 .matches = {
257 DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
258 DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"),
259 },
260 },
261 { /* Handle problems with rebooting on Dell 2400's */
262 .callback = set_bios_reboot,
263 .ident = "Dell PowerEdge 2400",
264 .matches = {
265 DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
266 DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"),
267 },
268 },
269 { /* Handle problems with rebooting on HP laptops */
270 .callback = set_bios_reboot,
271 .ident = "HP Compaq Laptop",
272 .matches = {
273 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
274 DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq"),
275 },
276 },
277 { }
278 };
280 static int __init reboot_init(void)
281 {
282 dmi_check_system(reboot_dmi_table);
283 return 0;
284 }
285 __initcall(reboot_init);
287 #else /* __x86_64__ */
289 #define machine_real_restart(x, y)
291 #endif
293 void machine_restart(void)
294 {
295 int i;
297 watchdog_disable();
298 console_start_sync();
300 local_irq_enable();
302 /* Ensure we are the boot CPU. */
303 if ( get_apic_id() != boot_cpu_physical_apicid )
304 {
305 /* Send IPI to the boot CPU (logical cpu 0). */
306 on_selected_cpus(cpumask_of_cpu(0), (void *)machine_restart,
307 NULL, 1, 0);
308 for ( ; ; )
309 halt();
310 }
312 smp_send_stop();
314 if ( tboot_in_measured_env() )
315 tboot_shutdown(TB_SHUTDOWN_REBOOT);
317 /* Rebooting needs to touch the page at absolute address 0. */
318 *((unsigned short *)__va(0x472)) = reboot_mode;
320 for ( ; ; )
321 {
322 switch ( reboot_type )
323 {
324 case BOOT_KBD:
325 /* Pulse the keyboard reset line. */
326 for ( i = 0; i < 100; i++ )
327 {
328 kb_wait();
329 udelay(50);
330 outb(0xfe,0x64); /* pulse reset low */
331 udelay(50);
332 }
333 /* fall through */
334 case BOOT_TRIPLE:
335 asm volatile ( "lidt %0 ; int3" : "=m" (no_idt) );
336 break;
337 case BOOT_BIOS:
338 machine_real_restart(jump_to_bios, sizeof(jump_to_bios));
339 break;
340 case BOOT_ACPI:
341 acpi_reboot();
342 break;
343 }
345 reboot_type = BOOT_KBD;
346 }
347 }
349 /*
350 * Local variables:
351 * mode: C
352 * c-set-style: "BSD"
353 * c-basic-offset: 4
354 * tab-width: 4
355 * indent-tabs-mode: nil
356 * End:
357 */