diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-10 16:14:41 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-10 16:14:41 -0700 |
commit | bec706838ec2f9c8c2b99e88a1270d7cba159b06 (patch) | |
tree | 96ec3ccbab3596dee79ef874483238853351a4f8 /arch/x86/boot/bioscall.S | |
parent | bb7762961d3ce745688e9050e914c1d3f980268d (diff) | |
parent | ee0736627d3347be0be2769fa7b26431f9726c9d (diff) |
Merge branch 'x86-setup-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'x86-setup-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
x86, setup: fix comment in the "glove box" code
x86, setup: "glove box" BIOS interrupts in the video code
x86, setup: "glove box" BIOS interrupts in the MCA code
x86, setup: "glove box" BIOS interrupts in the EDD code
x86, setup: "glove box" BIOS interrupts in the APM code
x86, setup: "glove box" BIOS interrupts in the core boot code
x86, setup: "glove box" BIOS calls -- infrastructure
Diffstat (limited to 'arch/x86/boot/bioscall.S')
-rw-r--r-- | arch/x86/boot/bioscall.S | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/arch/x86/boot/bioscall.S b/arch/x86/boot/bioscall.S new file mode 100644 index 00000000000..507793739ea --- /dev/null +++ b/arch/x86/boot/bioscall.S @@ -0,0 +1,82 @@ +/* ----------------------------------------------------------------------- + * + * Copyright 2009 Intel Corporation; author H. Peter Anvin + * + * This file is part of the Linux kernel, and is made available under + * the terms of the GNU General Public License version 2 or (at your + * option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * "Glove box" for BIOS calls. Avoids the constant problems with BIOSes + * touching registers they shouldn't be. + */ + + .code16 + .text + .globl intcall + .type intcall, @function +intcall: + /* Self-modify the INT instruction. Ugly, but works. */ + cmpb %al, 3f + je 1f + movb %al, 3f + jmp 1f /* Synchronize pipeline */ +1: + /* Save state */ + pushfl + pushw %fs + pushw %gs + pushal + + /* Copy input state to stack frame */ + subw $44, %sp + movw %dx, %si + movw %sp, %di + movw $11, %cx + rep; movsd + + /* Pop full state from the stack */ + popal + popw %gs + popw %fs + popw %es + popw %ds + popfl + + /* Actual INT */ + .byte 0xcd /* INT opcode */ +3: .byte 0 + + /* Push full state to the stack */ + pushfl + pushw %ds + pushw %es + pushw %fs + pushw %gs + pushal + + /* Re-establish C environment invariants */ + cld + movzwl %sp, %esp + movw %cs, %ax + movw %ax, %ds + movw %ax, %es + + /* Copy output state from stack frame */ + movw 68(%esp), %di /* Original %cx == 3rd argument */ + andw %di, %di + jz 4f + movw %sp, %si + movw $11, %cx + rep; movsd +4: addw $44, %sp + + /* Restore state and return */ + popal + popw %gs + popw %fs + popfl + retl + .size intcall, .-intcall |