xref: /OK3568_Linux_fs/kernel/arch/x86/boot/bioscall.S (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun/* SPDX-License-Identifier: GPL-2.0-or-later */
2*4882a593Smuzhiyun/* -----------------------------------------------------------------------
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun *   Copyright 2009-2014 Intel Corporation; author H. Peter Anvin
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * ----------------------------------------------------------------------- */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun/*
9*4882a593Smuzhiyun * "Glove box" for BIOS calls.  Avoids the constant problems with BIOSes
10*4882a593Smuzhiyun * touching registers they shouldn't be.
11*4882a593Smuzhiyun */
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun	.code16
14*4882a593Smuzhiyun	.section ".inittext","ax"
15*4882a593Smuzhiyun	.globl	intcall
16*4882a593Smuzhiyun	.type	intcall, @function
17*4882a593Smuzhiyunintcall:
18*4882a593Smuzhiyun	/* Self-modify the INT instruction.  Ugly, but works. */
19*4882a593Smuzhiyun	cmpb	%al, 3f
20*4882a593Smuzhiyun	je	1f
21*4882a593Smuzhiyun	movb	%al, 3f
22*4882a593Smuzhiyun	jmp	1f		/* Synchronize pipeline */
23*4882a593Smuzhiyun1:
24*4882a593Smuzhiyun	/* Save state */
25*4882a593Smuzhiyun	pushfl
26*4882a593Smuzhiyun	pushw	%fs
27*4882a593Smuzhiyun	pushw	%gs
28*4882a593Smuzhiyun	pushal
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun	/* Copy input state to stack frame */
31*4882a593Smuzhiyun	subw	$44, %sp
32*4882a593Smuzhiyun	movw	%dx, %si
33*4882a593Smuzhiyun	movw	%sp, %di
34*4882a593Smuzhiyun	movw	$11, %cx
35*4882a593Smuzhiyun	rep; movsd
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun	/* Pop full state from the stack */
38*4882a593Smuzhiyun	popal
39*4882a593Smuzhiyun	popw	%gs
40*4882a593Smuzhiyun	popw	%fs
41*4882a593Smuzhiyun	popw	%es
42*4882a593Smuzhiyun	popw	%ds
43*4882a593Smuzhiyun	popfl
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun	/* Actual INT */
46*4882a593Smuzhiyun	.byte	0xcd		/* INT opcode */
47*4882a593Smuzhiyun3:	.byte	0
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun	/* Push full state to the stack */
50*4882a593Smuzhiyun	pushfl
51*4882a593Smuzhiyun	pushw	%ds
52*4882a593Smuzhiyun	pushw	%es
53*4882a593Smuzhiyun	pushw	%fs
54*4882a593Smuzhiyun	pushw	%gs
55*4882a593Smuzhiyun	pushal
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun	/* Re-establish C environment invariants */
58*4882a593Smuzhiyun	cld
59*4882a593Smuzhiyun	movzwl	%sp, %esp
60*4882a593Smuzhiyun	movw	%cs, %ax
61*4882a593Smuzhiyun	movw	%ax, %ds
62*4882a593Smuzhiyun	movw	%ax, %es
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun	/* Copy output state from stack frame */
65*4882a593Smuzhiyun	movw	68(%esp), %di	/* Original %cx == 3rd argument */
66*4882a593Smuzhiyun	andw	%di, %di
67*4882a593Smuzhiyun	jz	4f
68*4882a593Smuzhiyun	movw	%sp, %si
69*4882a593Smuzhiyun	movw	$11, %cx
70*4882a593Smuzhiyun	rep; movsd
71*4882a593Smuzhiyun4:	addw	$44, %sp
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun	/* Restore state and return */
74*4882a593Smuzhiyun	popal
75*4882a593Smuzhiyun	popw	%gs
76*4882a593Smuzhiyun	popw	%fs
77*4882a593Smuzhiyun	popfl
78*4882a593Smuzhiyun	retl
79*4882a593Smuzhiyun	.size	intcall, .-intcall
80