xref: /freebsd/stand/efi/loader/arch/amd64/exc.S (revision e32fecd0c2c3ee37c47ee100f169e7eb0282a873)
1/*-
2 * Copyright (c) 2016 The FreeBSD Foundation
3 *
4 * This software was developed by Konstantin Belousov under sponsorship
5 * from the FreeBSD Foundation.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * $FreeBSD$
29 */
30
31	.macro	EH	N, err=1
32	.align	8
33	.globl	EXC\N\()_handler
34EXC\N\()_handler:
35	.if	\err != 1
36	pushq	$0
37	.endif
38	pushq	%rax
39	pushq	%rdx
40	pushq	%rcx
41	movl	$\N,%ecx
42	jmp	all_handlers
43	.endm
44
45	.text
46	EH	0,0
47	EH	1,0
48	EH	2,0
49	EH	3,0
50	EH	4,0
51	EH	5,0
52	EH	6,0
53	EH	7,0
54	EH	8
55	EH	9,0
56	EH	10
57	EH	11
58	EH	12
59	EH	13
60	EH	14
61	EH	16,0
62	EH	17
63	EH	18,0
64	EH	19,0
65	EH	20,0
66
67	.globl	exc_rsp
68all_handlers:
69	cmpq	%rsp,exc_rsp(%rip)
70	je	exception
71
72	/*
73	 * Interrupt, not exception.
74	 * First, copy the hardware interrupt frame to the previous stack.
75	 * Our handler always has private IST stack.
76	 */
77	movq	(6*8)(%rsp),%rax	/* saved %rsp value, AKA old stack */
78	subq	(5*8),%rax
79	movq	(3*8)(%rsp),%rdx	/* copy %rip to old stack */
80	movq	%rdx,(%rax)
81	movq	(4*8)(%rsp),%rdx	/* copy %cs */
82	movq	%rdx,(1*8)(%rax)
83	movq	(5*8)(%rsp),%rdx	/* copy %rflags */
84	movq	%rdx,(2*8)(%rax)
85	movq	(6*8)(%rsp),%rdx	/* copy %rsp */
86	movq	%rdx,(3*8)(%rax)
87	movq	(7*8)(%rsp),%rdx	/* copy %ss */
88	movq	%rdx,(4*8)(%rax)
89
90	/*
91	 * Now simulate invocation of the original interrupt handler
92	 * with retq.  We switch stacks and execute retq from the old
93	 * stack since there is no free registers at the last moment.
94	 */
95	subq	$16,%rax
96	leaq	fw_intr_handlers(%rip),%rdx
97	movq	(%rdx,%rcx,8),%rdx /* push intr handler address on old stack */
98	movq	%rdx,8(%rax)
99	movq	(2*8)(%rsp),%rcx   /* saved %rax is put on top of old stack */
100	movq	%rcx,(%rax)
101	movq	(%rsp),%rcx
102	movq	8(%rsp),%rdx
103
104	movq	32(%rsp),%rsp	/* switch to old stack */
105	popq	%rax
106	retq
107
108exception:
109	/*
110	 * Form the struct trapframe on our IST stack.
111	 * Skip three words, which are currently busy with temporal
112	 * saves.
113	 */
114	pushq	%r15
115	pushq	%r14
116	pushq	%r13
117	pushq	%r12
118	pushq	%r11
119	pushq	%r10
120	pushq	%rbp
121	pushq	%rbx
122	pushq	$0	/* %rax	*/
123	pushq	%r9
124	pushq	%r8
125	pushq	$0	/* %rcx */
126	pushq	$0	/* %rdx	*/
127	pushq	%rsi
128	pushq	%rdi
129
130	/*
131	 * Move %rax, %rdx, %rcx values into the final location,
132	 * from the three words which were skipped above.
133	 */
134	movq	0x88(%rsp),%rax
135	movq	%rax,0x30(%rsp)	/* tf_rax */
136	movq	0x78(%rsp),%rax
137	movq	%rax,0x18(%rsp)	/* tf_rcx */
138	movq	0x80(%rsp),%rax
139	movq	%rax,0x10(%rsp)	/* tf_rdx */
140
141	/*
142	 * And fill the three words themself.
143	 */
144	movq	%cr2,%rax
145	movq	%rax,0x80(%rsp)	/* tf_addr */
146	movl	%ecx,0x78(%rsp)	/* tf_trapno */
147	movw	%ds,0x8e(%rsp)
148	movw	%es,0x8c(%rsp)
149	movw	%fs,0x7c(%rsp)
150	movw	%gs,0x7e(%rsp)
151	movw	$0,0x88(%rsp)	/* tf_flags */
152
153	/*
154	 * Call dump routine.
155	 */
156	movq	%rsp,%rdi
157	callq	report_exc
158
159	/*
160	 * Hang after reporting. Interrupts are already disabled.
161	 */
1621:
163	hlt
164	jmp	1b
165