-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
yaml --- r: 235162 b: refs/heads/master c: 3d35ac3 h: refs/heads/master v: v3
- Loading branch information
H. Peter Anvin
committed
Feb 18, 2011
1 parent
27522a3
commit 9b4dec3
Showing
6 changed files
with
163 additions
and
108 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
--- | ||
refs/heads/master: 014eea518af3d141e276664cf40ef3da899eba35 | ||
refs/heads/master: 3d35ac346e981162eeba391e496faceed4753e7b |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
#include <linux/linkage.h> | ||
#include <linux/init.h> | ||
#include <asm/segment.h> | ||
#include <asm/page_types.h> | ||
|
||
/* | ||
* The following code and data reboots the machine by switching to real | ||
* mode and jumping to the BIOS reset entry point, as if the CPU has | ||
* really been reset. The previous version asked the keyboard | ||
* controller to pulse the CPU reset line, which is more thorough, but | ||
* doesn't work with at least one type of 486 motherboard. It is easy | ||
* to stop this code working; hence the copious comments. | ||
* | ||
* This code is called with the restart type (0 = BIOS, 1 = APM) in %eax. | ||
*/ | ||
.section ".x86_trampoline","a" | ||
.balign 16 | ||
.code32 | ||
ENTRY(machine_real_restart_asm) | ||
r_base = . | ||
/* Get our own relocated address */ | ||
call 1f | ||
1: popl %ebx | ||
subl $1b, %ebx | ||
|
||
/* Patch post-real-mode segment jump */ | ||
movw dispatch_table(%ebx,%ecx,2),%cx | ||
movw %cx, 101f(%ebx) | ||
movw %ax, 102f(%ebx) | ||
|
||
/* Set up the IDT for real mode. */ | ||
lidtl machine_real_restart_idt(%ebx) | ||
|
||
/* | ||
* Set up a GDT from which we can load segment descriptors for real | ||
* mode. The GDT is not used in real mode; it is just needed here to | ||
* prepare the descriptors. | ||
*/ | ||
lgdtl machine_real_restart_gdt(%ebx) | ||
|
||
/* | ||
* Load the data segment registers with 16-bit compatible values | ||
*/ | ||
movl $16, %ecx | ||
movl %ecx, %ds | ||
movl %ecx, %es | ||
movl %ecx, %fs | ||
movl %ecx, %gs | ||
movl %ecx, %ss | ||
ljmpl $8, $1f - r_base | ||
|
||
/* | ||
* This is 16-bit protected mode code to disable paging and the cache, | ||
* switch to real mode and jump to the BIOS reset code. | ||
* | ||
* The instruction that switches to real mode by writing to CR0 must be | ||
* followed immediately by a far jump instruction, which set CS to a | ||
* valid value for real mode, and flushes the prefetch queue to avoid | ||
* running instructions that have already been decoded in protected | ||
* mode. | ||
* | ||
* Clears all the flags except ET, especially PG (paging), PE | ||
* (protected-mode enable) and TS (task switch for coprocessor state | ||
* save). Flushes the TLB after paging has been disabled. Sets CD and | ||
* NW, to disable the cache on a 486, and invalidates the cache. This | ||
* is more like the state of a 486 after reset. I don't know if | ||
* something else should be done for other chips. | ||
* | ||
* More could be done here to set up the registers as if a CPU reset had | ||
* occurred; hopefully real BIOSs don't assume much. This is not the | ||
* actual BIOS entry point, anyway (that is at 0xfffffff0). | ||
* | ||
* Most of this work is probably excessive, but it is what is tested. | ||
*/ | ||
.code16 | ||
1: | ||
xorl %ecx, %ecx | ||
movl %cr0, %eax | ||
andl $0x00000011, %eax | ||
orl $0x60000000, %eax | ||
movl %eax, %cr0 | ||
movl %ecx, %cr3 | ||
movl %cr0, %edx | ||
andl $0x60000000, %edx /* If no cache bits -> no wbinvd */ | ||
jz 2f | ||
wbinvd | ||
2: | ||
andb $0x10, %al | ||
movl %eax, %cr0 | ||
.byte 0xea /* ljmpw */ | ||
101: .word 0 /* Offset */ | ||
102: .word 0 /* Segment */ | ||
|
||
bios: | ||
ljmpw $0xf000, $0xfff0 | ||
|
||
apm: | ||
movw $0x1000, %ax | ||
movw %ax, %ss | ||
movw $0xf000, %sp | ||
movw $0x5307, %ax | ||
movw $0x0001, %bx | ||
movw $0x0003, %cx | ||
int $0x15 | ||
|
||
END(machine_real_restart_asm) | ||
|
||
.balign 16 | ||
/* These must match <asm/reboot.h */ | ||
dispatch_table: | ||
.word bios - r_base | ||
.word apm - r_base | ||
END(dispatch_table) | ||
|
||
.balign 16 | ||
machine_real_restart_idt: | ||
.word 0xffff /* Length - real mode default value */ | ||
.long 0 /* Base - real mode default value */ | ||
END(machine_real_restart_idt) | ||
|
||
.balign 16 | ||
ENTRY(machine_real_restart_gdt) | ||
.quad 0 /* Self-pointer, filled in by PM code */ | ||
.quad 0 /* 16-bit code segment, filled in by PM code */ | ||
/* | ||
* 16-bit data segment with the selector value 16 = 0x10 and | ||
* base value 0x100; since this is consistent with real mode | ||
* semantics we don't have to reload the segments once CR0.PE = 0. | ||
*/ | ||
.quad GDT_ENTRY(0x0093, 0x100, 0xffff) | ||
END(machine_real_restart_gdt) |