blob: 3ee26332af82151bff2caa86c2e06177908db0ee [file] [log] [blame]
/*
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef X86_EXCEPTION_H
#define X86_EXCEPTION_H
#ifndef _ASMLANGUAGE
#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 */ \
".long 0\n\t" /* ISR_LIST.tss */ \
".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) \
/* 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
*/
#define __EXCEPTION_CONNECT(handler, vector, codepush) \
__asm__ ( \
_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" \
"1:\n\t" \
codepush \
"push $" STRINGIFY(handler) "\n\t" \
"jmp _exception_enter\n\t" \
".popsection\n\t" \
)
/**
* @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) \
__EXCEPTION_CONNECT(handler, vector, "push $0\n\t")
/**
* @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) \
__EXCEPTION_CONNECT(handler, vector, "")
#endif /* _ASMLANGUAGE */
#endif /* X86_EXCEPTION_H */