| /* ----------------------------------------------------------------------- | |
| * | |
| * Copyright 2009-2014 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 | |
| .section ".inittext","ax" | |
| .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 |