2016-07-27 05:55:41 +08:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2016 Intel Corporation
|
|
|
|
*
|
2017-01-19 09:01:01 +08:00
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
2016-07-27 05:55:41 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef X86_EXCEPTION_H
|
|
|
|
#define X86_EXCEPTION_H
|
|
|
|
|
|
|
|
#ifndef _ASMLANGUAGE
|
|
|
|
|
2016-09-27 05:34:33 +08:00
|
|
|
#include <toolchain/common.h>
|
|
|
|
|
|
|
|
#define _EXCEPTION_INTLIST(vector) \
|
|
|
|
".pushsection .gnu.linkonce.intList.exc_" #vector "\n\t" \
|
|
|
|
".long 1f\n\t" /* ISR_LIST.fnc */ \
|
|
|
|
".long -1\n\t" /* ISR_LIST.irq */ \
|
|
|
|
".long -1\n\t" /* ISR_LIST.priority */ \
|
|
|
|
".long " STRINGIFY(vector) "\n\t" /* ISR_LIST.vec */ \
|
|
|
|
".long 0\n\t" /* ISR_LIST.dpl */ \
|
2017-07-15 04:29:19 +08:00
|
|
|
".long 0\n\t" /* ISR_LIST.tss */ \
|
2016-09-27 05:34:33 +08:00
|
|
|
".popsection\n\t" \
|
|
|
|
|
|
|
|
/* Extra preprocessor indirection to ensure arguments get expanded before
|
|
|
|
* concatenation takes place
|
|
|
|
*/
|
|
|
|
#define __EXCEPTION_STUB_NAME(handler, vec) \
|
|
|
|
_ ## handler ## _vector_ ## vec ## _stub
|
|
|
|
|
|
|
|
#define _EXCEPTION_STUB_NAME(handler, vec) \
|
|
|
|
__EXCEPTION_STUB_NAME(handler, vec) \
|
|
|
|
|
2016-07-27 05:55:41 +08:00
|
|
|
/* Unfortunately, GCC extended asm doesn't work at toplevel so we need
|
|
|
|
* to stringify stuff.
|
|
|
|
*
|
|
|
|
* What we are doing here is generating entires in the .intList section
|
|
|
|
* and also the assembly language stubs for the exception. We use
|
|
|
|
* .gnu.linkonce section prefix so that the linker only includes the
|
|
|
|
* first one of these it encounters for a particular vector. In this
|
|
|
|
* way it's easy for applications or drivers to install custom exception
|
|
|
|
* handlers without having to #ifdef out previous instances such as in
|
|
|
|
* arch/x86/core/fatal.c
|
|
|
|
*/
|
2016-09-27 05:34:33 +08:00
|
|
|
#define __EXCEPTION_CONNECT(handler, vector, codepush) \
|
2016-07-27 05:55:41 +08:00
|
|
|
__asm__ ( \
|
2016-09-27 05:34:33 +08:00
|
|
|
_EXCEPTION_INTLIST(vector) \
|
|
|
|
".pushsection .gnu.linkonce.t.exc_" STRINGIFY(vector) \
|
|
|
|
"_stub, \"ax\"\n\t" \
|
|
|
|
".global " STRINGIFY(_EXCEPTION_STUB_NAME(handler, vector)) "\n\t" \
|
|
|
|
STRINGIFY(_EXCEPTION_STUB_NAME(handler, vector)) ":\n\t" \
|
2016-07-27 05:55:41 +08:00
|
|
|
"1:\n\t" \
|
2016-09-27 05:34:33 +08:00
|
|
|
codepush \
|
|
|
|
"push $" STRINGIFY(handler) "\n\t" \
|
|
|
|
"jmp _exception_enter\n\t" \
|
2016-07-27 05:55:41 +08:00
|
|
|
".popsection\n\t" \
|
|
|
|
)
|
|
|
|
|
2016-09-27 05:34:33 +08:00
|
|
|
|
2016-07-27 05:55:41 +08:00
|
|
|
/**
|
|
|
|
* @brief Connect an exception handler that doesn't expect error code
|
|
|
|
*
|
|
|
|
* Assign an exception handler to a particular vector in the IDT.
|
|
|
|
*
|
|
|
|
* @param handler A handler function of the prototype
|
|
|
|
* void handler(const NANO_ESF *esf)
|
|
|
|
* @param vector Vector index in the IDT
|
|
|
|
*/
|
|
|
|
#define _EXCEPTION_CONNECT_NOCODE(handler, vector) \
|
2016-09-27 05:34:33 +08:00
|
|
|
__EXCEPTION_CONNECT(handler, vector, "push $0\n\t")
|
2016-07-27 05:55:41 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Connect an exception handler that does expect error code
|
|
|
|
*
|
|
|
|
* Assign an exception handler to a particular vector in the IDT.
|
|
|
|
* The error code will be accessible in esf->errorCode
|
|
|
|
*
|
|
|
|
* @param handler A handler function of the prototype
|
|
|
|
* void handler(const NANO_ESF *esf)
|
|
|
|
* @param vector Vector index in the IDT
|
|
|
|
*/
|
|
|
|
#define _EXCEPTION_CONNECT_CODE(handler, vector) \
|
2016-09-27 05:34:33 +08:00
|
|
|
__EXCEPTION_CONNECT(handler, vector, "")
|
2016-07-27 05:55:41 +08:00
|
|
|
|
|
|
|
#endif /* _ASMLANGUAGE */
|
|
|
|
|
|
|
|
#endif /* X86_EXCEPTION_H */
|