1 /*
2  * Copyright (c) 2016 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_ARCH_X86_INCLUDE_IA32_EXCEPTION_H_
8 #define ZEPHYR_ARCH_X86_INCLUDE_IA32_EXCEPTION_H_
9 
10 #ifndef _ASMLANGUAGE
11 
12 #include <toolchain/common.h>
13 
14 #define _EXCEPTION_INTLIST(vector, dpl) \
15 	".pushsection .gnu.linkonce.intList.exc_" #vector "\n\t" \
16 	".long 1f\n\t"				/* ISR_LIST.fnc */ \
17 	".long -1\n\t"				/* ISR_LIST.irq */ \
18 	".long -1\n\t"				/* ISR_LIST.priority */ \
19 	".long " STRINGIFY(vector) "\n\t"	/* ISR_LIST.vec */ \
20 	".long " STRINGIFY(dpl) "\n\t"		/* ISR_LIST.dpl */ \
21 	".long 0\n\t"				/* ISR_LIST.tss */ \
22 	".popsection\n\t" \
23 
24 /* Extra preprocessor indirection to ensure arguments get expanded before
25  * concatenation takes place
26  */
27 #define __EXCEPTION_STUB_NAME(handler, vec) \
28 	_ ## handler ## _vector_ ## vec ## _stub
29 
30 #define _EXCEPTION_STUB_NAME(handler, vec) \
31 	__EXCEPTION_STUB_NAME(handler, vec) \
32 
33 /* Unfortunately, GCC extended asm doesn't work at toplevel so we need
34  * to stringify stuff.
35  *
36  * What we are doing here is generating entires in the .intList section
37  * and also the assembly language stubs for the exception. We use
38  * .gnu.linkonce section prefix so that the linker only includes the
39  * first one of these it encounters for a particular vector. In this
40  * way it's easy for applications or drivers to install custom exception
41  * handlers without having to #ifdef out previous instances such as in
42  * arch/x86/core/fatal.c
43  */
44 #define __EXCEPTION_CONNECT(handler, vector, dpl, codepush) \
45 	__asm__ ( \
46 	 _EXCEPTION_INTLIST(vector, dpl)		      \
47 	".pushsection .gnu.linkonce.t.exc_" STRINGIFY(vector) \
48 		  "_stub, \"ax\"\n\t" \
49 	".global " STRINGIFY(_EXCEPTION_STUB_NAME(handler, vector)) "\n\t" \
50 	STRINGIFY(_EXCEPTION_STUB_NAME(handler, vector)) ":\n\t" \
51 	"1:\n\t" \
52 	codepush \
53 	"push $" STRINGIFY(handler) "\n\t" \
54 	"jmp _exception_enter\n\t" \
55 	".popsection\n\t" \
56 	)
57 
58 
59 /**
60  * @brief Connect an exception handler that doesn't expect error code
61  *
62  * Assign an exception handler to a particular vector in the IDT.
63  *
64  * @param handler A handler function of the prototype
65  *                void handler(const z_arch_esf_t *esf)
66  * @param vector Vector index in the IDT
67  */
68 #define _EXCEPTION_CONNECT_NOCODE(handler, vector, dpl) \
69 	__EXCEPTION_CONNECT(handler, vector, dpl, "push $0\n\t")
70 
71 /**
72  * @brief Connect an exception handler that does expect error code
73  *
74  * Assign an exception handler to a particular vector in the IDT.
75  * The error code will be accessible in esf->errorCode
76  *
77  * @param handler A handler function of the prototype
78  *                void handler(const z_arch_esf_t *esf)
79  * @param vector Vector index in the IDT
80  */
81 #define _EXCEPTION_CONNECT_CODE(handler, vector, dpl) \
82 	__EXCEPTION_CONNECT(handler, vector, dpl, "")
83 
84 #endif /* _ASMLANGUAGE */
85 
86 #endif /* ZEPHYR_ARCH_X86_INCLUDE_IA32_EXCEPTION_H_ */
87