1 #include <linux/linkage.h>
2 #include <linux/init.h>
3 #include <asm/segment.h>
4 #include <asm/page_types.h>
7 * The following code and data reboots the machine by switching to real
8 * mode and jumping to the BIOS reset entry point, as if the CPU has
9 * really been reset. The previous version asked the keyboard
10 * controller to pulse the CPU reset line, which is more thorough, but
11 * doesn't work with at least one type of 486 motherboard. It is easy
12 * to stop this code working; hence the copious comments.
14 * This code is called with the restart type (0 = BIOS, 1 = APM) in %eax.
16 .section ".x86_trampoline","a"
19 ENTRY(machine_real_restart_asm)
21 /* Get our own relocated address */
24 subl $(1b - r_base), %ebx
26 /* Compute the equivalent real-mode segment */
30 /* Patch post-real-mode segment jump */
31 movw (dispatch_table - r_base)(%ebx,%eax,2),%ax
32 movw %ax, (101f - r_base)(%ebx)
33 movw %cx, (102f - r_base)(%ebx)
35 /* Set up the IDT for real mode. */
36 lidtl (machine_real_restart_idt - r_base)(%ebx)
39 * Set up a GDT from which we can load segment descriptors for real
40 * mode. The GDT is not used in real mode; it is just needed here to
41 * prepare the descriptors.
43 lgdtl (machine_real_restart_gdt - r_base)(%ebx)
46 * Load the data segment registers with 16-bit compatible values
54 ljmpl $8, $1f - r_base
57 * This is 16-bit protected mode code to disable paging and the cache,
58 * switch to real mode and jump to the BIOS reset code.
60 * The instruction that switches to real mode by writing to CR0 must be
61 * followed immediately by a far jump instruction, which set CS to a
62 * valid value for real mode, and flushes the prefetch queue to avoid
63 * running instructions that have already been decoded in protected
66 * Clears all the flags except ET, especially PG (paging), PE
67 * (protected-mode enable) and TS (task switch for coprocessor state
68 * save). Flushes the TLB after paging has been disabled. Sets CD and
69 * NW, to disable the cache on a 486, and invalidates the cache. This
70 * is more like the state of a 486 after reset. I don't know if
71 * something else should be done for other chips.
73 * More could be done here to set up the registers as if a CPU reset had
74 * occurred; hopefully real BIOSs don't assume much. This is not the
75 * actual BIOS entry point, anyway (that is at 0xfffffff0).
77 * Most of this work is probably excessive, but it is what is tested.
83 andl $0x00000011, %eax
88 andl $0x60000000, %edx /* If no cache bits -> no wbinvd */
94 .byte 0xea /* ljmpw */
95 101: .word 0 /* Offset */
96 102: .word 0 /* Segment */
99 ljmpw $0xf000, $0xfff0
110 END(machine_real_restart_asm)
113 /* These must match <asm/reboot.h */
120 machine_real_restart_idt:
121 .word 0xffff /* Length - real mode default value */
122 .long 0 /* Base - real mode default value */
123 END(machine_real_restart_idt)
126 ENTRY(machine_real_restart_gdt)
127 .quad 0 /* Self-pointer, filled in by PM code */
128 .quad 0 /* 16-bit code segment, filled in by PM code */
130 * 16-bit data segment with the selector value 16 = 0x10 and
131 * base value 0x100; since this is consistent with real mode
132 * semantics we don't have to reload the segments once CR0.PE = 0.
134 .quad GDT_ENTRY(0x0093, 0x100, 0xffff)
135 END(machine_real_restart_gdt)